owlrunkit 0.14.0 → 0.15.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 +27 -0
- package/README.md +46 -2
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +76 -14
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +1 -1
- package/package.json +1 -1
- package/packages/attest/distribution-manifest-v1.json +5 -0
- package/packages/attest/src/quick.mjs +5 -0
- package/registry-release-policy-v1.json +1 -1
- package/sbom.spdx.json +5 -5
- package/scripts/runkit-contract/core-contract.mjs +140 -4
- package/scripts/runkit-contract/install-codex-skill.mjs +505 -11
- package/scripts/runkit-contract/lifecycle-orchestration.mjs +119 -4
- package/scripts/runkit-contract/onboarding-doctor.mjs +205 -7
- package/scripts/runkit-contract/profile-onboarding.mjs +188 -10
- package/scripts/runkit-contract/registry-adoption-gate.mjs +111 -0
- package/scripts/runkit-contract/registry-adoption.mjs +2 -1
- package/scripts/runkit-contract/runkit-cli.mjs +65 -23
- package/scripts/runkit-contract/schemas/verification-finalize-attempt-v1.schema.json +52 -0
- package/scripts/runkit-contract/schemas/verification-preflight-v1.schema.json +52 -0
|
@@ -21,6 +21,45 @@ const RELEASE_EVIDENCE_FIELDS = Object.freeze([
|
|
|
21
21
|
"version",
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
|
+
const STORED_EVIDENCE_FIELDS = Object.freeze([
|
|
25
|
+
"authorizationGranted",
|
|
26
|
+
"authority",
|
|
27
|
+
"decision",
|
|
28
|
+
"exactSpec",
|
|
29
|
+
"installedBinding",
|
|
30
|
+
"packageName",
|
|
31
|
+
"registryRelease",
|
|
32
|
+
"schemaVersion",
|
|
33
|
+
"status",
|
|
34
|
+
"version",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const STORED_RELEASE_FIELDS = Object.freeze([
|
|
38
|
+
"integrity",
|
|
39
|
+
"packageName",
|
|
40
|
+
"registry",
|
|
41
|
+
"shasum",
|
|
42
|
+
"tarballUrl",
|
|
43
|
+
"version",
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
const STORED_INSTALL_FIELDS = Object.freeze([
|
|
47
|
+
"integrity",
|
|
48
|
+
"packageName",
|
|
49
|
+
"requestedSpec",
|
|
50
|
+
"resolved",
|
|
51
|
+
"version",
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
function isRecord(value) {
|
|
55
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function hasExactFields(value, fields) {
|
|
59
|
+
return isRecord(value)
|
|
60
|
+
&& Object.keys(value).sort().join("\n") === [...fields].sort().join("\n");
|
|
61
|
+
}
|
|
62
|
+
|
|
24
63
|
function decision(policy, issueCodes) {
|
|
25
64
|
return {
|
|
26
65
|
schemaVersion: "OwlCodaRunKitRegistryAdoptionDecisionV1",
|
|
@@ -45,6 +84,78 @@ export function isCanonicalSha512Integrity(value) {
|
|
|
45
84
|
return bytes.length === 64 && bytes.toString("base64") === match[1];
|
|
46
85
|
}
|
|
47
86
|
|
|
87
|
+
export function validateStoredRegistryAdoptionEvidence({
|
|
88
|
+
evidence,
|
|
89
|
+
packageName,
|
|
90
|
+
version,
|
|
91
|
+
localInstall,
|
|
92
|
+
}) {
|
|
93
|
+
const issues = [];
|
|
94
|
+
const exactSpec = `${packageName}@${version}`;
|
|
95
|
+
const expectedTarball = expectedRegistryTarballUrl(packageName, version);
|
|
96
|
+
if (
|
|
97
|
+
!hasExactFields(evidence, STORED_EVIDENCE_FIELDS)
|
|
98
|
+
|| evidence.schemaVersion !== "OwlCodaRunKitRegistryAdoptionEvidenceV1"
|
|
99
|
+
|| evidence.status !== "adopted"
|
|
100
|
+
|| evidence.decision !== "ELIGIBLE"
|
|
101
|
+
|| evidence.packageName !== packageName
|
|
102
|
+
|| evidence.version !== version
|
|
103
|
+
|| evidence.exactSpec !== exactSpec
|
|
104
|
+
|| evidence.authorizationGranted !== false
|
|
105
|
+
) {
|
|
106
|
+
issues.push("adoption_evidence_invalid");
|
|
107
|
+
}
|
|
108
|
+
const release = evidence?.registryRelease;
|
|
109
|
+
if (
|
|
110
|
+
!hasExactFields(release, STORED_RELEASE_FIELDS)
|
|
111
|
+
|| release.registry !== OFFICIAL_NPM_REGISTRY
|
|
112
|
+
|| release.packageName !== packageName
|
|
113
|
+
|| release.version !== version
|
|
114
|
+
|| !/^[0-9a-f]{40}$/i.test(release.shasum)
|
|
115
|
+
|| !isCanonicalSha512Integrity(release.integrity)
|
|
116
|
+
|| release.tarballUrl !== expectedTarball
|
|
117
|
+
) {
|
|
118
|
+
issues.push("adoption_registry_binding_invalid");
|
|
119
|
+
}
|
|
120
|
+
const installed = evidence?.installedBinding;
|
|
121
|
+
if (
|
|
122
|
+
!hasExactFields(installed, STORED_INSTALL_FIELDS)
|
|
123
|
+
|| installed.requestedSpec !== exactSpec
|
|
124
|
+
|| installed.packageName !== packageName
|
|
125
|
+
|| installed.version !== version
|
|
126
|
+
|| installed.integrity !== release?.integrity
|
|
127
|
+
|| installed.resolved !== expectedTarball
|
|
128
|
+
) {
|
|
129
|
+
issues.push("adoption_installed_binding_invalid");
|
|
130
|
+
}
|
|
131
|
+
if (
|
|
132
|
+
!hasExactFields(evidence?.authority, ["foreignProjectWrite", "git", "release"])
|
|
133
|
+
|| evidence.authority.git !== false
|
|
134
|
+
|| evidence.authority.release !== false
|
|
135
|
+
|| evidence.authority.foreignProjectWrite !== false
|
|
136
|
+
) {
|
|
137
|
+
issues.push("adoption_authority_invalid");
|
|
138
|
+
}
|
|
139
|
+
if (
|
|
140
|
+
localInstall !== undefined
|
|
141
|
+
&& (
|
|
142
|
+
localInstall.status !== "bound"
|
|
143
|
+
|| localInstall.requestedSpec !== exactSpec
|
|
144
|
+
|| localInstall.packageName !== packageName
|
|
145
|
+
|| localInstall.version !== version
|
|
146
|
+
|| localInstall.integrity !== release?.integrity
|
|
147
|
+
|| localInstall.resolved !== expectedTarball
|
|
148
|
+
)
|
|
149
|
+
) {
|
|
150
|
+
issues.push("adoption_local_install_drift");
|
|
151
|
+
}
|
|
152
|
+
const issueCodes = [...new Set(issues)].sort();
|
|
153
|
+
return {
|
|
154
|
+
valid: issueCodes.length === 0,
|
|
155
|
+
issueCodes,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
48
159
|
function validReleaseEvidence(policy, release) {
|
|
49
160
|
if (
|
|
50
161
|
policy.registry !== OFFICIAL_NPM_REGISTRY
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
OFFICIAL_NPM_REGISTRY,
|
|
11
11
|
evaluateRegistryAdoption,
|
|
12
12
|
} from "./registry-adoption-gate.mjs";
|
|
13
|
+
import { CORE_VERSION } from "./core-contract.mjs";
|
|
13
14
|
import {
|
|
14
15
|
readLocalInstallBinding,
|
|
15
16
|
readRegistryExact,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
import { writeJsonExclusiveAtomically } from "./provenance-common.mjs";
|
|
19
20
|
|
|
20
21
|
const PACKAGE_NAME = "owlrunkit";
|
|
21
|
-
const CANDIDATE_VERSION =
|
|
22
|
+
const CANDIDATE_VERSION = CORE_VERSION;
|
|
22
23
|
const EXACT_SPEC = `${PACKAGE_NAME}@${CANDIDATE_VERSION}`;
|
|
23
24
|
|
|
24
25
|
const POLICY = Object.freeze({
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
|
+
CORE_VERSION,
|
|
18
19
|
RUNTIME_ROOT,
|
|
19
20
|
acceptedCloseoutVerificationIssues,
|
|
20
21
|
createCoreArtifact,
|
|
@@ -73,6 +74,8 @@ import {
|
|
|
73
74
|
} from "./profile-onboarding.mjs";
|
|
74
75
|
import {
|
|
75
76
|
formatDoctorHuman,
|
|
77
|
+
readAdoptionReadiness,
|
|
78
|
+
readProfileLauncherReadiness,
|
|
76
79
|
runDoctor,
|
|
77
80
|
} from "./onboarding-doctor.mjs";
|
|
78
81
|
import {
|
|
@@ -81,7 +84,7 @@ import {
|
|
|
81
84
|
} from "./registry-adoption.mjs";
|
|
82
85
|
import { OFFICIAL_NPM_REGISTRY } from "./registry-adoption-gate.mjs";
|
|
83
86
|
|
|
84
|
-
const TOP_LEVEL_HELP = `OwlRunKit
|
|
87
|
+
const TOP_LEVEL_HELP = `OwlRunKit ${CORE_VERSION}
|
|
85
88
|
|
|
86
89
|
Usage:
|
|
87
90
|
owlrunkit <command> [options]
|
|
@@ -89,7 +92,7 @@ Usage:
|
|
|
89
92
|
Start here:
|
|
90
93
|
owlrunkit doctor --workspace .
|
|
91
94
|
owlrunkit profiles detect --workspace . --dry-run
|
|
92
|
-
owlrunkit adopt --workspace . --exact owlrunkit
|
|
95
|
+
owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION}
|
|
93
96
|
|
|
94
97
|
Quick Verification
|
|
95
98
|
owlrunkit quick-verify --workspace . -- <command> [args...]
|
|
@@ -121,23 +124,61 @@ function withHumanOutput(result, humanOutput) {
|
|
|
121
124
|
return result;
|
|
122
125
|
}
|
|
123
126
|
|
|
124
|
-
function
|
|
127
|
+
function profilesReadiness(root) {
|
|
128
|
+
if (!root) return { valid: false, launcherWarnings: [] };
|
|
129
|
+
try {
|
|
130
|
+
const validation = validateProfiles({ workspaceRoot: root });
|
|
131
|
+
const launchers = readProfileLauncherReadiness({ workspaceRoot: root });
|
|
132
|
+
return {
|
|
133
|
+
valid: validation.valid === true && launchers.ready,
|
|
134
|
+
launcherWarnings: launchers.launcherWarnings,
|
|
135
|
+
};
|
|
136
|
+
} catch {
|
|
137
|
+
return { valid: false, launcherWarnings: [] };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function onboardingProjection(root, recovery = null) {
|
|
142
|
+
const profiles = profilesReadiness(root);
|
|
143
|
+
const adoption = root
|
|
144
|
+
? readAdoptionReadiness({ workspaceRoot: root })
|
|
145
|
+
: { status: "missing" };
|
|
146
|
+
const profilesReady = profiles.valid;
|
|
147
|
+
const adoptionReady = adoption.status === "ok";
|
|
148
|
+
if (profilesReady && adoptionReady) {
|
|
149
|
+
return {
|
|
150
|
+
nextAllowedAction: recovery?.nextAllowedAction ?? "plan_new_execution",
|
|
151
|
+
completed: true,
|
|
152
|
+
steps: [],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const steps = [
|
|
156
|
+
{
|
|
157
|
+
id: "doctor",
|
|
158
|
+
command: "owlrunkit doctor --workspace .",
|
|
159
|
+
},
|
|
160
|
+
...(!profilesReady
|
|
161
|
+
? profiles.launcherWarnings.length > 0
|
|
162
|
+
? [{
|
|
163
|
+
id: "profile_launchers_review",
|
|
164
|
+
command: "owlrunkit doctor --workspace .",
|
|
165
|
+
}]
|
|
166
|
+
: [{
|
|
167
|
+
id: "profiles_detect",
|
|
168
|
+
command: "owlrunkit profiles detect --workspace . --dry-run",
|
|
169
|
+
}]
|
|
170
|
+
: []),
|
|
171
|
+
...(!adoptionReady
|
|
172
|
+
? [{
|
|
173
|
+
id: "adopt_or_start",
|
|
174
|
+
command: `owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or owlrunkit start`,
|
|
175
|
+
}]
|
|
176
|
+
: []),
|
|
177
|
+
];
|
|
125
178
|
return {
|
|
126
179
|
nextAllowedAction: "run_onboarding_diagnostics",
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
id: "doctor",
|
|
130
|
-
command: "owlrunkit doctor --workspace .",
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
id: "profiles_detect",
|
|
134
|
-
command: "owlrunkit profiles detect --workspace . --dry-run",
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
id: "adopt_or_start",
|
|
138
|
-
command: "owlrunkit adopt --workspace . --exact owlrunkit@0.14.0 or owlrunkit start",
|
|
139
|
-
},
|
|
140
|
-
],
|
|
180
|
+
completed: false,
|
|
181
|
+
steps,
|
|
141
182
|
};
|
|
142
183
|
}
|
|
143
184
|
|
|
@@ -666,10 +707,11 @@ function closeoutGateRejected(runId, decision, issues) {
|
|
|
666
707
|
}
|
|
667
708
|
|
|
668
709
|
async function initialize(options) {
|
|
669
|
-
const
|
|
710
|
+
const root = workspace(options);
|
|
711
|
+
const initialized = await initializeProjectRunKit({ workspaceRoot: root });
|
|
670
712
|
const result = {
|
|
671
713
|
...initialized,
|
|
672
|
-
onboarding: onboardingProjection(),
|
|
714
|
+
onboarding: onboardingProjection(root),
|
|
673
715
|
nextAllowedAction: "run_onboarding_diagnostics",
|
|
674
716
|
};
|
|
675
717
|
if (options.json === true) return result;
|
|
@@ -681,7 +723,7 @@ async function initialize(options) {
|
|
|
681
723
|
"Next:",
|
|
682
724
|
"1. owlrunkit doctor --workspace .",
|
|
683
725
|
"2. owlrunkit profiles detect --workspace . --dry-run",
|
|
684
|
-
|
|
726
|
+
`3. owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or owlrunkit start`,
|
|
685
727
|
"",
|
|
686
728
|
].join("\n"),
|
|
687
729
|
);
|
|
@@ -936,7 +978,7 @@ function inspect(options) {
|
|
|
936
978
|
execution: executions.find(execution => execution.runId === requestedRunId),
|
|
937
979
|
}
|
|
938
980
|
: { mode: "summary" };
|
|
939
|
-
return { ...result, summary, view, onboarding: onboardingProjection() };
|
|
981
|
+
return { ...result, summary, view, onboarding: onboardingProjection(root, recovery) };
|
|
940
982
|
}
|
|
941
983
|
|
|
942
984
|
function closeout(options) {
|
|
@@ -1128,9 +1170,9 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
|
|
|
1128
1170
|
return withHumanOutput({
|
|
1129
1171
|
status: "version",
|
|
1130
1172
|
exitCode: 0,
|
|
1131
|
-
version:
|
|
1173
|
+
version: CORE_VERSION,
|
|
1132
1174
|
authorizationGranted: false,
|
|
1133
|
-
},
|
|
1175
|
+
}, `owlrunkit ${CORE_VERSION}\n`);
|
|
1134
1176
|
}
|
|
1135
1177
|
const separatorIndex = rest.indexOf("--");
|
|
1136
1178
|
if (separatorIndex >= 0 && command !== "verify" && command !== "quick-verify") {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://owlcoda.dev/schemas/runkit/verification-finalize-attempt-v1.json",
|
|
4
|
+
"title": "OwlCoda RunKit Verification Finalize Attempt V1",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"runId",
|
|
10
|
+
"verificationId",
|
|
11
|
+
"status",
|
|
12
|
+
"gateStatus",
|
|
13
|
+
"finalizeRequestPath",
|
|
14
|
+
"finalizeRequestSha256",
|
|
15
|
+
"result",
|
|
16
|
+
"authorizationGranted"
|
|
17
|
+
],
|
|
18
|
+
"properties": {
|
|
19
|
+
"schemaVersion": {
|
|
20
|
+
"const": "OwlCodaRunKitVerificationFinalizeAttemptV1"
|
|
21
|
+
},
|
|
22
|
+
"runId": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
25
|
+
},
|
|
26
|
+
"verificationId": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
29
|
+
},
|
|
30
|
+
"status": {
|
|
31
|
+
"const": "rejected"
|
|
32
|
+
},
|
|
33
|
+
"gateStatus": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"finalizeRequestPath": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
},
|
|
41
|
+
"finalizeRequestSha256": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"pattern": "^[a-f0-9]{64}$"
|
|
44
|
+
},
|
|
45
|
+
"result": {
|
|
46
|
+
"type": "object"
|
|
47
|
+
},
|
|
48
|
+
"authorizationGranted": {
|
|
49
|
+
"const": false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://owlcoda.dev/schemas/runkit/verification-preflight-v1.json",
|
|
4
|
+
"title": "OwlCoda RunKit Verification Preflight V1",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"runId",
|
|
10
|
+
"verificationId",
|
|
11
|
+
"status",
|
|
12
|
+
"issueCode",
|
|
13
|
+
"executable",
|
|
14
|
+
"commandArgvSha256",
|
|
15
|
+
"authorizationGranted"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"schemaVersion": {
|
|
19
|
+
"const": "OwlCodaRunKitVerificationPreflightV1"
|
|
20
|
+
},
|
|
21
|
+
"runId": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
24
|
+
},
|
|
25
|
+
"verificationId": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$"
|
|
28
|
+
},
|
|
29
|
+
"status": {
|
|
30
|
+
"const": "rejected"
|
|
31
|
+
},
|
|
32
|
+
"issueCode": {
|
|
33
|
+
"enum": [
|
|
34
|
+
"verify_executable_absolute_path_required",
|
|
35
|
+
"verify_executable_missing",
|
|
36
|
+
"verify_executable_not_regular_file",
|
|
37
|
+
"verify_executable_symlink_rejected"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"executable": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 1
|
|
43
|
+
},
|
|
44
|
+
"commandArgvSha256": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"pattern": "^[a-f0-9]{64}$"
|
|
47
|
+
},
|
|
48
|
+
"authorizationGranted": {
|
|
49
|
+
"const": false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|