Skip to content

Define attested Fastly and CLI release contracts - #1262

Open
prk-Jr wants to merge 6 commits into
mainfrom
spec/1235-release-attestation
Open

prk-Jr wants to merge 6 commits into
mainfrom
spec/1235-release-attestation

Conversation

@prk-Jr

@prk-Jr prk-Jr commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Define attested Fastly wasm and three Linux/macOS ts distributions with artifact-specific provenance/SPDX SBOMs and immutable publication, so operators can verify and submit canonical bytes.
  • Select assurance before execution: complete-byte Fastly A/B equality blocks publication; CLI comparisons are reported while every selected required profile remains mandatory. Verified-byte production deployment precedes separate upstream integration.
  • Resolve review 5484754857 with a normative contract, evidence-backed feasibility register and concrete implementation dependencies; reconcile Build tsjs bundles into a private OUT_DIR and validate the set #1214/Report deployed git version in x-ts-version #1213 rather than invent competing build mechanisms.

Changes

File Change
docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Rewrite around 29 requirements, threat model, exact evidence/policy checks, shared JS inputs, actual Fastly behavior, source/branch eligibility, test traceability, rollout and all 32 inline dispositions.
docs/superpowers/specs/schemas/release-index-v1.schema.json Add a closed Draft 2020-12 structural contract with exact artifact/profile combinations, safe names/digests and role-specific size bounds.
docs/superpowers/specs/2026-10-12-1235-release-attestation-feasibility.md Record executed full-build/runtime/tool probes, corrected overstatements, a disposition for every requirement and the implementation dependency order.
docs/superpowers/specs/2026-01-15-attestation-design.md Identify the replacement binary-attestation direction while retaining historical runtime material for #161.

The first cohort is Fastly plus three native CLI assets. Other adapters, retained-input archives, separately bootstrapped operator reconstruction and official offline deployment require independent follow-up specs and do not gate #1235 closure. The initial manual verified-byte production route permits distribution before the new Fastly-only EdgeZero prebuilt API is ready; integrated production/staging remains a separate milestone.

The feasibility audit found and corrected concrete limits: optimized CLI bytes do not retain the complete prepared JS bundles; old-macOS hosted qualification cannot be assumed; gh needs policy/REST checks beyond command success; artifact metadata does not identify a producing job/attempt; Fastly packing preserves local fixtures and accepts non-wasm; first-clone response loss can remain unresolved. Native compatibility, complete real-artifact SBOMs, actual hosted signing/publication and live Fastly submission remain explicit implementation gates. This spec-only PR does not claim a qualified release pipeline or runtime implementation.

Closes

Refs #1235. This PR satisfies its separate spec-review prerequisite once approved and merged. Implementation and remaining issue criteria stay open; Phase 2 and the separate upstream integration milestone do not become hidden closure requirements.

Test plan

  • Independent requirements/build/deployment investigation and spec review; all 32 review comments mapped to concrete changes.
  • Complete AGENTS.md Rust format, eight clippy aliases, adapter/reuse tests, parity tests, host CLI helper, native build-digest test/lint.
  • JS build, 50 test files / 1,208 tests, no type errors and JS formatting with pinned Node 24.12.0.
  • Documentation lint/format/VitePress build, repository Markdown formatting, staged-domain lint and diff checks.
  • JSON Schema meta-validation: five valid and forty invalid fixtures; requirement/review coverage, relative references and shell syntax checked.
  • Feasibility probes: full-byte matching local Fastly builds; actual Viceroy publisher response with injection; full ARM64 CLI build/outside-checkout initialization; shared JS A/B; selected native/SPDX fixture; pinned gh online/offline and negative checks; adversarial provider-free packing.

Viceroy certificate loading and native localhost/browser fixtures needed execution outside the sandbox. Those retries used the same tests without TLS weakening or source changes. Local synthetic build/tool probes establish their stated limits; they do not replace the pending hosted/other-platform/provider qualification.

Checklist

  • Changes follow AGENTS.md and remain documentation/schema only.
  • No secrets, credentials, generated executables or runtime implementation committed.
  • Required implementation validation and unresolved qualification are explicit.
  • Maintainer approval and merge precede an implementation PR, as Publish attested release binaries with build provenance and SBOMs #1235 requires.

