Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6fbab22
docs: add delegated release service implementation plan
ascorbic Jul 10, 2026
1f0d5ff
style: format
emdashbot[bot] Jul 10, 2026
e396d03
ci: update query-count snapshots
emdashbot[bot] Jul 10, 2026
5554669
Merge branch 'main' into feat/delegated-release-service
ascorbic Jul 10, 2026
c44fbdb
Merge branch 'main' into feat/delegated-release-service
ascorbic Jul 10, 2026
a5e8e0b
docs: make gate zero ratification-only (#1915)
ascorbic Jul 10, 2026
2e778e4
feat(registry): add delegated release contracts (#1918)
ascorbic Jul 10, 2026
3de643a
fix(plugin-cli): preserve profile extensions on publish (#1920)
ascorbic Jul 10, 2026
e819a5f
feat(plugin-cli): add profile policy command (#1925)
ascorbic Jul 10, 2026
9c4ce3c
feat(registry): add verification primitives (#1929)
ascorbic Jul 10, 2026
c76e7fb
feat(registry): validate canonical plugin bundles (#1932)
ascorbic Jul 10, 2026
5c8f2ee
feat(plugin-types): add declared access escalation (#1937)
ascorbic Jul 11, 2026
2ae4c5d
docs: record Sigstore workerd spike (#1943)
ascorbic Jul 11, 2026
982ccea
feat(registry): verify Sigstore provenance (#1951)
ascorbic Jul 11, 2026
b40f0d6
docs: rebaseline delegated release plan
ascorbic Jul 11, 2026
e8ffe1d
docs: sequence workload verification after service scaffold
ascorbic Jul 11, 2026
8b3e5ea
feat(registry): verify authoritative release records (#1969)
ascorbic Jul 12, 2026
5b8ae32
feat(auth): add required passkey verification (#1970)
ascorbic Jul 12, 2026
e9f6c37
feat(release-service): scaffold Worker foundation (#1971)
ascorbic Jul 12, 2026
5473b88
Merge branch 'main' into feat/delegated-release-service
ascorbic Jul 12, 2026
26bcbc6
ci: update query-count snapshots
emdashbot[bot] Jul 12, 2026
7947be6
fix: restore D1 query-count collection (#1975)
ascorbic Jul 12, 2026
241659c
feat(release-service): verify GitHub Actions workloads (#1974)
ascorbic Jul 12, 2026
a79133c
docs: record confidential OAuth custody validation
ascorbic Jul 12, 2026
5b0d760
feat(release-service): add envelope encryption (#1990)
ascorbic Jul 12, 2026
0954341
docs: defer deployed PDS validation
ascorbic Jul 12, 2026
7549878
feat(registry): add create-only delegated publishing (#1993)
ascorbic Jul 12, 2026
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
5 changes: 5 additions & 0 deletions .changeset/bright-otters-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/registry-lexicons": minor
---

Adds experimental package profile policy and release provenance lexicon contracts.
5 changes: 5 additions & 0 deletions .changeset/calm-access-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/plugin-types": minor
---

Adds canonical declared-access comparison, structured escalation diffs, and stable digest input generation.
5 changes: 5 additions & 0 deletions .changeset/canonical-bundle-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/registry-verification": minor
---

Adds canonical, runtime-neutral validation for plugin bundle archives and exports their security limits.
5 changes: 5 additions & 0 deletions .changeset/cli-canonical-bundle-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/plugin-cli": patch
---

Rejects unsafe or malformed plugin bundles before publishing with consistent archive and manifest validation.
5 changes: 5 additions & 0 deletions .changeset/core-canonical-bundle-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"emdash": patch
---

Rejects unsafe, mismatched, or non-canonical marketplace plugin bundles during installation, including archives with links or extended headers that older parsing may have ignored.
6 changes: 6 additions & 0 deletions .changeset/create-only-delegated-releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@emdash-cms/registry-client": minor
"@emdash-cms/registry-lexicons": minor
---

Adds the exact create-only delegated release scope and a narrow API for publishing immutable package releases.
6 changes: 6 additions & 0 deletions .changeset/direct-pds-record-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@emdash-cms/registry-client": minor
"@emdash-cms/registry-verification": minor
---

Adds authoritative direct-PDS package reads and shared signed record, policy, and provenance verification reports.
5 changes: 5 additions & 0 deletions .changeset/lucky-verifiers-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/registry-verification": minor
---

Adds shared registry checksum verification and bounded HTTPS resource fetching primitives.
5 changes: 5 additions & 0 deletions .changeset/passkey-uv-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/auth": minor
---

Adds configurable passkey user verification and typed, versioned WebAuthn challenge context while preserving preferred verification by default.
5 changes: 5 additions & 0 deletions .changeset/preserve-profile-extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/plugin-cli": patch
---

Fixes subsequent `emdash-plugin publish` commands removing existing package-profile extensions.
5 changes: 5 additions & 0 deletions .changeset/profile-policy-editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/plugin-cli": minor
---

Adds `emdash-plugin policy set` for editing an existing package's signed release policy.
5 changes: 5 additions & 0 deletions .changeset/provenance-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/registry-verification": minor
---

Adds offline GitHub Actions Sigstore SLSA v1 provenance verification for Node and Cloudflare Workers.
5 changes: 5 additions & 0 deletions .changeset/shared-plugin-manifest-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@emdash-cms/plugin-types": minor
---

Adds the authoritative plugin manifest schema and access reconciliation helpers to the shared manifest contract.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ jobs:
- run: pnpm test:unit
env:
EMDASH_TEST_PG: postgres://postgres:test@localhost:5432/emdash_test
- run: pnpm --filter @emdash-cms/release-service typecheck
- run: pnpm --filter @emdash-cms/release-service test
# Render tests use the Astro Vite plugin (vitest.repro.config.ts);
# they can't run under the plain-node config in test:unit.
- run: pnpm --filter emdash exec vitest run --config vitest.repro.config.ts
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ examples/wp-theme-unit-test/
# pattern so we can re-include the agents subdirectory.
.opencode/*
!.opencode/agents/
!.opencode/plans/
.opencode/plans/*
!.opencode/plans/delegated-release-service/
!.opencode/plans/delegated-release-service/**

# .claude is local-only EXCEPT for the symlinks pointing at AGENTS.md and skills/
.claude/*
Expand Down
1,134 changes: 1,134 additions & 0 deletions .opencode/plans/delegated-release-service/implementation-plan.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# W0.5 Sigstore verification in workerd

This is the completed W0.5 decision record. W2.5 production implementation landed in #1951.

## Proven facts

The external spike used `@sigstore/verify@4.1.0`, `@sigstore/bundle@5.0.0`, and `@sigstore/protobuf-specs@0.5.1` with workerd, compatibility date `2026-07-11`, and `nodejs_compat`. It exercised `bundleFromJSON`, `TrustedRoot.fromJSON`, `toTrustMaterial`, `toSignedEntity`, and `Verifier.verify` offline against a vendored trust root.

The fixture was the public Sigstore SLSA v1 provenance for `@sigstore/core@4.0.1`, generated by `sigstore/sigstore-js` `.github/workflows/release.yml` through `actions/attest-build-provenance`. Exact sources:

- Archive: `https://registry.npmjs.org/@sigstore/core/-/core-4.0.1.tgz`
- Attestation API: `https://registry.npmjs.org/-/npm/v1/attestations/@sigstore%2fcore@4.0.1`
- Source commit: `https://github.com/sigstore/sigstore-js/tree/d406ea60b342ca37cdeecd7afedb992cd189db92`
- Workflow: `https://github.com/sigstore/sigstore-js/blob/d406ea60b342ca37cdeecd7afedb992cd189db92/.github/workflows/release.yml`
- Archive SHA-256: `8cc190e4385ee18399950148723aecd8db6e835668c361e4b6014435ba202643`
- Archive SHA-512 and DSSE subject digest: `f6fe61463ba39f9357abca3b5c511480bc80b5daf9222b1be29cccd39bb72bad484b9ab784fde5b96027764d1190f3cb4d41684db83b55bf38510d5941e6a359`
- Bundle SHA-256: `f925318b749b898f2cdfb7bdf59542c34e970c016488ecbcfa67ec5b7ffb1452`
- `gh attestation trusted-root` output from 2026-07-11 SHA-256: `65ca537f6ed8a47fd0e560c421baa1f6c1efb8b25fc200d8c5c02c0e92eb2b9c`

With `tlogThreshold: 1`, `ctlogThreshold: 1`, `timestampThreshold: 1`, the exact certificate SAN, and issuer `https://token.actions.githubusercontent.com`, the Sigstore library verified the fixture's DSSE signature, certificate chain, Rekor SET and inclusion proof, signed checkpoint, CT evidence, and identity. The surrounding spike separately hashed the archive and matched it to the signed statement's subject digest; `Verifier.verify` does not perform that artifact binding. The timestamp threshold was satisfied by the transparency-log integrated time; this fixture contained no RFC3161 timestamp and did not exercise a TSA.

The selected packages do not verify this fixture unmodified in workerd. `@sigstore/core` omits the `node:crypto.verify` algorithm for the primary DSSE envelope signature, Rekor SET, and signed checkpoint. Node accepts that omitted argument for these P-256 keys; workerd throws. The external spike proved that explicitly supplying SHA-256 for each fixture P-256 verification makes the complete public Sigstore/Fulcio/Rekor path pass while tampered signatures, payloads, Merkle proofs, identities, issuers, and artifact digests still fail.

Node documents `crypto.verify` algorithm selection at `https://nodejs.org/api/crypto.html#cryptoverifyalgorithm-data-key-signature-callback`: `null` or `undefined` is key-type-dependent, notably for Ed25519/Ed448. Sigstore `PublicKeyDetails` separately binds supported ECDSA curves to digest algorithms. A general `algorithm ?? "sha256"` substitution is therefore incorrect.

## Identity mapping

| Field | Fixture value | Authoritative binding and required agreement |
| ---------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Repository ID | `495574555` | Fulcio OID `.15`; predicate `internalParameters.github.repository_id` agrees |
| Workflow path | `.github/workflows/release.yml` | Predicate `externalParameters.workflow.path`; certificate workflow identity supplies the authoritative full URI |
| Workflow ref | `refs/heads/main` | Predicate workflow ref; exact SAN, build-signer URI OID `.9`, and build-config URI OID `.18` agree |
| Commit SHA | `d406ea60b342ca37cdeecd7afedb992cd189db92` | Fulcio digest OIDs `.10`, `.13`, and `.19`; resolved dependency `gitCommit` agrees |
| Source ref | `refs/heads/main` | Fulcio OID `.14`; predicate workflow ref agrees |
| Certificate identity | `https://github.com/sigstore/sigstore-js/.github/workflows/release.yml@refs/heads/main` | Exact SAN; OIDs `.9` and `.18` agree |
| SLSA `builder.id` | `https://github.com/actions/runner/github-hosted` | Signed predicate runner class, not the RFC workflow identity |
| Invocation | `https://github.com/sigstore/sigstore-js/actions/runs/28204693054/attempts/1` | Fulcio OID `.21`; predicate invocation ID agrees |
| RFC `sourceRepository` | `https://github.com/sigstore/sigstore-js` | Authoritative SourceRepositoryURI OID `.12`; predicate workflow repository must agree |
| RFC `builderId` | `https://github.com/sigstore/sigstore-js/.github/workflows/release.yml@refs/heads/main` | Authoritative exact SAN/build-config URI OID `.18`; predicate repository, path, and ref must compose to the same URI |

Predicate fields are signed but workflow-controlled. Production policy must safely decode the modern DER UTF8String Fulcio extensions and require predicate agreement. RFC `builderId` is not SLSA `builder.id`.

## W2.5 resolution

- #1951 resolves the algorithm-selection gap with a narrowly scoped, lockfile-pinned `@sigstore/core@4.0.1` patch. The published package bundles the patched behavior; packed-output tests run in workerd so consumers do not depend on workspace patch application.
- Verification derives algorithms from validated key details and rejects unsupported or contradictory keys. Node and workerd exercise the same contract, including DSSE, SET, checkpoint, identity, predicate, and artifact bindings.
- The package vendors a reviewed public trust root and performs no runtime trust-API fetch. Trust-root refresh remains an explicit reviewed maintenance operation.
- `ProvenanceVerifier` implements all-or-nothing bundle checksum, trust, transparency, identity, predicate, artifact, repository, and builder agreement. Failed supplied provenance is never treated as absent.
- Support remains limited to public Sigstore/Fulcio/Rekor. GitHub-private Fulcio/TSA requires a separate real fixture and trust-domain test before support can be claimed.
Loading
Loading