@xemahq/xema 0.51.0 → 0.53.0
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/dist/commands/edition.js +1 -1
- package/dist/commands/edition.js.map +1 -1
- package/dist/edition/verify-image-evidence.bundle.mjs +957 -852
- package/dist/edition/verify-image-evidence.bundle.provenance.json +490 -490
- package/dist/runtime/edition/verb-map.d.ts +1 -0
- package/dist/runtime/edition/verb-map.d.ts.map +1 -1
- package/dist/runtime/edition/verb-map.js +2 -0
- package/dist/runtime/edition/verb-map.js.map +1 -1
- package/edition/README.md +4 -1
- package/edition/assemble-producer-input.mjs +244 -83
- package/edition/assemble-third-party-input.mjs +336 -0
- package/edition/edition-protocol.mjs +4 -1
- package/edition/evidence-input-mode.mjs +136 -0
- package/edition/image-evidence.mjs +19 -1
- package/edition/kernel-contract-authority.mjs +10 -2
- package/edition/kernel-package.mjs +13 -0
- package/edition/lib.mjs +51 -37
- package/edition/oci-evidence-verbs.mjs +21 -6
- package/edition/operation-requirements.mjs +11 -0
- package/edition/oras.mjs +5 -4
- package/edition/platform-service-class.mjs +4 -2
- package/edition/produce-image-source-evidence.mjs +33 -17
- package/edition/registry-credentials.mjs +24 -2
- package/edition/third-party-source-evidence.mjs +8 -1
- package/edition/third-party-source-flags.mjs +1 -1
- package/package.json +3 -3
|
@@ -31,6 +31,7 @@ export declare enum EditionChartSetOperation {
|
|
|
31
31
|
}
|
|
32
32
|
export declare enum EditionEvidenceKind {
|
|
33
33
|
AssembleInput = "assemble-input",
|
|
34
|
+
AssembleThirdPartyInput = "assemble-third-party-input",
|
|
34
35
|
Statement = "statement",
|
|
35
36
|
AssembleSet = "assemble-set",
|
|
36
37
|
CheckCommitted = "check-committed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb-map.d.ts","sourceRoot":"","sources":["../../../src/runtime/edition/verb-map.ts"],"names":[],"mappings":"AAKA,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,cAAc,oBAAoB;IAClC,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,GAAG,QAAQ;IACX,eAAe,qBAAqB;IACpC,eAAe,qBAAqB;IACpC,kBAAkB,yBAAyB;IAC3C,cAAc,oBAAoB;IAClC,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,QAAQ,cAAc;IACtB,cAAc,oBAAoB;IAClC,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAGD,oBAAY,wBAAwB;IAClC,OAAO,YAAY;IACnB,YAAY,kBAAkB;CAC/B;AAGD,oBAAY,mBAAmB;IAC7B,aAAa,mBAAmB;IAChC,SAAS,cAAc;IACvB,WAAW,iBAAiB;IAC5B,cAAc,oBAAoB;IAClC,WAAW,iBAAiB;IAC5B,GAAG,QAAQ;CACZ;AAGD,oBAAY,wBAAwB;IAClC,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,SAAS,cAAc;CACxB;AAGD,oBAAY,gBAAgB;IAC1B,KAAK,UAAU;IACf,eAAe,qBAAqB;IACpC,kBAAkB,yBAAyB;CAC5C;AAGD,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,MAAM,WAAW;CAClB;AAGD,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAE1F,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,cAAc,GAAG,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAuBnI,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAGtF,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,QAAQ,CAAC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAK/F,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"verb-map.d.ts","sourceRoot":"","sources":["../../../src/runtime/edition/verb-map.ts"],"names":[],"mappings":"AAKA,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,cAAc,oBAAoB;IAClC,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,GAAG,QAAQ;IACX,eAAe,qBAAqB;IACpC,eAAe,qBAAqB;IACpC,kBAAkB,yBAAyB;IAC3C,cAAc,oBAAoB;IAClC,QAAQ,aAAa;IACrB,IAAI,SAAS;IACb,KAAK,UAAU;IACf,aAAa,mBAAmB;IAChC,QAAQ,cAAc;IACtB,cAAc,oBAAoB;IAClC,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,KAAK,UAAU;IACf,OAAO,YAAY;CACpB;AAGD,oBAAY,wBAAwB;IAClC,OAAO,YAAY;IACnB,YAAY,kBAAkB;CAC/B;AAGD,oBAAY,mBAAmB;IAC7B,aAAa,mBAAmB;IAChC,uBAAuB,+BAA+B;IACtD,SAAS,cAAc;IACvB,WAAW,iBAAiB;IAC5B,cAAc,oBAAoB;IAClC,WAAW,iBAAiB;IAC5B,GAAG,QAAQ;CACZ;AAGD,oBAAY,wBAAwB;IAClC,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,WAAW,gBAAgB;IAC3B,SAAS,cAAc;CACxB;AAGD,oBAAY,gBAAgB;IAC1B,KAAK,UAAU;IACf,eAAe,qBAAqB;IACpC,kBAAkB,yBAAyB;CAC5C;AAGD,oBAAY,oBAAoB;IAC9B,OAAO,YAAY;IACnB,MAAM,WAAW;CAClB;AAGD,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE,MAAM,CAAC,CAE1F,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CACvC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,cAAc,GAAG,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAuBnI,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAGtF,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,QAAQ,CAAC,MAAM,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAK/F,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAUxH,CAAC;AAGF,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAE9C,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAI1E,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAEhC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IAExC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAiDD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAoBtG"}
|
|
@@ -38,6 +38,7 @@ var EditionChartSetOperation;
|
|
|
38
38
|
var EditionEvidenceKind;
|
|
39
39
|
(function (EditionEvidenceKind) {
|
|
40
40
|
EditionEvidenceKind["AssembleInput"] = "assemble-input";
|
|
41
|
+
EditionEvidenceKind["AssembleThirdPartyInput"] = "assemble-third-party-input";
|
|
41
42
|
EditionEvidenceKind["Statement"] = "statement";
|
|
42
43
|
EditionEvidenceKind["AssembleSet"] = "assemble-set";
|
|
43
44
|
EditionEvidenceKind["CheckCommitted"] = "check-committed";
|
|
@@ -100,6 +101,7 @@ exports.EDITION_EVIDENCE_STATEMENT_ENTRY = {
|
|
|
100
101
|
};
|
|
101
102
|
exports.EDITION_EVIDENCE_ENTRY = {
|
|
102
103
|
[EditionEvidenceKind.AssembleInput]: 'assemble-producer-input.mjs',
|
|
104
|
+
[EditionEvidenceKind.AssembleThirdPartyInput]: 'assemble-third-party-input.mjs',
|
|
103
105
|
[EditionEvidenceKind.AssembleSet]: exports.EDITION_EVIDENCE_STATEMENT_ENTRY[EditionEvidenceStatement.Completeness],
|
|
104
106
|
[EditionEvidenceKind.CheckCommitted]: 'check-committed-image-evidence.mjs',
|
|
105
107
|
[EditionEvidenceKind.PlanRefresh]: 'plan-image-evidence-refresh.mjs',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verb-map.js","sourceRoot":"","sources":["../../../src/runtime/edition/verb-map.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"verb-map.js","sourceRoot":"","sources":["../../../src/runtime/edition/verb-map.ts"],"names":[],"mappings":"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"}
|
package/edition/README.md
CHANGED
|
@@ -89,6 +89,7 @@ xema edition chart-set <resolve|source-commit> ...
|
|
|
89
89
|
xema edition arming --channel <release|develop> --data-root <dir> --kernel <dir>
|
|
90
90
|
xema edition verify-evidence <id> --descriptor <abs path> [--json]
|
|
91
91
|
xema edition evidence <assemble-input|check-committed|plan-refresh|statement|assemble-set|oci> ...
|
|
92
|
+
xema edition evidence assemble-third-party-input --bundle <oci repository>@sha256:<hex> --contract-authority <file> --image <image repository>@sha256:<hex> --subject-id <component image name> --provenance <absolute exported SLSA v1 predicate> --registry-credentials <file> --output <path> [--ttl-seconds <n>] # a third-party publisher's producer input, no root flags (see Third-party sources)
|
|
92
93
|
```
|
|
93
94
|
|
|
94
95
|
Results are JSON on stdout and diagnostics on stderr. Exit 0 is success and 1 is a refusal. `xema edition <verb> --help` names the roots and flags each verb takes.
|
|
@@ -146,7 +147,7 @@ The edition library builds, validates and verifies evidence statements; it never
|
|
|
146
147
|
|
|
147
148
|
## Kernel protocol and pins
|
|
148
149
|
|
|
149
|
-
The CLI is coupled to the kernel's edition protocol, not to the kernel package. `@xemahq/contracts` exports the protocol identity as data (`dist/edition-protocol/edition-protocol.json`: `{contentDigest, provisional, version}`). This CLI supports protocols v28, v30, v31, v32, v33, v34, v35 and
|
|
150
|
+
The CLI is coupled to the kernel's edition protocol, not to the kernel package. `@xemahq/contracts` exports the protocol identity as data (`dist/edition-protocol/edition-protocol.json`: `{contentDigest, provisional, version}`). This CLI supports protocols v28, v30, v31, v32, v33, v34, v35, v36, v37, v38 and v38 (no published kernel declares v29; a CLI lists a protocol only while every kernel published under it exports what the CLI imports; v27 and older kernels lack `serviceImageSubjects`, so a data root whose pinned kernel speaks v27 or older stays on an earlier CLI), pinned to its digest and vendored, and REFUSES an identity with `provisional: true`; every loader that executes the kernel, `xema edition check` first, and the evidence verifier compare only that identity and refuse an unsupported one, naming the supported and the declared versions. A protocol change needs a CLI release first; only then does the data root repin its kernel authority.
|
|
150
151
|
|
|
151
152
|
A develop edition does not take the kernel's develop head blindly: `xema edition develop choose-kernel --kernel <package dir> [--kernel-pin <40-hex>] --out <file>` reads the declared protocol of each commit on the checkout's first-parent history (from source, unbuilt) and chooses the newest one this CLI supports. It writes `{chosenSha, headSha, held, reason}` (`reason`: `head-supported` | `head-ahead` | `explicit-pin`; `held` is `head-ahead`), and when held prints `kernel held at v<N> (<sha12>), head at v<M> (<sha12>): raise the CLI` (stdout only, never persisted). The head is the checkout's `refs/remotes/origin/develop` (a full-history checkout). An explicit pin wins but is still checked, and must be on that head's first-parent history (`not-on-develop` otherwise); when no commit is supported it refuses (`EditionProtocolMismatchError`, `no-supported-commit`; the walk ends at the first commit with no declaration file) and never falls back to the head; a declaration that exists but does not parse, at the head or any walked commit, is refused by name (`unparseable`), never skipped. `freeze-graph` applies the same check to `--kernel-sha`.
|
|
152
153
|
|
|
@@ -160,6 +161,8 @@ A develop edition does not take the kernel's develop head blindly: `xema edition
|
|
|
160
161
|
## Third-party sources
|
|
161
162
|
|
|
162
163
|
- **Zero-config.** A data root with no `third-party-source-pins.json`, an empty one or an unparsable one has NO third-party source: every `kind: oci` declared source and every third-party image subject is refused, naming the loader's reason. The pin file is the explicit grant; a trust-policy row alone grants nothing. When the file exists, its sha256 is part of the evidence trust pin, so it moves only together with `xema edition repin-evidence-trust`.
|
|
164
|
+
- **Publisher input.** The publisher's own GitHub-hosted workflow, on `refs/heads/main`, assembles the producer input of each image with `xema edition evidence assemble-third-party-input` (usage above), one run per image. It runs on public inputs only: this CLI and the `@xemahq/contracts` it ships (both from npm), the publisher's checkout at `GITHUB_WORKSPACE` (holding `GITHUB_SHA`), its own registry credential declaration (`--registry-credentials`, the `image-registry-credentials.json` format, naming environment variables, never a secret) and the `GITHUB_*` context. It takes no root flag and reads no data root. `--contract-authority` is the kernel contract authority object the vendor's evidence trust pin names; it must be the kernel this CLI ships, so the publisher installs the matching CLI version. The subject is the bundle's (`--bundle`, read by digest) `oci-image` service or worker component named `--subject-id`; `path` is the directory of the one `xema-biome.json` at `GITHUB_SHA` whose hash is the bundle's; `sourceTreeHash` is hashed over the checkout with no cross-repo inputs (publisher-attested); the image is read by digest (`--image`) and must carry its cosign SLSA v1 and SBOM attestations; the builder digests come from the exported predicate (`--provenance`, VCS revision `GITHUB_SHA`). The lifetime is `--ttl-seconds` or the first-party default (72h); the trust policy's `maxProducerTtlSeconds` ceiling is enforced by the vendor's third-party pin writer (`index runtime-image-source --trusted-write --third-party`) and by `verify-evidence`, and the signer rows and image ownership are checked by the pin writer. It refuses unless `RUNNER_ENVIRONMENT` is `github-hosted` and `GITHUB_REF` is `refs/heads/main`. The output is the exact input `xema edition evidence statement producer` accepts.
|
|
165
|
+
- **Publisher evidence (public-input mode).** The rest of the publisher's run uses the same verbs as first party with `--contract-authority <file>` in place of `--data-root`/`--kernel`: `xema edition evidence statement producer stage` (no OIDC), a keyless `cosign attest-blob --new-bundle-format` of each staged statement in an `id-token: write` job, `statement producer accept --cosign <abs path>` (no OIDC), then `oci attach-plan`, `oras attach` and `oci validate`. Passing both modes, or neither, is refused by name. The authority and schemas come from the file and the `@xemahq/contracts` this CLI bundles, through the one resolution `assemble-third-party-input` uses. Accept verifies every bundle's signature but holds cosign to no version: the vendor's admission re-verifies with its pinned cosign. The publisher installs the xema CLI whose bundled `@xemahq/contracts` matches the authority; an authority whose contracts digest is not the bundled one is refused, naming both digests.
|
|
163
166
|
- **Seal.** A third-party image subject is sealed BY DIGEST from its pin: it keeps the publisher's `imageRef`, its platforms are read at `<imageRef>@<manifestDigest>`, and its `contentHash` (the publisher's `sourceTreeHash`) is never used as a tag, a develop coordinate, a cache key or a build-ledger key. It is not a develop-coverage subject and is excluded from the first-party fleet-coordinate verdict. Its producer evidence in the edition's evidence set is the committed evidence the pin records, checked byte for byte against the pin's digests.
|
|
164
167
|
- **Revocation.** A sealed lock keeps its seal-time verdict; there is no expiry machinery. To revoke a source: remove its pin and its trust-policy rows, regenerate the runtime image source index, run `xema edition repin-evidence-trust`, and reseal every edition that includes the biome. An edition already delivered is not recalled.
|
|
165
168
|
- **What this does not prove.**
|
|
@@ -132,6 +132,13 @@ const SOURCE_REPO_PATTERN = /^(?:repos|submodules)\/[a-zA-Z0-9_.-]+$/;
|
|
|
132
132
|
// The kernel's `CanonicalIdentifierSchema` shape (runId / subject id).
|
|
133
133
|
const CANONICAL_IDENTIFIER_PATTERN =
|
|
134
134
|
/^[a-zA-Z0-9](?:[a-zA-Z0-9._:/@+-]{0,254}[a-zA-Z0-9])?$/;
|
|
135
|
+
/** `--subject-id` has the kernel's `CanonicalIdentifierSchema` shape. */
|
|
136
|
+
export function assertCanonicalSubjectId(subjectId) {
|
|
137
|
+
if (!CANONICAL_IDENTIFIER_PATTERN.test(subjectId ?? '')) {
|
|
138
|
+
throw new Error(`--subject-id ${JSON.stringify(subjectId ?? null)} is not a canonical identifier`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
135
142
|
// cosign v2 attaches every attestation of a subject as one layer of the
|
|
136
143
|
// single `sha256-<subject-digest>.att` manifest; each layer is a DSSE
|
|
137
144
|
// envelope whose `predicateType` annotation names the attestation.
|
|
@@ -848,6 +855,54 @@ export async function resolveImageArtifactEvidence({
|
|
|
848
855
|
if (!SHA256_HEX_PATTERN.test(sourceTreeHash ?? '')) {
|
|
849
856
|
throw new Error('sourceTreeHash must be 64 lowercase sha256 hex characters');
|
|
850
857
|
}
|
|
858
|
+
assertReferenceProvenance(referenceProvenance);
|
|
859
|
+
const { authority, repository } = splitImageRef(imageRepository);
|
|
860
|
+
const declarations = loadRegistryCredentialDeclarations(distributionsRoot);
|
|
861
|
+
const credential = resolveRegistryCredential({ authority, declarations, env });
|
|
862
|
+
const client = registryFor
|
|
863
|
+
? registryFor({ authority, credential })
|
|
864
|
+
: new OrasRegistry({ credential, fetchImpl });
|
|
865
|
+
return publishedArtifactEvidence({
|
|
866
|
+
client,
|
|
867
|
+
repository,
|
|
868
|
+
imageRepository,
|
|
869
|
+
read: { tag: sourceTreeHash },
|
|
870
|
+
expectedDigest: manifestDigest,
|
|
871
|
+
coordinate: `${imageRepository}:${sourceTreeHash}`,
|
|
872
|
+
referenceProvenance,
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* The artifact section of a producer subject read BY DIGEST: the manifest at
|
|
878
|
+
* `<imageRepository>@<manifestDigest>` (its bytes must hash to that digest),
|
|
879
|
+
* its hash-proven platforms and its cosign SBOM + SLSA attestation digests. A
|
|
880
|
+
* third-party publisher's image carries no `:<sourceTreeHash>` tag
|
|
881
|
+
* (`evidence assemble-third-party-input`), so nothing is read by tag.
|
|
882
|
+
*/
|
|
883
|
+
export async function resolveImageArtifactEvidenceByDigest({
|
|
884
|
+
client,
|
|
885
|
+
imageRepository,
|
|
886
|
+
manifestDigest,
|
|
887
|
+
referenceProvenance,
|
|
888
|
+
}) {
|
|
889
|
+
if (!SHA256_DIGEST_PATTERN.test(manifestDigest ?? '')) {
|
|
890
|
+
throw new Error('the image manifest digest must be an exact sha256:<64-hex> digest');
|
|
891
|
+
}
|
|
892
|
+
assertReferenceProvenance(referenceProvenance);
|
|
893
|
+
const { repository } = splitImageRef(imageRepository);
|
|
894
|
+
return publishedArtifactEvidence({
|
|
895
|
+
client,
|
|
896
|
+
repository,
|
|
897
|
+
imageRepository,
|
|
898
|
+
read: { digest: manifestDigest },
|
|
899
|
+
expectedDigest: manifestDigest,
|
|
900
|
+
coordinate: `${imageRepository}@${manifestDigest}`,
|
|
901
|
+
referenceProvenance,
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function assertReferenceProvenance(referenceProvenance) {
|
|
851
906
|
if (
|
|
852
907
|
typeof referenceProvenance !== 'object' ||
|
|
853
908
|
referenceProvenance === null ||
|
|
@@ -858,19 +913,29 @@ export async function resolveImageArtifactEvidence({
|
|
|
858
913
|
'it is what binds the selected provenance attestation to the primary build',
|
|
859
914
|
);
|
|
860
915
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/** The artifact evidence of the manifest `read` names (exactly one of `{tag}` or `{digest}`), which must be `expectedDigest`. */
|
|
919
|
+
async function publishedArtifactEvidence({
|
|
920
|
+
client,
|
|
921
|
+
repository,
|
|
922
|
+
imageRepository,
|
|
923
|
+
read,
|
|
924
|
+
expectedDigest,
|
|
925
|
+
coordinate,
|
|
926
|
+
referenceProvenance,
|
|
927
|
+
}) {
|
|
928
|
+
const top =
|
|
929
|
+
read.tag === undefined
|
|
930
|
+
? await client.getManifestByDigest(repository, read.digest)
|
|
931
|
+
: await client.getManifestByTag(repository, read.tag);
|
|
932
|
+
if (top.digest !== expectedDigest) {
|
|
870
933
|
throw new Error(
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
934
|
+
read.tag === undefined
|
|
935
|
+
? `${coordinate} was served as ${top.digest}: the registry returned a manifest that is not the digest it was read by`
|
|
936
|
+
: `${coordinate} serves ${top.digest}, not the caller-declared ${expectedDigest} — ` +
|
|
937
|
+
'the image was not published from this source identity (wrong build commit, ' +
|
|
938
|
+
'or the cross-repo record at the build commit differs from the one this source carries)',
|
|
874
939
|
);
|
|
875
940
|
}
|
|
876
941
|
// Proves EVERY platform by its own hash-verified image config and refuses
|
|
@@ -879,7 +944,7 @@ export async function resolveImageArtifactEvidence({
|
|
|
879
944
|
const published = await resolvePublishedPlatforms({
|
|
880
945
|
client,
|
|
881
946
|
repository,
|
|
882
|
-
|
|
947
|
+
...read,
|
|
883
948
|
coordinate,
|
|
884
949
|
});
|
|
885
950
|
if (published.indexDigest !== top.digest) {
|
|
@@ -944,6 +1009,69 @@ export async function resolveImageArtifactEvidence({
|
|
|
944
1009
|
*/
|
|
945
1010
|
export const DEFAULT_PRODUCER_TTL_SECONDS = 3 * 24 * 60 * 60;
|
|
946
1011
|
|
|
1012
|
+
/** Where the ceiling on a producer lifetime is held: the closed set of producer kinds. */
|
|
1013
|
+
export const ProducerTtlCeilingSource = Object.freeze({
|
|
1014
|
+
/** First party: the data root's trust policy `maxProducerTtlSeconds`, read here. */
|
|
1015
|
+
TrustPolicy: 'trust-policy',
|
|
1016
|
+
/**
|
|
1017
|
+
* A third-party publisher on public inputs: the vendor policy's `maxProducerTtlSeconds`, enforced by
|
|
1018
|
+
* the third-party pin writer (`index runtime-image-source --trusted-write --third-party`) and `verify-evidence`.
|
|
1019
|
+
*/
|
|
1020
|
+
VendorAdmission: 'vendor-admission',
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
/** The latest instant an RFC 3339 `expiresAt` (four-digit year) can name. */
|
|
1024
|
+
const LATEST_EXPIRES_AT = Date.UTC(9999, 11, 31, 23, 59, 59);
|
|
1025
|
+
|
|
1026
|
+
/** `--ttl-seconds` as given, or undefined when it is not. */
|
|
1027
|
+
export const producerTtlSecondsFlag = (value) => (value === undefined ? undefined : Number(value));
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* The producer lifetime of an input issued at `now`. The default is DEFAULT_PRODUCER_TTL_SECONDS, bowed to the
|
|
1031
|
+
* ceiling when it is read here (`ceiling.source` TrustPolicy, `ceiling.maxTtlSeconds`); an explicit value above that
|
|
1032
|
+
* ceiling is refused. With VendorAdmission the ceiling is the vendor policy's, enforced by the third-party pin writer
|
|
1033
|
+
* (`index runtime-image-source --trusted-write --third-party`) and `verify-evidence`; this CLI holds no second one. Either way a value that is not a positive integer, or whose `expiresAt` is past the last
|
|
1034
|
+
* instant RFC 3339 can name, is refused by name.
|
|
1035
|
+
*/
|
|
1036
|
+
export function resolveProducerTtlSeconds({ ttlSeconds, now, ceiling }) {
|
|
1037
|
+
let maxTtlSeconds;
|
|
1038
|
+
if (ceiling?.source === ProducerTtlCeilingSource.TrustPolicy) {
|
|
1039
|
+
({ maxTtlSeconds } = ceiling);
|
|
1040
|
+
if (!Number.isSafeInteger(maxTtlSeconds) || maxTtlSeconds < 1) {
|
|
1041
|
+
throw new Error(`the trust policy's maxProducerTtlSeconds ${String(maxTtlSeconds)} is not a positive integer`);
|
|
1042
|
+
}
|
|
1043
|
+
} else if (ceiling?.source === ProducerTtlCeilingSource.VendorAdmission) {
|
|
1044
|
+
maxTtlSeconds = null;
|
|
1045
|
+
} else {
|
|
1046
|
+
throw new Error(`a producer TTL ceiling source is one of ${Object.values(ProducerTtlCeilingSource).join(', ')}`);
|
|
1047
|
+
}
|
|
1048
|
+
// The DEFAULT bows to the policy ceiling; an EXPLICIT `--ttl-seconds` above
|
|
1049
|
+
// it still fails below. Tightening `maxProducerTtlSeconds` is a legitimate
|
|
1050
|
+
// operator decision, and it must not break every producer until someone
|
|
1051
|
+
// edits a constant in this file — but a caller who NAMES a lifetime the
|
|
1052
|
+
// verifier will reject has made a mistake, and gets told so.
|
|
1053
|
+
const effective =
|
|
1054
|
+
ttlSeconds ?? (maxTtlSeconds === null ? DEFAULT_PRODUCER_TTL_SECONDS : Math.min(DEFAULT_PRODUCER_TTL_SECONDS, maxTtlSeconds));
|
|
1055
|
+
if (maxTtlSeconds !== null && (!Number.isSafeInteger(effective) || effective < 1 || effective > maxTtlSeconds)) {
|
|
1056
|
+
throw new Error(
|
|
1057
|
+
`--ttl-seconds must be an integer between 1 and the trust policy's maxProducerTtlSeconds (${maxTtlSeconds})`,
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
if (!Number.isSafeInteger(effective) || effective < 1) {
|
|
1061
|
+
throw new Error(
|
|
1062
|
+
`--ttl-seconds must be a positive integer number of seconds (got ${String(ttlSeconds)}); the vendor policy's ` +
|
|
1063
|
+
'maxProducerTtlSeconds is its ceiling, enforced by the pin writer and verify-evidence',
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
if (now + effective * 1000 > LATEST_EXPIRES_AT) {
|
|
1067
|
+
throw new Error(
|
|
1068
|
+
`--ttl-seconds ${effective} puts expiresAt past ${new Date(LATEST_EXPIRES_AT).toISOString()}, the last instant an ` +
|
|
1069
|
+
'RFC 3339 time can name',
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
return effective;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
947
1075
|
function readProducerTtlSeconds(distributionsRoot) {
|
|
948
1076
|
const declared = editionWorkspaceConfig().evidenceTrustPolicy.policy;
|
|
949
1077
|
if (declared === null) {
|
|
@@ -1011,9 +1139,7 @@ export async function assembleProducerInput({
|
|
|
1011
1139
|
`--subject-kind "${String(subjectKind)}" must be one of ${subjectKinds.join(', ')}`,
|
|
1012
1140
|
);
|
|
1013
1141
|
}
|
|
1014
|
-
|
|
1015
|
-
throw new Error('--subject-id is not a canonical identifier');
|
|
1016
|
-
}
|
|
1142
|
+
assertCanonicalSubjectId(subjectId);
|
|
1017
1143
|
if (!SOURCE_REPO_PATTERN.test(sourceRepo ?? '')) {
|
|
1018
1144
|
throw new Error(
|
|
1019
1145
|
`--source-repo "${String(sourceRepo)}" must be an aggregator-plane repository (repos/<name> or submodules/<name>)`,
|
|
@@ -1090,24 +1216,42 @@ export async function assembleProducerInput({
|
|
|
1090
1216
|
fetchImpl,
|
|
1091
1217
|
registryFor,
|
|
1092
1218
|
});
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
effectiveTtlSeconds
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1219
|
+
const effectiveTtlSeconds = resolveProducerTtlSeconds({
|
|
1220
|
+
ttlSeconds,
|
|
1221
|
+
now,
|
|
1222
|
+
ceiling: { source: ProducerTtlCeilingSource.TrustPolicy, maxTtlSeconds: readProducerTtlSeconds(distributionsRoot) },
|
|
1223
|
+
});
|
|
1224
|
+
const input = producerInputDocument({
|
|
1225
|
+
contractAuthority,
|
|
1226
|
+
context,
|
|
1227
|
+
builder,
|
|
1228
|
+
now,
|
|
1229
|
+
ttlSeconds: effectiveTtlSeconds,
|
|
1230
|
+
subject: {
|
|
1231
|
+
kind: subjectKind,
|
|
1232
|
+
id: subjectId,
|
|
1233
|
+
repositoryUrl: source.repositoryUrl,
|
|
1234
|
+
repo: sourceRepo,
|
|
1235
|
+
path: sourcePath,
|
|
1236
|
+
sourceCommit,
|
|
1237
|
+
sourceManifestHash: source.sourceManifestHash,
|
|
1238
|
+
sourceTreeHash: source.sourceTreeHash,
|
|
1239
|
+
imageRepository,
|
|
1240
|
+
...artifact,
|
|
1241
|
+
},
|
|
1242
|
+
});
|
|
1243
|
+
assertAssembledProducerInput({ input, schemas, contractAuthority, context });
|
|
1244
|
+
return input;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* The producer input of ONE subject, in the exact shape
|
|
1249
|
+
* `produce-image-source-evidence.mjs` accepts. `context` is
|
|
1250
|
+
* {@link assertWorkflowContext}'s and `builder` {@link deriveBuilder}'s; the
|
|
1251
|
+
* subject carries every per-subject field (source identity and artifact).
|
|
1252
|
+
*/
|
|
1253
|
+
export function producerInputDocument({ contractAuthority, context, builder, now, ttlSeconds, subject }) {
|
|
1254
|
+
return {
|
|
1111
1255
|
schemaVersion: 1,
|
|
1112
1256
|
contractAuthority: { ...contractAuthority },
|
|
1113
1257
|
sourceHashAlgorithm: imageInputSourceHashAlgorithm(),
|
|
@@ -1131,31 +1275,36 @@ export async function assembleProducerInput({
|
|
|
1131
1275
|
runId: context.runId,
|
|
1132
1276
|
runAttempt: context.runAttempt,
|
|
1133
1277
|
issuedAt: rfc3339(now),
|
|
1134
|
-
expiresAt: rfc3339(now +
|
|
1135
|
-
expectedSubjects: [`${
|
|
1278
|
+
expiresAt: rfc3339(now + ttlSeconds * 1000),
|
|
1279
|
+
expectedSubjects: [`${subject.kind}:${subject.id}`],
|
|
1136
1280
|
subjects: [
|
|
1137
1281
|
{
|
|
1138
|
-
kind:
|
|
1139
|
-
id:
|
|
1140
|
-
repositoryUrl:
|
|
1141
|
-
repo:
|
|
1142
|
-
path:
|
|
1143
|
-
sourceCommit,
|
|
1144
|
-
sourceManifestHash:
|
|
1145
|
-
sourceTreeHash:
|
|
1146
|
-
imageRepository,
|
|
1147
|
-
manifestDigest:
|
|
1148
|
-
manifestMediaType:
|
|
1149
|
-
platforms:
|
|
1150
|
-
sbomDigest:
|
|
1151
|
-
provenanceDigest:
|
|
1282
|
+
kind: subject.kind,
|
|
1283
|
+
id: subject.id,
|
|
1284
|
+
repositoryUrl: subject.repositoryUrl,
|
|
1285
|
+
repo: subject.repo,
|
|
1286
|
+
path: subject.path,
|
|
1287
|
+
sourceCommit: subject.sourceCommit,
|
|
1288
|
+
sourceManifestHash: subject.sourceManifestHash,
|
|
1289
|
+
sourceTreeHash: subject.sourceTreeHash,
|
|
1290
|
+
imageRepository: subject.imageRepository,
|
|
1291
|
+
manifestDigest: subject.manifestDigest,
|
|
1292
|
+
manifestMediaType: subject.manifestMediaType,
|
|
1293
|
+
platforms: subject.platforms,
|
|
1294
|
+
sbomDigest: subject.sbomDigest,
|
|
1295
|
+
provenanceDigest: subject.provenanceDigest,
|
|
1152
1296
|
},
|
|
1153
1297
|
],
|
|
1154
1298
|
};
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
/**
|
|
1302
|
+
* Prove an assembled input satisfies the producer BEFORE anything reads it:
|
|
1303
|
+
* the exact field contract, then the kernel statement schema the producer
|
|
1304
|
+
* builds (the same parse produce-image-source-evidence.mjs runs before
|
|
1305
|
+
* signing), then the GitHub context the producer compares against.
|
|
1306
|
+
*/
|
|
1307
|
+
export function assertAssembledProducerInput({ input, schemas, contractAuthority, context }) {
|
|
1159
1308
|
assertProducerInput(input, contractAuthority);
|
|
1160
1309
|
buildImageSourceStatements(input, schemas, contractAuthority);
|
|
1161
1310
|
assertGitHubProducerContext(input, {
|
|
@@ -1164,23 +1313,13 @@ export async function assembleProducerInput({
|
|
|
1164
1313
|
sha: context.sha,
|
|
1165
1314
|
workflowRef: context.workflowRef,
|
|
1166
1315
|
});
|
|
1167
|
-
return input;
|
|
1168
1316
|
}
|
|
1169
1317
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
return value;
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
async function main() {
|
|
1179
|
-
const args = configureEditionWorkspaceFromArgv(process.argv.slice(2), [
|
|
1180
|
-
WorkspaceRoot.Data,
|
|
1181
|
-
WorkspaceRoot.Sources,
|
|
1182
|
-
WorkspaceRoot.Kernel,
|
|
1183
|
-
]);
|
|
1318
|
+
/**
|
|
1319
|
+
* The `--name value` pairs of an assembler's argv: each flag once, each with a
|
|
1320
|
+
* value, none outside `known`.
|
|
1321
|
+
*/
|
|
1322
|
+
export function readAssemblerFlags(args, known) {
|
|
1184
1323
|
const flags = new Map();
|
|
1185
1324
|
for (let index = 0; index < args.length; index += 2) {
|
|
1186
1325
|
const flag = args[index];
|
|
@@ -1197,6 +1336,39 @@ async function main() {
|
|
|
1197
1336
|
}
|
|
1198
1337
|
flags.set(name, value);
|
|
1199
1338
|
}
|
|
1339
|
+
for (const name of flags.keys()) {
|
|
1340
|
+
if (!known.has(name)) {
|
|
1341
|
+
throw new Error(`unknown option "--${name}"`);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return flags;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Write an assembled input to `output`. The output directory is caller scratch
|
|
1349
|
+
* space — created deterministically (the producer action's input-manifest
|
|
1350
|
+
* must be repository-relative, so the caller cannot sidestep this by pointing
|
|
1351
|
+
* at RUNNER_TEMP). `wx` refuses to overwrite an existing manifest.
|
|
1352
|
+
*/
|
|
1353
|
+
export function writeProducerInputFile(output, input) {
|
|
1354
|
+
mkdirSync(dirname(output), { recursive: true });
|
|
1355
|
+
writeFileSync(output, serializeJson(input), { flag: 'wx', mode: 0o600 });
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
function requireValue(flags, name) {
|
|
1359
|
+
const value = flags.get(name);
|
|
1360
|
+
if (value === undefined) {
|
|
1361
|
+
throw new Error(`--${name} is required`);
|
|
1362
|
+
}
|
|
1363
|
+
return value;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
async function main() {
|
|
1367
|
+
const args = configureEditionWorkspaceFromArgv(process.argv.slice(2), [
|
|
1368
|
+
WorkspaceRoot.Data,
|
|
1369
|
+
WorkspaceRoot.Sources,
|
|
1370
|
+
WorkspaceRoot.Kernel,
|
|
1371
|
+
]);
|
|
1200
1372
|
const known = new Set([
|
|
1201
1373
|
'output',
|
|
1202
1374
|
'image-repository',
|
|
@@ -1211,11 +1383,7 @@ async function main() {
|
|
|
1211
1383
|
'provenance',
|
|
1212
1384
|
'ttl-seconds',
|
|
1213
1385
|
]);
|
|
1214
|
-
|
|
1215
|
-
if (!known.has(name)) {
|
|
1216
|
-
throw new Error(`unknown option "--${name}"`);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1386
|
+
const flags = readAssemblerFlags(args, known);
|
|
1219
1387
|
const output = resolve(requireValue(flags, 'output'));
|
|
1220
1388
|
const input = await assembleProducerInput({
|
|
1221
1389
|
imageRepository: requireValue(flags, 'image-repository'),
|
|
@@ -1228,16 +1396,9 @@ async function main() {
|
|
|
1228
1396
|
provenancePath: resolve(requireValue(flags, 'provenance')),
|
|
1229
1397
|
sourceManifestHash: flags.get('source-manifest-hash'),
|
|
1230
1398
|
sourceTreeHash: flags.get('source-tree-hash'),
|
|
1231
|
-
ttlSeconds: flags.
|
|
1232
|
-
? Number(flags.get('ttl-seconds'))
|
|
1233
|
-
: undefined,
|
|
1399
|
+
ttlSeconds: producerTtlSecondsFlag(flags.get('ttl-seconds')),
|
|
1234
1400
|
});
|
|
1235
|
-
|
|
1236
|
-
// (the producer action's input-manifest must be repository-relative, so the
|
|
1237
|
-
// caller cannot sidestep this by pointing at RUNNER_TEMP). `wx` below still
|
|
1238
|
-
// refuses to overwrite an existing manifest.
|
|
1239
|
-
mkdirSync(dirname(output), { recursive: true });
|
|
1240
|
-
writeFileSync(output, serializeJson(input), { flag: 'wx', mode: 0o600 });
|
|
1401
|
+
writeProducerInputFile(output, input);
|
|
1241
1402
|
console.log(
|
|
1242
1403
|
`[assemble-producer-input] wrote ${output} for subject ` +
|
|
1243
1404
|
`${input.subjects[0].kind}:${input.subjects[0].id} ` +
|