@prk-Jr prk-Jr self-assigned this Oct 9, 2026
@prk-Jr
prk-Jr requested review from aram356 and jevansnyc October 9, 2026 07:54

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This spec answers #1235 with attested release artifacts, verified deployment and byte-for-byte reproducible builds, then defines Phase 2 contracts for Cloudflare, Spin and Axum. Its trust boundaries are careful: build provenance, release membership, publisher identity and runtime claims are kept distinct, and the no-configuration rule is stated well. The main problems are scope and fit. It makes reproducibility of every artifact an all-or-nothing release gate and ties #1235's closure to Phase 2. It designs past two in-flight PRs (#1214 and #1213) that already change the same mechanisms. It doesn't account for how releases are branched or what the gh verifier needs. Several tool facts (Fastly packing and deploy, --signer-workflow matching, the Spin ABI) also need correcting.

The architecture I recommend preserves four small ownership boundaries:

flowchart TD
    A[Controlled build and composition evidence] --> B[Signing and immutable publication]
    B --> C[Trusted Server verifier library]
    P[Trusted local policy and source approval] --> C
    C --> D[Opaque VerifiedArtifact with retained bytes]
    D --> E[EdgeZero prepared payload and resolved context]
    E --> F[Observed operation state and recovery record]
Loading

Internally, the verifier should separately establish build evidence, official publication and consumer/action authorization before constructing VerifiedArtifact. EdgeZero should preserve payload integrity and own concrete lifecycle operations. It should not implement IAB release policy.

6 of the inline comments below carry a one-click GitHub suggestion: use Commit suggestion (or Add suggestion to batch for several at once) to apply them. The rest describe the change in prose because it spans several sections or lines outside a single contiguous range.

Blocking

🔧 wrench

  • One reproducibility gate makes every artifact wait for the hardest one: see inline at line 63
  • Strict JS mode should build on #1214, not beside it: see inline at line 265
  • The verifier's gh prerequisites and trust chain aren't specified: see inline at line 357
  • Build facts should be derived where possible, follow the env naming convention, and reconcile with #1213: see inline at line 559
  • Rollout steps 2 and 3 are in an order that can't be executed: see inline at line 787
  • Phase 2 in the acceptance criteria keeps #1235 open until Spin migrates: see inline at line 835

❓ question

  • Which branch are release tags cut from?: see inline at line 320

Non-blocking

♻️ refactor

  • Put the release-index v1 schema in the spec: see inline at line 255
  • Build tsjs once per release and require identical embedded JS across artifacts: see inline at line 278
  • Cargo's own output already separates host and target units; the wrapper and Syft add a component without adding coverage: see inline at line 294
  • Drop RELEASE_SETTINGS_READ_TOKEN and check the published release instead: see inline at line 347
  • --signer-workflow is a prefix match; pin the exact certificate identity: see inline at line 380
  • The pack output doesn't match "exactly one bin/main.wasm member" (suggestion): see inline at lines 528-529
  • State what compute deploy does on the native route (suggestion): see inline at line 553

🤔 thinking

  • reusable-sandbox is runtime-gated, so it may belong in the canonical artifact: see inline at line 61
  • The A/B gate measures nondeterminism, not environment sensitivity: see inline at line 208
  • Separate assurance dimensions from release-cohort selection: see inline at line 208
  • The CLI platform baselines exclude common operator hosts: see inline at line 234
  • Define SBOM coverage before settling the recorder mechanism: see inline at line 294
  • A local reusable workflow ties the signer identity to the source commit: see inline at line 326
  • Make the evidence graph and verifier policy normative: see inline at line 357
  • The release record gives the tag object for annotated tags, not the commit: see inline at line 361
  • The publication record carries the same trust as pinning the artifact digest: see inline at line 473
  • The EdgeZero seam is new surface, not an addition to an existing typed one: see inline at line 514
  • Validate observed Fastly bindings, not only manifest declarations: see inline at line 514
  • Recovery needs retained state and explicit ownership: see inline at line 537
  • Specify Cloudflare's actual configuration handoff: see inline at line 650
  • Spin's locked SDK targets a WASI 0.3 release candidate, not plain WASIp2: see inline at line 658

