owlrunkit 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/CHANGELOG.md +9 -0
- package/LICENSE +674 -0
- package/NOTICE.md +137 -0
- package/README.md +44 -0
- package/SOURCE.md +10 -0
- package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_1.md +160 -0
- package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +459 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +408 -0
- package/integrations/codex/skills/owlcoda-runkit/agents/openai.yaml +4 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/agents-snippet.md +7 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +10 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/coverage-adopt-request.json +26 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/execution-delivery-packet.json +13 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/finalize-request.json +18 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/goal-contract.json +11 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/profiles.json +9 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/ready-for-commit-request.json +11 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/resource-preflight-request.json +56 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/resume-request.json +10 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/snapshot-request.json +23 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/verification-context.json +15 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/verification-receipt.json +11 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/verify-plan-request.json +31 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/visual-smoke-request.json +32 -0
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/worker-lease.json +7 -0
- package/package.json +24 -0
- package/packages/attest/LICENSE +674 -0
- package/packages/attest/README.md +63 -0
- package/packages/attest/cli/owlcoda-attest.mjs +155 -0
- package/packages/attest/consumer-surface-v1.json +255 -0
- package/packages/attest/distribution-manifest-v1.json +104 -0
- package/packages/attest/fixtures/bad/accepted-authority-leak.json +7 -0
- package/packages/attest/fixtures/bad/accepted-failed-receipt.json +7 -0
- package/packages/attest/fixtures/bad/active-context-binding-mismatch.json +7 -0
- package/packages/attest/fixtures/bad/active-source-binding-mismatch.json +7 -0
- package/packages/attest/fixtures/bad/context-fingerprint-mismatch.json +7 -0
- package/packages/attest/fixtures/bad/duplicate-object-key.json +8 -0
- package/packages/attest/fixtures/bad/multiple-active-leaves.json +10 -0
- package/packages/attest/fixtures/bad/orphan-replacement.json +7 -0
- package/packages/attest/fixtures/bad/root-shape-extra-property.json +8 -0
- package/packages/attest/fixtures/bad/source-fingerprint-mismatch.json +7 -0
- package/packages/attest/fixtures/good/accepted-replacement-chain.json +59 -0
- package/packages/attest/fixtures/good/blocked-single-leaf.json +9 -0
- package/packages/attest/fixtures/index.json +90 -0
- package/packages/attest/sbom.spdx.json +33 -0
- package/packages/attest/schemas/attestation-ref-v1.schema.json +44 -0
- package/packages/attest/schemas/attestation-result-v1.schema.json +163 -0
- package/packages/attest/schemas/offline-attestation-bundle-v1.schema.json +30 -0
- package/packages/attest/schemas/public-verification-bundle-v1.schema.json +74 -0
- package/packages/attest/schemas/quick-verification-receipt-v1.schema.json +219 -0
- package/packages/attest/schemas/workspace-snapshot-v1.schema.json +135 -0
- package/packages/attest/src/canonical.mjs +12 -0
- package/packages/attest/src/formal.mjs +762 -0
- package/packages/attest/src/index.mjs +113 -0
- package/packages/attest/src/offline-bundle.mjs +108 -0
- package/packages/attest/src/quick-receipt-contract.mjs +156 -0
- package/packages/attest/src/quick.mjs +274 -0
- package/packages/attest/src/reference-contract.mjs +64 -0
- package/packages/attest/src/reference.mjs +131 -0
- package/packages/attest/src/workspace-snapshot.mjs +171 -0
- package/registry-release-policy-v1.json +34 -0
- package/sbom.spdx.json +39 -0
- package/scripts/runkit-contract/acceptance-evidence.mjs +103 -0
- package/scripts/runkit-contract/core-contract.mjs +392 -0
- package/scripts/runkit-contract/coverage-adoption.mjs +414 -0
- package/scripts/runkit-contract/delivery-create.mjs +252 -0
- package/scripts/runkit-contract/delivery-selection.mjs +31 -0
- package/scripts/runkit-contract/finalize.mjs +790 -0
- package/scripts/runkit-contract/inspect-presentation.mjs +183 -0
- package/scripts/runkit-contract/install-codex-skill.mjs +239 -0
- package/scripts/runkit-contract/lease-lifecycle.mjs +324 -0
- package/scripts/runkit-contract/lifecycle-orchestration.mjs +415 -0
- package/scripts/runkit-contract/offline-store.mjs +248 -0
- package/scripts/runkit-contract/profile-impact.mjs +223 -0
- package/scripts/runkit-contract/provenance-common.mjs +153 -0
- package/scripts/runkit-contract/quick-attest.mjs +4 -0
- package/scripts/runkit-contract/quick-canonical.mjs +41 -0
- package/scripts/runkit-contract/quick-metrics.mjs +86 -0
- package/scripts/runkit-contract/quick-receipt.mjs +139 -0
- package/scripts/runkit-contract/quick-verify.mjs +201 -0
- package/scripts/runkit-contract/quick-workspace-snapshot.mjs +3 -0
- package/scripts/runkit-contract/ready-for-commit.mjs +188 -0
- package/scripts/runkit-contract/receipt-lineage.mjs +332 -0
- package/scripts/runkit-contract/registry-adoption-gate.mjs +117 -0
- package/scripts/runkit-contract/repair-execution.mjs +997 -0
- package/scripts/runkit-contract/resource-preflight.mjs +829 -0
- package/scripts/runkit-contract/resume-execution.mjs +569 -0
- package/scripts/runkit-contract/runkit-cli.mjs +1214 -0
- package/scripts/runkit-contract/schemas/closeout-receipt-v2.schema.json +42 -0
- package/scripts/runkit-contract/schemas/core-artifact-v2.schema.json +23 -0
- package/scripts/runkit-contract/schemas/core-artifact.schema.json +23 -0
- package/scripts/runkit-contract/schemas/coverage-adopt-request-v1.schema.json +66 -0
- package/scripts/runkit-contract/schemas/engine-pin-v2.schema.json +14 -0
- package/scripts/runkit-contract/schemas/engine-pin.schema.json +14 -0
- package/scripts/runkit-contract/schemas/evidence-coverage-index-v1.schema.json +131 -0
- package/scripts/runkit-contract/schemas/finalize-request-v1.schema.json +131 -0
- package/scripts/runkit-contract/schemas/profiles.schema.json +47 -0
- package/scripts/runkit-contract/schemas/project-config-v2.schema.json +13 -0
- package/scripts/runkit-contract/schemas/project-config.schema.json +13 -0
- package/scripts/runkit-contract/schemas/ready-for-commit-v1.schema.json +26 -0
- package/scripts/runkit-contract/schemas/replayable-evidence-v1.schema.json +82 -0
- package/scripts/runkit-contract/schemas/resource-preflight-request-v1.schema.json +178 -0
- package/scripts/runkit-contract/schemas/resource-preflight-v1.schema.json +153 -0
- package/scripts/runkit-contract/schemas/resume-attempt-v1.schema.json +80 -0
- package/scripts/runkit-contract/schemas/resume-request-v1.schema.json +77 -0
- package/scripts/runkit-contract/schemas/snapshot-v1.schema.json +71 -0
- package/scripts/runkit-contract/schemas/verification-context-v1.schema.json +92 -0
- package/scripts/runkit-contract/schemas/verification-plan-v1.schema.json +150 -0
- package/scripts/runkit-contract/schemas/verification-receipt-v2.schema.json +118 -0
- package/scripts/runkit-contract/schemas/verify-plan-request-v1.schema.json +56 -0
- package/scripts/runkit-contract/schemas/visual-smoke-request-v1.schema.json +64 -0
- package/scripts/runkit-contract/schemas/visual-smoke-result-v1.schema.json +68 -0
- package/scripts/runkit-contract/snapshot.mjs +340 -0
- package/scripts/runkit-contract/source-fingerprint.mjs +404 -0
- package/scripts/runkit-contract/templates/coverage-adopt-request.json +26 -0
- package/scripts/runkit-contract/templates/finalize-request.json +18 -0
- package/scripts/runkit-contract/templates/goal-contract.json +11 -0
- package/scripts/runkit-contract/templates/ready-for-commit-request.json +11 -0
- package/scripts/runkit-contract/templates/resource-preflight-request.json +56 -0
- package/scripts/runkit-contract/templates/resume-request.json +10 -0
- package/scripts/runkit-contract/templates/snapshot-request.json +23 -0
- package/scripts/runkit-contract/templates/verify-plan-request.json +31 -0
- package/scripts/runkit-contract/templates/visual-smoke-request.json +32 -0
- package/scripts/runkit-contract/templates/worker-lease.json +7 -0
- package/scripts/runkit-contract/verification-context.mjs +141 -0
- package/scripts/runkit-contract/verification-plan.mjs +608 -0
- package/scripts/runkit-contract/verification-receipt-gate.mjs +566 -0
- package/scripts/runkit-contract/visual-smoke.mjs +410 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
4
|
+
const REUSE_POLICIES = new Set([
|
|
5
|
+
"portable",
|
|
6
|
+
"platform_bound",
|
|
7
|
+
"environment_bound",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function validateAllowedKeys(value, label, allowedKeys) {
|
|
15
|
+
if (!isRecord(value)) return [];
|
|
16
|
+
const allowed = new Set(allowedKeys);
|
|
17
|
+
return Object.keys(value)
|
|
18
|
+
.filter((key) => !allowed.has(key))
|
|
19
|
+
.map((key) => `${label} contains unsupported field: ${key}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function canonicalJson(value) {
|
|
23
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
24
|
+
if (isRecord(value)) {
|
|
25
|
+
return `{${Object.keys(value)
|
|
26
|
+
.sort()
|
|
27
|
+
.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
|
|
28
|
+
.join(",")}}`;
|
|
29
|
+
}
|
|
30
|
+
return JSON.stringify(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function validateNamedEntries(values, label, fields) {
|
|
34
|
+
const issues = [];
|
|
35
|
+
if (!Array.isArray(values)) return [`${label} must be an array.`];
|
|
36
|
+
const identities = new Set();
|
|
37
|
+
for (const [index, value] of values.entries()) {
|
|
38
|
+
if (!isRecord(value)) {
|
|
39
|
+
issues.push(`${label}[${index}] must be an object.`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
issues.push(...validateAllowedKeys(value, `${label}[${index}]`, fields));
|
|
43
|
+
for (const field of fields) {
|
|
44
|
+
if (typeof value[field] !== "string" || value[field].length === 0) {
|
|
45
|
+
issues.push(`${label}[${index}].${field} must be a non-empty string.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const identity = value[fields[0]];
|
|
49
|
+
if (typeof identity === "string") {
|
|
50
|
+
if (identities.has(identity)) issues.push(`${label} contains duplicate ${fields[0]}: ${identity}`);
|
|
51
|
+
identities.add(identity);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return issues;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validateHashEntries(values, label, identityField, hashField) {
|
|
58
|
+
const issues = validateNamedEntries(values, label, [identityField, hashField]);
|
|
59
|
+
if (Array.isArray(values)) {
|
|
60
|
+
for (const [index, value] of values.entries()) {
|
|
61
|
+
if (isRecord(value) && typeof value[hashField] === "string" && !SHA256_PATTERN.test(value[hashField])) {
|
|
62
|
+
issues.push(`${label}[${index}].${hashField} must be a lowercase SHA-256.`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return issues;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function validateVerificationContext(context) {
|
|
70
|
+
if (!isRecord(context)) return { valid: false, issues: ["Verification context must be an object."] };
|
|
71
|
+
const issues = validateAllowedKeys(context, "Verification context", [
|
|
72
|
+
"schemaVersion",
|
|
73
|
+
"reusePolicy",
|
|
74
|
+
"platform",
|
|
75
|
+
"toolchains",
|
|
76
|
+
"lockfiles",
|
|
77
|
+
"fixtures",
|
|
78
|
+
"services",
|
|
79
|
+
"environment",
|
|
80
|
+
]);
|
|
81
|
+
if (context.schemaVersion !== "OwlCodaRunKitVerificationContextV1") {
|
|
82
|
+
issues.push("Unsupported verification context schemaVersion.");
|
|
83
|
+
}
|
|
84
|
+
if (!REUSE_POLICIES.has(context.reusePolicy)) {
|
|
85
|
+
issues.push("reusePolicy must be portable, platform_bound, or environment_bound.");
|
|
86
|
+
}
|
|
87
|
+
if (context.reusePolicy === "portable" && context.platform !== null) {
|
|
88
|
+
issues.push("portable verification context must use platform=null.");
|
|
89
|
+
}
|
|
90
|
+
if (context.reusePolicy !== "portable") {
|
|
91
|
+
if (!isRecord(context.platform)
|
|
92
|
+
|| typeof context.platform.os !== "string"
|
|
93
|
+
|| typeof context.platform.arch !== "string") {
|
|
94
|
+
issues.push("Bound verification context requires platform.os and platform.arch.");
|
|
95
|
+
} else {
|
|
96
|
+
issues.push(...validateAllowedKeys(context.platform, "platform", ["os", "arch"]));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
issues.push(...validateNamedEntries(context.toolchains, "toolchains", ["name", "version"]));
|
|
100
|
+
issues.push(...validateHashEntries(context.lockfiles, "lockfiles", "path", "sha256"));
|
|
101
|
+
issues.push(...validateHashEntries(context.fixtures, "fixtures", "id", "sha256"));
|
|
102
|
+
issues.push(...validateNamedEntries(context.services, "services", ["id", "identity"]));
|
|
103
|
+
issues.push(...validateHashEntries(context.environment, "environment", "name", "valueSha256"));
|
|
104
|
+
if (
|
|
105
|
+
context.reusePolicy === "environment_bound"
|
|
106
|
+
&& Array.isArray(context.fixtures)
|
|
107
|
+
&& Array.isArray(context.services)
|
|
108
|
+
&& Array.isArray(context.environment)
|
|
109
|
+
&& context.fixtures.length + context.services.length + context.environment.length === 0
|
|
110
|
+
) {
|
|
111
|
+
issues.push("environment_bound verification context requires material fixtures, services, or environment identity.");
|
|
112
|
+
}
|
|
113
|
+
return { valid: issues.length === 0, issues };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function sortedEntries(values) {
|
|
117
|
+
return [...values].map((value) => structuredClone(value)).sort((left, right) => {
|
|
118
|
+
const leftCanonical = canonicalJson(left);
|
|
119
|
+
const rightCanonical = canonicalJson(right);
|
|
120
|
+
return leftCanonical < rightCanonical ? -1 : leftCanonical > rightCanonical ? 1 : 0;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function canonicalVerificationContext(context) {
|
|
125
|
+
const validation = validateVerificationContext(context);
|
|
126
|
+
if (!validation.valid) throw new Error(validation.issues.join("; "));
|
|
127
|
+
return canonicalJson({
|
|
128
|
+
schemaVersion: context.schemaVersion,
|
|
129
|
+
reusePolicy: context.reusePolicy,
|
|
130
|
+
platform: context.platform === null ? null : structuredClone(context.platform),
|
|
131
|
+
toolchains: sortedEntries(context.toolchains),
|
|
132
|
+
lockfiles: sortedEntries(context.lockfiles),
|
|
133
|
+
fixtures: sortedEntries(context.fixtures),
|
|
134
|
+
services: sortedEntries(context.services),
|
|
135
|
+
environment: sortedEntries(context.environment),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function verificationContextFingerprint(context) {
|
|
140
|
+
return createHash("sha256").update(canonicalVerificationContext(context)).digest("hex");
|
|
141
|
+
}
|