diff --git a/docs/OPERABILITY.md b/docs/OPERABILITY.md index e96d053c..23a22c6e 100644 --- a/docs/OPERABILITY.md +++ b/docs/OPERABILITY.md @@ -60,7 +60,7 @@ Release publication occurs only from an exact integrated protected head. The rel Before publication: 1. fetch the current protected `main` ref and require the release tag event commit SHA to equal that exact integration tip, not merely be an ancestor of it; -2. build exactly three regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, and `SHA256SUMS`; +2. build exactly four regular top-level release files: exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`; 3. reject missing, duplicate, non-regular, stale, or unexpected local entries and verify the local digests; 4. after upload, query the authenticated paginated GitHub Releases API and require the resumed remote draft asset-name set to equal the local release directory exactly; 5. require every remote asset state to be uploaded and every GitHub-reported `sha256:` digest to equal the exact transferred local file digest; diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index 34e903fc..d9cde200 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -56,7 +56,7 @@ At minimum, maintain regressions for: - autosave stale validators, conflict/failure recovery, ambiguous transport outcomes, duplicate/no-op lifecycle transitions, callback exceptions, queue bounds, flush/close behavior, and durable-validator coherence; - selection/revision races and document movement during asynchronous hashing; - Office formula prefixes, invalid XML characters, malicious strings, path/publication races, invalid worksheet names, invalid freeze panes, cyclic input, pathological nesting, excessive container size, and partial write failure; -- package/release stale draft assets, unexpected or non-regular local entries, exact three-file inventory violations, incomplete remote uploads, GitHub-vs-local digest mismatch, stale exact-head evidence, mutable provenance inputs, and isolated packed-consumer behavior. +- package/release stale draft assets, unexpected or non-regular local entries, exact four-file inventory violations, incomplete remote uploads, GitHub-vs-local digest mismatch, stale exact-head evidence, mutable provenance inputs, and isolated packed-consumer behavior. ## Concurrency and failure testing @@ -68,7 +68,7 @@ Host persistence transactions, tenant isolation, distributed collaboration autho A release candidate requires the exact integrated protected head to satisfy applicable CI, security, JavaScript/TypeScript 100% statement/branch/function/line coverage, Office coverage.py 100% report plus public-docstring completeness, package-consumer, accessibility, browser differential, Office artifact, SBOM/provenance, reproducibility, unresolved-thread, actually required independent-review, and release-workflow gates. Queued, skipped-required, cancelled, absent, stale-head, predecessor-head, status-only, or synthetic-merge evidence is not accepted as success. -The release workflow must also satisfy the normative `docs/CONTRACTS.md` draft inventory contract: exactly one npm tarball, exactly one Office wheel, and `SHA256SUMS`; no other top-level entry; remote uploaded asset names exactly equal local names; and every GitHub-reported `sha256:` digest equals the exact transferred local file digest. Missing, stale, unexpected, non-regular, incomplete, or digest-mismatched assets are failures, not cleanup opportunities. +The release workflow must also satisfy the normative `docs/CONTRACTS.md` draft inventory contract: exactly one npm tarball, exactly one Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`; no other top-level entry; remote uploaded asset names exactly equal local names; and every GitHub-reported `sha256:` digest equals the exact transferred local file digest. Missing, stale, unexpected, non-regular, incomplete, or digest-mismatched assets are failures, not cleanup opportunities. The 0.6.0 rich-clipboard release line specifically requires the protected dependency-locked **Playwright 1.62.0** Chromium, Firefox, and WebKit differential gate on the exact integrated protected release candidate before publication. Deterministic jsdom coverage remains useful but is not a substitute for browser-engine acceptance. Tagged release evidence must be generated anew from the release candidate and must verify the exact packed npm artifact, not merely reuse a previously green feature-branch run. diff --git a/src/releaseCanonicalArtifactInventory.test.ts b/src/releaseCanonicalArtifactInventory.test.ts new file mode 100644 index 00000000..90bc21dd --- /dev/null +++ b/src/releaseCanonicalArtifactInventory.test.ts @@ -0,0 +1,40 @@ +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +import { describe, expect, it } from 'vitest'; + +const repositoryFile = (path: string): string => + readFileSync(resolve(process.cwd(), path), 'utf8'); + +describe('canonical release artifact inventory', () => { + it('keeps protected release documents aligned with the four-file SBOM boundary', () => { + const contracts = repositoryFile('docs/CONTRACTS.md'); + const operability = repositoryFile('docs/OPERABILITY.md'); + const releaseSecurity = repositoryFile('docs/release-security.md'); + const testStrategy = repositoryFile('docs/TEST_STRATEGY.md'); + + expect(releaseSecurity).toContain( + 'Each successful GitHub release contains exactly four files', + ); + expect(releaseSecurity).toContain('`inkspan.spdx.json`'); + + expect(contracts).toContain('exactly four regular top-level files'); + expect(contracts).toContain('`inkspan.spdx.json`'); + expect(contracts).toMatch(/release evidence \| exact four-file draft inventory/u); + + expect(testStrategy).toContain('exact four-file inventory violations'); + expect(testStrategy).toContain( + 'exactly one npm tarball, exactly one Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`', + ); + + expect(operability).toContain('build exactly four regular top-level release files'); + expect(operability).toContain( + 'exactly one npm tarball, exactly one Inkspan Office wheel, `inkspan.spdx.json`, and `SHA256SUMS`', + ); + + for (const document of [contracts, testStrategy, operability]) { + expect(document).not.toContain('exactly three regular top-level files'); + expect(document).not.toContain('exact three-file draft inventory'); + } + }); +});