From a9048789c19c63eaa4481d3470144538a58dca0d Mon Sep 17 00:00:00 2001 From: TensorNull Date: Tue, 21 Jul 2026 16:56:29 +0800 Subject: [PATCH] Close Public Preview review gaps --- AGENTS.md | 48 ++++++++++++++----------------- RELEASING.md | 29 +++++++++++++------ tests/standalone-content.test.mjs | 13 ++++++--- tests/workflow-contract.test.mjs | 7 +++++ 4 files changed, 59 insertions(+), 38 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index aa97227..8d4a3f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,32 +44,28 @@ The unscoped `cometapi` package is the primary Node SDK. `@cometapi` is the standard scope for future official scoped packages; do not introduce new official packages under `@cometapi-dev`. -Before the first remote push: - -1. Apply the accepted identity to package metadata and public documents. Make - the Public Preview gate and publish validation require the same normalized - `git+https://github.com/cometapi-dev/cometapi-node.git` repository value. -2. Remove `.github/CODEOWNERS` and every check, fixture, test, or document that - requires it. Do not replace it with an individual owner. -3. Refactor `npm run check:public-preview` to collect and report all violations - in one run while returning non-zero if any violation exists. Keep checks for - canonical identity, contacts, repository metadata, public-safe language, - and standalone content. -4. Gate scheduled live smoke with a `LIVE_SMOKE_ENABLED` repository variable - and gate Release Please with `RELEASE_PLEASE_ENABLED`. Unset or non-true - values must prevent those workflows from running. Leave both disabled - throughout Private Remote Validation and leave Release Please disabled - through the initial manual alpha. -5. Run every local offline, package, fixture, compatibility, self-containment, - public-content, secret, and workflow-static-validation gate. - -When authorized, create an empty private repository without generated files, -make the sanitized repository content its first commit, push the default -branch, and wait for credential-free CI. Do not configure branch or tag rules, -Private Vulnerability Reporting, secrets, protected environments, Trusted -Publishing, live smoke, tags, releases, or registry publication during the -private stage. Record the real CI result and stop before any visibility change, -even when all checks pass. +Before requesting visibility-change authorization: + +1. Confirm the current `main` includes every approved private closeout and that + its blocking Node.js 22 and 24 CI checks pass. +2. Run the complete local offline, package, fixture, compatibility, + self-containment, public-content, secret, workflow-static-validation, and + Public Preview gates from the final private `main`. +3. Review open failing dependency-update pull requests before visibility + changes and repair, close, or explicitly defer them with a recorded reason; + do not treat their branch failures as evidence that the current `main` + failed validation. +4. Confirm the repository remains private and that public-only repository or + tag rules, Private Vulnerability Reporting, secrets, protected environments, + Trusted Publishing, live smoke, tags, releases, and registry publication + have not been configured or exercised. +5. Record the final private evidence and stop for explicit maintainer + authorization before changing repository visibility. + +Private repository creation, the sanitized first history, and the initial push +are complete historical steps and must not be repeated. Their procedure and +evidence belong in `RELEASING.md`. Keep Release Please disabled through the +initial manual alpha. ## Product Contract diff --git a/RELEASING.md b/RELEASING.md index 05678d5..113d57a 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -218,11 +218,13 @@ The repository maintains four independently auditable workflows: `release.published` event can trigger publication. - `publish.yml`: rejects mutable releases and tag commits outside `main`, packs and tests one exact artifact, requires a protected live smoke for that release - tag, publishes the same file through npm OIDC, and verifies the dist-tag, - integrity, provenance attestation, signatures, deduplication, and public - installation. A rerun resumes after an already accepted version only when its - registry integrity matches the downloaded artifact, then repeats all bounded - registry-state and signature checks. + tag, and publishes the same file through npm OIDC by default. Only + `0.1.0-alpha.1` may use the one-time protected-token bootstrap when npm does + not permit Trusted Publisher configuration before the package exists. The + workflow verifies the dist-tag, integrity, provenance attestation, signatures, + deduplication, and public installation. A rerun resumes after an already + accepted version only when its registry integrity matches the downloaded + artifact, then repeats all bounded registry-state and signature checks. Third-party actions are pinned to full commit SHAs. Workflow permissions remain read-only except where a documented job requires more; `id-token: write` belongs @@ -307,12 +309,23 @@ one-time exception: `next` dist-tag, and fails if the token is absent when publication is needed. 3. That run verifies and publishes the exact artifact with public access and provenance, then verifies registry installation. -4. A maintainer immediately configures OIDC, removes the environment variable +4. After the first publication, an authorized maintainer adds the + company-controlled owner and verifies the resulting owner list: + + ```bash + npm owner add cometapi-team cometapi + npm owner ls cometapi + ``` + + Record evidence that the output lists `cometapi-team`; Registry Alpha owner + setup is incomplete until it does. + +5. A maintainer immediately configures OIDC, removes the environment variable and secret, revokes the token, and restricts token-based publishing. -5. The project immediately prepares and publishes `0.1.0-alpha.2` through +6. The project immediately prepares and publishes `0.1.0-alpha.2` through OIDC, verifies its provenance and public installation, and confirms that `next` resolves to `0.1.0-alpha.2`. -6. The release record documents the exception and both public-install evidence +7. The release record documents the exception and both public-install evidence layers. This exception must never become a reusable source-controlled publishing path. diff --git a/tests/standalone-content.test.mjs b/tests/standalone-content.test.mjs index df958a5..9f157a1 100644 --- a/tests/standalone-content.test.mjs +++ b/tests/standalone-content.test.mjs @@ -73,18 +73,23 @@ describe("standalone content", () => { }); }); - it("reports private artifacts and sibling workspaces", () => { + it("reports private artifacts, reference directories, and sibling workspaces", () => { withTemporaryDirectory((root) => { const privateArtifact = ["SDK", "PRD.md"].join("_"); + const privateReference = ["references", "private.md"].join("/"); const siblingWorkspace = `${["cometapi", "python"].join("-")}/README.md`; writeFileSync( join(root, "notes.md"), - `See ${privateArtifact} and ${siblingWorkspace}.\n`, + `See ${privateArtifact}, ${privateReference}, and ${siblingWorkspace}.\n`, ); const violations = collectStandaloneContentViolations(root); - expect(violations).toHaveLength(2); - expect(violations.join("\n")).toMatch(/private material/); + expect(violations).toHaveLength(3); + expect( + violations.filter((violation) => + violation.includes("private material"), + ), + ).toHaveLength(2); expect(violations.join("\n")).toMatch(/sibling repository/); }); }); diff --git a/tests/workflow-contract.test.mjs b/tests/workflow-contract.test.mjs index 24d9666..f6cbe1f 100644 --- a/tests/workflow-contract.test.mjs +++ b/tests/workflow-contract.test.mjs @@ -89,6 +89,13 @@ describe("GitHub Actions workflow contract", () => { }); it("matches the required environment reviewer configuration", () => { + const liveSmokeWorkflow = workflow("live-smoke.yml"); + const liveSmoke = job(liveSmokeWorkflow, "smoke").replace( + /\n\s*#\s*/g, + " ", + ); + expect(liveSmoke).toContain("without required reviewers"); + const publishWorkflow = workflow("publish.yml"); expect(job(publishWorkflow, "live-smoke")).toContain( "without required reviewers",