🏕 camp site

  • Bound verification processes and evidence (suggestion): see inline at line 412
  • The "configuration baked into the wasm" claims go beyond CI comments (suggestion): see inline at line 788

⛏ nitpick

  • The scaffold is the repository-root file (suggestion): see inline at line 163
  • artifact-metadata: write isn't needed for file attestations (suggestion): see inline at line 335

Cross-cutting / body-level findings

  • ♻️ Add an explicit threat model. §1 lists each claim and what it doesn't establish, but there is no adversary table. Add one row per adversary (asset or mirror tampering, a malicious evidence-transfer path, a compromised dependency or build script, a rogue tag pusher, a compromised runner image, a compromised operator host, GitHub itself) with its capability, the check that defends against it, and what remains. Each check in the spec can then cite the threat it defends against, which makes it easier to see which checks earn their cost, for example the settings token at line 347 and the publication record at line 473.
  • ♻️ Write it as a contract. The spec is about 16,000 words with no BCP 14 keywords (42 lowercase "must", no MUST or SHOULD), and paragraphs such as lines 176, 202 and 208 each carry six to ten requirements without IDs. The test plan and acceptance criteria paraphrase each other without traceability. Suggest requirement IDs with BCP 14 keywords, one table mapping requirement → test → acceptance item → #1235 "Done when", and rationale moved to an appendix. Also give the "release manifest" (line 60) and "release-tools manifest" (lines 288 and 412) names and paths; "manifest" already means edgezero.toml and fastly.toml elsewhere in the spec.
  • 🌱 Cloudflare notes for the follow-up spec (§12, lines 642-654):
    • worker-build 0.8.5 downloads the wasm-bindgen CLI (0.2.126), binaryen version_130 and @esbuild/linux-x64 0.28.1 (separate from the JS lockfile's esbuild 0.27.3) with no checksum check. A network-denied recipe needs them pre-seeded with digest checks, through WASM_BINDGEN_BIN, WASM_OPT_BIN and ESBUILD_BIN or its cache layout.
    • Output-changing switches to control include CUSTOM_SHIM, RUN_TO_COMPLETION, COREDUMP/COREDUMP_FLAGS, NO_MINIFY, --no-opt and --panic-unwind. worker-build also adds an sdk workers-rs entry to the wasm producers section.
    • build.sh installs worker-build without --locked and derives its version from Cargo.lock at run time.
    • The .tar.zst canonical archive brings back the archive/member identity question that line 242 avoids for Phase 1. Publishing the members as raw assets plus an attested modules.json inventory keeps every subject a raw file.
    • The versions API silently drops unresolved inherit bindings unless bindings_inherit=strict is set, and inherit/keep_bindings resolve against the latest uploaded version, which may not be the deployed one. Line 650's "fail when unresolved" needs bindings_inherit=strict and an explicit version_id.
  • 🏕 Mark the January spec as superseded. docs/superpowers/specs/2026-01-15-attestation-design.md still says **Status:** Proposal and doesn't point here. #1235 says this spec replaces its binary-attestation sections, so a one-line "superseded in part by" banner in that file would keep readers from following it.

CI Status

  • cargo fmt: PASS (required)
  • cargo test: PASS (required)
  • format-docs: PASS (required)
  • format-typescript: PASS (required)
  • Analyze (actions): PASS
  • Analyze (javascript-typescript): PASS
  • Analyze (javascript-typescript): PASS
  • Analyze (python): PASS
  • Analyze (rust): PASS
  • browser integration tests: PASS
  • cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • cargo test (axum native): PASS
  • cargo test (cross-adapter parity): PASS
  • cargo test (ts CLI, native) (macos-latest): PASS
  • cargo test (ts CLI, native) (ubuntu-latest): PASS
  • CLAUDE.md symlink guard: PASS
  • CodeQL: PASS
  • integration tests: PASS
  • integration tests (Fastly EC lifecycle): PASS
  • prepare integration artifacts: PASS
  • vitest: PASS

Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
Comment thread docs/superpowers/specs/2026-10-09-1235-release-attestation-design.md Outdated
@prk-Jr prk-Jr changed the title Design release attestation and reproducible builds for all adapters Define attested Fastly and CLI release contracts Oct 12, 2026
@prk-Jr
prk-Jr requested a review from aram356 October 12, 2026 06:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants