Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 22 additions & 26 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 21 additions & 8 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
13 changes: 9 additions & 4 deletions tests/standalone-content.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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/);
});
});
Expand Down
7 changes: 7 additions & 0 deletions tests/workflow-contract.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down