owlrunkit 0.15.0 → 0.16.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 +100 -0
- package/README.md +274 -66
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +223 -117
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/ready-for-commit-request.json +2 -2
- package/package.json +2 -2
- package/packages/attest/distribution-manifest-v1.json +10 -0
- package/packages/attest/src/quick.mjs +10 -0
- package/registry-release-policy-v1.json +8 -2
- package/sbom.spdx.json +5 -5
- package/scripts/runkit-contract/assurance-router.mjs +119 -0
- package/scripts/runkit-contract/core-contract.mjs +250 -115
- package/scripts/runkit-contract/core-successor.mjs +2043 -0
- package/scripts/runkit-contract/deployment-workflow.mjs +2040 -0
- package/scripts/runkit-contract/finalize.mjs +242 -21
- package/scripts/runkit-contract/fleet-discovery.mjs +456 -0
- package/scripts/runkit-contract/formal-workflow.mjs +850 -0
- package/scripts/runkit-contract/human-status.mjs +553 -0
- package/scripts/runkit-contract/inspect-presentation.mjs +25 -8
- package/scripts/runkit-contract/install-codex-skill.mjs +73 -30
- package/scripts/runkit-contract/lease-lifecycle.mjs +8 -2
- package/scripts/runkit-contract/lifecycle-orchestration.mjs +135 -12
- package/scripts/runkit-contract/onboarding-doctor.mjs +43 -90
- package/scripts/runkit-contract/owner-authority-trust.mjs +230 -0
- package/scripts/runkit-contract/owner-deployment-decision.mjs +385 -0
- package/scripts/runkit-contract/profile-onboarding.mjs +841 -13
- package/scripts/runkit-contract/project-cli-resolver.mjs +701 -0
- package/scripts/runkit-contract/project-control-parser.mjs +830 -0
- package/scripts/runkit-contract/project-control-state.mjs +28 -0
- package/scripts/runkit-contract/provenance-common.mjs +19 -2
- package/scripts/runkit-contract/ready-for-commit.mjs +330 -18
- package/scripts/runkit-contract/remote-deployment.mjs +1596 -0
- package/scripts/runkit-contract/remote-process-adapter.mjs +177 -0
- package/scripts/runkit-contract/runkit-bootstrap.mjs +131 -0
- package/scripts/runkit-contract/runkit-cli.mjs +1097 -21
- package/scripts/runkit-contract/schemas/assurance-route-v1.schema.json +26 -0
- package/scripts/runkit-contract/schemas/core-successor-batch-receipt-v1.schema.json +126 -0
- package/scripts/runkit-contract/schemas/core-successor-plan-v1.schema.json +155 -0
- package/scripts/runkit-contract/schemas/core-successor-project-success-receipt-v1.schema.json +72 -0
- package/scripts/runkit-contract/schemas/deployment-execute-request-v1.schema.json +63 -0
- package/scripts/runkit-contract/schemas/deployment-lineage-v1.schema.json +292 -0
- package/scripts/runkit-contract/schemas/deployment-prepare-receipt-v1.schema.json +140 -0
- package/scripts/runkit-contract/schemas/fleet-discovery-v1.schema.json +31 -0
- package/scripts/runkit-contract/schemas/fleet-manifest-v1.schema.json +20 -0
- package/scripts/runkit-contract/schemas/fleet-root-registry-v1.schema.json +34 -0
- package/scripts/runkit-contract/schemas/human-status-v1.schema.json +102 -0
- package/scripts/runkit-contract/schemas/owner-authority-trust-v1.schema.json +66 -0
- package/scripts/runkit-contract/schemas/owner-deployment-authority-v1.schema.json +46 -0
- package/scripts/runkit-contract/schemas/owner-deployment-authority-v2.schema.json +94 -0
- package/scripts/runkit-contract/schemas/owner-deployment-decision-v1.schema.json +102 -0
- package/scripts/runkit-contract/schemas/owner-migration-authority-v1.schema.json +33 -0
- package/scripts/runkit-contract/schemas/owner-migration-authority-v2.schema.json +67 -0
- package/scripts/runkit-contract/schemas/profile-apply-receipt-v1.schema.json +32 -0
- package/scripts/runkit-contract/schemas/profile-detection-v2.schema.json +145 -0
- package/scripts/runkit-contract/schemas/ready-for-commit-v2.schema.json +37 -0
- package/scripts/runkit-contract/schemas/remote-deployment-manifest-v1.schema.json +379 -0
- package/scripts/runkit-contract/schemas/remote-deployment-result-v1.schema.json +153 -0
- package/scripts/runkit-contract/schemas/remote-deployment-stage-journal-v1.schema.json +183 -0
- package/scripts/runkit-contract/schemas/remote-target-v1.schema.json +32 -0
- package/scripts/runkit-contract/schemas/source-candidate-v2.schema.json +152 -0
- package/scripts/runkit-contract/schemas/verification-receipt-v2.schema.json +13 -0
- package/scripts/runkit-contract/snapshot.mjs +1 -1
- package/scripts/runkit-contract/source-candidate.mjs +1382 -0
- package/scripts/runkit-contract/ssh-remote-adapter.mjs +1184 -0
- package/scripts/runkit-contract/sync-core016-release-identity.mjs +161 -0
- package/scripts/runkit-contract/templates/assurance-request.json +13 -0
- package/scripts/runkit-contract/templates/core-successor-owner-authority.json +15 -0
- package/scripts/runkit-contract/templates/deployment-execute-request.json +39 -0
- package/scripts/runkit-contract/templates/deployment-owner-authority.json +23 -0
- package/scripts/runkit-contract/templates/deployment-owner-decision.json +26 -0
- package/scripts/runkit-contract/templates/fleet-manifest.json +8 -0
- package/scripts/runkit-contract/templates/fleet-root-registry.json +8 -0
- package/scripts/runkit-contract/templates/owner-authority-trust.json +16 -0
- package/scripts/runkit-contract/templates/ready-for-commit-request.json +2 -2
- package/scripts/runkit-contract/templates/remote-deployment-manifest.json +108 -0
- package/scripts/runkit-contract/verification-receipt-gate.mjs +28 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
readFileSync,
|
|
5
|
+
renameSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
import { currentCoreIdentity } from "./core-contract.mjs";
|
|
12
|
+
|
|
13
|
+
const RELEASE_FILES = Object.freeze({
|
|
14
|
+
packageManifest: "packages/runkit/package.json",
|
|
15
|
+
attestManifest: "packages/attest/distribution-manifest-v1.json",
|
|
16
|
+
attestRuntime: "packages/attest/src/quick.mjs",
|
|
17
|
+
skillMarkdown: "integrations/codex/skills/owlcoda-runkit/SKILL.md",
|
|
18
|
+
skillConfig:
|
|
19
|
+
"integrations/codex/skills/owlcoda-runkit/assets/templates/config.json",
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const ATTEST_RUNTIME_CORE016 =
|
|
23
|
+
/(coreVersion:\s*"0\.16\.0",\s*coreManifestSha256:\s*")sha256:[a-f0-9]{64}("\s*,?)/gu;
|
|
24
|
+
|
|
25
|
+
function readJson(ref) {
|
|
26
|
+
return JSON.parse(readFileSync(ref, "utf8"));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function bytes(value) {
|
|
30
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function writeAtomic(ref, value) {
|
|
34
|
+
const temporary = `${ref}.sync-${process.pid}`;
|
|
35
|
+
writeFileSync(temporary, value, { flag: "wx" });
|
|
36
|
+
renameSync(temporary, ref);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function exactCore(actual, expected, includeSourceRef) {
|
|
40
|
+
return actual?.contractVersion === expected.contractVersion
|
|
41
|
+
&& actual?.coreVersion === expected.coreVersion
|
|
42
|
+
&& actual?.coreManifestSha256 === expected.coreManifestSha256
|
|
43
|
+
&& (
|
|
44
|
+
!includeSourceRef
|
|
45
|
+
|| actual?.coreSourceRef === expected.coreSourceRef
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function synchronizeCore016ReleaseIdentityV1({
|
|
50
|
+
repositoryRoot,
|
|
51
|
+
core,
|
|
52
|
+
write = false,
|
|
53
|
+
}) {
|
|
54
|
+
const root = path.resolve(repositoryRoot);
|
|
55
|
+
if (
|
|
56
|
+
core?.contractVersion !== "0.2"
|
|
57
|
+
|| core?.coreVersion !== "0.16.0"
|
|
58
|
+
|| !/^sha256:[a-f0-9]{64}$/u.test(
|
|
59
|
+
core?.coreManifestSha256 ?? "",
|
|
60
|
+
)
|
|
61
|
+
|| core?.coreSourceRef !== `artifact:${core.coreManifestSha256}`
|
|
62
|
+
) throw new Error("core016_release_identity_invalid");
|
|
63
|
+
const refs = Object.fromEntries(Object.entries(RELEASE_FILES).map(
|
|
64
|
+
([key, relative]) => [key, path.join(root, relative)],
|
|
65
|
+
));
|
|
66
|
+
const packageManifest = readJson(refs.packageManifest);
|
|
67
|
+
if (
|
|
68
|
+
packageManifest.name !== "owlrunkit"
|
|
69
|
+
|| packageManifest.version !== "0.16.0"
|
|
70
|
+
) throw new Error("core016_release_package_invalid");
|
|
71
|
+
const attestManifest = readJson(refs.attestManifest);
|
|
72
|
+
const candidateIndexes = attestManifest.supportedProducerCoreIdentities
|
|
73
|
+
?.map((identity, index) => ({ identity, index }))
|
|
74
|
+
.filter(({ identity }) => identity?.coreVersion === "0.16.0") ?? [];
|
|
75
|
+
if (candidateIndexes.length !== 1) {
|
|
76
|
+
throw new Error("core016_release_attest_candidate_ambiguous");
|
|
77
|
+
}
|
|
78
|
+
const attestRuntime = readFileSync(refs.attestRuntime, "utf8");
|
|
79
|
+
const runtimeMatches = [...attestRuntime.matchAll(ATTEST_RUNTIME_CORE016)];
|
|
80
|
+
if (runtimeMatches.length !== 1) {
|
|
81
|
+
throw new Error("core016_release_attest_runtime_candidate_ambiguous");
|
|
82
|
+
}
|
|
83
|
+
const skillMarkdown = readFileSync(refs.skillMarkdown, "utf8");
|
|
84
|
+
const skillHashes = skillMarkdown.match(/sha256:[a-f0-9]{64}/gu) ?? [];
|
|
85
|
+
if (skillHashes.length !== 1) {
|
|
86
|
+
throw new Error("core016_release_skill_identity_ambiguous");
|
|
87
|
+
}
|
|
88
|
+
const skillConfig = readJson(refs.skillConfig);
|
|
89
|
+
const mismatches = [];
|
|
90
|
+
if (!exactCore(candidateIndexes[0].identity, core, false)) {
|
|
91
|
+
mismatches.push("attest");
|
|
92
|
+
}
|
|
93
|
+
if (!runtimeMatches[0][0].includes(core.coreManifestSha256)) {
|
|
94
|
+
mismatches.push("attest_runtime");
|
|
95
|
+
}
|
|
96
|
+
if (skillHashes[0] !== core.coreManifestSha256) {
|
|
97
|
+
mismatches.push("skill_markdown");
|
|
98
|
+
}
|
|
99
|
+
if (!exactCore(skillConfig.core, core, true)) {
|
|
100
|
+
mismatches.push("skill_config");
|
|
101
|
+
}
|
|
102
|
+
if (write && mismatches.length > 0) {
|
|
103
|
+
attestManifest.supportedProducerCoreIdentities[
|
|
104
|
+
candidateIndexes[0].index
|
|
105
|
+
] = {
|
|
106
|
+
contractVersion: core.contractVersion,
|
|
107
|
+
coreVersion: core.coreVersion,
|
|
108
|
+
coreManifestSha256: core.coreManifestSha256,
|
|
109
|
+
};
|
|
110
|
+
writeAtomic(refs.attestManifest, bytes(attestManifest));
|
|
111
|
+
writeAtomic(
|
|
112
|
+
refs.attestRuntime,
|
|
113
|
+
attestRuntime.replace(
|
|
114
|
+
ATTEST_RUNTIME_CORE016,
|
|
115
|
+
`$1${core.coreManifestSha256}$2`,
|
|
116
|
+
),
|
|
117
|
+
);
|
|
118
|
+
writeAtomic(
|
|
119
|
+
refs.skillMarkdown,
|
|
120
|
+
skillMarkdown.replace(skillHashes[0], core.coreManifestSha256),
|
|
121
|
+
);
|
|
122
|
+
writeAtomic(refs.skillConfig, bytes({
|
|
123
|
+
...skillConfig,
|
|
124
|
+
core: structuredClone(core),
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
status: mismatches.length === 0 ? "exact" : write ? "synchronized" : "drifted",
|
|
129
|
+
core: structuredClone(core),
|
|
130
|
+
mismatches,
|
|
131
|
+
changed: write ? mismatches : [],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function main(argv) {
|
|
136
|
+
const write = argv.includes("--write");
|
|
137
|
+
const rootIndex = argv.indexOf("--repository-root");
|
|
138
|
+
const repositoryRoot = rootIndex === -1
|
|
139
|
+
? path.resolve(fileURLToPath(new URL("../..", import.meta.url)))
|
|
140
|
+
: argv[rootIndex + 1];
|
|
141
|
+
if (!repositoryRoot) throw new Error("repository_root_required");
|
|
142
|
+
const result = synchronizeCore016ReleaseIdentityV1({
|
|
143
|
+
repositoryRoot,
|
|
144
|
+
core: currentCoreIdentity(),
|
|
145
|
+
write,
|
|
146
|
+
});
|
|
147
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
148
|
+
if (!write && result.status !== "exact") process.exitCode = 2;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (process.argv[1]
|
|
152
|
+
&& path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
153
|
+
try {
|
|
154
|
+
main(process.argv.slice(2));
|
|
155
|
+
} catch (error) {
|
|
156
|
+
process.stderr.write(
|
|
157
|
+
`${error instanceof Error ? error.stack : String(error)}\n`,
|
|
158
|
+
);
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"needsDurableEvidence": true,
|
|
3
|
+
"needsFormalAcceptance": false,
|
|
4
|
+
"mayMutateProject": false,
|
|
5
|
+
"externalSideEffects": false,
|
|
6
|
+
"longRunning": false,
|
|
7
|
+
"interruptionRecovery": false,
|
|
8
|
+
"dirtyParallelWorkspace": false,
|
|
9
|
+
"exactCommandCount": 1,
|
|
10
|
+
"writerCount": 0,
|
|
11
|
+
"riskCategories": [],
|
|
12
|
+
"authorizationGranted": false
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitOwnerMigrationAuthorityV2",
|
|
3
|
+
"authorityId": "replace-with-owner-authority-id",
|
|
4
|
+
"decision": "approved",
|
|
5
|
+
"scope": "migrate_declared_core_successor_fleet",
|
|
6
|
+
"planSha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
7
|
+
"fromCoreSetSha256": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
8
|
+
"toCoreManifestSha256": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
9
|
+
"fleetManifestSha256": "sha256:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
10
|
+
"signerKeyId": "replace-with-owner-key-id",
|
|
11
|
+
"signatureAlgorithm": "ed25519",
|
|
12
|
+
"authorizationGranted": false,
|
|
13
|
+
"authoritySha256": "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
14
|
+
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitDeploymentExecuteRequestV1",
|
|
3
|
+
"executeRunId": "replace-with-execute-run-id",
|
|
4
|
+
"executeGoal": {
|
|
5
|
+
"path": ".owlcoda/runkit/executions/replace-with-execute-run-id/goal-contract.json",
|
|
6
|
+
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
7
|
+
},
|
|
8
|
+
"prepareReceiptSha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
9
|
+
"target": {
|
|
10
|
+
"schemaVersion": "OwlCodaRunKitRemoteTargetV1",
|
|
11
|
+
"targetId": "replace-with-target-id",
|
|
12
|
+
"environment": "production",
|
|
13
|
+
"host": "replace.example.invalid",
|
|
14
|
+
"port": 22,
|
|
15
|
+
"user": "deploy",
|
|
16
|
+
"hostKeySha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
17
|
+
"machineIdentitySha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
|
18
|
+
},
|
|
19
|
+
"ownerAuthority": {
|
|
20
|
+
"path": "authorities/replace-with-execute-run-id.json",
|
|
21
|
+
"sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
|
|
22
|
+
},
|
|
23
|
+
"ownerDecision": {
|
|
24
|
+
"path": "authorities/replace-with-owner-decision-id.json",
|
|
25
|
+
"sha256": "1111111111111111111111111111111111111111111111111111111111111111"
|
|
26
|
+
},
|
|
27
|
+
"ownerDecisionSnapshot": {
|
|
28
|
+
"path": ".owlcoda/runkit/deployments/replace-with-execute-run-id/owner-decision-snapshot.json",
|
|
29
|
+
"sha256": "2222222222222222222222222222222222222222222222222222222222222222"
|
|
30
|
+
},
|
|
31
|
+
"workItemId": "deployment-execute",
|
|
32
|
+
"profileId": "deployment",
|
|
33
|
+
"resourcePreflight": {
|
|
34
|
+
"path": ".owlcoda/runkit/executions/replace-with-execute-run-id/resource-preflights/replace-with-preflight-id.json",
|
|
35
|
+
"sha256": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
|
36
|
+
},
|
|
37
|
+
"deploy": true,
|
|
38
|
+
"destructive": false
|
|
39
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitOwnerDeploymentAuthorityV2",
|
|
3
|
+
"authorityId": "replace-with-owner-authority-id",
|
|
4
|
+
"decision": "approved",
|
|
5
|
+
"scope": "execute_exact_remote_deployment",
|
|
6
|
+
"executeRunId": "replace-with-execute-run-id",
|
|
7
|
+
"prepareReceiptSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
8
|
+
"targetSha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
9
|
+
"artifactSha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
10
|
+
"remoteManifestFileSha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
11
|
+
"remoteDeploymentIntentSha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
12
|
+
"ownerDecisionId": "replace-with-owner-decision-id",
|
|
13
|
+
"ownerDecisionSha256": "1111111111111111111111111111111111111111111111111111111111111111",
|
|
14
|
+
"signerKeyId": "replace-with-owner-key-id",
|
|
15
|
+
"signatureAlgorithm": "ed25519",
|
|
16
|
+
"permissions": {
|
|
17
|
+
"deploy": true,
|
|
18
|
+
"destructive": false
|
|
19
|
+
},
|
|
20
|
+
"authorizationGranted": false,
|
|
21
|
+
"authoritySha256": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
22
|
+
"signature": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
|
|
23
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitOwnerDeploymentDecisionV1",
|
|
3
|
+
"decisionId": "replace-with-owner-decision-id",
|
|
4
|
+
"decisionVersion": 1,
|
|
5
|
+
"provenance": {
|
|
6
|
+
"kind": "owner_explicit",
|
|
7
|
+
"sourceRef": "replace-with-owner-controlled-source-ref",
|
|
8
|
+
"recordedAt": "2026-08-01T00:00:00.000Z"
|
|
9
|
+
},
|
|
10
|
+
"project": {
|
|
11
|
+
"projectId": "replace-with-project-id",
|
|
12
|
+
"scope": "replace-with-deployment-scope"
|
|
13
|
+
},
|
|
14
|
+
"supersedesDecisionSha256": null,
|
|
15
|
+
"deploymentMode": "clean_install",
|
|
16
|
+
"existingProjectAssets": "replace",
|
|
17
|
+
"legacyRollbackAllowed": false,
|
|
18
|
+
"dataAuthority": {
|
|
19
|
+
"mode": "initialize_new",
|
|
20
|
+
"sourceRef": "replace-with-owner-controlled-data-authority-ref"
|
|
21
|
+
},
|
|
22
|
+
"serviceActivationAuthorized": false,
|
|
23
|
+
"baselineCutAuthorized": false,
|
|
24
|
+
"destructiveScope": [],
|
|
25
|
+
"decisionSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitOwnerAuthorityTrustV1",
|
|
3
|
+
"keys": [
|
|
4
|
+
{
|
|
5
|
+
"keyId": "replace-with-owner-key-id",
|
|
6
|
+
"algorithm": "ed25519",
|
|
7
|
+
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nreplace-with-ed25519-public-key\n-----END PUBLIC KEY-----\n",
|
|
8
|
+
"publicKeySha256": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
9
|
+
"purposes": [
|
|
10
|
+
"core_successor",
|
|
11
|
+
"remote_deployment"
|
|
12
|
+
],
|
|
13
|
+
"status": "active"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"schemaVersion": "
|
|
3
|
-
"
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitReadyForCommitRequestV2",
|
|
3
|
+
"sourceCandidatePath": ".owlcoda/runkit/executions/replace-with-run-id/source-candidates/replace-with-candidate.json",
|
|
4
4
|
"verificationGateInputPath": ".owlcoda/runkit/executions/replace-with-run-id/verification-receipts/replace-with-receipt/verification-gate-input.json",
|
|
5
5
|
"roots": [
|
|
6
6
|
{
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "OwlCodaRunKitRemoteDeploymentManifestV1",
|
|
3
|
+
"deploymentId": "replace-with-deployment-id",
|
|
4
|
+
"deploymentLineageSha256": null,
|
|
5
|
+
"mode": "first",
|
|
6
|
+
"ownerDecision": {
|
|
7
|
+
"decisionId": "replace-with-owner-decision-id",
|
|
8
|
+
"decisionVersion": 1,
|
|
9
|
+
"decisionSha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
10
|
+
"deploymentMode": "clean_install",
|
|
11
|
+
"existingProjectAssets": "replace",
|
|
12
|
+
"legacyRollbackAllowed": false,
|
|
13
|
+
"dataAuthority": {
|
|
14
|
+
"mode": "initialize_new",
|
|
15
|
+
"sourceRef": "replace-with-owner-controlled-data-authority-ref"
|
|
16
|
+
},
|
|
17
|
+
"serviceActivationAuthorized": false,
|
|
18
|
+
"baselineCutAuthorized": false,
|
|
19
|
+
"destructiveScope": []
|
|
20
|
+
},
|
|
21
|
+
"serviceActivation": false,
|
|
22
|
+
"baselineCut": false,
|
|
23
|
+
"target": {
|
|
24
|
+
"schemaVersion": "OwlCodaRunKitRemoteTargetV1",
|
|
25
|
+
"targetId": "replace-with-target-id",
|
|
26
|
+
"environment": "production",
|
|
27
|
+
"host": "replace.example.invalid",
|
|
28
|
+
"port": 22,
|
|
29
|
+
"user": "deploy",
|
|
30
|
+
"hostKeySha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
31
|
+
"machineIdentitySha256": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
|
32
|
+
},
|
|
33
|
+
"adapter": {
|
|
34
|
+
"kind": "builtin_ssh",
|
|
35
|
+
"adapterId": "builtin-ssh-v1",
|
|
36
|
+
"version": "1.0.0",
|
|
37
|
+
"executable": "/replace/with/exact/owlrunkit/scripts/runkit-contract/ssh-remote-adapter.mjs",
|
|
38
|
+
"sha256": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
39
|
+
"knownHostsPath": "/replace/with/exact/project/known_hosts",
|
|
40
|
+
"sshExecutable": "/usr/bin/ssh",
|
|
41
|
+
"sshExecutableSha256": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
42
|
+
"remoteHelper": {
|
|
43
|
+
"path": "/usr/local/libexec/owlrunkit-remote-helper",
|
|
44
|
+
"protocol": "OwlCodaRunKitSshRemoteHelperV1",
|
|
45
|
+
"version": "1.0.0",
|
|
46
|
+
"capabilities": [
|
|
47
|
+
"execute",
|
|
48
|
+
"reconcile"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"authentication": {
|
|
52
|
+
"mode": "agent",
|
|
53
|
+
"identityFile": null
|
|
54
|
+
},
|
|
55
|
+
"stageContracts": {
|
|
56
|
+
"install": {
|
|
57
|
+
"archiveFormat": "tar_gzip",
|
|
58
|
+
"releaseRoot": "/opt/owlapp/releases",
|
|
59
|
+
"currentSymlink": "/opt/owlapp/current"
|
|
60
|
+
},
|
|
61
|
+
"systemd": {
|
|
62
|
+
"unitName": "owlapp.service",
|
|
63
|
+
"unitFile": {
|
|
64
|
+
"sourcePath": "deploy/owlapp.service",
|
|
65
|
+
"destinationPath": "/etc/systemd/system/owlapp.service",
|
|
66
|
+
"sha256": "1111111111111111111111111111111111111111111111111111111111111111"
|
|
67
|
+
},
|
|
68
|
+
"daemonReload": true,
|
|
69
|
+
"enable": true,
|
|
70
|
+
"restart": true
|
|
71
|
+
},
|
|
72
|
+
"nginx": {
|
|
73
|
+
"siteName": "owlapp",
|
|
74
|
+
"configFile": {
|
|
75
|
+
"sourcePath": "deploy/owlapp.nginx.conf",
|
|
76
|
+
"destinationPath": "/etc/nginx/sites-available/owlapp.conf",
|
|
77
|
+
"sha256": "2222222222222222222222222222222222222222222222222222222222222222"
|
|
78
|
+
},
|
|
79
|
+
"enabledLinkPath": "/etc/nginx/sites-enabled/owlapp.conf",
|
|
80
|
+
"configTest": true,
|
|
81
|
+
"reload": true
|
|
82
|
+
},
|
|
83
|
+
"smoke": {
|
|
84
|
+
"checks": [
|
|
85
|
+
{
|
|
86
|
+
"checkId": "service-active",
|
|
87
|
+
"kind": "systemd_active",
|
|
88
|
+
"unitName": "owlapp.service"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"credentialRef": "agent:replace/with/credential-reference",
|
|
95
|
+
"artifact": {
|
|
96
|
+
"path": "dist/replace-with-artifact.tgz",
|
|
97
|
+
"sha256": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
98
|
+
"size": 0,
|
|
99
|
+
"mediaType": "application/gzip"
|
|
100
|
+
},
|
|
101
|
+
"upload": {
|
|
102
|
+
"remotePath": "/srv/releases/replace-with-artifact.tgz",
|
|
103
|
+
"createOnly": true
|
|
104
|
+
},
|
|
105
|
+
"priorDeployment": null,
|
|
106
|
+
"expectedRemoteFiles": [],
|
|
107
|
+
"deletionAllowlist": []
|
|
108
|
+
}
|
|
@@ -51,6 +51,33 @@ function isRisk(value) {
|
|
|
51
51
|
]).has(category));
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function validateSourceArtifactShape(receipt, sourceGate) {
|
|
55
|
+
if (receipt.sourceArtifact === undefined) return [];
|
|
56
|
+
const artifact = receipt.sourceArtifact;
|
|
57
|
+
if (
|
|
58
|
+
!isRecord(artifact)
|
|
59
|
+
|| !new Set(["delivery_packet_v1", "source_candidate_v2"])
|
|
60
|
+
.has(artifact.kind)
|
|
61
|
+
|| artifact.runId !== receipt.runId
|
|
62
|
+
|| typeof artifact.path !== "string"
|
|
63
|
+
|| artifact.path.length === 0
|
|
64
|
+
|| artifact.path.startsWith("/")
|
|
65
|
+
|| artifact.path.split("/").some(segment => (
|
|
66
|
+
segment.length === 0 || segment === "." || segment === ".."
|
|
67
|
+
))
|
|
68
|
+
|| !isSha256(artifact.sha256)
|
|
69
|
+
|| !isSha256(artifact.sourceFingerprint)
|
|
70
|
+
|| artifact.sourceFingerprint !== receipt.sourceFingerprint
|
|
71
|
+
|| artifact.sourceFingerprint !== sourceGate?.recomputedFingerprint
|
|
72
|
+
) {
|
|
73
|
+
return [issue(
|
|
74
|
+
"source_artifact_binding_malformed",
|
|
75
|
+
"sourceArtifact must exactly bind the active run, source bytes, path, and fingerprint.",
|
|
76
|
+
)];
|
|
77
|
+
}
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
|
|
54
81
|
function sameRisk(left, right) {
|
|
55
82
|
return left?.riskMode === right?.riskMode
|
|
56
83
|
&& JSON.stringify(left?.riskCategories) === JSON.stringify(right?.riskCategories);
|
|
@@ -425,6 +452,7 @@ export function validateVerificationReceiptGate({
|
|
|
425
452
|
if (commandReceiptShapeIssues.length > 0) {
|
|
426
453
|
return malformedResult(commandReceiptShapeIssues, lineage);
|
|
427
454
|
}
|
|
455
|
+
issues.push(...validateSourceArtifactShape(activeReceipt, sourceGate));
|
|
428
456
|
|
|
429
457
|
if (
|
|
430
458
|
activeReceipt.sourceFingerprint.toLowerCase()
|