@dynamicalsystems/idl-conformance 0.12.0 → 0.13.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/assets/vectors/dsg.extension.release_1/accept/compute-release.json +8 -0
- package/assets/vectors/dsg.extension.release_1/accept/noncompute-release-without-fake-compute.json +8 -0
- package/assets/vectors/dsg.extension.release_1/accept/signature-binds-canonical-body.json +9 -0
- package/assets/vectors/dsg.extension.release_1/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.extension.release_1/reject/component-dependency-cycle.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/compute-requires-job-class.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/duplicate-component-id-with-different-body.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/missing-component-dependency.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/mutable-release-status-forbidden.json +8 -0
- package/assets/vectors/dsg.extension.release_1/reject/noncompute-cannot-claim-artifact.json +8 -0
- package/assets/vectors/dsg.extension.release_1/reject/signature-rejects-altered-signature.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/signature-rejects-substituted-body-digest.json +9 -0
- package/assets/vectors/dsg.extension.release_1/reject/signature-rejects-wrong-key.json +9 -0
- package/assets/vectors/dsg.organization.release_1/accept/activeSet-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/admission-revoked.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/admission-superseded.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/admission-suspended.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/admissionRecord-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/available-catalog-pins-semantic-documents.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/boundAttestation-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/build-lock-complete.json +9 -0
- package/assets/vectors/dsg.organization.release_1/accept/catalog-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/dependencyLock-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/import-pending.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/import-refused.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/import-staged.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/import-verified.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/memberObservation-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/organizationBuild-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/organizationRelease-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/refused-admission-without-invented-approval.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/releaseEligibility-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/releaseStatusObservation-valid.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/resolved-typed-dependency-closure.json +8 -0
- package/assets/vectors/dsg.organization.release_1/accept/retired-release-remains-executable-in-current-active-set.json +9 -0
- package/assets/vectors/dsg.organization.release_1/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/activation-requires-authority.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/admission-requires-decision-authority.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/available-catalog-cannot-carry-unavailable-reason.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-cannot-contain-attestation.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-cannot-contain-authority.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-cannot-self-reference.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-lock-extra-entry.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-lock-mismatched-entry.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-lock-omitted-entry.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/build-lock-reordered-entries.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/catalog-rejects-mismatched-active-set.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/duplicate-release-member-id.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/lock-cannot-contain-unreachable-entry.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/lock-cannot-have-dependency-cycle.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/lock-cannot-omit-transitive-member.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/lock-requires-deterministic-entry-order.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/negative-member-needs-reason.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/pending-import-cannot-carry-terminal-disposition.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/ready-member-needs-evidence.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/refused-admission-cannot-approve-use.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/release-requires-exact-member-subject.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/release-status-is-separate-observation.json +8 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-needs-current-active-set.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-refuses-new-activate.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-refuses-new-admit.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-refuses-new-import.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-refuses-new-resolve.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/retired-release-refuses-new-select.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/revoked-release-refuses-existing-execution.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/stale-trust-view-cannot-restore-release.json +9 -0
- package/assets/vectors/dsg.organization.release_1/reject/verified-import-cannot-be-missing.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-capabilitySelection.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-dependencyLock.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-organization.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-profile.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-project.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-releaseDeclaration.json +8 -0
- package/assets/vectors/dsg.organization.source_3/accept/source-releaseMember.json +8 -0
- package/assets/vectors/dsg.organization.source_3/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.organization.source_3/reject/overlay-path-cannot-escape.json +8 -0
- package/assets/vectors/dsg.organization.source_3/reject/source-cannot-grant-authority.json +8 -0
- package/assets/vectors/dsg.organization.source_3/reject/source-members-use-paths.json +8 -0
- package/assets/vectors/dsg.run.execution-binding_1/accept/authorization-allows-unexpired-idempotent-replay.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/accept/authorization-binds-consumed-lease.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/accept/binding-separates-metadata-and-executable.json +8 -0
- package/assets/vectors/dsg.run.execution-binding_1/accept/provider-uses-platform-manifest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/archive-digest-cannot-replace-executable-manifest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-expired-checked-time.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-jointly-altered-generation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-accepted-generation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-case.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-envelope.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-generation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-law.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-operation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/authorization-rejects-wrong-reservation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/binding-requires-provider-manifest-digest.json +8 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/config-digest-cannot-replace-executable-manifest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-cross-workflow-catalog.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-gpu-seconds-over-class.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-installation-mismatch.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-missing-execute-approval.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-non-execute-eligibility.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-parallelism-over-class.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-refused-admission.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-release-mismatch.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-revoked-eligibility.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-run-seconds-over-class.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-stale-trust-view.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-wrong-active-set.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-wrong-admission.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-wrong-execute-binding.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-wrong-inline-digest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/envelope-rejects-wrong-selection.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/index-digest-cannot-replace-executable-manifest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/job-class-cannot-substitute-artifact.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/metadata-bytes-must-match-reference.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/metadata-digest-cannot-replace-executable-manifest.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/operation-binding-rejects-wrong-operation.json +9 -0
- package/assets/vectors/dsg.run.execution-binding_1/reject/operation-binding-rejects-wrong-target.json +9 -0
- package/assets/vectors/dsg.run.job-class_1/accept/class-pins-one-way-artifact-binding.json +8 -0
- package/assets/vectors/dsg.run.job-class_1/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.run.job-class_1/reject/class-requires-exact-artifact.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/accept/archive-hash-is-detached-provenance.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/accept/oci-metadata-types-digest-roles.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/accept/single-platform-image-without-index.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/digest/canonical-envelope.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/archive-hash-is-not-semantic-executable-field.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/artifact-cannot-refer-back-to-class.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/digest-bearing-repository.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/index-media-type-cannot-be-executable-manifest.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/malformed-repository.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/missing-repository.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/scheme-bearing-repository.json +8 -0
- package/assets/vectors/dsg.run.workload-artifact_1/reject/tag-bearing-repository.json +8 -0
- package/checklist.json +7 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{reference-adapter-DDCyFCeV.mjs → reference-adapter-BJ-RkYd3.mjs} +253 -3
- package/dist/reference-adapter-BJ-RkYd3.mjs.map +1 -0
- package/dist/{reference-adapter-B9dycZns.cjs → reference-adapter-C6kR4r8N.cjs} +250 -0
- package/package.json +2 -2
- package/src/reference-adapter.ts +2 -0
- package/src/release-semantics.ts +488 -0
- package/dist/reference-adapter-DDCyFCeV.mjs.map +0 -1
|
@@ -1430,6 +1430,255 @@ function streamDigest(bytes) {
|
|
|
1430
1430
|
}
|
|
1431
1431
|
}
|
|
1432
1432
|
//#endregion
|
|
1433
|
+
//#region src/release-semantics.ts
|
|
1434
|
+
function digest(value) {
|
|
1435
|
+
return (0, node_crypto.createHash)("sha256").update((0, _dynamicalsystems_orn_schemas.jcsStringify)(value)).digest("hex");
|
|
1436
|
+
}
|
|
1437
|
+
function same(a, b) {
|
|
1438
|
+
return a.orn === b.orn && a.sha256 === b.sha256;
|
|
1439
|
+
}
|
|
1440
|
+
function unique(values) {
|
|
1441
|
+
return new Set(values).size === values.length;
|
|
1442
|
+
}
|
|
1443
|
+
function ordered(values) {
|
|
1444
|
+
return values.every((value, index) => index === 0 || values[index - 1] < value);
|
|
1445
|
+
}
|
|
1446
|
+
function graphError(entries, roots) {
|
|
1447
|
+
if (!unique(entries.map((entry) => entry.id))) return "duplicate-member-id";
|
|
1448
|
+
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
1449
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1450
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1451
|
+
function visit(id) {
|
|
1452
|
+
if (visiting.has(id)) return "dependency-cycle";
|
|
1453
|
+
if (visited.has(id)) return;
|
|
1454
|
+
const entry = byId.get(id);
|
|
1455
|
+
if (!entry) return "unresolved-dependency";
|
|
1456
|
+
visiting.add(id);
|
|
1457
|
+
for (const dependency of entry.dependsOn) {
|
|
1458
|
+
const error = visit(dependency);
|
|
1459
|
+
if (error) return error;
|
|
1460
|
+
}
|
|
1461
|
+
visiting.delete(id);
|
|
1462
|
+
visited.add(id);
|
|
1463
|
+
}
|
|
1464
|
+
for (const root of roots) {
|
|
1465
|
+
const error = visit(root);
|
|
1466
|
+
if (error) return error;
|
|
1467
|
+
}
|
|
1468
|
+
return visited.size === entries.length ? void 0 : "extraneous-lock-entry";
|
|
1469
|
+
}
|
|
1470
|
+
function parse(schema, refine) {
|
|
1471
|
+
return (bytes) => {
|
|
1472
|
+
let value;
|
|
1473
|
+
try {
|
|
1474
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
1475
|
+
} catch (error) {
|
|
1476
|
+
return {
|
|
1477
|
+
ok: false,
|
|
1478
|
+
reason: `not UTF-8 JSON: ${String(error)}`
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
if (!Check(schema, value)) {
|
|
1482
|
+
const error = Errors(schema, value).First();
|
|
1483
|
+
return {
|
|
1484
|
+
ok: false,
|
|
1485
|
+
reason: `${error?.path ?? ""}: ${error?.message ?? "schema mismatch"}`
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
const error = refine(value);
|
|
1489
|
+
return error ? {
|
|
1490
|
+
ok: false,
|
|
1491
|
+
reason: error
|
|
1492
|
+
} : { ok: true };
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
const ExecutionIdentityContext = _dynamicalsystems_idl.ExecutionRequestEnvelopeSchema;
|
|
1496
|
+
const ExecutionAuthorizationContext = (0, _dynamicalsystems_idl.closed)({
|
|
1497
|
+
request: _dynamicalsystems_idl.ExecutionRequestEnvelopeSchema,
|
|
1498
|
+
lease: _dynamicalsystems_idl.DispatchLeaseSchema,
|
|
1499
|
+
accepted: _dynamicalsystems_idl.AcceptedSchema,
|
|
1500
|
+
checkedAt: _dynamicalsystems_idl.UtcSecond
|
|
1501
|
+
});
|
|
1502
|
+
const ReleaseSignatureContext = (0, _dynamicalsystems_idl.closed)({
|
|
1503
|
+
release: _dynamicalsystems_idl.ExtensionReleaseSchema,
|
|
1504
|
+
signature: _dynamicalsystems_idl.ExtensionReleaseSignatureSchema
|
|
1505
|
+
});
|
|
1506
|
+
const OrganizationBuildContext = (0, _dynamicalsystems_idl.closed)({
|
|
1507
|
+
build: _dynamicalsystems_idl.OrganizationBuildSchema,
|
|
1508
|
+
dependencyLock: _dynamicalsystems_idl.DependencyLockSchema
|
|
1509
|
+
});
|
|
1510
|
+
const ReleaseEligibilityContext = (0, _dynamicalsystems_idl.closed)({
|
|
1511
|
+
eligibility: _dynamicalsystems_idl.ReleaseEligibilitySchema,
|
|
1512
|
+
currentActiveSet: _dynamicalsystems_idl.Reference,
|
|
1513
|
+
activeSet: _dynamicalsystems_idl.ActiveSetSchema
|
|
1514
|
+
});
|
|
1515
|
+
function releaseSemanticAdapters() {
|
|
1516
|
+
return {
|
|
1517
|
+
"dsg.organization.release/1#dependencyLock": parse(_dynamicalsystems_idl.DependencyLockSchema, (lock) => {
|
|
1518
|
+
if (!ordered(lock.roots) || !ordered(lock.entries.map((entry) => entry.id))) return "unsorted-lock";
|
|
1519
|
+
for (const entry of lock.entries) {
|
|
1520
|
+
if (!ordered(entry.dependsOn) || !ordered(entry.selectedMemberIds)) return "unsorted-lock";
|
|
1521
|
+
if (entry.kind === "extension-release" && !entry.reference.orn.startsWith("orn:dsg.core.extension.release:")) return "wrong-release-space";
|
|
1522
|
+
if (entry.kind === "workload-artifact" && !entry.reference.orn.startsWith("orn:dsg.core.extension.workload-artifact:")) return "wrong-artifact-space";
|
|
1523
|
+
}
|
|
1524
|
+
return graphError(lock.entries, lock.roots);
|
|
1525
|
+
}),
|
|
1526
|
+
"dsg.extension.release/1#semantic.signatureBinding": parse(ReleaseSignatureContext, ({ release, signature }) => {
|
|
1527
|
+
const bodySha256 = digest(release);
|
|
1528
|
+
if (signature.bodySha256 !== bodySha256 || signature.release.sha256 !== bodySha256) return "signature-body-digest-mismatch";
|
|
1529
|
+
if (signature.release.orn !== release.releaseOrn || signature.publisher !== release.publisher) return "signature-identity-mismatch";
|
|
1530
|
+
try {
|
|
1531
|
+
const publicKey = (0, node_crypto.createPublicKey)({
|
|
1532
|
+
key: Buffer.concat([Buffer.from("302a300506032b6570032100", "hex"), Buffer.from(signature.publicKey, "hex")]),
|
|
1533
|
+
format: "der",
|
|
1534
|
+
type: "spki"
|
|
1535
|
+
});
|
|
1536
|
+
if (!(0, node_crypto.verify)(null, Buffer.from((0, _dynamicalsystems_orn_schemas.jcsStringify)(release), "utf8"), publicKey, Buffer.from(signature.signature, "hex"))) return "invalid-release-signature";
|
|
1537
|
+
} catch {
|
|
1538
|
+
return "invalid-release-signature";
|
|
1539
|
+
}
|
|
1540
|
+
}),
|
|
1541
|
+
"dsg.extension.release/1#release": parse(_dynamicalsystems_idl.ExtensionReleaseSchema, (release) => {
|
|
1542
|
+
if (release.releaseOrn !== `orn:dsg.core.extension.release:${release.namespace}/${release.name}@${release.version}`) return "release-name-mismatch";
|
|
1543
|
+
if (!unique(release.dependencies.map((dependency) => dependency.id))) return "duplicate-dependency-id";
|
|
1544
|
+
const error = graphError(release.components, release.components.map((component) => component.id));
|
|
1545
|
+
if (error) return error;
|
|
1546
|
+
const kinds = new Set(release.components.map((component) => component.kind));
|
|
1547
|
+
if (release.compute && (!kinds.has("job-class") || !kinds.has("workload-artifact"))) return "missing-compute-component";
|
|
1548
|
+
for (const component of release.components) if (component.kind === "workload-artifact" && !component.reference.orn.startsWith("orn:dsg.core.extension.workload-artifact:")) return "wrong-artifact-space";
|
|
1549
|
+
}),
|
|
1550
|
+
"dsg.organization.release/1#organizationBuild": parse(_dynamicalsystems_idl.OrganizationBuildSchema, (build) => {
|
|
1551
|
+
const orderedBy = (values, key) => ordered(values.map(key));
|
|
1552
|
+
if (!orderedBy(build.sourceDocuments, (document) => document.path)) return "unsorted-source-closure";
|
|
1553
|
+
if (!orderedBy(build.projects, (project) => project.id) || !orderedBy(build.selections, (selection) => selection.id) || build.selections.some((selection) => !orderedBy(selection.members, (member) => member.id)) || !orderedBy(build.components, (component) => [
|
|
1554
|
+
component.extensionRelease.orn,
|
|
1555
|
+
component.extensionRelease.sha256,
|
|
1556
|
+
component.memberId
|
|
1557
|
+
].join("\0")) || !orderedBy(build.typedReleases, (release) => release.id) || !orderedBy(build.instructions, (reference) => `${reference.orn}\0${reference.sha256}`) || !orderedBy(build.handling, (reference) => `${reference.orn}\0${reference.sha256}`) || !orderedBy(build.releaseDeclarations, (reference) => `${reference.orn}\0${reference.sha256}`) || !orderedBy(build.releaseMembers, (member) => member.id)) return "unsorted-build";
|
|
1558
|
+
if (!unique(build.projects.map((project) => project.id)) || !unique(build.selections.map((selection) => selection.id)) || !unique(build.releaseMembers.map((member) => member.id))) return "duplicate-member-id";
|
|
1559
|
+
const components = /* @__PURE__ */ new Map();
|
|
1560
|
+
for (const component of build.components) {
|
|
1561
|
+
const key = `${component.extensionRelease.orn}\0${component.extensionRelease.sha256}\0${component.memberId}`;
|
|
1562
|
+
if (components.has(key)) return "duplicate-component-id";
|
|
1563
|
+
components.set(key, component);
|
|
1564
|
+
}
|
|
1565
|
+
for (const selection of build.selections) {
|
|
1566
|
+
if (!unique(selection.members.map((member) => member.id))) return "duplicate-member-id";
|
|
1567
|
+
for (const member of selection.members) {
|
|
1568
|
+
const component = components.get(`${selection.extensionRelease.orn}\0${selection.extensionRelease.sha256}\0${member.id}`);
|
|
1569
|
+
if (!component || component.kind !== member.kind || !same(component.reference, member.reference)) return "selected-component-mismatch";
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}),
|
|
1573
|
+
"dsg.organization.release/1#semantic.organizationBuild": parse(OrganizationBuildContext, ({ build, dependencyLock }) => {
|
|
1574
|
+
if (build.dependencyLock.sha256 !== digest(dependencyLock)) return "dependency-lock-digest-mismatch";
|
|
1575
|
+
if ((0, _dynamicalsystems_orn_schemas.jcsStringify)(build.typedReleases) !== (0, _dynamicalsystems_orn_schemas.jcsStringify)(dependencyLock.entries)) return "typed-release-lock-mismatch";
|
|
1576
|
+
}),
|
|
1577
|
+
"dsg.organization.release/1#organizationRelease": parse(_dynamicalsystems_idl.OrganizationReleaseSchema, (release) => unique(release.members.map((member) => member.id)) ? void 0 : "duplicate-member-id"),
|
|
1578
|
+
"dsg.organization.release/1#admissionRecord": parse(_dynamicalsystems_idl.AdmissionRecordSchema, (admission) => {
|
|
1579
|
+
if (!unique(admission.components.map((component) => component.id))) return "duplicate-member-id";
|
|
1580
|
+
if (admission.status === "admitted" && !unique(admission.approvedUses.map((use) => use.use))) return "duplicate-approved-use";
|
|
1581
|
+
}),
|
|
1582
|
+
"dsg.organization.release/1#activeSet": parse(_dynamicalsystems_idl.ActiveSetSchema, (activeSet) => {
|
|
1583
|
+
if (!unique(activeSet.members.map((member) => `${member.selectionId}\0${member.memberId}`))) return "duplicate-active-member";
|
|
1584
|
+
for (const member of activeSet.members) if (!unique(member.components.map((component) => component.id))) return "duplicate-member-id";
|
|
1585
|
+
}),
|
|
1586
|
+
"dsg.organization.release/1#catalog": parse(_dynamicalsystems_idl.CatalogSchema, (catalog) => {
|
|
1587
|
+
if (!unique(catalog.entries.map((entry) => entry.id))) return "duplicate-catalog-entry";
|
|
1588
|
+
for (const entry of catalog.entries) {
|
|
1589
|
+
if (!same(entry.activeSet, catalog.activeSet)) return "catalog-active-set-mismatch";
|
|
1590
|
+
if (entry.jobClass === null !== (entry.workloadArtifact === null)) return "incomplete-compute-provenance";
|
|
1591
|
+
}
|
|
1592
|
+
}),
|
|
1593
|
+
"dsg.organization.release/1#releaseEligibility": parse(_dynamicalsystems_idl.ReleaseEligibilitySchema, (eligibility) => {
|
|
1594
|
+
if (!same(eligibility.release, eligibility.observation.subject)) return "status-subject-mismatch";
|
|
1595
|
+
if (!same(eligibility.trustView, eligibility.observation.trustView)) return "stale-trust-view";
|
|
1596
|
+
if (eligibility.observation.status === "revoked") return "release-revoked";
|
|
1597
|
+
if (eligibility.observation.status === "retired" && (eligibility.operation !== "execute" || eligibility.activeSet === null)) return "release-retired";
|
|
1598
|
+
}),
|
|
1599
|
+
"dsg.organization.release/1#semantic.releaseEligibility": parse(ReleaseEligibilityContext, ({ eligibility, currentActiveSet, activeSet }) => {
|
|
1600
|
+
if (!same(eligibility.release, eligibility.observation.subject)) return "status-subject-mismatch";
|
|
1601
|
+
if (!same(eligibility.trustView, eligibility.observation.trustView)) return "stale-trust-view";
|
|
1602
|
+
if (eligibility.observation.status === "revoked") return "release-revoked";
|
|
1603
|
+
if (eligibility.observation.status !== "retired") return;
|
|
1604
|
+
if (eligibility.operation !== "execute" || eligibility.activeSet === null) return "release-retired";
|
|
1605
|
+
if (!same(eligibility.activeSet, currentActiveSet) || currentActiveSet.sha256 !== digest(activeSet)) return "inactive-set";
|
|
1606
|
+
if (!activeSet.members.some((member) => same(member.extensionRelease, eligibility.release))) return "release-not-active";
|
|
1607
|
+
}),
|
|
1608
|
+
"dsg.run.execution-binding/1#semantic.executionAuthorization": parse(ExecutionAuthorizationContext, ({ request, lease, accepted, checkedAt }) => {
|
|
1609
|
+
if (accepted.generation !== request.operation.expectedGeneration + 1) return "accepted-generation-mismatch";
|
|
1610
|
+
if (accepted.operationId !== request.operation.operationId) return "accepted-operation-mismatch";
|
|
1611
|
+
if (accepted.planDigest !== request.operation.planDigest) return "accepted-plan-mismatch";
|
|
1612
|
+
const { operation, binding } = request;
|
|
1613
|
+
if (!same(binding.reservation, operation.reservation)) return "binding-reservation-mismatch";
|
|
1614
|
+
if (lease.operationId !== operation.operationId) return "lease-operation-mismatch";
|
|
1615
|
+
if (lease.generation !== accepted.generation) return "lease-generation-mismatch";
|
|
1616
|
+
if (lease.caseOrn !== operation.case.orn) return "lease-case-mismatch";
|
|
1617
|
+
if (lease.envelopeSha256 !== digest(operation)) return "lease-envelope-mismatch";
|
|
1618
|
+
if (lease.lawSha256 !== operation.document.law.bundle.sha256) return "lease-law-mismatch";
|
|
1619
|
+
if (!same(lease.reservation, binding.reservation)) return "lease-reservation-mismatch";
|
|
1620
|
+
if (Date.parse(lease.expiresAt) <= Date.parse(lease.consumedAt)) return "invalid-dispatch-lease-window";
|
|
1621
|
+
if (Date.parse(checkedAt) >= Date.parse(lease.expiresAt)) return "expired-dispatch-lease";
|
|
1622
|
+
}),
|
|
1623
|
+
"dsg.run.execution-binding/1#semantic.executionIdentity": parse(ExecutionIdentityContext, ({ binding, operation, jobClass, workloadArtifact: artifact, workloadArtifactProvenance: provenance, admission, activeSet, releaseEligibility, selection, catalogEntry }) => {
|
|
1624
|
+
if (releaseEligibility.operation !== "execute") return "eligibility-operation-mismatch";
|
|
1625
|
+
if (releaseEligibility.observation.status === "revoked") return "release-revoked";
|
|
1626
|
+
if (!same(releaseEligibility.observation.subject, releaseEligibility.release)) return "eligibility-subject-mismatch";
|
|
1627
|
+
if (!same(releaseEligibility.observation.trustView, releaseEligibility.trustView)) return "eligibility-observation-trust-mismatch";
|
|
1628
|
+
if (releaseEligibility.observation.status === "retired" && (releaseEligibility.operation !== "execute" || releaseEligibility.activeSet === null || !same(releaseEligibility.activeSet, binding.activeSet))) return "release-retired";
|
|
1629
|
+
if (binding.selection.sha256 !== digest(selection)) return "selection-digest-mismatch";
|
|
1630
|
+
if (selection.id !== catalogEntry.selectionId || selection.id !== admission.selectionId) return "selection-id-mismatch";
|
|
1631
|
+
if (!same(selection.extensionRelease, binding.extensionRelease) || !same(catalogEntry.extensionRelease, binding.extensionRelease)) return "selection-release-mismatch";
|
|
1632
|
+
if (catalogEntry.availability !== "available") return "catalog-entry-unavailable";
|
|
1633
|
+
if (!same(catalogEntry.activeSet, binding.activeSet) || !same(catalogEntry.workflow, binding.workflow) || catalogEntry.jobClass === null || !same(catalogEntry.jobClass, binding.jobClass) || catalogEntry.workloadArtifact === null || !same(catalogEntry.workloadArtifact, binding.workloadArtifact)) return "catalog-binding-mismatch";
|
|
1634
|
+
if (!same(releaseEligibility.release, binding.extensionRelease)) return "eligibility-release-mismatch";
|
|
1635
|
+
if (!same(releaseEligibility.trustView, binding.trustView)) return "eligibility-trust-view-mismatch";
|
|
1636
|
+
if (releaseEligibility.activeSet === null || !same(releaseEligibility.activeSet, binding.activeSet)) return "eligibility-active-set-mismatch";
|
|
1637
|
+
if (admission.status !== "admitted") return "admission-refused";
|
|
1638
|
+
if (!admission.approvedUses.some((approved) => approved.use === "execute" && same(approved.binding, binding.jobClass))) return "execution-use-not-approved";
|
|
1639
|
+
if (operation.document.resources.maxRunSeconds > jobClass.bounds.maxRunSeconds) return "run-seconds-exceed-class";
|
|
1640
|
+
if (operation.document.resources.maxGpuSeconds > jobClass.bounds.maxGpuSeconds) return "gpu-seconds-exceed-class";
|
|
1641
|
+
if (operation.document.resources.maxParallelism > jobClass.bounds.maxParallelism) return "parallelism-exceeds-class";
|
|
1642
|
+
if (binding.admission.sha256 !== digest(admission)) return "admission-digest-mismatch";
|
|
1643
|
+
if (binding.activeSet.sha256 !== digest(activeSet)) return "active-set-digest-mismatch";
|
|
1644
|
+
if (binding.installation !== admission.installation || binding.installation !== activeSet.installation) return "installation-mismatch";
|
|
1645
|
+
if (!same(binding.organizationBuild, admission.build) || !same(binding.organizationBuild, activeSet.build)) return "organization-build-mismatch";
|
|
1646
|
+
if (!same(binding.organizationRelease, admission.release) || !same(binding.organizationRelease, activeSet.release)) return "organization-release-mismatch";
|
|
1647
|
+
if (!same(binding.extensionRelease, admission.extensionRelease)) return "admission-release-mismatch";
|
|
1648
|
+
const activeMember = activeSet.members.find((member) => same(member.admission, binding.admission) && same(member.extensionRelease, binding.extensionRelease));
|
|
1649
|
+
if (!activeMember) return "release-not-active";
|
|
1650
|
+
if (activeMember.selectionId !== selection.id || activeMember.memberId !== catalogEntry.memberId) return "active-member-identity-mismatch";
|
|
1651
|
+
const selectedComponents = selection.members.map((component) => component.reference);
|
|
1652
|
+
const activeComponents = activeMember.components.map((component) => component.reference);
|
|
1653
|
+
const admittedComponents = admission.components.map((component) => component.reference);
|
|
1654
|
+
for (const required of [
|
|
1655
|
+
binding.workflow,
|
|
1656
|
+
binding.jobClass,
|
|
1657
|
+
binding.workloadArtifact,
|
|
1658
|
+
binding.eventCatalog
|
|
1659
|
+
]) {
|
|
1660
|
+
if (!selectedComponents.some((component) => same(component, required))) return "selected-component-mismatch";
|
|
1661
|
+
if (!activeComponents.some((component) => same(component, required))) return "active-component-mismatch";
|
|
1662
|
+
if (!admittedComponents.some((component) => same(component, required))) return "admitted-component-mismatch";
|
|
1663
|
+
}
|
|
1664
|
+
if (binding.operation.sha256 !== digest(operation)) return "operation-digest-mismatch";
|
|
1665
|
+
if (!same(binding.target, operation.document.placement)) return "operation-target-mismatch";
|
|
1666
|
+
if (!same(binding.jobClass, operation.document.classContract)) return "operation-job-class-mismatch";
|
|
1667
|
+
if (!same(binding.workloadArtifact, operation.document.workload)) return "operation-workload-mismatch";
|
|
1668
|
+
if (!same(binding.law, operation.document.law.bundle)) return "operation-law-mismatch";
|
|
1669
|
+
if (binding.workloadArtifact.sha256 !== digest(artifact)) return "artifact-metadata-digest-mismatch";
|
|
1670
|
+
if (binding.jobClass.sha256 !== digest(jobClass)) return "job-class-digest-mismatch";
|
|
1671
|
+
if (!same(jobClass.workloadArtifact, binding.workloadArtifact)) return "job-class-artifact-mismatch";
|
|
1672
|
+
if (!same(jobClass.eventCatalog, binding.eventCatalog)) return "event-catalog-mismatch";
|
|
1673
|
+
if (!same(provenance.artifact, binding.workloadArtifact)) return "provenance-subject-mismatch";
|
|
1674
|
+
if ((0, _dynamicalsystems_orn_schemas.jcsStringify)(provenance.source) !== (0, _dynamicalsystems_orn_schemas.jcsStringify)(artifact.source)) return "source-provenance-mismatch";
|
|
1675
|
+
if (binding.executableManifestSha256 !== artifact.executable.manifest.sha256) return "wrong-executable-digest-role";
|
|
1676
|
+
if (artifact.executable.platform.os !== "linux" || artifact.executable.platform.architecture !== "amd64") return "unsupported-executable-platform";
|
|
1677
|
+
if (!jobClass.platforms.includes(`${artifact.executable.platform.os}/${artifact.executable.platform.architecture}`)) return "job-class-platform-mismatch";
|
|
1678
|
+
})
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
//#endregion
|
|
1433
1682
|
//#region src/reference-adapter.ts
|
|
1434
1683
|
function referenceAdapter() {
|
|
1435
1684
|
const adapter = {};
|
|
@@ -1468,6 +1717,7 @@ function referenceAdapter() {
|
|
|
1468
1717
|
};
|
|
1469
1718
|
}
|
|
1470
1719
|
adapter[`${_dynamicalsystems_idl.EVENT_PROFILE}#digest.streamSeal`] = streamDigest;
|
|
1720
|
+
Object.assign(adapter, releaseSemanticAdapters());
|
|
1471
1721
|
return adapter;
|
|
1472
1722
|
}
|
|
1473
1723
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamicalsystems/idl-conformance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"homepage": "https://github.com/DynamicalSystemsGroup/dsg-idl#readme",
|
|
5
5
|
"bugs": "https://github.com/DynamicalSystemsGroup/dsg-idl/issues",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@dynamicalsystems/orn-schemas": "0.1.0",
|
|
43
|
-
"@dynamicalsystems/idl": "0.
|
|
43
|
+
"@dynamicalsystems/idl": "0.13.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "24.13.3",
|
package/src/reference-adapter.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { jcsStringify } from "@dynamicalsystems/orn-schemas";
|
|
|
8
8
|
import { PROFILES, EVENT_PROFILE } from "@dynamicalsystems/idl";
|
|
9
9
|
import type { Adapter, ParseResult } from "./adapter.js";
|
|
10
10
|
import { streamDigest } from "./stream-digest.js";
|
|
11
|
+
import { releaseSemanticAdapters } from "./release-semantics.js";
|
|
11
12
|
|
|
12
13
|
export function referenceAdapter(): Adapter {
|
|
13
14
|
const adapter: Record<string, (bytes: Uint8Array) => ParseResult> = {};
|
|
@@ -40,5 +41,6 @@ export function referenceAdapter(): Adapter {
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
adapter[`${EVENT_PROFILE}#digest.streamSeal`] = streamDigest;
|
|
44
|
+
Object.assign(adapter, releaseSemanticAdapters());
|
|
43
45
|
return adapter;
|
|
44
46
|
}
|