@kungfu-tech/buildchain 4.0.0 → 4.0.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -5
- package/actions/promote-buildchain-ref/README.md +11 -6
- package/architecture/internal-capabilities.json +11 -2
- package/architecture/maintainability-policy.json +149 -17
- package/architecture/v4-floating-consumer-policy.json +75 -0
- package/architecture/v4-floating-consumer-policy.md +32 -0
- package/architecture/v4-runtime-ref-resume-authority.json +64 -0
- package/architecture/v4-stage-capsule-qualification.json +2 -2
- package/bin/internal/trust-release-release-handlers.mjs +5 -0
- package/contracts/fixtures/v4-floating-consumer-policy-v1/cases.json +53 -0
- package/contracts/fixtures/v4-runtime-ref-resume-authority-v1/scenario.json +15 -0
- package/contracts/v4-floating-consumer-policy-receipt-v1.schema.json +105 -0
- package/contracts/v4-runtime-ref-resume-authority-v1.schema.json +235 -0
- package/dist/site/buildchain-contract.json +101 -31
- package/dist/site/buildchain-site.json +73 -27
- package/dist/site/capability-registry.json +3 -3
- package/dist/site/controller-registry.json +62 -6
- package/dist/site/kfd-claims.json +68 -13
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +6 -6
- package/dist/site/node-api-registry.json +799 -127
- package/dist/site/page-registry.json +63 -17
- package/dist/site/public-surface-audit.json +49 -17
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +2 -0
- package/dist/site/site-manifest.json +10 -10
- package/dist/site/workflow-registry.json +46 -18
- package/docs/MAP.md +2 -0
- package/docs/dev-delivery-warrant.md +19 -1
- package/docs/lifecycle-protocol.md +41 -0
- package/docs/node-api-reference.md +207 -134
- package/docs/reusable-build-surface.md +41 -0
- package/docs/runtime-train-validation.md +10 -0
- package/docs/v4-runtime-ref-resume-authority.md +69 -0
- package/docs/versioning.md +1 -0
- package/package.json +6 -4
- package/packages/core/artifact-signing.js +61 -0
- package/packages/core/buildchain-config.js +66 -1
- package/packages/core/dev-delivery-proof.js +37 -3
- package/packages/core/dev-delivery-warrant.js +3 -3
- package/packages/core/index.js +2 -0
- package/packages/core/publication-authority.js +5 -5
- package/packages/core/release-candidate.js +79 -19
- package/packages/core/release-passport.js +239 -33
- package/packages/core/v4-floating-consumer-evidence.js +324 -0
- package/packages/core/v4-floating-consumer-policy.js +446 -0
- package/packages/core/v4-floating-consumer-release-passport.js +126 -0
- package/packages/core/v4-runtime-ref-resume-authority.js +625 -0
- package/packages/core/v4-runtime-selector-persistence.js +228 -0
- package/packages/core/workflow-yaml-contract.js +48 -0
- package/scripts/audit-publication-control-plane.mjs +31 -31
- package/scripts/check-inventory.mjs +1 -1
- package/scripts/check-v4-floating-consumer-policy-contract.mjs +198 -0
- package/scripts/check-v4-public-dogfood-contract.mjs +6 -11
- package/scripts/dev-delivery-source-proof-reuse.mjs +631 -0
- package/scripts/dev-pr-auto-merge.mjs +37 -48
- package/scripts/dev-pr-delivery-warrant.mjs +205 -2
- package/scripts/dev-pr-prequeue-guard.mjs +399 -0
- package/scripts/ensure-github-release.mjs +3 -3
- package/scripts/generate-channel-build-workflow.mjs +3 -0
- package/scripts/generate-channel-promotion-workflow.mjs +112 -12
- package/scripts/generate-release-candidate-passport.mjs +41 -33
- package/scripts/init-repo.mjs +5 -1
- package/scripts/inspect-artifact-signing-requests.mjs +6 -0
- package/scripts/npm-publish-transaction.mjs +101 -89
- package/scripts/resume-from-candidate-run.mjs +11 -14
- package/scripts/seal-artifact-signing-requests.mjs +6 -0
- package/scripts/site-capability-metadata.mjs +2 -0
- package/scripts/v4-consumer-policy.mjs +231 -0
|
@@ -102,6 +102,36 @@ The router is generated from `.build.yml`'s input/output surface. Run
|
|
|
102
102
|
`node scripts/generate-channel-build-workflow.mjs` after changing the advanced
|
|
103
103
|
build workflow; inventory and unit tests reject a stale generated router.
|
|
104
104
|
|
|
105
|
+
### v4 floating consumer admission
|
|
106
|
+
|
|
107
|
+
The v4 public surfaces add a source policy gate before dependency setup, matrix
|
|
108
|
+
planning, build, publication, or promotion work. Tracked caller YAML may use
|
|
109
|
+
only `@v4` or `@v4-alpha`, and the repository must commit both
|
|
110
|
+
`.buildchain/contract-lock.json` and `.buildchain/alpha-contract-lock.json`.
|
|
111
|
+
Source-persisted exact SHAs, exact defaults, repository/input/environment
|
|
112
|
+
indirection, nested composite indirection, a missing lock, or a stale selected
|
|
113
|
+
lock fail closed.
|
|
114
|
+
|
|
115
|
+
Admission emits a rooted receipt binding the caller source, public workflow,
|
|
116
|
+
visible selector and workflow-shell SHA, actual runtime SHA, both lock roots,
|
|
117
|
+
and policy/scanner roots. A trusted `workflow_dispatch` train or SHA remains a
|
|
118
|
+
non-persistent runtime override: the tracked floating selector and its selected
|
|
119
|
+
lock still bind the visible workflow shell. Release-candidate evidence carries
|
|
120
|
+
the receipt; promotion certifies it independently; final v4 Release Passport
|
|
121
|
+
construction requires the matching certification.
|
|
122
|
+
|
|
123
|
+
Transient train, authority, and exact-SHA selections additionally produce a
|
|
124
|
+
provider-readback-bound runtime authorization receipt. A resumed failed tail
|
|
125
|
+
uses a fresh attempt and records the original build runtime, the resume runtime,
|
|
126
|
+
the exact sealed Stage Capsules reused per platform, and the platforms rebuilt
|
|
127
|
+
in the final Release Passport. See
|
|
128
|
+
[`v4-runtime-ref-resume-authority.md`](v4-runtime-ref-resume-authority.md).
|
|
129
|
+
|
|
130
|
+
See the normative
|
|
131
|
+
[`v4 floating consumer policy`](../architecture/v4-floating-consumer-policy.md)
|
|
132
|
+
and its machine declaration for the exact acceptance boundary. This policy does
|
|
133
|
+
not change v3 behavior.
|
|
134
|
+
|
|
105
135
|
## Advanced Workflow
|
|
106
136
|
|
|
107
137
|
Consumers that need direct workflow-shell or runtime control call the advanced
|
|
@@ -699,6 +729,17 @@ For a declared macOS `archive`, the authority safely extracts the sealed
|
|
|
699
729
|
container, signs and verifies every Mach-O payload, signs Mach-O payloads inside
|
|
700
730
|
embedded Python wheels, rebuilds each affected wheel's PEP 427 `RECORD`, and
|
|
701
731
|
recreates the original zip or tar.gz before returning the exact final bytes.
|
|
732
|
+
Archives whose executable hosts a JIT runtime can additionally request the
|
|
733
|
+
Buildchain-owned `entitlements_profile = "jit-executable-v1"` and exact paths,
|
|
734
|
+
for example `entitlements_paths = ["product/runtime/python/bin/python3"]`.
|
|
735
|
+
Paths are relative to the extracted archive root. The authority
|
|
736
|
+
then attaches only `com.apple.security.cs.allow-jit` to the exact executable
|
|
737
|
+
Mach-O files sealed in `entitlements_paths`, leaves every other executable and
|
|
738
|
+
library without exception entitlements, and records the profile, paths, and
|
|
739
|
+
entitled executable count in provider evidence. Consumer-provided entitlement
|
|
740
|
+
files and wildcard target paths are unsupported. The profile is valid only for
|
|
741
|
+
Apple `archive` requests and fails closed on an unsafe, missing,
|
|
742
|
+
non-executable, duplicate, or unsealed target path.
|
|
702
743
|
Windows `pe` and `binary` artifacts
|
|
703
744
|
resolve to timestamped native `windows-authenticode`; Windows PE never falls
|
|
704
745
|
back to a detached signature. Linux and other non-native binary files,
|
|
@@ -176,3 +176,13 @@ actions, configuration parsing, and lifecycle behavior. It cannot validate
|
|
|
176
176
|
changes that require the outer reusable workflow YAML itself to change, such as
|
|
177
177
|
new jobs, permissions, workflow outputs, or matrix topology. Those changes need
|
|
178
178
|
a canary workflow path or a temporary explicit workflow ref.
|
|
179
|
+
|
|
180
|
+
## v4 persisted-selector boundary
|
|
181
|
+
|
|
182
|
+
For v4 consumers, never commit a train or exact SHA in a `uses` node. Keep the
|
|
183
|
+
caller on `@v4` or `@v4-alpha`, retain both stable and alpha contract locks, and
|
|
184
|
+
pass a temporary train/SHA only through the trusted `workflow_dispatch`
|
|
185
|
+
`buildchain-ref` input. Consumer admission binds the selected lock to the exact
|
|
186
|
+
workflow-shell commit while recording the separately resolved runtime SHA.
|
|
187
|
+
Therefore a train can exercise candidate runtime code without weakening the
|
|
188
|
+
durable floating-selector policy or masquerading as a channel promotion.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: draft
|
|
3
|
+
period: ongoing
|
|
4
|
+
theme: buildchain-v4-runtime-ref-resume-authority
|
|
5
|
+
doc_type: contract-guide
|
|
6
|
+
source_level: local-files
|
|
7
|
+
confidence: high
|
|
8
|
+
sensitivity: public
|
|
9
|
+
evidence_grade: A
|
|
10
|
+
review_state: unreviewed
|
|
11
|
+
last_reviewed: 2026-08-15
|
|
12
|
+
ai_provenance:
|
|
13
|
+
model_family: GPT-5
|
|
14
|
+
product: Codex
|
|
15
|
+
generated_at: 2026-08-14
|
|
16
|
+
invisible_context: not asserted
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Buildchain v4 transient runtime and resume authority
|
|
20
|
+
|
|
21
|
+
Buildchain v4 consumers keep `v4` or `v4-alpha` in tracked workflow source.
|
|
22
|
+
A train, authority ref, or exact SHA is transient run data, never a new
|
|
23
|
+
committed default. The public promotion router accepts that escape only from a
|
|
24
|
+
trusted `workflow_dispatch` actor with write, maintain, or admin permission.
|
|
25
|
+
Before heavy promotion work, it binds an exact source tree, operator reason,
|
|
26
|
+
dual consumer contract-lock roots, the floating-consumer policy receipt, a
|
|
27
|
+
clean persistence scan, and GitHub provider readbacks proving that the selected
|
|
28
|
+
runtime is reachable from an approved v4 ref.
|
|
29
|
+
|
|
30
|
+
The persistence scan covers tracked workflow, composite-action, JSON, TOML, and
|
|
31
|
+
YAML surfaces. Exact SHA, train/authority defaults, and runtime selectors hidden
|
|
32
|
+
through repository variables, secrets, or environment indirection reject the
|
|
33
|
+
run. OIDC, IAM, and other external authority references are inventoried as
|
|
34
|
+
metadata only; credential values are never read or written to evidence.
|
|
35
|
+
|
|
36
|
+
## Resume after a floating ref moves
|
|
37
|
+
|
|
38
|
+
A late platform failure is resumed as a new governed attempt. It is not a
|
|
39
|
+
GitHub failed-job rerun. The lineage keeps runtime A (the runtime that built and
|
|
40
|
+
sealed each reusable Stage Capsule) separate from runtime B (the authorized
|
|
41
|
+
runtime executing the new attempt). A Capsule is reusable only when its source
|
|
42
|
+
SHA, source tree, platform, policy root, build runtime, identity root, Capsule
|
|
43
|
+
root, and artifact digest still match. Valid unaffected platforms are restored;
|
|
44
|
+
only missing platforms rebuild. Stale, ambiguous, unsealed, cross-source, or
|
|
45
|
+
cross-policy evidence fails closed.
|
|
46
|
+
|
|
47
|
+
This deliberately does not weaken the existing Stage Capsule resume planner's
|
|
48
|
+
`runtime-changed` invalidation. That planner decides whether a stage may be
|
|
49
|
+
reused under one expected build identity. This contract instead proves that an
|
|
50
|
+
already sealed output built under runtime A remains the exact product input
|
|
51
|
+
while a distinct orchestration attempt runs under runtime B. Runtime B never
|
|
52
|
+
rewrites the Capsule's build identity.
|
|
53
|
+
|
|
54
|
+
Final Release Passport evidence embeds the complete authorization receipt and
|
|
55
|
+
the A+B resume lineage under `v4RuntimeResume`. The section binds the new
|
|
56
|
+
attempt, floating-ref movement, reused and rebuilt platform partition,
|
|
57
|
+
consumer-policy receipt, resume plan, and final public readback roots. Tampering
|
|
58
|
+
with either document or crossing authorization/lineage roots rejects Passport
|
|
59
|
+
construction and verification.
|
|
60
|
+
|
|
61
|
+
Normative files:
|
|
62
|
+
|
|
63
|
+
- `architecture/v4-runtime-ref-resume-authority.json`
|
|
64
|
+
- `contracts/v4-runtime-ref-resume-authority-v1.schema.json`
|
|
65
|
+
- `packages/core/v4-runtime-ref-resume-authority.js`
|
|
66
|
+
- `scripts/authorize-promotion-runtime-override.cjs`
|
|
67
|
+
|
|
68
|
+
This contract changes no v3 behavior, grants no provider mutation authority,
|
|
69
|
+
and stores no credential material.
|
package/docs/versioning.md
CHANGED
|
@@ -79,6 +79,7 @@ repository changes are patch".
|
|
|
79
79
|
|
|
80
80
|
| Date | Action | Line | Faces | Class | Rationale | PR |
|
|
81
81
|
| ---------- | ------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
|
|
82
|
+
| 2026-08-14 | extend-minor | `v4.0` | source-qualification-proof-v2, source-proof-reuse-decision, reusable-check-workflow | additive | Forward-port opt-in exact accepted source-proof reuse for merge groups, binding source, base, patch, runtime, plan, policy, closure, dependency, required-context, producer receipt, and caller run. Any missing or changed predicate fails closed to the existing full source lifecycle, which remains the default. | |
|
|
82
83
|
| 2026-08-11 | extend-minor | `v4.0` | release-blocker-repair-contract, release-blocker-priority-claim, release-train-node-export, dev-delivery-warrant-node-export | additive | Forward-port rooted successor candidate generations, exact semantic patch identity across cut and Dev landings, publication blocking through conflict or mismatch, and the narrow non-preemptive Warrant blocker lane already protected and self-dogfood-proven on v3. | |
|
|
83
84
|
| 2026-08-10 | extend-minor | `v4.0` | release-cut-contract, release-train-state-machine, release-train-node-export | additive | Forward-port the provider-neutral rooted Release Cut and idempotent Release Train state contract already proven on v3; candidate, tree, Alpha base, runtime, generation, and authority stay frozen while later Dev movement remains an observation rather than implicit supersession. | |
|
|
84
85
|
| 2026-08-08 | extend-minor | `v4.0` | dev-delivery-warrant-read-candidate, rust-state-projection, dev-delivery-cli | additive | Add an opt-in, qualification-bound read projection behind `observe --read-mode v4`; v3 remains the sole writer and default reader, mutation commands ignore the switch, failures stop, and rollback is the explicit caller change back to v3. | |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kungfu-tech/buildchain",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.1-alpha.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Buildchain Release Passport, release governance, CLI toolkit, and site facts.",
|
|
6
6
|
"repository": "https://github.com/kungfu-systems/buildchain",
|
|
@@ -40,6 +40,8 @@
|
|
|
40
40
|
"./release-line-bootstrap": "./packages/core/release-line-bootstrap.js",
|
|
41
41
|
"./readme-badges": "./packages/core/readme-badges.js",
|
|
42
42
|
"./public-surface-audit": "./packages/core/public-surface-audit.js",
|
|
43
|
+
"./v4-floating-consumer-policy": "./packages/core/v4-floating-consumer-policy.js",
|
|
44
|
+
"./v4-runtime-ref-resume-authority": "./packages/core/v4-runtime-ref-resume-authority.js",
|
|
43
45
|
"./logging": "./packages/core/logging.js",
|
|
44
46
|
"./portable-dev-cache": "./packages/core/portable-dev-cache.js",
|
|
45
47
|
"./publication-artifact": "./packages/core/publication-artifact.js",
|
|
@@ -123,10 +125,10 @@
|
|
|
123
125
|
"packageManager": "pnpm@11.7.0",
|
|
124
126
|
"scripts": {
|
|
125
127
|
"operator:windows-jit": "bash scripts/aws-windows-jit-operator.sh",
|
|
126
|
-
"check": "pnpm run check:static && node scripts/check-v4-public-dogfood-contract.mjs && pnpm run check:v4-bridge && pnpm run check:v4-contracts && node scripts/check-maintainability.mjs && node scripts/check-internal-architecture.mjs && node scripts/check-inventory.mjs && node scripts/check-core-mechanism-inventory.mjs && node scripts/check-release-tail-contract.mjs && node scripts/v4-architecture.mjs validate && node scripts/v4-warrant-shadow-plan.mjs validate && pnpm run check:site && pnpm run check:workflows && pnpm run test:unit && pnpm run check:golden-path && node scripts/check-action-bundles.mjs",
|
|
127
|
-
"check:static": "node scripts/check-javascript-syntax.mjs && prettier --check architecture/*.json contracts/release-tail-provider-bindings-v1.schema.json contracts/v4-canonical-contracts-v1.schema.json contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json contracts/v4-delivery-warrant-trace-v1.schema.json contracts/v4-host-contract-v1.schema.json contracts/v4-provider-operation-journal-v1.schema.json contracts/v4-release-activation-shadow-v1.schema.json contracts/v4-stable-publication-fence-v1.schema.json contracts/v4-partial-mutation-recovery-v1.schema.json contracts/v4-stage-capsule-v1.schema.json contracts/v4-stage-capsule-store-v1.schema.json contracts/v4-stage-capsule-resume-v1.schema.json contracts/release-tail-capabilities-v1.schema.json contracts/fixtures/release-tail-capabilities-v1/*.json contracts/fixtures/v4-delivery-warrant-trace-v1/*.json contracts/fixtures/v4-provider-operation-journal-v1/*.json contracts/fixtures/v4-provider-readback-idempotency-v1/*.json contracts/fixtures/v4-release-activation-shadow-v1/*.json contracts/fixtures/v4-stable-publication-fence-v1/*.json contracts/fixtures/v4-partial-mutation-recovery-v1/*.json contracts/fixtures/v4-stage-capsule-v1/*.json contracts/fixtures/v4-stage-capsule-store-v1/*.json contracts/fixtures/v4-stage-capsule-resume-v1/*.json bin/internal/command-registry.mjs packages/core/v4-canonical-contracts.js packages/core/v4-provider-operation-journal.js packages/core/v4-provider-readback-idempotency.js packages/core/v4-release-activation-shadow.js packages/core/v4-stable-publication-fence.js packages/core/v4-partial-mutation-recovery-qualification.js packages/core/v4-stage-capsule.js packages/core/v4-stage-capsule-store.js packages/core/v4-stage-capsule-local-store.js packages/core/v4-platform-stage-checkpoints.js packages/core/v4-stage-capsule-resume-planner.js packages/core/v4-stage-capsule-qualification.js packages/core/v4-stage-capsule-qualification-campaign.js packages/core/v4-delivery-warrant-fixture-runner.js packages/core/v4-delivery-warrant-read-candidate.js packages/core/v4-delivery-warrant-semantic-diff-gate.js packages/core/v4-delivery-warrant-shadow-adapter.js scripts/authorize-promotion-runtime-override.cjs scripts/check-core-mechanism-inventory.mjs scripts/check-release-tail-contract.mjs scripts/check-javascript-syntax.mjs scripts/check-maintainability.mjs scripts/check-v4-public-dogfood-contract.mjs scripts/maintainability-metrics.mjs scripts/public-reference.mjs scripts/site-reference-registry.mjs scripts/generate-public-reference.mjs scripts/v4-architecture.mjs scripts/v4-bridge-bootstrap.mjs scripts/v4-bridge-evidence.mjs scripts/v4-host-adapter.mjs scripts/v4-platform-stage-checkpoint-rehearsal.mjs scripts/v4-stage-capsule-resume-rehearsal.mjs scripts/v4-stage-capsule-qualification.mjs scripts/v4-warrant-shadow-plan.mjs scripts/verify-golden-path.mjs tests/authorize-promotion-runtime-override.test.mjs tests/command-registry.test.mjs tests/core-mechanism-inventory.test.mjs tests/release-tail-contract.test.mjs tests/maintainability.test.mjs tests/promotion-responsibilities.test.mjs tests/public-reference.test.mjs tests/v4-architecture.test.mjs tests/v4-bridge.test.mjs tests/v4-canonical-contracts.test.mjs tests/v4-delivery-warrant-fixture-runner.test.mjs tests/v4-delivery-warrant-read-candidate.test.mjs tests/v4-platform-stage-checkpoints.test.mjs tests/v4-provider-operation-journal.test.mjs tests/v4-provider-readback-idempotency.test.mjs tests/v4-public-dogfood-contract.test.mjs tests/v4-release-activation-shadow.test.mjs tests/v4-stable-publication-fence.test.mjs tests/v4-partial-mutation-recovery-qualification.test.mjs tests/v4-stage-capsule.test.mjs tests/v4-stage-capsule-store.test.mjs tests/v4-stage-capsule-resume-planner.test.mjs tests/v4-stage-capsule-qualification.test.mjs tests/v4-warrant-shadow-plan.test.mjs",
|
|
128
|
+
"check": "pnpm run check:static && node scripts/check-v4-public-dogfood-contract.mjs && node scripts/check-v4-floating-consumer-policy-contract.mjs && pnpm run check:v4-bridge && pnpm run check:v4-contracts && node scripts/check-maintainability.mjs && node scripts/check-internal-architecture.mjs && node scripts/check-inventory.mjs && node scripts/check-core-mechanism-inventory.mjs && node scripts/check-release-tail-contract.mjs && node scripts/v4-architecture.mjs validate && node scripts/v4-warrant-shadow-plan.mjs validate && pnpm run check:site && pnpm run check:workflows && pnpm run test:unit && pnpm run check:golden-path && node scripts/check-action-bundles.mjs",
|
|
129
|
+
"check:static": "node scripts/check-javascript-syntax.mjs && prettier --check architecture/*.json contracts/release-tail-provider-bindings-v1.schema.json contracts/v4-canonical-contracts-v1.schema.json contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json contracts/v4-delivery-warrant-trace-v1.schema.json contracts/v4-floating-consumer-policy-receipt-v1.schema.json contracts/v4-runtime-ref-resume-authority-v1.schema.json contracts/v4-host-contract-v1.schema.json contracts/v4-provider-operation-journal-v1.schema.json contracts/v4-release-activation-shadow-v1.schema.json contracts/v4-stable-publication-fence-v1.schema.json contracts/v4-partial-mutation-recovery-v1.schema.json contracts/v4-stage-capsule-v1.schema.json contracts/v4-stage-capsule-store-v1.schema.json contracts/v4-stage-capsule-resume-v1.schema.json contracts/release-tail-capabilities-v1.schema.json contracts/fixtures/release-tail-capabilities-v1/*.json contracts/fixtures/v4-delivery-warrant-trace-v1/*.json contracts/fixtures/v4-floating-consumer-policy-v1/*.json contracts/fixtures/v4-runtime-ref-resume-authority-v1/*.json contracts/fixtures/v4-provider-operation-journal-v1/*.json contracts/fixtures/v4-provider-readback-idempotency-v1/*.json contracts/fixtures/v4-release-activation-shadow-v1/*.json contracts/fixtures/v4-stable-publication-fence-v1/*.json contracts/fixtures/v4-partial-mutation-recovery-v1/*.json contracts/fixtures/v4-stage-capsule-v1/*.json contracts/fixtures/v4-stage-capsule-store-v1/*.json contracts/fixtures/v4-stage-capsule-resume-v1/*.json bin/internal/command-registry.mjs packages/core/v4-canonical-contracts.js packages/core/v4-floating-consumer-evidence.js packages/core/v4-floating-consumer-policy.js packages/core/v4-floating-consumer-release-passport.js packages/core/v4-runtime-ref-resume-authority.js packages/core/v4-runtime-selector-persistence.js packages/core/v4-provider-operation-journal.js packages/core/v4-provider-readback-idempotency.js packages/core/v4-release-activation-shadow.js packages/core/v4-stable-publication-fence.js packages/core/v4-partial-mutation-recovery-qualification.js packages/core/v4-stage-capsule.js packages/core/v4-stage-capsule-store.js packages/core/v4-stage-capsule-local-store.js packages/core/v4-platform-stage-checkpoints.js packages/core/v4-stage-capsule-resume-planner.js packages/core/v4-stage-capsule-qualification.js packages/core/v4-stage-capsule-qualification-campaign.js packages/core/v4-delivery-warrant-fixture-runner.js packages/core/v4-delivery-warrant-read-candidate.js packages/core/v4-delivery-warrant-semantic-diff-gate.js packages/core/v4-delivery-warrant-shadow-adapter.js scripts/authorize-promotion-runtime-override.cjs scripts/check-core-mechanism-inventory.mjs scripts/check-release-tail-contract.mjs scripts/check-javascript-syntax.mjs scripts/check-maintainability.mjs scripts/dev-pr-prequeue-guard.mjs scripts/check-v4-public-dogfood-contract.mjs scripts/maintainability-metrics.mjs scripts/public-reference.mjs scripts/site-reference-registry.mjs scripts/generate-public-reference.mjs scripts/v4-architecture.mjs scripts/v4-bridge-bootstrap.mjs scripts/v4-bridge-evidence.mjs scripts/v4-consumer-policy.mjs scripts/v4-host-adapter.mjs scripts/v4-platform-stage-checkpoint-rehearsal.mjs scripts/v4-stage-capsule-resume-rehearsal.mjs scripts/v4-stage-capsule-qualification.mjs scripts/v4-warrant-shadow-plan.mjs scripts/verify-golden-path.mjs tests/authorize-promotion-runtime-override.test.mjs tests/command-registry.test.mjs tests/core-mechanism-inventory.test.mjs tests/release-tail-contract.test.mjs tests/maintainability.test.mjs tests/promotion-responsibilities.test.mjs tests/public-reference.test.mjs tests/v4-architecture.test.mjs tests/v4-bridge.test.mjs tests/v4-canonical-contracts.test.mjs tests/v4-delivery-warrant-fixture-runner.test.mjs tests/v4-delivery-warrant-read-candidate.test.mjs tests/v4-floating-consumer-policy.test.mjs tests/v4-runtime-ref-resume-authority.test.mjs tests/v4-platform-stage-checkpoints.test.mjs tests/v4-provider-operation-journal.test.mjs tests/v4-provider-readback-idempotency.test.mjs tests/v4-public-dogfood-contract.test.mjs tests/v4-release-activation-shadow.test.mjs tests/v4-stable-publication-fence.test.mjs tests/v4-partial-mutation-recovery-qualification.test.mjs tests/v4-stage-capsule.test.mjs tests/v4-stage-capsule-store.test.mjs tests/v4-stage-capsule-resume-planner.test.mjs tests/v4-stage-capsule-qualification.test.mjs tests/v4-warrant-shadow-plan.test.mjs",
|
|
128
130
|
"check:v4-bridge": "cargo fmt --manifest-path crates/buildchain-v4-bridge/Cargo.toml -- --check && cargo clippy --locked --manifest-path crates/buildchain-v4-bridge/Cargo.toml -- -D warnings && cargo test --locked --manifest-path crates/buildchain-v4-bridge/Cargo.toml",
|
|
129
|
-
"check:v4-contracts": "cargo fmt --manifest-path crates/buildchain-v4-contracts/Cargo.toml -- --check && cargo clippy --locked --manifest-path crates/buildchain-v4-contracts/Cargo.toml -- -D warnings && cargo test --locked --manifest-path crates/buildchain-v4-contracts/Cargo.toml && node --test tests/v4-canonical-contracts.test.mjs tests/v4-delivery-warrant-fixture-runner.test.mjs tests/v4-delivery-warrant-read-candidate.test.mjs tests/v4-platform-stage-checkpoints.test.mjs tests/v4-provider-operation-journal.test.mjs tests/v4-provider-readback-idempotency.test.mjs tests/v4-public-dogfood-contract.test.mjs tests/v4-release-activation-shadow.test.mjs tests/v4-stable-publication-fence.test.mjs tests/v4-partial-mutation-recovery-qualification.test.mjs tests/v4-stage-capsule.test.mjs tests/v4-stage-capsule-store.test.mjs tests/v4-stage-capsule-resume-planner.test.mjs tests/v4-stage-capsule-qualification.test.mjs",
|
|
131
|
+
"check:v4-contracts": "cargo fmt --manifest-path crates/buildchain-v4-contracts/Cargo.toml -- --check && cargo clippy --locked --manifest-path crates/buildchain-v4-contracts/Cargo.toml -- -D warnings && cargo test --locked --manifest-path crates/buildchain-v4-contracts/Cargo.toml && node --test tests/v4-canonical-contracts.test.mjs tests/v4-delivery-warrant-fixture-runner.test.mjs tests/v4-delivery-warrant-read-candidate.test.mjs tests/v4-floating-consumer-policy-contract.test.mjs tests/v4-floating-consumer-policy.test.mjs tests/v4-runtime-ref-resume-authority.test.mjs tests/v4-platform-stage-checkpoints.test.mjs tests/v4-provider-operation-journal.test.mjs tests/v4-provider-readback-idempotency.test.mjs tests/v4-public-dogfood-contract.test.mjs tests/v4-release-activation-shadow.test.mjs tests/v4-stable-publication-fence.test.mjs tests/v4-partial-mutation-recovery-qualification.test.mjs tests/v4-stage-capsule.test.mjs tests/v4-stage-capsule-store.test.mjs tests/v4-stage-capsule-resume-planner.test.mjs tests/v4-stage-capsule-qualification.test.mjs",
|
|
130
132
|
"check:workflows": "bash scripts/check-workflows.sh",
|
|
131
133
|
"generate:reference": "node scripts/generate-public-reference.mjs",
|
|
132
134
|
"check:reference": "node scripts/generate-public-reference.mjs --check",
|
|
@@ -9,6 +9,7 @@ export const ARTIFACT_SIGNING_AUTHORITY_CONTRACT =
|
|
|
9
9
|
|
|
10
10
|
const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/u;
|
|
11
11
|
const SOURCE_SHA_PATTERN = /^[0-9a-f]{40}$/u;
|
|
12
|
+
const ENTITLEMENTS_PROFILES = new Set(["none", "jit-executable-v1"]);
|
|
12
13
|
const FORBIDDEN_CREDENTIAL_KEYS =
|
|
13
14
|
/(?:certificate|password|private.?key|secret|token|notary|issuer|team.?id|environment)/iu;
|
|
14
15
|
|
|
@@ -88,6 +89,64 @@ function exactSourceSha(value, label) {
|
|
|
88
89
|
return normalized;
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
function entitlementsPaths(value) {
|
|
93
|
+
if (value === undefined) return [];
|
|
94
|
+
if (!Array.isArray(value)) {
|
|
95
|
+
throw new Error("signing entitlements paths must be an array");
|
|
96
|
+
}
|
|
97
|
+
const paths = value.map((entry, index) => {
|
|
98
|
+
const normalized = nonEmptyString(
|
|
99
|
+
entry,
|
|
100
|
+
`signing entitlements paths[${index}]`,
|
|
101
|
+
);
|
|
102
|
+
const parts = normalized.split("/");
|
|
103
|
+
if (
|
|
104
|
+
normalized.startsWith("/") ||
|
|
105
|
+
normalized.includes("\\") ||
|
|
106
|
+
normalized.includes(",") ||
|
|
107
|
+
parts.some((part) => part === "" || part === "." || part === "..")
|
|
108
|
+
) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`signing entitlements paths[${index}] must be a safe archive-relative path`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return normalized;
|
|
114
|
+
});
|
|
115
|
+
if (new Set(paths).size !== paths.length) {
|
|
116
|
+
throw new Error("signing entitlements paths must not contain duplicates");
|
|
117
|
+
}
|
|
118
|
+
return paths;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function signingEntitlements(profileId, kind, signature) {
|
|
122
|
+
const profile = String(signature.entitlementsProfile || "none").trim();
|
|
123
|
+
const paths = entitlementsPaths(signature.entitlementsPaths);
|
|
124
|
+
if (!ENTITLEMENTS_PROFILES.has(profile)) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`unsupported signing entitlements profile: ${profile || "<empty>"}`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (
|
|
130
|
+
profile !== "none" &&
|
|
131
|
+
(profileId !== "apple-developer-id" || kind !== "archive")
|
|
132
|
+
) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`signing entitlements profile ${profile} requires an Apple archive`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
if (
|
|
138
|
+
(profile === "none" && paths.length !== 0) ||
|
|
139
|
+
(profile !== "none" && paths.length === 0)
|
|
140
|
+
) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
"signing entitlements paths must be non-empty exactly when an entitlements profile is enabled",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return profile === "none"
|
|
146
|
+
? {}
|
|
147
|
+
: { entitlementsProfile: profile, entitlementsPaths: paths };
|
|
148
|
+
}
|
|
149
|
+
|
|
91
150
|
function assertNoCredentialMaterial(value, path = "request") {
|
|
92
151
|
if (!value || typeof value !== "object") return;
|
|
93
152
|
for (const [key, child] of Object.entries(value)) {
|
|
@@ -191,6 +250,7 @@ export function createArtifactSigningRequest({
|
|
|
191
250
|
platform,
|
|
192
251
|
artifactKind: kind,
|
|
193
252
|
});
|
|
253
|
+
const entitlementIntent = signingEntitlements(profile.id, kind, signature);
|
|
194
254
|
const request = {
|
|
195
255
|
schemaVersion: 1,
|
|
196
256
|
contract: ARTIFACT_SIGNING_REQUEST_CONTRACT,
|
|
@@ -253,6 +313,7 @@ export function createArtifactSigningRequest({
|
|
|
253
313
|
profile: profile.id,
|
|
254
314
|
provider: profile.provider,
|
|
255
315
|
semantics: profile.semantics,
|
|
316
|
+
...entitlementIntent,
|
|
256
317
|
},
|
|
257
318
|
delivery: {
|
|
258
319
|
mode: nonEmptyString(
|
|
@@ -61,6 +61,10 @@ const SUPPORTED_SIGNING_PROFILES = new Set([
|
|
|
61
61
|
"windows-authenticode",
|
|
62
62
|
"detached-signature-v1",
|
|
63
63
|
]);
|
|
64
|
+
const SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES = new Set([
|
|
65
|
+
"none",
|
|
66
|
+
"jit-executable-v1",
|
|
67
|
+
]);
|
|
64
68
|
const SUPPORTED_SIGNING_ARTIFACT_KINDS = new Set([
|
|
65
69
|
"auto", "binary", "archive", "blob", "directory", "mach-o", "app-bundle",
|
|
66
70
|
"framework-bundle", "plugin-bundle", "xpc-bundle", "dylib", "pkg", "dmg",
|
|
@@ -99,6 +103,27 @@ function normalizeStringArray(value, label) {
|
|
|
99
103
|
return value.map((entry, index) => assertString(entry, `${label}[${index}]`));
|
|
100
104
|
}
|
|
101
105
|
|
|
106
|
+
function normalizeSigningEntitlementsPaths(value, label) {
|
|
107
|
+
const paths = normalizeStringArray(value, label);
|
|
108
|
+
for (const [index, entry] of paths.entries()) {
|
|
109
|
+
const parts = entry.split("/");
|
|
110
|
+
if (
|
|
111
|
+
entry.startsWith("/") ||
|
|
112
|
+
entry.includes("\\") ||
|
|
113
|
+
entry.includes(",") ||
|
|
114
|
+
parts.some((part) => part === "" || part === "." || part === "..")
|
|
115
|
+
) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`${label}[${index}] must be a safe archive-relative path`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (new Set(paths).size !== paths.length) {
|
|
122
|
+
throw new Error(`${label} must not contain duplicate paths`);
|
|
123
|
+
}
|
|
124
|
+
return paths;
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
function getByDottedKey(target, key) {
|
|
103
128
|
return String(key)
|
|
104
129
|
.split(".")
|
|
@@ -362,7 +387,16 @@ function normalizeSigningSection(signing) {
|
|
|
362
387
|
const artifacts = signing.artifacts.map((artifact, index) => {
|
|
363
388
|
const label = `signing.artifacts[${index}]`;
|
|
364
389
|
assertPlainObject(artifact, label);
|
|
365
|
-
const allowedKeys = new Set([
|
|
390
|
+
const allowedKeys = new Set([
|
|
391
|
+
"id",
|
|
392
|
+
"path",
|
|
393
|
+
"profile",
|
|
394
|
+
"entitlements_profile",
|
|
395
|
+
"entitlements_paths",
|
|
396
|
+
"kind",
|
|
397
|
+
"platforms",
|
|
398
|
+
"required",
|
|
399
|
+
]);
|
|
366
400
|
for (const key of Object.keys(artifact)) {
|
|
367
401
|
if (!allowedKeys.has(key)) {
|
|
368
402
|
throw new Error(`${label}.${key} is not supported; declare desired signature state only`);
|
|
@@ -377,10 +411,41 @@ function normalizeSigningSection(signing) {
|
|
|
377
411
|
if (!SUPPORTED_SIGNING_ARTIFACT_KINDS.has(kind)) {
|
|
378
412
|
throw new Error(`${label}.kind is not a supported signing artifact kind`);
|
|
379
413
|
}
|
|
414
|
+
const entitlementsProfile =
|
|
415
|
+
artifact.entitlements_profile === undefined
|
|
416
|
+
? "none"
|
|
417
|
+
: assertString(
|
|
418
|
+
artifact.entitlements_profile,
|
|
419
|
+
`${label}.entitlements_profile`,
|
|
420
|
+
);
|
|
421
|
+
if (!SUPPORTED_SIGNING_ENTITLEMENTS_PROFILES.has(entitlementsProfile)) {
|
|
422
|
+
throw new Error(
|
|
423
|
+
`${label}.entitlements_profile must be one of none or jit-executable-v1`,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
if (entitlementsProfile !== "none" && kind !== "archive") {
|
|
427
|
+
throw new Error(
|
|
428
|
+
`${label}.entitlements_profile ${entitlementsProfile} requires kind = "archive"`,
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
const entitlementsPaths = normalizeSigningEntitlementsPaths(
|
|
432
|
+
artifact.entitlements_paths,
|
|
433
|
+
`${label}.entitlements_paths`,
|
|
434
|
+
);
|
|
435
|
+
if (
|
|
436
|
+
(entitlementsProfile === "none" && entitlementsPaths.length !== 0) ||
|
|
437
|
+
(entitlementsProfile !== "none" && entitlementsPaths.length === 0)
|
|
438
|
+
) {
|
|
439
|
+
throw new Error(
|
|
440
|
+
`${label}.entitlements_paths must be non-empty exactly when entitlements_profile is enabled`,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
380
443
|
return {
|
|
381
444
|
id: artifact.id === undefined ? artifactPath : assertString(artifact.id, `${label}.id`),
|
|
382
445
|
path: artifactPath,
|
|
383
446
|
profile,
|
|
447
|
+
entitlementsProfile,
|
|
448
|
+
entitlementsPaths,
|
|
384
449
|
kind,
|
|
385
450
|
platforms: normalizeStringArray(artifact.platforms, `${label}.platforms`),
|
|
386
451
|
required: optionalBoolean(artifact.required, true),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { devDeliveryClone as clone, devDeliveryContentRoot, devDeliveryExactRoot as exactRoot, devDeliveryExactSha as exactSha, devDeliveryPositiveInteger as positiveInteger, devDeliveryProtectedBase as protectedBase, devDeliveryRepository as repository, devDeliveryText as text, devDeliveryTimestamp as timestamp } from "./dev-delivery-common.js";
|
|
2
2
|
|
|
3
3
|
export const SOURCE_QUALIFICATION_PROOF_SCHEMA = "kungfu.buildchain.source-qualification-proof/v1";
|
|
4
|
+
export const SOURCE_QUALIFICATION_PROOF_V2_SCHEMA = "kungfu.buildchain.source-qualification-proof/v2";
|
|
4
5
|
export const PROJECT_CUT_REPLAY_PROOF_SCHEMA = "kungfu.buildchain.project-cut-replay-proof/v1";
|
|
5
6
|
export const INTEGRATION_DELIVERY_PROOF_SCHEMA = "kungfu.buildchain.integration-delivery-proof/v1";
|
|
6
7
|
|
|
@@ -49,10 +50,38 @@ export function createSourceQualificationProof(input = {}) {
|
|
|
49
50
|
return { ...body, proofRoot: devDeliveryContentRoot(sourceQualificationIdentity(body)) };
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
export function createSourceQualificationProofV2(input = {}) {
|
|
54
|
+
const body = {
|
|
55
|
+
schema: SOURCE_QUALIFICATION_PROOF_V2_SCHEMA,
|
|
56
|
+
rootSemantics: SOURCE_QUALIFICATION_ROOT_SEMANTICS,
|
|
57
|
+
authority: "exact-source-qualification",
|
|
58
|
+
repository: repository(input.repository),
|
|
59
|
+
protectedBase: protectedBase(input.protectedBase),
|
|
60
|
+
qualifiedBase: exactSha(input.qualifiedBase, "qualifiedBase"),
|
|
61
|
+
sourceIdentityRoot: exactRoot(input.sourceIdentityRoot, "sourceIdentityRoot"),
|
|
62
|
+
sourceHead: exactSha(input.sourceHead, "sourceHead"),
|
|
63
|
+
sourceTree: exactSha(input.sourceTree, "sourceTree"),
|
|
64
|
+
sourcePatchRoot: exactRoot(input.sourcePatchRoot, "sourcePatchRoot"),
|
|
65
|
+
planRoot: exactRoot(input.planRoot, "planRoot"),
|
|
66
|
+
closureRoot: exactRoot(input.closureRoot, "closureRoot"),
|
|
67
|
+
dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
|
|
68
|
+
toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"),
|
|
69
|
+
policyRoot: exactRoot(input.policyRoot, "policyRoot"),
|
|
70
|
+
requiredContextRoot: exactRoot(input.requiredContextRoot, "requiredContextRoot"),
|
|
71
|
+
controllerReceiptRoot: exactRoot(input.controllerReceiptRoot, "controllerReceiptRoot"),
|
|
72
|
+
sourceWorkflowRunId: positiveInteger(input.sourceWorkflowRunId, "sourceWorkflowRunId"),
|
|
73
|
+
affectedPaths: [...new Set((input.affectedPaths || []).map(text).filter(Boolean))].sort(),
|
|
74
|
+
shardEvidenceRoots: exactRoots(input.shardEvidenceRoots, "shardEvidenceRoots"),
|
|
75
|
+
qualifiedAt: timestamp(input.qualifiedAt, "qualifiedAt"),
|
|
76
|
+
};
|
|
77
|
+
body.observationRoot = devDeliveryContentRoot(sourceQualificationObservation(body));
|
|
78
|
+
return { ...body, proofRoot: devDeliveryContentRoot(sourceQualificationIdentity(body)) };
|
|
79
|
+
}
|
|
80
|
+
|
|
52
81
|
export function verifySourceQualificationProof(proofInput, expected = {}) {
|
|
53
82
|
try {
|
|
54
83
|
const proof = clone(proofInput || {});
|
|
55
|
-
if (proof.schema
|
|
84
|
+
if (![SOURCE_QUALIFICATION_PROOF_SCHEMA, SOURCE_QUALIFICATION_PROOF_V2_SCHEMA].includes(proof.schema)) return { ok: false, reason: "unsupported-schema" };
|
|
56
85
|
const proofRoot = proof.proofRoot;
|
|
57
86
|
delete proof.proofRoot;
|
|
58
87
|
if (proof.rootSemantics === undefined) {
|
|
@@ -65,7 +94,12 @@ export function verifySourceQualificationProof(proofInput, expected = {}) {
|
|
|
65
94
|
for (const [field, value] of Object.entries(expected)) {
|
|
66
95
|
if (value !== undefined && proof[field] !== value) return { ok: false, reason: `${field}-mismatch` };
|
|
67
96
|
}
|
|
68
|
-
|
|
97
|
+
if (proof.schema === SOURCE_QUALIFICATION_PROOF_V2_SCHEMA) {
|
|
98
|
+
if (proof.authority !== "exact-source-qualification") return { ok: false, reason: "non-exact-authority" };
|
|
99
|
+
createSourceQualificationProofV2(proof);
|
|
100
|
+
} else {
|
|
101
|
+
createSourceQualificationProof(proof);
|
|
102
|
+
}
|
|
69
103
|
return { ok: true, reason: "exact-source-proof", proofRoot };
|
|
70
104
|
} catch (error) {
|
|
71
105
|
return { ok: false, reason: "invalid-proof", error: error.message };
|
|
@@ -80,7 +114,7 @@ export function classifyDevDeliveryDelta({ proof, current = {} } = {}) {
|
|
|
80
114
|
reason: verification.reason,
|
|
81
115
|
reusable: false,
|
|
82
116
|
};
|
|
83
|
-
const exactPredicates = ["sourceIdentityRoot", "sourcePatchRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot"];
|
|
117
|
+
const exactPredicates = ["sourceIdentityRoot", "sourcePatchRoot", "planRoot", "closureRoot", "dependencyRoot", "toolchainRoot", ...(proof.schema === SOURCE_QUALIFICATION_PROOF_V2_SCHEMA ? ["qualifiedBase", "sourceHead", "sourceTree", "policyRoot", "requiredContextRoot"] : [])];
|
|
84
118
|
for (const field of exactPredicates) {
|
|
85
119
|
if (!current[field] || current[field] !== proof[field]) {
|
|
86
120
|
return {
|
|
@@ -5,7 +5,7 @@ import { DEV_DELIVERY_SETTLEMENT_RECEIPT_SCHEMA, createDevDeliveryTerminalSettle
|
|
|
5
5
|
import { compareReleaseBlockerPriority, normalizeReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
|
|
6
6
|
export { devDeliveryContentRoot } from "./dev-delivery-common.js";
|
|
7
7
|
export { RELEASE_BLOCKER_PRIORITY_CLAIM_SCHEMA, createReleaseBlockerPriorityClaim } from "./release-blocker-priority.js";
|
|
8
|
-
export { SOURCE_QUALIFICATION_PROOF_SCHEMA, PROJECT_CUT_REPLAY_PROOF_SCHEMA, INTEGRATION_DELIVERY_PROOF_SCHEMA, classifyDevDeliveryDelta, createIntegrationDeliveryProof, createProjectCutReplayPlan, createProjectCutReplayProof, createSourceQualificationProof, verifyIntegrationDeliveryProof, verifyProjectCutReplayProof, verifySourceQualificationProof } from "./dev-delivery-proof.js";
|
|
8
|
+
export { SOURCE_QUALIFICATION_PROOF_SCHEMA, SOURCE_QUALIFICATION_PROOF_V2_SCHEMA, PROJECT_CUT_REPLAY_PROOF_SCHEMA, INTEGRATION_DELIVERY_PROOF_SCHEMA, classifyDevDeliveryDelta, createIntegrationDeliveryProof, createProjectCutReplayPlan, createProjectCutReplayProof, createSourceQualificationProof, createSourceQualificationProofV2, verifyIntegrationDeliveryProof, verifyProjectCutReplayProof, verifySourceQualificationProof } from "./dev-delivery-proof.js";
|
|
9
9
|
export { DEV_DELIVERY_CANCELLATION_RECEIPT_SCHEMA };
|
|
10
10
|
export const DEV_DELIVERY_QUEUE_CONTRACT = "kungfu-buildchain-dev-delivery-warrant-queue";
|
|
11
11
|
export const DEV_DELIVERY_WARRANT_SCHEMA = "kungfu.buildchain.dev-delivery-warrant/v1";
|
|
@@ -70,7 +70,7 @@ function normalizeCandidate(input, expected) {
|
|
|
70
70
|
planRoot: exactRoot(input.planRoot, "planRoot"),
|
|
71
71
|
closureRoot: exactRoot(input.closureRoot, "closureRoot"),
|
|
72
72
|
dependencyRoot: exactRoot(input.dependencyRoot, "dependencyRoot"),
|
|
73
|
-
toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"),
|
|
73
|
+
toolchainRoot: exactRoot(input.toolchainRoot, "toolchainRoot"), ...(input.environmentRoot ? { environmentRoot: exactRoot(input.environmentRoot, "environmentRoot") } : {}), ...(Object.hasOwn(input, "sourceWorkflowRunId") ? { sourceWorkflowRunId: nonNegativeInteger(input.sourceWorkflowRunId, "candidate sourceWorkflowRunId", 0) } : {}),
|
|
74
74
|
priority: priority(input.priority),
|
|
75
75
|
enqueuedAt: timestamp(input.enqueuedAt, "candidate enqueuedAt"),
|
|
76
76
|
updatedAt: timestamp(input.updatedAt || input.enqueuedAt, "candidate updatedAt"),
|
|
@@ -79,7 +79,7 @@ function normalizeCandidate(input, expected) {
|
|
|
79
79
|
status,
|
|
80
80
|
terminal: input.terminal || null,
|
|
81
81
|
};
|
|
82
|
-
if (Object.hasOwn(input, "releaseBlockerPriority")) candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(input.releaseBlockerPriority, candidate, expected);
|
|
82
|
+
if (Object.hasOwn(input, "affectedPaths")) { if (!Array.isArray(input.affectedPaths)) throw new Error("candidate affectedPaths must be an array"); candidate.affectedPaths = [...new Set(input.affectedPaths.map(text).filter(Boolean))].sort(); } if (Object.hasOwn(input, "releaseBlockerPriority")) candidate.releaseBlockerPriority = normalizeReleaseBlockerPriorityClaim(input.releaseBlockerPriority, candidate, expected);
|
|
83
83
|
return candidate;
|
|
84
84
|
}
|
|
85
85
|
|
package/packages/core/index.js
CHANGED
|
@@ -639,6 +639,8 @@ export {
|
|
|
639
639
|
} from "./kfd3-surface-register.js";
|
|
640
640
|
|
|
641
641
|
export * from "./release-propagation.js";
|
|
642
|
+
export * from "./v4-floating-consumer-policy.js";
|
|
643
|
+
export * from "./v4-runtime-ref-resume-authority.js";
|
|
642
644
|
|
|
643
645
|
export {
|
|
644
646
|
RELEASE_ACTIVATION_CONTRACT,
|
|
@@ -639,18 +639,18 @@ function validatePublicationEvidence(publicationEvidence, admission) {
|
|
|
639
639
|
repository: admission.repository,
|
|
640
640
|
targetChannel: releaseCandidateEvidenceChannel(admission.channel),
|
|
641
641
|
});
|
|
642
|
-
if (!passportValidation.ok) {
|
|
643
|
-
|
|
644
|
-
}
|
|
642
|
+
if (!passportValidation.ok) throw new Error(`release-candidate passport did not qualify: ${passportValidation.errors.join("; ")}`);
|
|
643
|
+
const evidence = (key) => passport[key] ? { [key]: passport[key] } : {};
|
|
645
644
|
const candidateHash = sha256Json({
|
|
646
645
|
repository: passport.repository,
|
|
647
646
|
target: passport.target,
|
|
648
647
|
source: passport.source,
|
|
649
648
|
platformMatrix: passport.platformMatrix,
|
|
650
649
|
buildchain: passport.buildchain,
|
|
651
|
-
...(
|
|
650
|
+
...evidence("gateProfileEvidence"),
|
|
652
651
|
...(passport.familyEvidence ? { familyEvidence: passport.familyEvidence } : {}),
|
|
653
|
-
...(
|
|
652
|
+
...evidence("consumerPolicy"),
|
|
653
|
+
...evidence("controllerReceipts"),
|
|
654
654
|
});
|
|
655
655
|
if (normalizeDigest(passport.candidateHash, "releaseCandidatePassport.candidateHash") !== candidateHash) {
|
|
656
656
|
throw new Error("release-candidate passport candidate hash mismatch");
|