From 5f46f4b374538f09e6d728019eb12bde1870d241 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 16 Jul 2026 08:30:19 -0700 Subject: [PATCH 1/3] Incorporate #322: publisher TOCTOU pin, carry-policy blessing, snippet nits - publish-release.yml: checkout pins github.sha - the branch name is a moving pointer, so a commit landing between dispatch and checkout was released unvalidated; GITHUB_REF still names the branch for NBGV classification. - repo-config/README.md: .github/ holds GitHub-consumed configuration (workflows, Dependabot), not "Actions-owned"; the Downstream Carry section blesses the adapted repo-scoped self-audit carry (local AUDIT.md + spec/secrets.json auditing the repo against its committed repo-config baseline) as the standard shape - hub audit stays authoritative, hub never linked. - vscode-tasks-python.json: the aggregators are dependsOn-only (header says command-executing tasks are type: process), and the object group form makes Python Format / Python Test the default build/test tasks. Closes #322 (fires on promotion). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish-release.yml | 5 +++-- catalog/snippets/configs/vscode-tasks-python.json | 7 ++++--- repo-config/README.md | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 0f6c6159..7df5c2e4 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -42,11 +42,12 @@ jobs: with: dotnet-version: 10.x - # Full history so NBGV can compute the git height for the branch. + # Full history for NBGV; pin the dispatch-time commit (the branch name is a moving pointer, so a commit + # landing after dispatch would be released unvalidated). GITHUB_REF still names the branch for NBGV. - name: Checkout code step uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: - ref: ${{ github.ref_name }} + ref: ${{ github.sha }} fetch-depth: 0 # NBGV versions the dispatched ref: main is the public-release ref (clean X.Y.Z), develop a prerelease. diff --git a/catalog/snippets/configs/vscode-tasks-python.json b/catalog/snippets/configs/vscode-tasks-python.json index d3d97656..593f1078 100644 --- a/catalog/snippets/configs/vscode-tasks-python.json +++ b/catalog/snippets/configs/vscode-tasks-python.json @@ -1,7 +1,8 @@ { "version": "2.0.0", "tasks": [ - // Python language group. Every task is `type: process` (like the .NET snippet) so the command is + // Python language group. Every command-executing task is `type: process` (like the .NET snippet; the + // aggregators are dependsOn-only) so the command is // executed directly, never through a shell - it avoids `&&`/`;` chaining, which is not portable // (Windows PowerShell 5.1, still the default VS Code task shell on many setups, rejects `&&`). // Sequencing is expressed with `dependsOrder: sequence` + `dependsOn`, not shell operators. @@ -64,7 +65,7 @@ "Ruff Check", "Python Types" ], - "group": "build", + "group": { "kind": "build", "isDefault": true }, "problemMatcher": [] }, { @@ -75,7 +76,7 @@ "run", "pytest" ], - "group": "test", + "group": { "kind": "test", "isDefault": true }, "problemMatcher": [], "presentation": { "showReuseMessage": false, diff --git a/repo-config/README.md b/repo-config/README.md index a6421bc9..4cd93845 100644 --- a/repo-config/README.md +++ b/repo-config/README.md @@ -1,6 +1,6 @@ # repo-config -Repository and branch configuration held as committed files, kept out of `.github/` (which is reserved for GitHub-Actions-owned content). This mirrors the layout the fleet repos use. +Repository and branch configuration held as committed files, kept out of `.github/` (which holds the GitHub-consumed configuration - workflows, Dependabot). This mirrors the layout the fleet repos use. - `main.json` plus one `develop` variant - the branch rulesets as the writable API subset (`name`, `target`, `enforcement`, `bypass_actors`, `conditions`, `rules`). The `develop` payload is `develop.json` (`release` repos) or `operational/develop.json` (`operational` repos); the hub keeps both, a carried copy only its own model's (see "Downstream Carry"). These are the canonical expected payload the hub's audit (`AUDIT.md`, hub-only) diffs each repo's live rulesets against. - `operational/develop.json` - the `develop` ruleset for **operational** repos (registry `workflowModel: operational`): direct signed pushes, no PR gate. Present at the hub and in operational carries only - a carried `release` repo does not have it. See "Rulesets" below. @@ -11,7 +11,8 @@ Repository and branch configuration held as committed files, kept out of `.githu Every fleet repo carries this directory; the hub keeps the canonical copy. Rules for the carried copy: - **Carry only your model's `develop` variant.** A `release` repo carries `develop.json`; an `operational` repo carries `operational/develop.json` instead. `main.json` and `settings.json` are shared by both models. `configure.sh` aborts when the payload its model needs is missing rather than applying a partial configuration. -- **Hub-only references stay plain text.** The hub is a private repo: never URL-link it from a downstream repo - the link 404s for anyone without hub access. Files that exist only at the hub (`AUDIT.md`, `spec/`) are mentioned by name, not linked; links into files every repo carries (`AGENTS.md`) resolve everywhere and are fine. +- **Hub-only references stay plain text.** The hub is a private repo: never URL-link it from a downstream repo - the link 404s for anyone without hub access. Files whose canonical fleet-wide form lives only at the hub are mentioned by name, not linked; links into files every repo carries (`AGENTS.md`) resolve everywhere and are fine. +- **Adapted self-audit carry.** A downstream repo carries **locally adapted** `AUDIT.md` and `spec/secrets.json`, scoped to self-auditing its own rulesets, settings, and secrets against the committed `repo-config/` baseline - the standard shape, so the carried tooling is self-contained. The hub's fleet-wide audit remains authoritative, and the local copies never link the hub. - **The regen snippet targets the current repo**, so it works unchanged in a carried copy. ## Rulesets From 444742ba892e78f89b9d2effc129563d69675151 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 16 Jul 2026 08:37:32 -0700 Subject: [PATCH 2/3] Address Copilot on #323: harmonize hub-only labels, one-line comment The Adapted-self-audit-carry bullet contradicted the remaining "hub-only" parentheticals (file list, Secrets) - both now point at Downstream Carry; the publisher checkout comment shrinks back to one line. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish-release.yml | 3 +-- repo-config/README.md | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 7df5c2e4..951c7ec1 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -42,8 +42,7 @@ jobs: with: dotnet-version: 10.x - # Full history for NBGV; pin the dispatch-time commit (the branch name is a moving pointer, so a commit - # landing after dispatch would be released unvalidated). GITHUB_REF still names the branch for NBGV. + # Full history for NBGV; pin the dispatch-time commit - a push landing after dispatch must not release unvalidated. - name: Checkout code step uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/repo-config/README.md b/repo-config/README.md index 4cd93845..d5fc3b93 100644 --- a/repo-config/README.md +++ b/repo-config/README.md @@ -2,7 +2,7 @@ Repository and branch configuration held as committed files, kept out of `.github/` (which holds the GitHub-consumed configuration - workflows, Dependabot). This mirrors the layout the fleet repos use. -- `main.json` plus one `develop` variant - the branch rulesets as the writable API subset (`name`, `target`, `enforcement`, `bypass_actors`, `conditions`, `rules`). The `develop` payload is `develop.json` (`release` repos) or `operational/develop.json` (`operational` repos); the hub keeps both, a carried copy only its own model's (see "Downstream Carry"). These are the canonical expected payload the hub's audit (`AUDIT.md`, hub-only) diffs each repo's live rulesets against. +- `main.json` plus one `develop` variant - the branch rulesets as the writable API subset (`name`, `target`, `enforcement`, `bypass_actors`, `conditions`, `rules`). The `develop` payload is `develop.json` (`release` repos) or `operational/develop.json` (`operational` repos); the hub keeps both, a carried copy only its own model's (see "Downstream Carry"). These are the canonical expected payload the audit (the hub's fleet-wide `AUDIT.md`, or a carried repo-scoped adaptation - see "Downstream Carry") diffs the live rulesets against. - `operational/develop.json` - the `develop` ruleset for **operational** repos (registry `workflowModel: operational`): direct signed pushes, no PR gate. Present at the hub and in operational carries only - a carried `release` repo does not have it. See "Rulesets" below. - `configure.sh` - applies the rulesets to a repository via the GitHub API (create or full-payload update, idempotent). Run `repo-config/configure.sh [owner/repo] [release|operational]`; the model defaults to the registry `workflowModel` lookup. @@ -43,7 +43,7 @@ done ## Secrets -Publish credentials required per mechanism are enumerated in the hub's `spec/secrets.json` (hub-only). A repo needs only the mechanisms its own publish targets use - a source-only repo needs none of the publish credentials below. NuGet and PyPI use keyless OIDC Trusted Publishing (no stored key; the publish job needs `id-token: write`, and PyPI additionally an `environment: pypi` gate). Docker Hub has no OIDC equivalent and uses a stored `DOCKER_HUB_USERNAME` + `DOCKER_HUB_ACCESS_TOKEN` in both the Actions and Dependabot secret stores. Codegen and merge-bot repos add a GitHub App (`CODEGEN_APP_CLIENT_ID` + `CODEGEN_APP_PRIVATE_KEY` in both stores; the app must be installed, not just created). App-token call sites use `client-id`, never the deprecated `app-id`. +Publish credentials required per mechanism are enumerated in `spec/secrets.json` (canonical at the hub; a downstream repo carries a repo-scoped adaptation - see "Downstream Carry"). A repo needs only the mechanisms its own publish targets use - a source-only repo needs none of the publish credentials below. NuGet and PyPI use keyless OIDC Trusted Publishing (no stored key; the publish job needs `id-token: write`, and PyPI additionally an `environment: pypi` gate). Docker Hub has no OIDC equivalent and uses a stored `DOCKER_HUB_USERNAME` + `DOCKER_HUB_ACCESS_TOKEN` in both the Actions and Dependabot secret stores. Codegen and merge-bot repos add a GitHub App (`CODEGEN_APP_CLIENT_ID` + `CODEGEN_APP_PRIVATE_KEY` in both stores; the app must be installed, not just created). App-token call sites use `client-id`, never the deprecated `app-id`. ## Repo Settings From 1acb14b470d964ffb85018f40246e4fb2b99f8aa Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 16 Jul 2026 08:53:03 -0700 Subject: [PATCH 3/3] Pluralize payloads in the ruleset bullet (Copilot #323) Co-Authored-By: Claude Opus 4.8 (1M context) --- repo-config/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo-config/README.md b/repo-config/README.md index d5fc3b93..413c0671 100644 --- a/repo-config/README.md +++ b/repo-config/README.md @@ -2,7 +2,7 @@ Repository and branch configuration held as committed files, kept out of `.github/` (which holds the GitHub-consumed configuration - workflows, Dependabot). This mirrors the layout the fleet repos use. -- `main.json` plus one `develop` variant - the branch rulesets as the writable API subset (`name`, `target`, `enforcement`, `bypass_actors`, `conditions`, `rules`). The `develop` payload is `develop.json` (`release` repos) or `operational/develop.json` (`operational` repos); the hub keeps both, a carried copy only its own model's (see "Downstream Carry"). These are the canonical expected payload the audit (the hub's fleet-wide `AUDIT.md`, or a carried repo-scoped adaptation - see "Downstream Carry") diffs the live rulesets against. +- `main.json` plus one `develop` variant - the branch rulesets as the writable API subset (`name`, `target`, `enforcement`, `bypass_actors`, `conditions`, `rules`). The `develop` payload is `develop.json` (`release` repos) or `operational/develop.json` (`operational` repos); the hub keeps both, a carried copy only its own model's (see "Downstream Carry"). These are the canonical expected payloads that the audit (the hub's fleet-wide `AUDIT.md`, or a carried repo-scoped adaptation - see "Downstream Carry") diffs the live rulesets against. - `operational/develop.json` - the `develop` ruleset for **operational** repos (registry `workflowModel: operational`): direct signed pushes, no PR gate. Present at the hub and in operational carries only - a carried `release` repo does not have it. See "Rulesets" below. - `configure.sh` - applies the rulesets to a repository via the GitHub API (create or full-payload update, idempotent). Run `repo-config/configure.sh [owner/repo] [release|operational]`; the model defaults to the registry `workflowModel` lookup.