From 9cbb4b9fa0c599461bc6391d6010e18ccff9aafc Mon Sep 17 00:00:00 2001 From: XV Date: Mon, 14 Sep 2026 21:38:58 -0400 Subject: [PATCH] Converge plugin guidance on team policy --- AGENTS.md | 6 +- README.md | 21 +- openwiki/acg-release.md | 148 +--- openwiki/gh-settings.md | 102 +-- openwiki/quickstart.md | 15 +- plugins/acg-release/skills/macos/SKILL.md | 148 +--- .../skills/macos/references/standard.md | 751 +++++------------- plugins/gh-settings/skills/sync/SKILL.md | 110 +-- .../skills/sync/references/standard.md | 559 ++++--------- 9 files changed, 457 insertions(+), 1403 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cfd761d..99bca0d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,8 +3,8 @@ ## Repository This repository publishes ACG Box engineering standards as small Codex plugins. -Start with [OpenWiki quickstart](openwiki/quickstart.md). Read the owning plugin -skill and its direct references before you change runtime guidance. +Use [OpenWiki quickstart](openwiki/quickstart.md) for repository navigation. Read +the owning skill and relevant canonical sections when changing runtime guidance. ## Authority @@ -25,6 +25,8 @@ skill and its direct references before you change runtime guidance. skills, and `agents/openai.yaml`. - Keep one canonical standard. Link to it instead of copying its rules into OpenWiki or the README. +- Skills supply team policy, non-obvious constraints, and completion criteria. + Leave general implementation, troubleshooting, and test selection to the model. - Run `cargo make check`, the Plugin Creator validator, and the Skill Creator validator before a ready claim. - For durable workflow or layout changes, update source authority first. Then run diff --git a/README.md b/README.md index 66a8cad..fee0c2f 100644 --- a/README.md +++ b/README.md @@ -13,29 +13,16 @@ Small, reusable ACG Box engineering standards. ### GitHub Settings -`gh-settings` audits GitHub Enterprise, organization, and repository governance -without changing it by default. It puts each enforceable control at the highest -supported scope, separates central defaults from repository residuals, and shows the -exact planned fields or Web UI controls before an authorized reconciliation. It also -prevents implicit paid-product enablement and reads every changed setting back. -Its merge-commit-only baseline keeps merge commits enabled, disables squash and -rebase, and rejects conflicting linear-history rules. -Organization-wide mode is central-first and can require zero repository-owned -rulesets. Repository-scoped mode audits parent state but never widens authority to -change it. +`gh-settings` audits or reconciles GitHub governance against an authorized profile, +with central organization controls and repository-scoped operation. Read the [canonical GitHub settings standard](plugins/gh-settings/skills/sync/references/standard.md) or invoke `$gh-settings:sync` after installation. ### ACG Release -`acg-release` is the organization release-standard owner for repositories whose -canonical GitHub owner is `acg-box`. Its only current skill audits, migrates, -normalizes, operates, and verifies Developer ID releases for Sparkle-enabled macOS -ZIP applications. It stops as not applicable for repositories outside `acg-box/*` -and does not claim support for DMG, PKG, or non-Sparkle workflows. Future release -types get separate skills only after they have real evidence and an independent -owner contract. +`acg-release` guides Developer ID-notarized Sparkle macOS ZIP releases for +repositories whose canonical GitHub owner is `acg-box`. Read the [canonical ACG Box macOS release standard](plugins/acg-release/skills/macos/references/standard.md) or invoke `$acg-release:macos` after installation. diff --git a/openwiki/acg-release.md b/openwiki/acg-release.md index 49b8403..852eea6 100644 --- a/openwiki/acg-release.md +++ b/openwiki/acg-release.md @@ -15,133 +15,21 @@ openwiki: # ACG Release: macOS -## Runtime And Ownership Boundary - -`plugins/acg-release/` is the complete installed runtime for ACG Box organization -release standards. It currently contains one `macos` skill, its invocation metadata, -and one canonical Sparkle ZIP release standard. It has no executable, hook, app, MCP -server, credential, network client, template, or writable state. - -The plugin is extensible by release type, but only after a real release type has an -independent owner contract and evidence. Do not add empty skills, compatibility -aliases, or a generic root standard. The only current public invocation is -`$acg-release:macos`. - -The installed plugin guides repository work. GitHub Actions runs only the target -repository's checked-in adapter and never loads the plugin. - -## Applicability Gate - -The `macos` skill resolves the target repository's canonical GitHub owner before it -audits or changes release behavior. It continues only for `acg-box/*`. A repository -outside `acg-box` is not applicable: the skill must not audit it toward adoption, -change it, operate or verify its release under the standard, or inspect or apply the -ACG Box certificate, notary, Sparkle-key, secret, environment, or publisher topology. -An unresolved canonical owner is an applicability gap, not permission to assume -membership. - -```mermaid -flowchart TD - marketplace["marketplace entry"] --> plugin["acg-release manifest"] - plugin --> skill["macos skill"] - skill --> ownerGate{"canonical owner = acg-box?"} - ownerGate -->|no or unresolved| stop["stop: not applicable"] - ownerGate -->|yes| scopeGate{"Sparkle macOS ZIP?"} - scopeGate -->|no| stop - scopeGate -->|yes| standard["canonical macOS standard"] - standard --> adapter["target repository adapter"] - adapter --> workflow["repository-owned release workflow"] -``` - -This flow keeps plugin discovery, organization applicability, distribution scope, -target identity, and executable release work as separate owners. The skill loads -the detailed standard only after both applicability gates pass. - -## Release Policy And Adapter - -The current skill supports one regular Sparkle-enabled macOS app in a GitHub -Release ZIP. Production requires Developer ID Application signing, Hardened Runtime, -secure timestamps, Apple notarization, app stapling, strict code-signature checks, -Gatekeeper acceptance, a final post-stapling ZIP, Sparkle signature and appcast, -checksum, and draft-first GitHub publication. An Apple Development, Personal Team, -timestamp-free, unnotarized, or Open Anyway path is migration drift. - -The plugin contains no Apple Team ID, certificate suffix, product identity, or -Sparkle public key. Each applicable target repository owns its paid Team ID, -expected Developer ID identity selector, app and bundle identity, versions, assets, -feeds, entitlements, Sparkle pin and public key, build commands, and smoke tests. - -The skill does not support DMG, PKG, Mac App Store, bare-app, non-Sparkle, or -multi-product distribution. A future release type needs a separate skill only when -its owner contract exists. - -## Release And Trust Flow - -One immutable annotated stable tag binds the source. The workflow runs Linux source -validation, then macOS native test, build, signing, notarization, stapling, and -packaging, then a protected Linux publisher. The notarization upload ZIP is temporary -and never public. Apple must return an `Accepted` result and log before the app is -stapled. Only then does the workflow create the final ZIP and bind its exact bytes to -the Sparkle appcast signature and checksum. - -The publisher uses a secret-free protected `release` environment and the ephemeral -workflow token with `contents: write`; other jobs default to `contents: read`. -Publication is draft-first and non-idempotent. Final acceptance requires public -metadata and downloaded-byte verification. For uncertain responses, use -[bounded GitHub reconciliation](../plugins/acg-release/skills/macos/references/standard.md#bounded-github-reconciliation), -which owns recovery and reporting of unresolved publication state. - -Shared Developer ID and team App Store Connect API-key material uses unambiguous -organization-secret names. Conformance requires effective target access and no -lower-scope shadowing. Organization visibility `all` is allowed, while a tighter -`selected` scope is also conforming when it grants the repository access. Each -application keeps its own Sparkle private key and checks in its public key. - -Apple certificate creation or rotation, Sparkle-key rotation, secret mutation, -repository writes, tag push, environment approval, public Release mutation, and app -installation remain separate authorization boundaries. The release contract never -rotates the Developer ID certificate and Sparkle trust key in the same update. - -## Public-Surface Change Recipe - -A behavior change starts in `plugins/acg-release/skills/macos/SKILL.md` or its -canonical standard. Keep these surfaces synchronized: - -- `.agents/plugins/marketplace.json` discovers `acg-release` at - `./plugins/acg-release`. -- `plugins/acg-release/.codex-plugin/plugin.json` owns the organization scope, - plugin metadata, and `./skills/` entrypoint. -- `plugins/acg-release/skills/macos/agents/openai.yaml` owns the invocation label - and default prompt. -- `VERSION` and every plugin manifest use the same repository release version. -- `PRIVACY.md` owns the shared instruction-only privacy boundary. - -There is no generated, bundled, or published mirror in this repository. Validate -the internal skill and marketplace-resolved plugin boundary separately. Do not add -a generic workflow, signing script, or future skill until evidence gives it one -stable interface and validation owner. - -## Validation - -Run the Plugin Creator validator, Skill Creator validator, Plugin Eval, and -`cargo make check` when this plugin changes. Review the physical runtime file set: -only the manifest, `macos` skill, invocation metadata, and canonical reference -belong in the plugin. - -Forward tests must show three routing outcomes: an applicable legacy `acg-box` -Sparkle ZIP workflow is migration drift; an applicable Developer ID-notarized -fixture is preserved; and an outside-owner repository or a DMG, PKG, or non-Sparkle -request stops without adoption guidance or ACG Box topology. - -These checks prove checked-in guidance and installability only. They do not prove a -usable local Developer ID identity, notary credentials, hosted runner, protected -environment, GitHub publication, public bytes, Gatekeeper behavior, or installed -app. - -## Ownership Relationships - -The [marketplace entry](../.agents/plugins/marketplace.json) discovers this plugin; -the [operations guide](operations.md) validates its installable boundary. The -[canonical macOS standard](../plugins/acg-release/skills/macos/references/standard.md) -is the release authority, while this page explains repository structure and change -impact. +`plugins/acg-release/` contains the installed manifest, `macos` skill, invocation +metadata, and canonical release standard. It is instruction-only; target +repositories own executable release workflows and product-specific adapters. + +Use the [skill](../plugins/acg-release/skills/macos/SKILL.md) for applicability +and task scope. Use the [standard](../plugins/acg-release/skills/macos/references/standard.md) +for release requirements. Its sections cover source and workflow policy, secret +topology, signing, final assets, publication, trust-root changes, and acceptance. +Read the sections relevant to focused work, or the whole standard for a complete +release audit, migration, or operation. + +Change runtime policy in those source files. The manifest and +`agents/openai.yaml` describe the public invocation `$acg-release:macos`; the +marketplace resolves the plugin at `./plugins/acg-release`. Keep those surfaces +consistent when changing discovery or applicability. + +See [Operations](operations.md) for validation and installation. This wiki page +provides repository navigation; release policy remains in the canonical standard. diff --git a/openwiki/gh-settings.md b/openwiki/gh-settings.md index e90e80f..90fca04 100644 --- a/openwiki/gh-settings.md +++ b/openwiki/gh-settings.md @@ -15,88 +15,20 @@ openwiki: # GitHub Settings -## Runtime Boundary - -`plugins/gh-settings/` is the complete installed runtime. It contains one `sync` -skill, invocation metadata, and one canonical GitHub governance standard. It has no -executable, hook, app, MCP server, credential, network client, or writable state. - -The canonical standard owns operating-mode selection, target binding, central-first -classification, exact drift preview, public and private security baselines, mutation -authority, paid-product and automatic dependency submission billing gates, ruleset -migration or retirement safety, UI fallback, and authoritative readback. It -distinguishes an attached or enforced parent configuration from an unattached -catalog entry. Automatic dependency submission is a separate GitHub Actions workload, -not a Dependabot runner setting: supported manifests, Actions availability, runner -choice, and billing must be checked independently. Do not copy these rules into -OpenWiki. - -```mermaid -flowchart TD - marketplace["marketplace entry"] --> plugin["plugin manifest"] - plugin --> skill["sync skill"] - skill --> standard["canonical GitHub governance standard"] - standard --> currentDocs["current official GitHub docs"] - standard --> target["Enterprise, organization, and repository evidence"] -``` - -## Ownership And Modes - -The plugin owns GitHub governance audit and explicitly authorized reconciliation. -Organization-wide mode is central-first: it selects Enterprise enforcement, -organization enforcement, a central default, or a true repository residual in that -order. When the selected profile requires zero repository-owned rulesets, a nonzero -count on any repository fails acceptance. - -Repository-scoped mode binds one exact repository. It audits parent rulesets, -defaults, policies, and security configurations but keeps all parent state -read-only. A request for one repository never authorizes organization or Enterprise -mutation. - -The merge-commit-only baseline keeps the three repository merge toggles as residual -state and uses a parent pull-request rule where GitHub supports central allowed-method -enforcement. The standard requires a complete conflict check for linear-history -rules before activation. - -For security baselines, automatic dependency submission gets its own preview and -readback row. Enable it only after dependency graph, GitHub Actions, supported -ecosystem, runner, and billing evidence is bound; prefer free Dependabot graph jobs -where they take precedence. Private or internal repositories require explicit -acceptance of Actions usage and possible billing. - -A local ruleset in a zero-local profile is either migrated with equivalent parent -readback or explicitly retired after the user accepts the protection delta. The -workflow does not invent a team, role, app, or preservation adapter for semantics -that the approved profile says to remove. - -For stale previews or uncertain writes, use the canonical -[reconciliation rules](../plugins/gh-settings/skills/sync/references/standard.md#reconciliation). -That section owns bounded readback and the conditions for resuming writes. - -The public invocation is `$gh-settings:sync`. - -## Public-Surface Change Recipe - -A behavior change starts in `skills/sync/SKILL.md` or the canonical standard. Keep -these surfaces synchronized: - -- `.agents/plugins/marketplace.json` owns discovery at `./plugins/gh-settings`. -- `.codex-plugin/plugin.json` owns plugin metadata and the `./skills/` entrypoint. -- `agents/openai.yaml` owns the invocation label and default prompt. -- `VERSION` and every plugin manifest use the same repository release version. -- `PRIVACY.md` owns the shared instruction-only privacy boundary. - -GitHub APIs, UI controls, plans, and billing boundaries can change. The runtime -standard therefore requires current official documentation before live work instead -of treating a checked-in endpoint example as permanent authority. - -## Validation - -Run the Plugin Creator validator, the Skill Creator validator, and -`cargo make check`. Review the physical runtime file set: only the manifest, skill, -invocation metadata, and canonical reference belong in the plugin. Run Plugin Eval -when available. - -When installation is in scope, install after repository checks and verify pickup in -a fresh Codex task. Installation does not prove that the task that performed the -install loaded the new runtime. +`plugins/gh-settings/` contains the installed manifest, `sync` skill, invocation +metadata, and canonical governance standard. It has no executable runtime. + +Use the [skill](../plugins/gh-settings/skills/sync/SKILL.md) for task scope and the +[standard](../plugins/gh-settings/skills/sync/references/standard.md) for team +policy. The standard covers scope and authority, security profiles, dependency +submission, Dependabot defaults, rulesets, merge policy, other settings, and +reconciliation. Load the sections relevant to the requested profile; a complete +governance audit uses the whole standard. + +Change policy in those runtime files. The manifest and `agents/openai.yaml` +describe `$gh-settings:sync`; the marketplace resolves the plugin at +`./plugins/gh-settings`. Keep those surfaces consistent when changing discovery. + +See [Operations](operations.md) for validation and installation. GitHub's current +documentation and observed account state establish provider behavior; this page +is repository navigation, not a second governance standard. diff --git a/openwiki/quickstart.md b/openwiki/quickstart.md index 7e58887..48bff68 100644 --- a/openwiki/quickstart.md +++ b/openwiki/quickstart.md @@ -20,15 +20,8 @@ openwiki: `acg-box/exp` publishes small ACG Box engineering standards as Codex plugins. Both current plugins are instruction-only: -- `gh-settings` audits GitHub governance, puts enforceable controls at the highest - supported scope in organization-wide mode, keeps parent state read-only in - repository-scoped mode, previews exact drift, and reconciles only explicitly - approved changes. Its canonical standard is - [`plugins/gh-settings/skills/sync/references/standard.md`](../plugins/gh-settings/skills/sync/references/standard.md). -- `acg-release` owns release standards only for repositories whose canonical - GitHub owner is `acg-box`. Its only current skill manages Developer ID-notarized - Sparkle macOS ZIP releases. Its canonical standard is - [`plugins/acg-release/skills/macos/references/standard.md`](../plugins/acg-release/skills/macos/references/standard.md). +- [`gh-settings`](gh-settings.md) owns GitHub governance profiles. +- [`acg-release`](acg-release.md) owns the ACG Box macOS release standard. The repository has no application, reusable package, executable, MCP server, or checked-in test program. Installable runtime belongs under `plugins/`; maintainer @@ -40,8 +33,8 @@ context belongs under `openwiki/`. 2. Read [GitHub Settings](gh-settings.md) or [ACG Release: macOS](acg-release.md) for the plugin you are changing. 3. Read [Install And Validation](operations.md) for narrow checks and release limits. -4. Before changing runtime behavior, read the full canonical standard for the - selected plugin. +4. Before changing runtime behavior, read the relevant canonical sections for + the selected plugin. ## Task Routing diff --git a/plugins/acg-release/skills/macos/SKILL.md b/plugins/acg-release/skills/macos/SKILL.md index 8ae522f..c49c6db 100644 --- a/plugins/acg-release/skills/macos/SKILL.md +++ b/plugins/acg-release/skills/macos/SKILL.md @@ -1,128 +1,28 @@ --- name: macos -description: Manage Developer ID-notarized Sparkle macOS ZIP releases only when the repository's canonical GitHub owner is acg-box. Use when Codex must audit, migrate, normalize, operate one authorized stable release, reconcile a failed run, or verify published bytes. For repositories outside acg-box, stop as not applicable without adoption guidance, file changes, release work, or ACG Box topology. Do not use for DMG, PKG, or non-Sparkle workflows. +description: Use when auditing, adapting, or operating Developer ID-notarized Sparkle macOS ZIP releases for repositories whose canonical GitHub owner is acg-box. Excludes other owners, DMG, PKG, and non-Sparkle distribution. --- -# Manage ACG Box macOS Releases - -## Enforce The Organization Gate First - -Before any release audit or mutation, resolve the target repository's canonical -GitHub owner through its authoritative remote and provider metadata. Continue only -when that owner is `acg-box`. A directory name, fork name, user statement about -similar policy, or copied workflow does not replace this check. - -If the canonical owner is outside `acg-box`, stop as **not applicable**. Do not -audit the repository toward adoption, propose ACG Box normalization, change files, -operate or verify a release under this standard, or inspect or apply the ACG Box -secret and signing topology. If ownership cannot be resolved, stop with an -applicability gap instead of assuming access. - -This plugin owns ACG Box organization release standards. Its only current skill is -this macOS Sparkle ZIP skill. Add a separate skill only after a real release type -has evidence and an independent owner contract. Do not create empty future skills -or a generic root standard. The public invocation is -`$acg-release:macos`. - -## Confirm Scope And Authority - -After the organization gate passes, apply this skill only to an ACG Box macOS -application that distributes one regular Sparkle-enabled app bundle in a ZIP -through GitHub Releases. A DMG, PKG, bare app, non-Sparkle updater, Mac App Store -release, or other distribution lane needs a different owner. Report the scope -mismatch without adapting this standard to it. - -Only after the organization and distribution-scope gates pass, read [the canonical -standard](references/standard.md) completely before an audit, migration, -normalization, release operation, recovery, or verification. The target -repository's instructions, source, tests, workflows, runbooks, current provider -documentation, and observed GitHub and Apple state remain authoritative. - -Default to a read-only audit when the requested mode or mutation authority is not -clear. - -- **Audit:** inspect repository and live metadata without changing either. -- **Migrate or normalize:** change only the authorized repository. This mode does - not authorize certificate or secret changes, provider settings, tags, workflow - approvals, Releases, notarization submissions, or app installation. -- **Operate:** bind the exact repository, version, commit, target adapter, and - permitted release mutations. A clear request to publish one named version can - authorize its tag push and workflow follow-through. It does not authorize - certificate or Sparkle-key rotation, secret mutation, environment-rule changes, - tag movement, manual publication, release deletion, or local installation. -- **Verify or reconcile:** keep reads and bounded recovery inside the existing - release contract. Treat a new tag, new notarization submission, public-state - mutation, or destructive draft repair as a separate operation unless the current - authority clearly covers it. - -Keep these boundaries separate: repository writes, tag creation and push, -protected-environment approval, public Release mutation, installation, certificate -creation or rotation, Sparkle-key rotation, and secret mutation. Authority for one -boundary does not authorize another. - -## Enforce Developer ID Distribution - -The production policy is Developer ID Application signing with Hardened Runtime, -secure timestamps, Apple notarization, stapling, strict signature verification, and -Gatekeeper assessment. An Apple Development, Personal Team, ad hoc, timestamp-free, -unnotarized, or Open Anyway path is legacy drift to migrate. Never operate or -publish that path as an ACG Box production release. - -Do not invent an Apple Team ID, certificate suffix, signing identity, entitlement, -or product identity. Read these values from the target repository's adapter and -confirm them against the imported identity and signed code. Xcode account presence -alone does not prove that a usable Developer ID identity or notary credential exists. - -## Work - -1. Inventory the source validator, release workflow, native tests and build, - signing and packaging adapters, notarization flow, publisher, contract tests, - runbook, version owners, Sparkle pin, checked-in public key, effective secret - access, protected environment, tags, Releases, and relevant run evidence. -2. Bind every repository-owned adapter value. Keep app names, bundle identifiers, - Apple Team ID and identity selector, asset names, feed URLs, Sparkle versions and - revisions, entitlements, and public keys in the target repository. -3. Compare the evidence with the complete standard. Report exact drift, scope - mismatch, unavailable live evidence, and exceptions before mutation. A legacy - Apple Development workflow requires migration; it is not an alternate policy. -4. For migration or normalization, implement the smallest repository-owned adapter - and behavior tests. GitHub Actions must run from checked-in source and must never - depend on an installed Codex plugin. -5. For operation, complete credential-free validation before the authorized tag - leaves the machine. Confirm live certificate and notary readiness before the - workflow reaches privileged work. Push no tag until the named source passes and - release-trigger authority is explicit. Monitor only that workflow to a terminal - state. -6. Preserve the required artifact order: sign inside-out, verify, make a separate - notarization upload ZIP, obtain and read back an `Accepted` notarization result - and log, staple and validate the app, create the final public ZIP, then create - the Sparkle signature, appcast, and checksum from that final ZIP. -7. After publication, download the public assets and verify remote bytes, metadata, - checksum, appcast, Sparkle signature, notarization ticket, complete code-signing - graph, Gatekeeper acceptance, and version. Workflow success alone is not release - acceptance. -8. On failure, use the standard's bounded reconciliation rules. Never move a remote - tag, bypass notarization or environment approval, publish a draft manually, hide - uncertainty with unbounded retries, or rebuild bytes behind an existing signature. - -## Hard Boundaries - -- Never print, request in chat, copy into source, or persist secret values. Inspect - only secret names, scopes, effective access, and shadowing risk. -- Never create, revoke, renew, export, or rotate an Apple certificate or Sparkle - key without exact authority. Never rotate both trust roots in one update. -- Never infer live-release authority from repository-write authority, a passing - check, a local build, an installed account, or an installed app. -- Never weaken signing, timestamp, notarization, stapling, signature, or Gatekeeper - gates to make a release continue. -- Never require a target workflow to call this skill or any plugin runtime. -- Never convert an uncertain GitHub or Apple mutation into success without - authoritative readback of the exact intended state. - -## Report - -Report the canonical owner result, mode, scope result, authority used, current and -desired contract, repository adapters preserved, exact mutations, validation -evidence, release and public-asset evidence, and honest live-readiness gaps. -Distinguish checked-in validation from a successful notarized release under the -same exact pipeline. +# ACG Box macOS Releases + +Resolve the canonical GitHub owner from the authoritative remote and provider +metadata before release work. Continue only for `acg-box` repositories that +publish one regular Sparkle-enabled macOS app in a GitHub Release ZIP. Otherwise +stop as not applicable, without adoption guidance or use of ACG Box signing and +secret topology. Unresolved ownership is an applicability gap. + +Use the [release standard](references/standard.md) as the canonical team policy. +Read it in full for a complete release audit, migration, or operation. For a +focused question or repair, read the relevant sections and their dependencies. +Use current provider documentation for tool and API behavior. + +Repository changes, release publication, environment approval, installation, and +certificate, key, or secret changes have separate authorization boundaries. Use +existing authority for the requested work; default to a read-only audit when +mutation authority is unclear. A request to publish one named version can cover +its exact tag push and workflow follow-through, but does not authorize trust-root +rotation or changes to environment rules. + +The standard owns release requirements. The target repository owns product +identity, executable implementation, and tests. Complete the requested scope and +report the result, relevant evidence, and remaining gaps. diff --git a/plugins/acg-release/skills/macos/references/standard.md b/plugins/acg-release/skills/macos/references/standard.md index a2fb438..02e292f 100644 --- a/plugins/acg-release/skills/macos/references/standard.md +++ b/plugins/acg-release/skills/macos/references/standard.md @@ -1,185 +1,88 @@ # ACG Box macOS Sparkle ZIP Release Standard -## Purpose, Scope, And Authority - -This is the current macOS skill standard for the ACG Box organization release -plugin. Use it only for repositories whose canonical GitHub owner is `acg-box` and -for macOS applications that publish one regular, Sparkle-enabled app bundle as a -ZIP through GitHub Releases. It defines the shared trust and publication contract. -Each target repository owns its executable adapter and product identity. - -## Organization Applicability Gate - -Resolve the exact target repository and its canonical GitHub owner before any -release audit or mutation. Bind the canonical remote to GitHub provider metadata. -Continue only when the canonical owner is `acg-box`. - -For any repository outside `acg-box/*`, stop as **not applicable**. Do not audit it -toward this standard, propose adoption, change its files, operate or verify a -release under this contract, or inspect or apply the ACG Box certificate, notary, -Sparkle-key, secret, environment, or publisher topology. If the canonical owner -cannot be resolved, preserve the gap and stop before release work. - -Repository-write or release authority does not override this organization gate. -Changing a remote or transferring a repository is a separate operation and cannot -be used as an implicit path into applicability. - -This standard does not operate DMG, PKG, Mac App Store, bare-app, non-Sparkle, or -multi-product distribution lanes. Do not widen the skill to those formats during an -audit or release. Route them to a separate owner. - -Provider behavior can change. Before a live operation, check current official -Apple, Sparkle, GitHub, and tool documentation for every material API, -runner, signing, notarization, update, or publication rule. Current user direction, -target source, and observed provider state override old examples and prior release -conclusions. - -## Universal Release Invariants - -Every supported production release must satisfy all of these invariants: - -- one immutable annotated stable tag binds one reachable commit and version; -- credential-free validation and build finish before private material is written; -- every executable component is signed inside-out with a valid Developer ID - Application identity, Hardened Runtime, and a secure timestamp; -- strict code-signing verification passes before notarization; -- Apple returns an `Accepted` notarization result that is read back with its log; -- the app receives and validates a stapled ticket; -- Gatekeeper accepts the stapled app; -- the public ZIP is created only after stapling and is different from the temporary - notarization upload archive; -- the Sparkle signature, appcast length, and checksum bind the exact final ZIP; -- a secret-free protected publisher creates or repairs one private draft before one - final publication mutation; and -- final acceptance uses downloaded public bytes, not workflow success alone. - -An Apple Development, Personal Team, ad hoc, timestamp-free, unnotarized, or -**Open Anyway** distribution path is production drift. Audit it and plan its -migration. Never treat it as a supported alternate ACG Box release policy. +## Scope And Authority + +This standard applies only after the skill's canonical-owner and distribution +checks pass. It defines the shared ACG Box release contract. Each target +repository owns its executable adapter and product identity. + +Repository-write authority covers migration and normalization. Publishing one +named version requires release authority for its exact repository, version, +commit, tag push, and workflow. Environment approval, installation, certificate +or Sparkle-key lifecycle changes, secret changes, tag movement, release deletion, +and exceptional manual recovery require their own authority when not already +covered by the request. Preserve granted authority across follow-ups. + +## Production Contract + +Supported releases use Developer ID Application signing, Hardened Runtime, +secure timestamps, Apple notarization, stapling, strict signature verification, +and Gatekeeper acceptance. Apple Development, Personal Team, ad hoc, +timestamp-free, unnotarized, and Open Anyway distribution are migration drift, +not alternative production policies. + +The release binds one immutable annotated stable tag to one commit and version. +Credential-free validation and build precede access to signing secrets. The final +public ZIP contains the stapled app; its exact bytes determine the Sparkle +signature, appcast length, and checksum. Publication uses a private draft and a +protected publisher. Acceptance requires verification of downloaded public assets. ## Target Repository Adapter -Keep product and team identity in the target repository. Do not put these values in -this plugin: - -- repository owner, slug, canonical remote, and default branch; -- app name, bundle name, bundle identifier, deployment minimum, and architecture; -- version files, workspace package inventory, and build-number policy; -- release ZIP, appcast, checksum, feed, and download names or URLs; -- exact Sparkle source, version, revision, framework graph, and checked-in public - Ed25519 key; -- native test and build commands, app entitlements, and smoke-test scope; -- paid Apple Developer Team ID and the expected Developer ID Application identity - selector; -- Xcode and Swift selection rules; and -- protected-environment reviewer and tag policy. - -The target adapter must make each value observable and testable. Do not infer a -paid Team ID from an Apple Development certificate, an Xcode account, a display -name, a certificate-label suffix, or an earlier Personal Team workflow. Until ACG -Box publishes a stable organization-wide public selector, each target adapter owns -the exact Team ID and identity binding. - -The target repository must contain every workflow, script, test, and runbook that -GitHub Actions needs. A locally installed Codex plugin is never a workflow -dependency. - -Preserve the target repository's established implementation languages and owners. -Keep Shell thin around native macOS commands, strict error handling, traps, and -cleanup. Put GitHub API, JSON, SemVer, pagination, and publisher-state logic in a -repository-owned testable program instead of Shell. Do not migrate a stable binary, -plist, ZIP, or cryptographic validator only for language uniformity. - -## Authorization And Lifecycle Boundaries - -Treat each boundary independently: - -| Boundary | Effect | Required authority | -| --- | --- | --- | -| Audit and validation | Reads source, metadata, credentials metadata, or artifacts and runs checks | Read authority | -| Migration or normalization | Changes target repository files | Repository-write authority | -| Release trigger | Creates and pushes one exact annotated tag | Explicit release and Git authority | -| Notarization submission | Sends one signed candidate to Apple | Exact live-release authority and usable notary credentials | -| Deployment approval | Allows the protected `release` environment job to continue | Exact environment approval authority | -| Publication | Changes a private draft into a public GitHub Release | Explicit publication authority carried by the approved workflow | -| Installation or rollout | Installs or activates the app for a user | Separate deployment or installation authority | -| Certificate lifecycle | Creates, exports, renews, revokes, or rotates Developer ID material | Exact Apple certificate authority | -| Sparkle-key lifecycle | Generates, imports, backs up, recovers, or rotates an application key | Exact application trust-root authority | -| Secret lifecycle | Creates, changes, scopes, or deletes a GitHub secret | Exact secret and provider authority | - -A passing test, merged change, local account, installed certificate, local build, -tag, notarization submission, environment approval, public Release, and installed -app are different facts. Never use one as proof or authorization for another. - -## Immutable Source Contract - -Use one stable tag trigger and one source validator. - -- Accept only `vX.Y.Z`, with three decimal components, no leading zeroes, no - prerelease or build suffix, and a bounded component length. -- Require an annotated tag object that points directly to one commit. Reject a - lightweight tag, nested tag, or ambiguous resolution. -- Bind and validate the workflow repository, ref, event commit, checked-out commit, - tag commit, and canonical remote. -- Fetch complete tag history and canonical `main` without persisted checkout - credentials. -- Require the tag commit to be reachable from canonical `main`. -- Require the tag version to match every repository-declared application, - workspace, lockfile, bundle short version, and build version that the repository - owns. -- Require the exact official Sparkle source, repository-owned version, and resolved - revision. Disable automatic package resolution in the release build. -- Before tag push, require the candidate version to advance every existing remote - stable-version tag and public stable Release. -- Export the validated commit, version, Sparkle version, and revision to later - jobs. Recheck the bindings at each privileged boundary. -- Do not let the workflow create its own tag. - -Validate the candidate source before its tag is pushed. Once a remote tag exists, -never move, replace, force-update, or reuse it for different source. Correct a -source or build defect on `main`, advance the application version, and create a new -annotated tag. - -## Workflow Trust And Serialization - -Use one tag-triggered workflow with these ordered owners: - -1. a Linux source-validation job; -2. a macOS native test, build, signing, notarization, stapling, and packaging job; - and -3. a Linux GitHub publisher job. - -Apply these controls: - -- set workflow permissions to `contents: read` by default; -- grant `contents: write` only to the publisher job; -- set checkout to `persist-credentials: false`; -- pin third-party actions to reviewed immutable commit SHAs; -- set explicit job timeouts, including a bounded notarization wait; -- serialize stable releases through one global `release` concurrency group; -- set `cancel-in-progress: false`; and -- make the publisher depend on successful source validation and macOS packaging. - -Use a protected, repository-scoped `release` environment as the final approval and -audit boundary for the publisher. Restrict it to the authorized stable tag pattern -and require the selected reviewer policy. Keep this environment secret-free. The -publisher receives only the ephemeral `GITHUB_TOKEN`, the validated release -artifacts, and non-secret metadata. It must not receive Apple or Sparkle credentials. - -Do not add a second Release Preparation, Release Prep, Release Dry Run, or manual -publication lane. A credential-free local publisher `--dry-run` can validate local -assets, but it must make no GitHub request. - -Routine pull-request and `main` CI remains repository policy. It can be Linux-only -when the repository accepts later native feedback. It can include macOS when early -feedback justifies the cost. Never weaken the formal tag release's native macOS -tests, build, signing, notarization, or artifact verification because routine CI is -Linux-only. +Keep product-specific values in the target repository: app and bundle identity, +platform minimum and architecture, version owners and build-number policy, asset +names and URLs, Sparkle source/version/revision and public key, entitlements, +Apple Team ID and Developer ID identity selector, build and test commands, tool +selection, and protected-environment reviewer and tag policy. + +Verify the declared signing identity against the imported identity and signed +code. An Xcode account or an Apple Development certificate does not establish a +usable Developer ID identity or the paid Team ID. + +GitHub Actions must use checked-in repository workflows and programs. It must +never depend on an installed Codex plugin. Preserve established implementation +owners; choose implementation and tests to satisfy this contract. + +## Immutable Source + +Use one source validator and accept only annotated `vX.Y.Z` stable tags: decimal +components without leading zeroes, prerelease, or build suffixes. The tag must +point directly to one commit reachable from canonical `main`. + +Bind the workflow repository, ref, event commit, checkout, tag commit, and +canonical remote. The version must match all declared application, workspace, +lockfile, and bundle version owners. Pin the official Sparkle source, version, +and revision in the repository; disable automatic package resolution in the +release build. Carry these validated bindings across privileged job boundaries. + +Validate before tag push. A new candidate must advance every existing remote +stable tag and public stable Release. Recheck that condition before publication. +The workflow does not create its own tag. Never move or reuse a remote tag for +different source; fix source defects on `main` and release a new version. + +## Workflow And Publisher Isolation + +Use one tag-triggered workflow with Linux source validation, macOS native tests +and packaging, then a Linux publisher dependent on both preceding jobs. + +Use `contents: read` by default, `contents: write` only for the publisher, +`persist-credentials: false` for checkout, immutable reviewed action SHAs, and +explicit job timeouts. Serialize stable releases through one global `release` +concurrency group with `cancel-in-progress: false`. + +The publisher uses a protected, repository-scoped `release` environment restricted +to authorized stable tags and the selected reviewer policy. Keep it secret-free: +it receives the ephemeral `GITHUB_TOKEN`, validated assets, and public metadata, +with no Apple or Sparkle credentials. + +Do not add a separate Release Preparation, Release Dry Run, or manual publication +lane. A local publisher `--dry-run` validates assets without GitHub requests. +Routine PR and `main` CI can be Linux-only or include macOS under repository +policy; formal release validation always includes native macOS tests and build. ## Secret And Key Topology -Use these unambiguous ACG Box organization-secret names for shared Developer ID and -notary material: +Use these organization-secret names for shared signing and notary material: - `ACG_MACOS_DEVELOPER_ID_APPLICATION_P12_BASE64`; - `ACG_MACOS_DEVELOPER_ID_APPLICATION_P12_PASSWORD`; @@ -187,370 +90,136 @@ notary material: - `ACG_MACOS_NOTARY_API_ISSUER_ID`; and - `ACG_MACOS_NOTARY_API_PRIVATE_KEY_P8`. -Use a team App Store Connect API key for `notarytool`. The key ID, issuer ID, and -private `.p8` key form one credential set. This skill does not support Apple ID and -app-specific password authentication. If the team API-key credential set is not -usable, report a live-readiness gap and stop instead of improvising another notary -topology. - -The certificate secrets must contain one Developer ID Application identity and its -private key. Do not store a signing-identity label as a secret. Derive the installed -identity from the isolated temporary keychain, then require its certificate class, -validity, private-key presence, and Team ID to match the target adapter. - -An organization secret must give the exact target repository effective access. -Visibility `all` is an allowed current topology, not a rule that requires widening. -Visibility `selected` is conforming when it includes the target repository. Judge -any other supported visibility only by effective target access. Report a missing -target grant as drift. Do not report a tighter effective `selected` scope as drift. - -Reject a repository or environment secret with the same name as any organization -secret above. GitHub resolves a same-name lower-scope secret before the organization -secret, so shadowing makes provenance ambiguous. - -Keep each application's Sparkle private Ed25519 key in that application's -repository under an application-specific name such as -`_SPARKLE_PRIVATE_ED_KEY`. Never use a generic organization or -environment `SPARKLE_PRIVATE_ED_KEY`, and never reuse another application's key. - -Check the corresponding Sparkle public key into the target repository and embed -that same key in the app. Before appcast generation, derive or verify the public key -from the private secret and fail on a mismatch. A Sparkle public key is product -configuration, not a secret. This plugin contains no application public key. - -Use only the ephemeral workflow token for GitHub publication. Do not store a GitHub -token as a release secret. Never print, upload, or place private key or certificate -values in source, logs, fixtures, command arguments, cache entries, or artifacts. -When Sparkle accepts a private key on standard input, use that interface instead of -the deprecated direct-key argument. - -## Build Before Credentials And Restore Host State - -Run all credential-free release tests and the complete unsigned build before -writing certificate, notary, or Sparkle private material. Bind temporary staging to -the runner-designated temporary directory. Reject unsafe, pre-existing, broad, or -repository-owned staging paths. Expose Apple and Sparkle secrets only to the later -privileged packaging step. Credential-free validation and build steps must not -receive those secrets as environment inputs. - -Before changing the user keychain configuration, capture the exact user search list -and default keychain. Install an exit and signal cleanup before the first mutation. -The cleanup must run on every reachable success, failure, timeout, and cancellation -path. It must: - -1. restore the exact original user search list; -2. restore the exact original user default keychain; -3. read both values back and fail the run if restoration is incomplete; -4. delete the temporary keychain only after restoration; and -5. remove every decoded certificate, password file, notary `.p8` file, Sparkle-key - file, upload archive, and other private temporary file. - -Deletion of the temporary keychain without search-list and default restoration is -not cleanup. - -After the credential-free build: - -1. decode the P12 into the isolated staging directory; -2. create and unlock a temporary keychain; -3. make that keychain the sole user search-list keychain; -4. make it the user default keychain before changing its key partition list; -5. import the P12 and require exactly one usable Developer ID Application identity; -6. match the identity and certificate Team ID to the target adapter; and -7. write the notary team API private key only when the notarization step needs it, - with owner-only permissions. - -An Xcode account, a certificate file, or a successful import does not prove that a -usable Developer ID identity exists. Require a valid certificate, its private key, -the expected certificate class, and the adapter's Team ID as separate facts. - -## macOS Build And Inside-Out Signing - -Use the target repository's supported GitHub-hosted ARM64 macOS runner. Confirm the -runner architecture, selected Xcode and Swift versions, checked-out commit, -validated version, and release configuration before packaging. - -Stage one real `.app` bundle. Verify its plist identity, versions, feed, -checked-in Sparkle public key, deployment minimum, architecture, and update settings -before signing. - -Require an exact repository-owned Sparkle pin and revision. Do not impose one -Sparkle version across applications. Resolve -`Sparkle.framework/Versions/Current` dynamically as one safe direct-child version -directory. Reject an absolute target, parent traversal, missing target, extra -version directory, second alias, unknown executable, nested app, or unexpected XPC -service. - -Enumerate the accepted executable graph. Sign the innermost Mach-O binaries, -helpers, XPC services, frameworks, and other signed bundles before their containers, -then sign the outer app. Preserve entitlements only for a known component that -requires them. Never use `codesign --deep` to sign. - -Every signed object must have: - -- a valid `Developer ID Application:` authority; -- the target adapter's exact paid Team ID; -- Hardened Runtime; -- a secure timestamp; and -- only its repository-approved entitlements. - -Reject Apple Development, Mac App Distribution, ad hoc, expired, revoked, or -unexpected identities; missing or insecure timestamps; a different Team ID; an -unexpected entitlement; and outer `get-task-allow` or -`disable-library-validation` unless exact repository authority and current Apple -requirements prove a narrow exception. - -After inside-out signing, inspect every signed object and run strict read-only -verification on the complete graph. The final bundle check must be equivalent to -`codesign --verify --deep --strict --verbose=2`. Treat `--deep` only as verification -after explicit inside-out signing. - -## Notarization, Stapling, And Final ZIP Order - -Keep the notarization upload archive and the public release ZIP as two different -artifacts with different paths and purposes. - -1. After strict signature verification, create one temporary ZIP from the signed, - unstapled app for Apple notarization. Use an archive method that preserves the - bundle, resource forks, and symlinks. Mark this artifact as non-public. -2. Submit only that temporary ZIP with `notarytool`, the team API key ID, issuer ID, - private `.p8` path, a bounded wait, and machine-readable output. Never use - `--force` to bypass preflight problems. -3. Bind the returned submission ID to the exact source commit and upload artifact. - Require terminal status `Accepted` from the submit result and a separate - `notarytool info` readback. -4. Retrieve and parse the completed notarization log even when the status is - `Accepted`. Fail on an error. Preserve and report material warnings. The log is - run evidence, not a public release asset. -5. Staple the ticket to the original signed app. A ZIP cannot be stapled directly. -6. Run `stapler validate` on the app. Re-run the complete strict code-signature and - entitlement checks, then require `spctl --assess --type execute` to accept the - app as notarized Developer ID software. -7. Only after stapling and Gatekeeper acceptance, create the final public ZIP from - the stapled app. Never reuse or rename the notarization upload ZIP. -8. Extract the final ZIP into a new clean temporary directory. Recheck its one-app - root, stapled ticket, strict signature graph, product identity, version, and - Gatekeeper acceptance. -9. Generate the Sparkle Ed25519 signature and appcast entry from the exact final ZIP - bytes. Require the appcast length to equal the final ZIP byte length and verify - the signature with the checked-in public key. -10. Generate the lowercase SHA-256 checksum file from that same final ZIP. - -Do not rebuild, re-sign, re-staple, recompress, rename, or otherwise change the ZIP -after Sparkle signature or checksum generation. Remove the temporary notarization -upload archive during cleanup. Never publish it, sign it for Sparkle, or use it as -checksum input. - -## Exact Release Assets And Sparkle Trust - -Upload exactly three release assets: - -1. one repository-named final macOS ZIP that contains one expected `.app` root; -2. `appcast.xml`; and -3. one repository-named `.sha256` file for the final ZIP. - -The ZIP validator must bound the entry count, individual and total declared sizes, -path and metadata lengths, plist and XML sizes, and symlink targets. Reject duplicate -members, absolute paths, parent traversal, a second payload root, unexpected file -types, an unsafe Sparkle layout, and XML `DOCTYPE` or `ENTITY` declarations. - -The appcast must use the repository's canonical release and download URLs, -validated tag version, exact final ZIP byte length, declared platform and deployment -minimum, and an Ed25519 signature over the exact final ZIP bytes. Verify the -signature with the checked-in public key. - -The checksum file must contain the lowercase SHA-256 digest of the exact final ZIP -and its canonical file name in one accepted format. GitHub-generated source links do -not count as uploaded release assets. Do not add source archives, DMGs, PKGs, -installers, or other platform packages to this contract. - -## Certificate And Sparkle-Key Lifecycle - -Treat the application's checked-in Sparkle public key as a stable installed-client -trust root. Assign an accountable recovery owner for its private key and keep a -protected, tested backup outside the release runner. Do not regenerate the key for -convenience, repository migration, staff change, CI change, or a routine release. - -Track the Developer ID certificate's public fingerprint, Team ID, expiry, and -recovery owner in the appropriate protected operations system. Do not create, -export, renew, revoke, or rotate it during an ordinary release. Start a separately -authorized rotation before expiry and prove the replacement identity in a -non-publishing validation lane. - -Never rotate the Developer ID certificate and Sparkle Ed25519 key in the same -application update. Sparkle's regular-app fallback permits one trust root to validate -a change in the other, not simultaneous replacement. - -Every Sparkle-key migration plan must: - -- inventory the oldest supported installed Sparkle version and current trust keys; -- keep the Developer ID certificate stable while the Sparkle key changes; -- use the exact migration path in current Sparkle guidance; -- ship and verify any required transition update before removing the old key; -- test update installation from the oldest supported installed version; and -- retain protected recovery material until adoption evidence closes the migration. - -If `SUVerifyUpdateBeforeExtraction` is enabled, current Sparkle guidance can require -a Developer ID-signed DMG to rotate the Ed25519 key. That migration is outside this -ZIP-only skill. Stop and design a separately owned, separately authorized migration; -do not claim DMG support or weaken update verification. For DSA-to-Ed25519 migration, -follow Sparkle's staged dual-key and dual-signature guidance for the installed-client -versions that require it. - -When the Developer ID certificate changes, keep the Sparkle key stable and verify a -real update from a currently released version. When the Sparkle key changes, keep -the Developer ID certificate stable. A lost key, compromised key, or revoked -certificate is an incident and migration input, not permission for casual -regeneration or bypass. - -## Draft-First Publisher Contract - -The publisher must validate the local final asset triplet before its first GitHub -mutation. It must then use this state machine: - -1. Read all Releases through bounded pagination and enumerate all remote - stable-version tags. Reject a new candidate unless it advances the greatest - existing stable version across public Releases and every other remote stable tag. -2. Find zero or one release for the candidate tag. Reject duplicate same-tag - releases and conflicting public state. -3. Create one private same-tag draft, or reuse the known private draft. -4. Read all draft assets through bounded pagination. Delete every existing draft - asset by stable asset ID, including placeholders with missing digests. -5. Upload exactly the required final ZIP, appcast, and checksum. Leave no extra - uploaded asset. -6. Read back metadata and download every remote asset. Require the uploaded state, - safe integer size, canonical API and browser URLs, GitHub SHA-256 digest, exact - byte hash, exact set, and complete artifact validation. -7. Immediately before publication, repeat the remote annotated-tag, direct commit, - canonical `main` ancestry, complete stable-version, exact draft-ID, metadata, - and downloaded-byte checks. -8. Make one final state-changing request that sets `draft=false` and - `make_latest=true`. -9. Read the public release and download its bytes after a successful or uncertain - publication response. - -The final publication request is non-idempotent. Never blindly retry it. - -## Bounded GitHub Reconciliation - -Bound every read by page count, item count, response bytes, timeout, retry count, -and total delay. Validate pagination links or page transitions. Honor a valid -`Retry-After` value for HTTP 429. Retry only safe reads after a transient network -error or 5xx response. - -Do not blindly retry create, delete, upload, or publish requests. When a mutation -response is missing or uncertain, use bounded authoritative reads to decide whether -the intended state exists. Continue only when readback proves one unambiguous state. -If a new draft or public release is temporarily absent from a release listing, use -its known stable ID and bounded convergence. If readback does not converge, stop -further mutations and report the unresolved state. After an uncertain publication -request, do not claim that the release is private or public without authoritative -readback. - -An already public same-tag rerun is read-only and idempotent. Validate its remote -metadata and downloaded bytes, then exit successfully. Do not apply the new-release -version gate to that exact public retry, upload replacement assets, or compare the -public ZIP with a newly rebuilt ZIP whose container metadata can differ. - -## Version Monotonicity And Recovery - -Prevent version downgrade and rollback publication. A new public stable release -must be greater than every current public stable Release and every other remote -stable-version tag. Repeat this check immediately before publication because -another tag or Release can appear while the draft is prepared. An exact already -public same-tag read-only retry remains the only exception. - -For a transient safe-read or provider-state failure, rerun the unchanged workflow -only when the current runbook permits it. Let the publisher repair its private draft -and reconcile ambiguous GitHub state through its bounded rules. Reuse an existing -Apple submission only when its stable submission ID and exact upload-artifact -binding prove that reuse is correct; a new notarization submission is a new live -mutation. - -For a source, test, build, signing, certificate, notarization, key, metadata, or -artifact defect: - -- fix the owning source on `main`; -- advance the version; -- create a new annotated tag; and -- leave the old remote tag unchanged. - -Never move a remote tag, lower the version, publish a failed draft manually, delete -a public Release as an ordinary retry, bypass Apple rejection, or ask users to use -Open Anyway. Any exceptional destructive recovery requires exact user authority, a -refreshed remote-state preview, and the target repository's runbook. - -## Validation And Evidence - -Credential-free contract tests must cover behavior, not exact prose. At minimum, -cover: - -- supported Sparkle ZIP scope and explicit rejection of DMG, PKG, and non-Sparkle - operation; -- detection of Apple Development, Personal Team, timestamp-free, unnotarized, and - Open Anyway legacy drift; -- stable and invalid SemVer, annotated and lightweight tags, direct and nested tag - targets, repository/ref/SHA binding, version mismatch, `main` ancestry, and a - higher existing remote stable tag or public stable Release; -- exact Sparkle source, version, revision, safe dynamic `Current` layout, and - rejected extra or unsafe framework content; -- build-before-credential order, original keychain state capture, temporary - keychain order, restoration on every exit path, one-identity policy, inside-out - signing, Developer ID authority, Hardened Runtime, secure timestamp, target Team - ID, and entitlement rejection; -- separate notarization and public ZIP paths, bounded `notarytool` submission, - `Accepted` info and log readback, stapling, stapler validation, strict code-signing - verification, Gatekeeper acceptance, and final-ZIP-after-stapling order; -- ZIP bounds, duplicate and unsafe members, canonical appcast URLs, key mismatch, - invalid Ed25519 signatures, checksum format, and exact asset sets; -- effective organization-secret access, conforming `all` and `selected` scope, and - lower-scope shadow rejection; -- certificate and Sparkle-key lifecycle gates, including rejection of simultaneous - rotation; -- release and asset pagination, response limits, 429 and 5xx safe-read behavior, - ambiguous mutations, delayed draft visibility, duplicate releases, late tag or - version races, final byte races, and one final publish mutation; -- read-only already-public retries and credential-free local dry runs; and -- injected network and command boundaries that make no live mutation. - -Static validation and a successful local contract suite prove only the checked-in -adapter. They do not prove Apple account status, a usable Developer ID identity, -notary credentials, hosted runner behavior, protected-environment settings, GitHub -publication, public asset bytes, Gatekeeper behavior on another Mac, or user flows. - -For live release acceptance, verify all of these from the public Release: - -- the exact annotated tag, source commit, and pipeline revision; -- the workflow's terminal success and attempt history; -- a non-draft, non-prerelease, latest stable Release; -- exactly the final ZIP, appcast, and checksum assets; -- GitHub asset metadata and SHA-256 digests; -- downloaded remote bytes and checksum; -- appcast URL, length, version, and Ed25519 signature; -- the extracted app's stapled ticket, complete strict signature graph, Hardened - Runtime, secure timestamps, Developer ID identity, and target Team ID; -- Gatekeeper acceptance of the downloaded app; and -- repository-required launch, update, and product smoke tests when separately - authorized and available. - -Report which exact pipeline revision has live proof. Preserve a gap when later -hardening has only checked-in tests, or when certificate, notary, Apple service, -runner, environment, public download, Gatekeeper, or user-flow evidence is -unavailable. - -## Current Provider References - -Recheck these official sources before a live operation: - -- Apple: [Developer ID certificates](https://developer.apple.com/help/account/certificates/create-developer-id-certificates/), - [Notarizing macOS software before distribution](https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution), - [Customizing the notarization workflow](https://developer.apple.com/documentation/security/customizing-the-notarization-workflow), - [TN3147: Migrating to the latest notarization tool](https://developer.apple.com/documentation/technotes/tn3147-migrating-to-the-latest-notarization-tool), - and [Resolving common notarization issues](https://developer.apple.com/documentation/security/resolving-common-notarization-issues). -- Sparkle: [Documentation](https://sparkle-project.org/documentation/), - [Publishing an update](https://sparkle-project.org/documentation/publishing/), - and [Upgrading to EdDSA from DSA](https://sparkle-project.org/documentation/eddsa-migration/). -- GitHub: [Secrets reference](https://docs.github.com/en/actions/reference/security/secrets), - [Workflow syntax](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax), - [Deployments and environments](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments), - [REST releases](https://docs.github.com/en/rest/releases/releases), and - [REST release assets](https://docs.github.com/en/rest/releases/assets). +Notarization uses one team App Store Connect API-key credential set with +`notarytool`. Apple ID and app-specific password authentication are outside this +contract. The P12 contains one Developer ID Application identity and its private +key. Derive and verify the identity from the temporary keychain; do not store a +signing-identity label as a secret. + +Organization secrets must grant the exact repository effective access. Both +`all` and `selected` are conforming when access is effective; do not widen a valid +selected scope. Reject same-name repository or environment secrets that shadow +this organization material. + +Each application owns a repository secret such as +`_SPARKLE_PRIVATE_ED_KEY`. Do not share it between applications or +use a generic organization or environment `SPARKLE_PRIVATE_ED_KEY`. Check the +corresponding public key into the repository, embed it in the app, and verify +that the signing key matches it before appcast generation. + +Keep private material out of source, logs, caches, and artifacts. Use Sparkle's +standard-input key interface when available. GitHub publication uses only the +ephemeral workflow token, with no persistent GitHub release secret. + +## Build And Signing + +Complete credential-free tests and the unsigned build before exposing Apple or +Sparkle secrets to the packaging step. Use isolated temporary staging. + +Preserve and restore the original user keychain search list and default keychain +on exit, including failure or cancellation. Verify restoration before deleting +the temporary keychain, and remove private temporary material. Make the temporary +keychain the sole user search-list keychain and default before changing its key +partition list. Require exactly one usable Developer ID identity with the +adapter's Team ID. + +Use the repository's supported GitHub-hosted ARM64 macOS runner and tool versions. +Stage one app matching the declared identity, versions, feed, public key, +architecture, deployment minimum, and update settings. + +Resolve Sparkle's `Versions/Current` to a safe direct-child version directory and +validate its expected executable graph. Sign known binaries and nested bundles +inside-out, then the outer app. Do not use `codesign --deep` for signing. + +Every signed component must have the expected Developer ID authority and Team ID, +Hardened Runtime, secure timestamp, and approved entitlements. Outer +`get-task-allow` or `disable-library-validation` requires an explicit narrow +repository exception supported by current Apple requirements. Verify the complete +signed graph; the final bundle check is equivalent to +`codesign --verify --deep --strict --verbose=2`. + +## Notarization And Final Assets + +Preserve this artifact order: + +1. Verify the signed app and create a separate temporary notarization ZIP. +2. Submit that ZIP with the team API key and a bounded wait. Bind the submission + ID to its source and upload artifact. Require `Accepted` from submission and + `notarytool info`; read the log, reject errors, and report material warnings. +3. Staple the original app, validate its ticket, repeat strict signature checks, + and require Gatekeeper acceptance. +4. Create the final public ZIP from the stapled app. Extract and verify it before + generating the Sparkle signature, appcast, and checksum from those exact bytes. + +Never publish the notarization upload ZIP or modify the final ZIP after signature +and checksum generation. Publish exactly three assets: + +- the repository-named final ZIP with one expected `.app` root; +- `appcast.xml`; and +- the repository-named lowercase SHA-256 checksum file for that ZIP. + +Validate archive structure before extraction. The appcast must bind the canonical +release/download URLs, version, platform minimum, final ZIP byte length, and +Ed25519 signature verified with the checked-in public key. GitHub-generated source +links do not count as uploaded assets. + +## Draft Publication And Recovery + +Validate local assets before GitHub mutation. Create or reuse one private draft +for the candidate tag; replace its assets with exactly the final asset triplet. +Reject duplicate same-tag releases and conflicting public state. + +Before publication, verify the exact draft and uploaded assets by metadata and +downloaded bytes, including canonical URLs, sizes, GitHub SHA-256 digests, and +artifact validity. Recheck the annotated tag, commit, `main` ancestry, and version +advance. Publish with one final `draft=false`, `make_latest=true` mutation. +Resolve an uncertain publication result from authoritative state before any +further write. Report unresolved publication state without claiming that the +release is private or public. + +An already public same-tag rerun is read-only: verify its remote metadata and +assets. Do not apply the new-version gate, replace public assets, or compare them +against a fresh rebuild whose archive metadata can differ. + +Use the target runbook for recovery. Reuse an Apple submission only when its ID +and exact upload-artifact binding establish that it is the same candidate. +Do not bypass notarization or environment approval, manually publish a failed +draft, or delete a public release as routine recovery. + +## Trust-Root Changes + +Keep protected recovery ownership for the Developer ID certificate and each +application's Sparkle private key. Routine releases do not create or rotate them. +Never change the Developer ID certificate and Sparkle key in the same update. + +For an authorized rotation, follow current Sparkle guidance and test the update +from supported installed versions before retiring old trust material. Keep the +other trust root stable. If `SUVerifyUpdateBeforeExtraction` requires a signed +DMG for key migration, that migration is outside this ZIP-only skill. Legacy +DSA-to-Ed25519 transitions use the provider's staged migration path. + +## Acceptance + +Validate changed repository behavior against the relevant release contracts. +Select tests for the actual change. + +Live acceptance binds the exact pipeline revision, successful workflow, immutable +tag, and latest public stable Release. Verify downloaded asset hashes, appcast +signature and metadata, extracted app identity and version, stapled ticket, +complete signature graph, and Gatekeeper acceptance. Run repository-required app +or update checks when authorized. Local tests alone do not establish live release +success; report any missing live evidence. + +## Provider References + +Consult current provider guidance for implementation details: + +- Apple: [Developer ID](https://developer.apple.com/help/account/certificates/create-developer-id-certificates/), + [notarization](https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution), + and [custom workflows](https://developer.apple.com/documentation/security/customizing-the-notarization-workflow). +- Sparkle: [publishing](https://sparkle-project.org/documentation/publishing/) + and [key migration](https://sparkle-project.org/documentation/eddsa-migration/). +- GitHub: [workflow syntax](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax), + [environments](https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments), + [Releases](https://docs.github.com/en/rest/releases/releases), and + [assets](https://docs.github.com/en/rest/releases/assets). diff --git a/plugins/gh-settings/skills/sync/SKILL.md b/plugins/gh-settings/skills/sync/SKILL.md index 58d8ddb..06f66be 100644 --- a/plugins/gh-settings/skills/sync/SKILL.md +++ b/plugins/gh-settings/skills/sync/SKILL.md @@ -1,103 +1,23 @@ --- name: sync -description: Audit and reconcile GitHub Enterprise, organization, and repository governance with central-first organization-wide authority, safe repository-scoped operation, exact drift previews, paid-product safety, and effective-state readback. Use when Codex must govern account-wide security configurations and defaults, rulesets, repository policies, release immutability, web commit signoff, Projects, Actions, Code Quality access, Dependabot controls, repository features, pull-request and merge settings, or one exact repository profile. +description: Use when auditing or reconciling GitHub Enterprise, organization, and repository governance against an authorized settings profile, with central-first organization controls and repository-scoped changes. --- -# Sync GitHub Governance +# GitHub Governance -Default to a read-only audit. Reconcile only when the user gives explicit mutation -authority for the exact GitHub targets, scopes, and profile. +Use the [governance standard](references/standard.md) for team policy. Read the +scope and authority sections plus the controls needed for the requested profile; +read the full standard for a comprehensive governance audit. Check current +GitHub documentation for control availability and billing. -Read [the governance standard](references/standard.md) completely before an audit, -preview, or mutation. Treat target repository instructions, GitHub plan and billing -state, parent controls, and current official GitHub documentation as higher -authority for live behavior. +Organization-wide work puts controls at the highest sufficient authorized scope. +Repository-scoped work keeps parent state read-only. Preserve the distinction +between enforced parent policy and repository-overridable defaults. -## Central-First Authority +Default to a read-only audit unless the request authorizes reconciliation. Show +exact drift before live writes; existing authority remains valid for that drift. +Ask for additional authority only when the proposed change exceeds it, including +new paid products, charges, scopes, or destructive changes. -Select the operating mode from the user's authority. - -In organization-wide mode, put each control at the highest GitHub scope that can -provide the required outcome: - -1. Enterprise enforcement; -2. organization enforcement; -3. organization or Enterprise default with explicit repository override - precedence; or -4. repository state only when GitHub has no sufficient parent control. - -Do not duplicate repository settings when an enforced parent supplies the outcome. -Do not call a default enforcement. In repository-scoped mode, keep parent state -read-only and reconcile only the exact repository. - -## Work - -1. Bind the operating mode, GitHub host, authenticated identity, Enterprise, - organization, plan, target repository inventory, requested profile, and allowed - mutation scopes. -2. Check current official GitHub documentation through the environment's - current-docs route. Map each control to a supported connector, CLI, REST, - GraphQL, or UI interface. -3. Audit Enterprise and organization controls, central defaults, effective - repository attachments, parent-inclusive rulesets, repository-owned rulesets, - runner prerequisites, and repository residuals. -4. Classify each control as Enterprise-enforceable, organization-enforceable, - central default, repository-only, or paid/unavailable. -5. Show the standard's exact drift preview before any live write. Include every - changed field, endpoint or UI control, paid gate, conditional change, and exact - destructive object. -6. Refresh state. Apply only still-current approved drift. For a `migrate` - decision, create and verify the parent replacement before local deletion. For - an explicit `retire` decision, verify the accepted parent baseline first. -7. Read every changed control back from its authoritative interface. Re-audit - effective state for every repository after parent changes. - -## Hard Boundaries - -- Never broaden mutation authority from repository to organization or Enterprise, - or from organization to Enterprise. -- Never weaken, detach, bypass, or replace an inherited rule or enforced security - configuration without exact authority for that parent object. -- Never enable Code Security, Secret Protection, Code Quality, or another paid - product for a private or internal repository without explicit product and - billing authority. -- Treat Code Quality as separate from CodeQL and Code Security. For a requested - `No repositories` policy, do not start scans or accept charges to configure it. -- Keep Dependabot on the standard GitHub runner unless an exact eligible runner and - label exist. Do not create a runner or select one that can queue indefinitely. -- Treat automatic dependency submission as a separate GitHub Actions workload. - Check supported ecosystems, Actions availability, runner choice, and billing; - do not infer private-repository authority from free public-runner usage or from - the Dependabot runner setting. -- Preserve `dependabot.yml` and repository-override precedence for organization - defaults such as grouped security updates. -- Diagnose failed security configuration attachments. Allow active advanced CodeQL - setup when that is the safe way to preserve working public coverage. -- For a merge-commit-only profile, require merge commits, disable squash and - rebase, and reject any effective `required_linear_history` conflict before - activation. -- List parent-inclusive and repository-only rulesets separately. Delete only exact - repository-owned IDs in the approved preview and only after effective parent - replacement readback. -- When a zero-local-ruleset profile explicitly retires a repository rule, verify the - accepted parent baseline and delete the exact ID. Do not invent a preservation - team, role, app, or adapter for semantics the profile says to remove. -- Do not invent a team or role to replace a user-specific repository bypass. Verify - actor eligibility and exact access first; preserve the local rule when the - profile retains its semantics and no exact parent actor exists. -- Use protected credential delivery. Do not print, persist, request, or place - credentials in repository files or commands. -- Prefer supported machine interfaces. Use the GitHub Web UI only for an exact - control with no sufficient machine route, through an existing permitted session. -- Suspend writes when the preview is stale or a write result is uncertain. Use - the standard's reconciliation rules for bounded authoritative readback, refreshed - previews, and resumption within existing authority. Unresolved state blocks - further writes to the affected target; it does not establish success. - -## Report - -Report the bound identity and scopes, central authority decision, exact -before/desired/after values, parent attachments and effective state, operations, -paid or unavailable exceptions, ruleset migrations, repository residuals, and -repository-owned ruleset count for every in-scope repository. Do not claim effective -compliance from a successful request alone. +Verify effective settings after changes. Report the result, material drift and +exceptions, and evidence needed to assess completion. diff --git a/plugins/gh-settings/skills/sync/references/standard.md b/plugins/gh-settings/skills/sync/references/standard.md index 0445414..be688d3 100644 --- a/plugins/gh-settings/skills/sync/references/standard.md +++ b/plugins/gh-settings/skills/sync/references/standard.md @@ -1,409 +1,172 @@ # GitHub Governance Standard -## Purpose +## Scope And Authority -Use this standard to audit and reconcile GitHub Enterprise, organization, and -repository controls. Default to a read-only audit. Reconcile only the exact -targets, scopes, products, and values that the user authorizes. - -Use central-first authority. Put a control at the highest GitHub scope that can -manage the required outcome. Use repository settings only for controls that -GitHub cannot manage at Enterprise or organization scope, or for an explicit -repository exception that the parent policy permits. +Audit or reconcile the requested profile against the exact authorized GitHub +host, accounts, repositories, and mutation scopes. Use the complete in-scope +repository inventory, including private, internal, archived, and template +repositories. Establish identity, permissions, plan, and billing where they +affect the requested controls. -GitHub changes its APIs, plans, billing rules, and Web UI. Before each live -operation, use the current-documentation route and official GitHub documentation. -Bind the supported API version. Do not use examples in this standard as proof of -current availability. +Organization-wide work uses the highest sufficient authorized scope: Enterprise +enforcement, organization enforcement, parent defaults, then repository settings. +Repository-scoped work keeps parent state read-only while accounting for inherited +controls. Neither mode grants authority to modify a higher scope. -## Authority And Target Binding +A parent default is not enforcement. Preserve documented override precedence and +avoid duplicate lower-scope settings when an enforced parent provides the desired +outcome. Remove an equivalent lower-scope override only after effective inheritance +from its replacement is verified. -Resolve these facts before privileged collection: - -- GitHub host, API base URL, and selected API version; -- authenticated login, stable user ID, credential-delivery route, and effective - administration scopes; -- exact Enterprise slug and stable identity, when in scope; -- exact organization login, ID, node ID, plan, and billing boundary; -- the complete in-scope repository inventory, including IDs, node IDs, - visibility, archived state, template state, and permissions; -- requested profile and whether the request is audit-only or authorizes writes; -- allowed mutation scopes: Enterprise, organization, and repository; and -- observation time. - -A repository-scoped request does not authorize an organization or Enterprise -change. An organization-scoped request does not authorize an Enterprise change. -A profile is desired state. It is not proof that the current plan, product, or -parent policy permits that state. - -Use a protected credential adapter, connector, or supported CLI authentication -route declared by the active environment. Deliver a credential only to the named -GitHub consumer. Never show token values, inspect unrelated credential stores, or -fall across identities after an authorization failure. - -## Operating Modes - -Select one mode from the user's authorized scope before classification. - -### Organization-Wide Mode - -Use central-first authority across the complete Enterprise, organization, and -repository inventory. Put every supported control at Enterprise or organization -scope. Reconcile only true repository residuals. When the approved profile requires -zero repository-owned rulesets, treat a nonzero local count on any repository as -failed acceptance. - -### Repository-Scoped Mode - -Bind one exact repository and keep all Enterprise and organization state read-only. -Audit inherited rulesets, configurations, policies, and defaults so effective state -is correct, but do not mutate a parent. Reconcile only the repository values that -the request authorizes. Do not infer organization-wide authority from a repository -profile or from this standard's central-first default. - -## Central-First Decision Rule - -Classify each requested control before previewing a write. - -| Class | Meaning | Action | -| --- | --- | --- | -| Enterprise-enforceable | GitHub can enforce the outcome across the required Enterprise scope. | Own the control at Enterprise scope. | -| Organization-enforceable | GitHub cannot provide the required Enterprise control, but the organization can enforce it. | Own the control at organization scope. | -| Central default | GitHub can set a parent default, but a repository can override it. | Set the parent default and report override precedence. | -| Repository-only | GitHub has no sufficient Enterprise or organization control for the required outcome. | Reconcile each applicable repository. | -| Paid or unavailable | The active plan, product, interface, or prerequisite cannot provide the approved outcome safely. | Do not enable or emulate it. Report the gap. | - -Use the highest scope only when it provides equivalent or stronger semantics for -the requested target set. Do not replace an enforcement rule with a default. Do -not describe a default as effective enforcement. Do not write duplicate -repository settings when an enforced parent value already supplies the outcome. - -When a parent default is repository-overridable, audit the parent value and each -material repository override separately. Preserve documented precedence, such as -`dependabot.yml` over repository UI and repository UI over organization UI. - -When an organization setting overrides an equivalent Enterprise default, remove -the duplicate organization override only after the Enterprise default is active -and effective readback proves that the organization still inherits the intended -value. - -## Interface Selection - -Prefer the smallest supported interface that can read and write the same control: - -1. a purpose-built GitHub connector or supported API; -2. GitHub CLI as an authenticated API client; -3. the GitHub Web UI for one exact setting that has no sufficient supported - machine interface. - -Do not use the Web UI only because GitHub describes a control with a UI label. -First check current REST and GraphQL documentation. If a public interface exposes -read state but not mutation, use the UI only for the missing operation and verify -through both available surfaces when possible. - -For UI fallback, preserve the bound host, identity, account, repository, and -control. Use the existing signed-in session. If the session needs a new login or -credential entry, stop unless the user explicitly authorizes that login. Never -handle the credential value. Read the visible control, change only the previewed -value, submit, reload, and read it again. Record an inaccessible control as a gap. - -## Audit Inventory - -Collect the requested controls and the parent state that can determine their -effective values. Inventory every in-scope repository. Do not omit private, -internal, archived, or template repositories. - -### Security Configurations And Products - -List Enterprise and organization security configurations, their defaults, full -fields, enforcement, and attached repositories. For each repository, read the -attached configuration endpoint. A catalog entry without an attachment is not -effective state. Distinguish `attached`, `enforced`, `removed`, `failed`, and -transitional statuses. - -For a public baseline, audit these fields: - -- Code Security, CodeQL default setup, runner type, and advanced-setup - compatibility; -- Secret Protection, secret scanning, validity checks, extended metadata, - generic and AI detections, push protection, and bypass policy; -- dependency graph, automatic dependency submission, Dependabot alerts, - security updates, malware alerts, and delegated dismissal; -- private vulnerability reporting; and -- configuration enforcement and default repository visibility. - -For a maximum-free public baseline, enable automatic dependency submission with -the standard runner after GitHub Actions and current billing evidence are bound. -Report when the attached configuration is effective but no current supported -manifest can trigger a submission. - -Code Security and Secret Protection are free for public repositories. CodeQL -default setup cannot attach over active advanced setup unless the configuration -allows advanced setup. Preserve active advanced setup or use the explicit -"advanced setup allowed" option. Do not remove a working advanced setup only to -make a parent attachment succeed. - -For a free private or internal baseline, enable only features that current plan -evidence proves are free for that visibility. Dependency graph, Dependabot alerts, -and Dependabot security updates are available on all plans. Malware alerts require -Dependabot alerts and currently cover only supported ecosystems. Explicitly -disable automatic dependency submission unless the user accepts its GitHub Actions -usage and possible private-repository billing. Also disable Code Security, Secret -Protection, CodeQL, secret scanning, push protection, and their paid dependent -features. Keep delegated dismissal disabled when the current product requires Code -Security. - -Treat automatic dependency submission as a separate Actions workload, not as part -of the Dependabot runner setting. It requires dependency graph and GitHub Actions, -runs built-in workflows on supported manifests, and consumes Actions minutes. -Standard GitHub-hosted runners are free for public repositories; private and -internal repositories can consume included minutes and incur charges beyond the -allowance. Inspect current manifest ecosystems before enablement. Prefer the -no-charge Dependabot graph jobs where GitHub supports them because they take -precedence over automatic submission. Use the standard runner option unless an -exact eligible labeled runner is already available. Report when enablement has no -current effect because no supported manifest exists, and still read back the -configuration field and every attachment. - -Treat GitHub Code Quality as a separate product. Audit its Enterprise allowance, -organization repository access, enforcement, and repository state. Do not infer -authority from CodeQL or Code Security. Never enable Code Quality where the -approved result is `No repositories`. If GitHub cannot set and enforce that state -without starting scans or charges, leave the product disabled and report the gap. - -### Dependabot Global Controls - -Audit grouped security updates, malware alerts, delegated dismissal, and the -Dependabot runner type. Grouped updates require dependency graph, Dependabot -alerts, and Dependabot security updates. Enabling grouping can close and replace -existing pull requests. - -Prefer the organization default for grouping. Preserve current precedence: - -1. `dependabot.yml` group rules; -2. repository UI; and -3. organization UI. - -Use the standard GitHub runner by default. Inspect organization and Enterprise -runner inventories before selecting a labeled runner. Do not select a labeled or -self-hosted runner unless an eligible, available runner with the exact label -exists. Public repositories use GitHub-hosted runners. - -### Rulesets And Branch Protection - -List Enterprise, organization, and repository rulesets with full details. For each -repository, list rulesets with parents included and excluded. Classify each rule by -ID, name, target, source type, source, enforcement, bypass actors, conditions, and -rules. Inspect branch protection when it can add or conflict with effective state. - -For a profile that requires zero repository-owned rulesets, classify each local -rule as `migrate` or `retire` before deletion. - -- `migrate`: The profile retains the rule's semantics. Create a parent replacement - that preserves its exact target, ref pattern, rules, bypass actors, and - enforcement. Read back effective coverage before local deletion. -- `retire`: The user explicitly accepts removal and the disclosed protection delta. - Refresh sufficient parent protection, then delete only the exact local IDs from - the preview. Do not create a team, role, app, or other preservation adapter for - semantics that the approved profile says to remove. - -Never delete first, silently weaken retained protection, or widen bypass access. - -A user-specific repository bypass might not have an exact parent-scope actor. -Check current supported bypass types, source ownership, team visibility, membership, -and repository access before proposing a team or role. Secret teams are not eligible -for ruleset bypass. Do not create or alter an identity container without an exact -preview. When no exact central actor preserves retained semantics, keep the -repository rule and report the centralization gap unless the user explicitly -changes the profile to retire that rule. - -For pull-request rules, confirm that every target repository has at least one merge -method allowed by the parent rule before activation. Preserve existing lifecycle, -signature, deletion, non-fast-forward, workflow, and required-check rules unless -the user explicitly changes them. - -### Organization Defaults And Policies - -Audit current central controls for: - -- immutable releases; -- required signoff for web commits; -- commit-comments default and repository override behavior; -- organization and repository Projects availability; -- Actions repository access, allowed actions, SHA pinning, workflow-token - permissions, pull-request approval, and runner inventory; and -- security product access and enforcement. - -Release immutability is an organization policy when GitHub exposes that control. -Use repository release settings only when the requested target is outside the -central policy or GitHub does not expose the parent control. Web commit signoff is -an organization control. Commit comments are an organization default that -repository administrators can override. - -Do not change unrelated Actions policies during a settings profile reconciliation. -Preserve an existing safe setting unless the approved profile names another value. - -### Repository Residuals - -After central classification, audit only true residuals and allowed exceptions. -Typical residuals include: - -- Issues, Wikis, Discussions, Sponsorships, and Pull Requests; -- issue and pull-request creation policy; -- allowed merge methods and their unchanged title or message defaults; -- branch update suggestions, auto-merge, and head-branch deletion; -- commit comments when a repository override must be reconciled; and -- automatic closing of linked issues after merge. - -### Merge-Commit-Only Baseline - -When the approved profile selects merge-commit-only behavior, use these exact -repository values: +Use the environment's protected credential route and supported machine interfaces. +Use an existing permitted browser session only for an exact control without a +sufficient machine route. A new login needs user authority. Check current official +GitHub documentation for API support, product availability, and billing. + +## Security Profiles + +For a maximum-free public baseline, include Code Security and CodeQL, Secret +Protection and push protection, dependency graph, Dependabot alerts and security +updates, private vulnerability reporting, and applicable free dependent features. +Verify configuration fields, enforcement, defaults, and actual repository +attachments. An unattached configuration does not establish effective settings. + +Preserve active advanced CodeQL setup or select the supported advanced-setup +allowance when attaching a parent configuration. Do not remove working advanced +setup merely to make the attachment succeed. + +For a free private or internal baseline, enable only features supported without +charge by the current plan, including dependency graph and Dependabot alerts and +security updates. Disable Code Security, Secret Protection, CodeQL, secret scanning, +push protection, and paid dependent features unless separately authorized. Keep +malware alerts within their supported ecosystems and delegated dismissal disabled +when it requires a paid product. + +Code Quality is separate from CodeQL and Code Security. Check its account allowance, +repository access, and enforcement when in scope. A `No repositories` policy must +not start scans or incur charges; leave it disabled and report a gap if GitHub +cannot enforce that state without enablement. + +### Automatic Dependency Submission + +Treat automatic dependency submission as a separate Actions workload with its own +dependency-graph, Actions, ecosystem, runner, and billing prerequisites. It is not +controlled by the Dependabot runner setting. + +For a maximum-free public baseline, enable it with the standard runner after +confirming current free usage. For private or internal repositories, leave it +disabled unless the user accepts Actions usage and possible charges. Prefer free +Dependabot graph jobs where they take precedence. Report enablement with no current +effect when the repository has no supported manifest. + +### Dependabot Defaults + +Prefer organization defaults for grouped security updates. Preserve precedence: +`dependabot.yml` group rules, then repository UI, then organization UI. Grouping +requires dependency graph, alerts, and security updates, and can replace existing +pull requests. + +Use standard GitHub runners; public repositories use GitHub-hosted runners. Select +a labeled runner only when an exact eligible available runner exists. A settings +request does not require creating runner infrastructure. + +## Rulesets And Protection + +Inspect effective parent and repository rulesets separately, plus branch +protection that affects the requested outcome. Preserve retained rules and bypass +semantics when moving ownership. + +For a zero-repository-ruleset profile, distinguish two decisions for each local ID: + +- **Migrate:** The profile retains its semantics. Create and verify equivalent + parent target, ref, rule, actor, and enforcement coverage before local deletion. +- **Retire:** The user accepts removal and the disclosed protection delta. Verify + the accepted parent baseline and delete that exact local ID. Do not invent a + team, role, app, or adapter to preserve semantics the profile retires. + +A user-specific bypass may have no exact parent actor. Verify eligibility and +access before proposing a replacement; secret teams are not eligible. If retained +semantics have no equivalent parent actor, preserve the local rule and report the +gap unless the user changes the profile. Changes to identity containers need exact +authority. + +Before activating parent pull-request rules, every target repository must retain +an allowed merge path. Do not weaken inherited protection or widen bypass access +outside the approved change. + +### Merge-Commit-Only Profile + +Use these repository values: - `allow_merge_commit: true`; - `allow_squash_merge: false`; and - `allow_rebase_merge: false`. -Repository merge toggles remain repository residuals because an account ruleset -does not set those repository values. When a parent pull-request rule supports -allowed merge methods, use `allowed_merge_methods: ["merge"]` to enforce the same -outcome on its matched refs. - -Before activation, inspect every effective Enterprise, organization, repository, -and branch-protection rule for `required_linear_history` or another condition that -rejects merge commits. Do not leave an active conflict. Change or remove a -conflicting rule only when the approved preview names that exact parent object. -Preserve merge-title and merge-message defaults unless the profile names them. - -Apply visibility and feature prerequisites literally. `Sponsorships enabled for -public repositories` does not authorize a visibility change or a funding file. -If a control appears only after its prerequisite is enabled, classify the initial -state as unknown and make the dependent write conditional on fresh readback. - -## Exact Drift Preview - -Show the preview before the first live write. Bind it to the host, identity, -Enterprise, organization, complete repository inventory, API version, observation -time, selected operating mode, allowed mutation scopes, current parent state, and -user authority. - -Separate the preview into: - -1. Enterprise-enforceable changes; -2. organization-enforceable changes; -3. central defaults and repository override precedence; -4. repository-only residuals; -5. paid, unavailable, skipped, and unknown controls; and -6. destructive migrations. - -For a zero-repository-ruleset profile, list every local ruleset and mark it -`migrate` or `retire`. State the required acceptance value: local ruleset count -`0` for every repository. - -Use one row per control with these columns: - -| Scope | Control | Current | Desired | Authority/source | Planned interface | Status | -| --- | --- | --- | --- | --- | --- | --- | - -Use precise statuses such as `in sync`, `change`, `conditional change`, -`parent-controlled`, `central default`, `repository override`, `paid opt-in -required`, `unsupported`, and `unknown`. - -After the table, list operations in order. For REST, show method, path, and only -changed fields. For GraphQL, show the mutation, stable node ID, and changed inputs. -For UI, show the exact page and control. For deletion, show the exact object ID, -source, target, rules, and replacement. - -Give automatic dependency submission its own preview row with dependency-graph and -Actions prerequisites, supported-ecosystem evidence, runner choice, and the public -or private Actions billing result. Do not hide it inside the dependency-graph or -Dependabot-runner rows. - -The same user request can supply mutation authority when it binds the exact -accounts, repositories, profile, and scopes. The preview is still mandatory. Stop -for new authority if the preview adds a target, scope, product, charge, destructive -object, or value that the request did not bind. - -## Reconciliation - -Refresh every previewed value immediately before writing. Recompute drift. A -changed identity, target, visibility, parent control, product availability, -destructive object, or uncertain result invalidates the preview. Suspend affected -writes and use bounded authoritative reads to resolve the state. Refresh target -and identity bindings and show the corrected preview before resuming. Resume only -when the state is unambiguous and the remaining drift is covered by existing -authority. Obtain new authority for any added target, scope, product, charge, -destructive object, or value. If readback cannot resolve the state within its -bounds, report the gap and leave further writes to that target suspended. - -Apply the smallest sufficient writes. Use this order unless a dependency requires -a safer sequence: - -1. create or update non-destructive parent controls; -2. set and verify parent defaults, then remove duplicate lower-scope defaults; -3. prepare repository residuals that a new parent rule requires, such as an - allowed merge path; -4. attach enforced security configurations and wait for terminal status; -5. activate parent rulesets; -6. verify effective parent coverage; and -7. delete only exact migrated or explicitly retired repository-owned rules. - -Send only changed fields. Keep unrelated merge-title and message defaults. Separate -API families when their result or rollback boundary differs. Do not treat an -omitted response field as success. After an uncertain timeout or partial response, -stop writes to that target until authoritative readback resolves the result. - -For an asynchronous attachment, poll the authoritative status with bounded waits. -Do not report success while the status is `attaching`, `updating`, `failed`, -`removed`, or absent. Diagnose a failed attachment before retrying. Do not consume a -paid license to force attachment. - -## Readback And Result - -Read each changed control from its authoritative interface. Re-list parent and -repository-only rulesets. Re-read security configuration defaults, fields, -repository attachments, and effective security state. Reload each UI-only page. -Re-audit every repository after parent changes so local state and inherited state -remain distinct. - -Report: - -- bound target, identity, plan, API version, and observation time; -- Enterprise and organization controls and which values are enforced; -- central defaults and documented repository override precedence; -- each repository's attached configuration status and effective fields; -- before, desired, and read-back values for each changed control; -- exact operations and outcomes; -- migrated and deleted ruleset IDs with replacement evidence; -- repository-owned ruleset count for every repository and the profile acceptance - result; -- paid-product gates, conditional skips, unsupported controls, and failures; and -- remaining effective drift. - -Use `reconciled` only when every applicable desired value has authoritative -readback and no unresolved write remains. Otherwise use `partially reconciled` or -`audit complete` and state the exact gap. - -## Official Documentation Anchors - -Check current official versions of these sources before live work: - -- REST organizations: `https://docs.github.com/en/rest/orgs/orgs` -- REST repositories: `https://docs.github.com/en/rest/repos/repos` -- REST repository and account rulesets: - `https://docs.github.com/en/rest/repos/rules` -- REST code security configurations: - `https://docs.github.com/en/rest/code-security/configurations` -- REST Actions permissions: - `https://docs.github.com/en/rest/actions/permissions` -- GraphQL organizations and repositories: - `https://docs.github.com/en/graphql/reference` -- security configuration statuses and troubleshooting; -- public and private security-feature availability and billing; -- Dependabot security updates, grouping precedence, malware alerts, delegated - dismissal, and runner selection; -- automatic dependency submission, supported ecosystems, runner selection, and - GitHub Actions billing; -- immutable releases and organization repository defaults; -- organization commit-comments and web-signoff controls; and -- Code Quality enablement, enforcement, and billing. +Where supported, enforce `allowed_merge_methods: ["merge"]` in the parent +pull-request rule as well; it does not set the repository toggles. Resolve any +effective `required_linear_history` conflict before activation, with authority for +the exact conflicting object. Preserve merge-title and message defaults unless +the profile changes them. + +## Other Settings + +Apply central ownership to release immutability, web commit signoff, Projects, +Actions, and product policies where the current GitHub interface supports the +requested outcome. Commit comments can be a parent default with repository +overrides. Do not expand a settings request to unrelated Actions policies. + +Repository residuals include features such as Issues, Wikis, Discussions, +Sponsorships, pull-request availability and creation policy, merge options, +branch-update suggestions, auto-merge, head-branch deletion, and linked-issue +closure. Inspect the residuals requested by the profile. + +A visibility-dependent feature does not authorize changing visibility or adding a +funding file. If a prerequisite exposes a previously unavailable control, make the +dependent change conditional on its newly observed state. + +## Preview And Reconciliation + +Before live writes, show the exact targets, current and desired values, material +parent effects, planned interface, charges, and destructive object IDs. Identify +unknown or conditional changes. For automatic dependency submission, disclose its +own prerequisites and billing effect. Choose a presentation proportionate to the +requested scope. + +Existing user authority can cover the previewed changes. Request more authority +only for additional targets, scopes, products, charges, destructive objects, or +values outside that authority. + +Refresh material state before applying drift. Create and verify replacement parent +controls before deleting retained local protection, and establish allowed merge +methods before activating dependent parent rules. Resolve uncertain mutation +results from authoritative state before further writes to the affected target. +Show a corrected preview when material state changes; resume within existing +authority once the state is clear. Unresolved state leaves affected writes suspended. + +Verify changed controls and effective repository state after parent changes. +Security attachments must reach a successful terminal state; a failed or pending +attachment is not acceptance. Do not enable a paid product to force attachment. + +## Completion + +Report material changes, effective remaining drift, and unavailable or paid +exceptions with enough evidence to assess the requested profile. Include exact +ruleset migration or deletion results; a zero-local-ruleset profile requires a +verified count of zero for every target repository. + +Claim reconciliation only when applicable desired values have authoritative +readback and no unresolved write remains. Otherwise state the remaining gap. + +## Provider References + +Use current official documentation for the controls involved: + +- [Organizations](https://docs.github.com/en/rest/orgs/orgs) and + [repositories](https://docs.github.com/en/rest/repos/repos); +- [rulesets](https://docs.github.com/en/rest/repos/rules); +- [security configurations](https://docs.github.com/en/rest/code-security/configurations); +- [Actions permissions](https://docs.github.com/en/rest/actions/permissions); and +- [GraphQL](https://docs.github.com/en/graphql/reference). + +Consult the relevant product documentation for billing, default precedence, +attachment compatibility, and automatic dependency submission prerequisites.