owlrunkit 0.20.0 → 0.22.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 +88 -0
- package/README.md +102 -10
- package/docs/architecture/OWLCODA_RUNKIT_0201_RELEASE_TRUTH_AND_PROFILE_NORMALIZATION_PATCH_DECISION_20260813.md +95 -0
- package/docs/architecture/OWLCODA_RUNKIT_021_TEAM_DELIVERY_PHASE2_PRODUCT_DECISION_20260813.md +249 -0
- package/integrations/codex/skills/owlcoda-runkit/SKILL.md +117 -12
- package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
- package/package.json +1 -1
- package/packages/attest/README.md +7 -1
- package/packages/attest/consumer-surface-v3.json +275 -0
- package/packages/attest/distribution-manifest-v1.json +24 -0
- package/packages/attest/schemas/canonical-candidate-identity-v1.schema.json +112 -0
- package/packages/attest/schemas/foreign-workspace-filesystem-identity-v1.schema.json +32 -0
- package/packages/attest/schemas/quick-verification-receipt-v4.schema.json +226 -0
- package/packages/attest/src/candidate-identity.mjs +454 -0
- package/packages/attest/src/index.mjs +11 -0
- package/packages/attest/src/quick-receipt-contract.mjs +126 -5
- package/packages/attest/src/quick.mjs +53 -8
- package/{registry-release-policy-v1.json → registry-release-policy-v2.json} +8 -9
- package/sbom.spdx.json +4 -4
- package/scripts/runkit-contract/core-contract.mjs +19 -1
- package/scripts/runkit-contract/fleet-skill-plan.mjs +223 -0
- package/scripts/runkit-contract/formal-workflow.mjs +3 -1
- package/scripts/runkit-contract/hook-recovery.mjs +496 -0
- package/scripts/runkit-contract/inspect-presentation.mjs +187 -0
- package/scripts/runkit-contract/install-codex-skill.mjs +1 -0
- package/scripts/runkit-contract/onboarding-bootstrap.mjs +15 -0
- package/scripts/runkit-contract/onboarding-doctor.mjs +378 -9
- package/scripts/runkit-contract/profile-onboarding.mjs +6 -0
- package/scripts/runkit-contract/project-cli-resolver.mjs +17 -1
- package/scripts/runkit-contract/quick-metrics.mjs +9 -5
- package/scripts/runkit-contract/quick-verify.mjs +108 -24
- package/scripts/runkit-contract/registry-adoption-gate.mjs +12 -3
- package/scripts/runkit-contract/registry-adoption.mjs +10 -5
- package/scripts/runkit-contract/runkit-bootstrap.mjs +1 -0
- package/scripts/runkit-contract/runkit-cli.mjs +332 -30
- package/scripts/runkit-contract/schemas/delivery-lifecycle-v1.schema.json +91 -0
- package/scripts/runkit-contract/schemas/external-gate-v1.schema.json +68 -0
- package/scripts/runkit-contract/schemas/fleet-skill-upgrade-plan-v1.schema.json +140 -0
- package/scripts/runkit-contract/schemas/hook-recovery-v1.schema.json +592 -0
- package/scripts/runkit-contract/schemas/inspect-compact-v1.schema.json +93 -0
- package/scripts/runkit-contract/schemas/inspect-compact-v2.schema.json +122 -0
- package/scripts/runkit-contract/schemas/team-delivery-status-v2.schema.json +219 -0
- package/scripts/runkit-contract/schemas/team-delivery-status-v3.schema.json +113 -0
- package/scripts/runkit-contract/schemas/team-project-event-v6.schema.json +82 -0
- package/scripts/runkit-contract/schemas/team-project-event-v7.schema.json +80 -0
- package/scripts/runkit-contract/schemas/team-project-status-v4.schema.json +208 -0
- package/scripts/runkit-contract/schemas/team-recommendation-v2.schema.json +120 -0
- package/scripts/runkit-contract/sync-release-identity.mjs +87 -0
- package/scripts/runkit-contract/team-delivery.mjs +203 -3
- package/scripts/runkit-contract/team-project.mjs +1032 -11
|
@@ -24,6 +24,10 @@ import {
|
|
|
24
24
|
captureWorkspaceSnapshot,
|
|
25
25
|
workspaceSourceStateFingerprint,
|
|
26
26
|
} from "./quick-workspace-snapshot.mjs";
|
|
27
|
+
import {
|
|
28
|
+
captureCanonicalCandidateIdentityV1,
|
|
29
|
+
captureForeignWorkspaceFilesystemIdentityV1,
|
|
30
|
+
} from "../../packages/attest/src/candidate-identity.mjs";
|
|
27
31
|
import {
|
|
28
32
|
captureRuntimeTransition,
|
|
29
33
|
runtimeReportPath,
|
|
@@ -81,7 +85,13 @@ function inputArtifactResult(stdinArtifact) {
|
|
|
81
85
|
: { inputArtifacts: { stdin: stdinArtifact } };
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
function mutationTruth({
|
|
88
|
+
function mutationTruth({
|
|
89
|
+
workspaceBefore,
|
|
90
|
+
workspaceAfter,
|
|
91
|
+
isolationResult,
|
|
92
|
+
cleanupStatus,
|
|
93
|
+
foreignWorkspace = null,
|
|
94
|
+
}) {
|
|
85
95
|
const workspaceSourceChanged = workspaceSourceStateFingerprint(workspaceBefore)
|
|
86
96
|
!== workspaceSourceStateFingerprint(workspaceAfter);
|
|
87
97
|
const boundIgnoredChanged = workspaceBefore.ignoredPathsBound === true
|
|
@@ -89,12 +99,15 @@ function mutationTruth({ workspaceBefore, workspaceAfter, isolationResult, clean
|
|
|
89
99
|
const dependencyChanged = isolationResult?.dependencyChanged === true;
|
|
90
100
|
const consumerSourceChanged = (isolationResult?.consumerDelta.sourcePaths.length ?? 0) > 0;
|
|
91
101
|
const cleanupFailed = cleanupStatus === "cleanup_failed";
|
|
102
|
+
const foreignChanged = foreignWorkspace !== null
|
|
103
|
+
&& foreignWorkspace.zeroWriteObserved !== true;
|
|
92
104
|
const issueCodes = [
|
|
93
105
|
...(workspaceSourceChanged ? ["source_mutated_during_verification"] : []),
|
|
94
106
|
...(boundIgnoredChanged ? ["bound_ignored_path_mutated_during_verification"] : []),
|
|
95
107
|
...(dependencyChanged ? ["dependency_environment_mutated_during_verification"] : []),
|
|
96
108
|
...(consumerSourceChanged ? ["consumer_source_mutated_during_verification"] : []),
|
|
97
109
|
...(cleanupFailed ? ["quick_isolation_cleanup_failed"] : []),
|
|
110
|
+
...(foreignChanged ? ["foreign_workspace_mutated_during_verification"] : []),
|
|
98
111
|
];
|
|
99
112
|
const decisions = [
|
|
100
113
|
...(workspaceSourceChanged ? ["invalidated_by_command_source_mutation"] : []),
|
|
@@ -102,6 +115,7 @@ function mutationTruth({ workspaceBefore, workspaceAfter, isolationResult, clean
|
|
|
102
115
|
...(dependencyChanged ? ["invalidated_by_dependency_environment_mutation"] : []),
|
|
103
116
|
...(consumerSourceChanged ? ["invalidated_by_consumer_source_mutation"] : []),
|
|
104
117
|
...(cleanupFailed ? ["invalidated_by_isolation_cleanup_failure"] : []),
|
|
118
|
+
...(foreignChanged ? ["invalidated_by_foreign_workspace_mutation"] : []),
|
|
105
119
|
];
|
|
106
120
|
return {
|
|
107
121
|
mutationDecision: decisions.length === 0
|
|
@@ -125,10 +139,26 @@ function mutationTruth({ workspaceBefore, workspaceAfter, isolationResult, clean
|
|
|
125
139
|
consumerIgnoredArtifacts: (isolationResult?.consumerDelta.ignoredPaths.length ?? 0) > 0
|
|
126
140
|
? "changed_and_discarded"
|
|
127
141
|
: isolationResult === null ? "not_isolated" : "none",
|
|
142
|
+
...(foreignWorkspace === null
|
|
143
|
+
? {}
|
|
144
|
+
: { foreignTarget: foreignChanged ? "changed" : "unchanged" }),
|
|
128
145
|
},
|
|
129
146
|
};
|
|
130
147
|
}
|
|
131
148
|
|
|
149
|
+
function rootsOverlap(left, right) {
|
|
150
|
+
const leftToRight = path.relative(left, right);
|
|
151
|
+
const rightToLeft = path.relative(right, left);
|
|
152
|
+
return leftToRight === ""
|
|
153
|
+
|| rightToLeft === ""
|
|
154
|
+
|| (leftToRight !== ".."
|
|
155
|
+
&& !leftToRight.startsWith(`..${path.sep}`)
|
|
156
|
+
&& !path.isAbsolute(leftToRight))
|
|
157
|
+
|| (rightToLeft !== ".."
|
|
158
|
+
&& !rightToLeft.startsWith(`..${path.sep}`)
|
|
159
|
+
&& !path.isAbsolute(rightToLeft));
|
|
160
|
+
}
|
|
161
|
+
|
|
132
162
|
function isolationReceipt(isolation, isolationResult, cleanupStatus) {
|
|
133
163
|
if (isolation === null) return null;
|
|
134
164
|
return {
|
|
@@ -150,6 +180,7 @@ function isolationReceipt(isolation, isolationResult, cleanupStatus) {
|
|
|
150
180
|
|
|
151
181
|
export async function runQuickVerification({
|
|
152
182
|
workspaceRoot,
|
|
183
|
+
foreignWorkspaceRoot,
|
|
153
184
|
commandArgv,
|
|
154
185
|
stdinFile,
|
|
155
186
|
isolate = false,
|
|
@@ -165,18 +196,27 @@ export async function runQuickVerification({
|
|
|
165
196
|
authorizationGranted: false,
|
|
166
197
|
};
|
|
167
198
|
}
|
|
168
|
-
let
|
|
199
|
+
let controllerRoot;
|
|
200
|
+
let sourceRoot;
|
|
169
201
|
try {
|
|
170
|
-
|
|
202
|
+
controllerRoot = realpathSync(workspaceRoot);
|
|
203
|
+
sourceRoot = foreignWorkspaceRoot === undefined
|
|
204
|
+
? controllerRoot
|
|
205
|
+
: realpathSync(foreignWorkspaceRoot);
|
|
206
|
+
if (foreignWorkspaceRoot !== undefined && rootsOverlap(controllerRoot, sourceRoot)) {
|
|
207
|
+
throw new Error("Controller and source workspace overlap.");
|
|
208
|
+
}
|
|
171
209
|
} catch {
|
|
172
210
|
return {
|
|
173
211
|
status: "quick_verification_input_invalid",
|
|
174
212
|
exitCode: 3,
|
|
175
|
-
issues: ["
|
|
213
|
+
issues: ["Controller or source workspace does not exist or is not safely separated."],
|
|
176
214
|
authorizationGranted: false,
|
|
177
215
|
};
|
|
178
216
|
}
|
|
179
|
-
|
|
217
|
+
const foreignMode = foreignWorkspaceRoot !== undefined;
|
|
218
|
+
const effectiveIsolation = isolate === true || foreignMode;
|
|
219
|
+
if (dependencyRoot !== undefined && effectiveIsolation !== true) {
|
|
180
220
|
return {
|
|
181
221
|
status: "quick_verification_input_invalid",
|
|
182
222
|
exitCode: 3,
|
|
@@ -184,6 +224,14 @@ export async function runQuickVerification({
|
|
|
184
224
|
authorizationGranted: false,
|
|
185
225
|
};
|
|
186
226
|
}
|
|
227
|
+
if (foreignMode && captureRuntime === true) {
|
|
228
|
+
return {
|
|
229
|
+
status: "quick_verification_input_invalid",
|
|
230
|
+
exitCode: 3,
|
|
231
|
+
issues: ["Foreign Quick does not capture external runtime transitions."],
|
|
232
|
+
authorizationGranted: false,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
187
235
|
if (!Array.isArray(ignoredPaths) || ignoredPaths.some(value => typeof value !== "string")) {
|
|
188
236
|
return {
|
|
189
237
|
status: "quick_verification_input_invalid",
|
|
@@ -206,7 +254,7 @@ export async function runQuickVerification({
|
|
|
206
254
|
try {
|
|
207
255
|
const selected = path.isAbsolute(stdinFile)
|
|
208
256
|
? stdinFile
|
|
209
|
-
: path.resolve(
|
|
257
|
+
: path.resolve(sourceRoot, stdinFile);
|
|
210
258
|
stdinBytes = readFileBytesBounded(selected).bytes;
|
|
211
259
|
} catch (error) {
|
|
212
260
|
return {
|
|
@@ -219,25 +267,32 @@ export async function runQuickVerification({
|
|
|
219
267
|
}
|
|
220
268
|
|
|
221
269
|
let workspaceBefore;
|
|
270
|
+
let foreignWorkspaceBefore = null;
|
|
222
271
|
let store;
|
|
223
272
|
let stdinArtifact = null;
|
|
224
273
|
let persistedStdinPath;
|
|
225
274
|
let isolation = null;
|
|
226
275
|
try {
|
|
227
|
-
workspaceBefore = captureWorkspaceSnapshot(
|
|
228
|
-
|
|
276
|
+
workspaceBefore = captureWorkspaceSnapshot(sourceRoot, { ignoredPaths });
|
|
277
|
+
if (foreignMode) {
|
|
278
|
+
foreignWorkspaceBefore = {
|
|
279
|
+
candidate: captureCanonicalCandidateIdentityV1(sourceRoot),
|
|
280
|
+
filesystem: captureForeignWorkspaceFilesystemIdentityV1(sourceRoot),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
store = createQuickReceiptStore(controllerRoot);
|
|
229
284
|
if (stdinBytes !== undefined) {
|
|
230
285
|
const persistedInput = persistQuickInputArtifact({
|
|
231
|
-
workspaceRoot:
|
|
286
|
+
workspaceRoot: controllerRoot,
|
|
232
287
|
store,
|
|
233
288
|
bytes: stdinBytes,
|
|
234
289
|
});
|
|
235
290
|
stdinArtifact = persistedInput.artifact;
|
|
236
291
|
persistedStdinPath = persistedInput.inputPath;
|
|
237
292
|
}
|
|
238
|
-
if (
|
|
239
|
-
isolation = prepareQuickIsolation({ workspaceRoot:
|
|
240
|
-
const stableSource = captureWorkspaceSnapshot(
|
|
293
|
+
if (effectiveIsolation === true) {
|
|
294
|
+
isolation = prepareQuickIsolation({ workspaceRoot: sourceRoot, dependencyRoot });
|
|
295
|
+
const stableSource = captureWorkspaceSnapshot(sourceRoot, { ignoredPaths });
|
|
241
296
|
if (stableSource.sourceFingerprint !== workspaceBefore.sourceFingerprint) {
|
|
242
297
|
throw new Error("Source workspace changed while the temporary consumer was being prepared.");
|
|
243
298
|
}
|
|
@@ -254,7 +309,7 @@ export async function runQuickVerification({
|
|
|
254
309
|
}
|
|
255
310
|
|
|
256
311
|
const [executable, ...argv] = commandArgv;
|
|
257
|
-
const executionCwd = isolation?.consumerRoot ??
|
|
312
|
+
const executionCwd = isolation?.consumerRoot ?? sourceRoot;
|
|
258
313
|
const expectedRuntimeReportPath = captureRuntime
|
|
259
314
|
? runtimeReportPath(store.receiptRoot)
|
|
260
315
|
: null;
|
|
@@ -279,6 +334,7 @@ export async function runQuickVerification({
|
|
|
279
334
|
const finishedAt = new Date().toISOString();
|
|
280
335
|
|
|
281
336
|
let workspaceAfter;
|
|
337
|
+
let foreignWorkspace = null;
|
|
282
338
|
let isolationResult = null;
|
|
283
339
|
let cleanupStatus = "not_required";
|
|
284
340
|
try {
|
|
@@ -286,7 +342,21 @@ export async function runQuickVerification({
|
|
|
286
342
|
isolationResult = inspectQuickIsolation(isolation);
|
|
287
343
|
cleanupStatus = removeQuickIsolation(isolation);
|
|
288
344
|
}
|
|
289
|
-
workspaceAfter = captureWorkspaceSnapshot(
|
|
345
|
+
workspaceAfter = captureWorkspaceSnapshot(sourceRoot, { ignoredPaths });
|
|
346
|
+
if (foreignMode) {
|
|
347
|
+
const candidateAfter = captureCanonicalCandidateIdentityV1(sourceRoot);
|
|
348
|
+
const filesystemAfter = captureForeignWorkspaceFilesystemIdentityV1(sourceRoot);
|
|
349
|
+
foreignWorkspace = {
|
|
350
|
+
candidateBefore: foreignWorkspaceBefore.candidate,
|
|
351
|
+
candidateAfter,
|
|
352
|
+
filesystemBefore: foreignWorkspaceBefore.filesystem,
|
|
353
|
+
filesystemAfter,
|
|
354
|
+
zeroWriteObserved: foreignWorkspaceBefore.candidate.candidateFingerprint
|
|
355
|
+
=== candidateAfter.candidateFingerprint
|
|
356
|
+
&& foreignWorkspaceBefore.filesystem.filesystemFingerprint
|
|
357
|
+
=== filesystemAfter.filesystemFingerprint,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
290
360
|
} catch (error) {
|
|
291
361
|
if (isolation !== null && cleanupStatus === "not_required") {
|
|
292
362
|
removeQuickIsolation(isolation);
|
|
@@ -306,16 +376,20 @@ export async function runQuickVerification({
|
|
|
306
376
|
workspaceAfter,
|
|
307
377
|
isolationResult,
|
|
308
378
|
cleanupStatus,
|
|
379
|
+
foreignWorkspace,
|
|
309
380
|
});
|
|
310
381
|
const sourceMutated = mutation.mutationDecision !== "source_unchanged";
|
|
311
|
-
const
|
|
382
|
+
const receiptV4 = foreignMode;
|
|
383
|
+
const receiptV3 = !receiptV4 && (effectiveIsolation === true || ignoredPaths.length > 0);
|
|
312
384
|
let persisted;
|
|
313
385
|
try {
|
|
314
386
|
persisted = persistQuickReceipt({
|
|
315
|
-
workspaceRoot:
|
|
387
|
+
workspaceRoot: controllerRoot,
|
|
316
388
|
store,
|
|
317
389
|
receipt: {
|
|
318
|
-
schemaVersion:
|
|
390
|
+
schemaVersion: receiptV4
|
|
391
|
+
? "OwlCodaQuickVerificationReceiptV4"
|
|
392
|
+
: receiptV3
|
|
319
393
|
? "OwlCodaQuickVerificationReceiptV3"
|
|
320
394
|
: stdinArtifact === null
|
|
321
395
|
? "OwlCodaQuickVerificationReceiptV1"
|
|
@@ -334,13 +408,19 @@ export async function runQuickVerification({
|
|
|
334
408
|
argv,
|
|
335
409
|
cwd: executionCwd,
|
|
336
410
|
},
|
|
337
|
-
...(receiptV3
|
|
411
|
+
...(receiptV3 || receiptV4
|
|
338
412
|
? {
|
|
339
|
-
sourceWorkspaceRoot:
|
|
413
|
+
sourceWorkspaceRoot: sourceRoot,
|
|
340
414
|
executionIsolation: isolationReceipt(isolation, isolationResult, cleanupStatus),
|
|
341
415
|
mutationClasses: mutation.mutationClasses,
|
|
342
416
|
}
|
|
343
417
|
: {}),
|
|
418
|
+
...(receiptV4
|
|
419
|
+
? {
|
|
420
|
+
controllerWorkspaceRoot: controllerRoot,
|
|
421
|
+
foreignWorkspace,
|
|
422
|
+
}
|
|
423
|
+
: {}),
|
|
344
424
|
...(stdinArtifact === null
|
|
345
425
|
? {}
|
|
346
426
|
: { inputArtifacts: { stdin: stdinArtifact } }),
|
|
@@ -382,7 +462,7 @@ export async function runQuickVerification({
|
|
|
382
462
|
if (expectedRuntimeReportPath !== null) {
|
|
383
463
|
try {
|
|
384
464
|
runtimeTransition = captureRuntimeTransition({
|
|
385
|
-
workspaceRoot:
|
|
465
|
+
workspaceRoot: controllerRoot,
|
|
386
466
|
quickReceiptPath: persisted.receiptPath,
|
|
387
467
|
runtimeReportPath: expectedRuntimeReportPath,
|
|
388
468
|
});
|
|
@@ -398,7 +478,7 @@ export async function runQuickVerification({
|
|
|
398
478
|
const runtimeFields = runtimeTransition === null ? {} : { runtimeTransition };
|
|
399
479
|
|
|
400
480
|
if (sourceMutated) {
|
|
401
|
-
const attestCommand = quickAttestCommand(
|
|
481
|
+
const attestCommand = quickAttestCommand(controllerRoot, persisted.receiptPath);
|
|
402
482
|
return {
|
|
403
483
|
status: "quick_verification_source_mutated",
|
|
404
484
|
exitCode: 2,
|
|
@@ -408,6 +488,7 @@ export async function runQuickVerification({
|
|
|
408
488
|
commandExitCode: execution.exitCode,
|
|
409
489
|
mutationDecision: mutation.mutationDecision,
|
|
410
490
|
issueCodes: mutation.issueCodes,
|
|
491
|
+
...(foreignMode ? { targetZeroWrite: foreignWorkspace.zeroWriteObserved } : {}),
|
|
411
492
|
...inputArtifactResult(stdinArtifact),
|
|
412
493
|
outputSummary,
|
|
413
494
|
evidenceStorage,
|
|
@@ -419,7 +500,7 @@ export async function runQuickVerification({
|
|
|
419
500
|
};
|
|
420
501
|
}
|
|
421
502
|
if (runtimeTransition?.status === "runtime_transition_invalid") {
|
|
422
|
-
const attestCommand = quickAttestCommand(
|
|
503
|
+
const attestCommand = quickAttestCommand(controllerRoot, persisted.receiptPath);
|
|
423
504
|
return {
|
|
424
505
|
status: "quick_verification_runtime_truth_invalid",
|
|
425
506
|
exitCode: 1,
|
|
@@ -432,6 +513,7 @@ export async function runQuickVerification({
|
|
|
432
513
|
commandExitCode: execution.exitCode,
|
|
433
514
|
mutationDecision: "source_unchanged",
|
|
434
515
|
issueCodes: mutation.issueCodes,
|
|
516
|
+
...(foreignMode ? { targetZeroWrite: foreignWorkspace.zeroWriteObserved } : {}),
|
|
435
517
|
...inputArtifactResult(stdinArtifact),
|
|
436
518
|
outputSummary,
|
|
437
519
|
evidenceStorage,
|
|
@@ -443,7 +525,7 @@ export async function runQuickVerification({
|
|
|
443
525
|
};
|
|
444
526
|
}
|
|
445
527
|
if (execution.launchError || execution.exitCode !== 0) {
|
|
446
|
-
const attestCommand = quickAttestCommand(
|
|
528
|
+
const attestCommand = quickAttestCommand(controllerRoot, persisted.receiptPath);
|
|
447
529
|
return {
|
|
448
530
|
status: "quick_verification_failed",
|
|
449
531
|
exitCode: 1,
|
|
@@ -453,6 +535,7 @@ export async function runQuickVerification({
|
|
|
453
535
|
commandExitCode: execution.exitCode,
|
|
454
536
|
mutationDecision: "source_unchanged",
|
|
455
537
|
issueCodes: mutation.issueCodes,
|
|
538
|
+
...(foreignMode ? { targetZeroWrite: foreignWorkspace.zeroWriteObserved } : {}),
|
|
456
539
|
...inputArtifactResult(stdinArtifact),
|
|
457
540
|
outputSummary,
|
|
458
541
|
evidenceStorage,
|
|
@@ -463,7 +546,7 @@ export async function runQuickVerification({
|
|
|
463
546
|
authorizationGranted: false,
|
|
464
547
|
};
|
|
465
548
|
}
|
|
466
|
-
const attestCommand = quickAttestCommand(
|
|
549
|
+
const attestCommand = quickAttestCommand(controllerRoot, persisted.receiptPath);
|
|
467
550
|
return {
|
|
468
551
|
status: "quick_verification_passed",
|
|
469
552
|
exitCode: 0,
|
|
@@ -473,6 +556,7 @@ export async function runQuickVerification({
|
|
|
473
556
|
commandExitCode: 0,
|
|
474
557
|
mutationDecision: "source_unchanged",
|
|
475
558
|
issueCodes: mutation.issueCodes,
|
|
559
|
+
...(foreignMode ? { targetZeroWrite: foreignWorkspace.zeroWriteObserved } : {}),
|
|
476
560
|
...inputArtifactResult(stdinArtifact),
|
|
477
561
|
outputSummary,
|
|
478
562
|
evidenceStorage,
|
|
@@ -61,12 +61,15 @@ function hasExactFields(value, fields) {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function decision(policy, issueCodes) {
|
|
64
|
+
const version = policy.schemaVersion === "OwlCodaRunKitRegistryReleasePolicyV2"
|
|
65
|
+
? policy.artifactVersion
|
|
66
|
+
: policy.candidateVersion;
|
|
64
67
|
return {
|
|
65
68
|
schemaVersion: "OwlCodaRunKitRegistryAdoptionDecisionV1",
|
|
66
69
|
decision: issueCodes.length === 0 ? "ELIGIBLE" : "INELIGIBLE",
|
|
67
70
|
issueCodes,
|
|
68
71
|
packageName: policy.packageName,
|
|
69
|
-
version
|
|
72
|
+
version,
|
|
70
73
|
authorizationGranted: false,
|
|
71
74
|
};
|
|
72
75
|
}
|
|
@@ -157,6 +160,9 @@ export function validateStoredRegistryAdoptionEvidence({
|
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
function validReleaseEvidence(policy, release) {
|
|
163
|
+
const version = policy.schemaVersion === "OwlCodaRunKitRegistryReleasePolicyV2"
|
|
164
|
+
? policy.artifactVersion
|
|
165
|
+
: policy.candidateVersion;
|
|
160
166
|
if (
|
|
161
167
|
policy.registry !== OFFICIAL_NPM_REGISTRY
|
|
162
168
|
|| Object.keys(release).sort().join("\n") !== RELEASE_EVIDENCE_FIELDS.join("\n")
|
|
@@ -164,7 +170,7 @@ function validReleaseEvidence(policy, release) {
|
|
|
164
170
|
|| !isCanonicalSha512Integrity(release.integrity)
|
|
165
171
|
|| release.tarballUrl !== expectedRegistryTarballUrl(
|
|
166
172
|
policy.packageName,
|
|
167
|
-
|
|
173
|
+
version,
|
|
168
174
|
)
|
|
169
175
|
) {
|
|
170
176
|
return false;
|
|
@@ -198,13 +204,16 @@ export function evaluateRegistryAdoption({ policy, releaseEvidence, install }) {
|
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
const release = releaseEvidence;
|
|
207
|
+
const version = policy.schemaVersion === "OwlCodaRunKitRegistryReleasePolicyV2"
|
|
208
|
+
? policy.artifactVersion
|
|
209
|
+
: policy.candidateVersion;
|
|
201
210
|
if (!validReleaseEvidence(policy, release)) {
|
|
202
211
|
return decision(policy, ["registry_release_evidence_invalid"]);
|
|
203
212
|
}
|
|
204
213
|
if (
|
|
205
214
|
release.registry !== policy.registry
|
|
206
215
|
|| release.packageName !== policy.packageName
|
|
207
|
-
|| release.version !==
|
|
216
|
+
|| release.version !== version
|
|
208
217
|
) {
|
|
209
218
|
return decision(policy, ["registry_release_evidence_mismatch"]);
|
|
210
219
|
}
|
|
@@ -23,10 +23,10 @@ const CANDIDATE_VERSION = CORE_VERSION;
|
|
|
23
23
|
const EXACT_SPEC = `${PACKAGE_NAME}@${CANDIDATE_VERSION}`;
|
|
24
24
|
|
|
25
25
|
const POLICY = Object.freeze({
|
|
26
|
-
schemaVersion: "
|
|
27
|
-
status: "
|
|
26
|
+
schemaVersion: "OwlCodaRunKitRegistryReleasePolicyV2",
|
|
27
|
+
status: "release_artifact_registry_gated",
|
|
28
28
|
packageName: PACKAGE_NAME,
|
|
29
|
-
|
|
29
|
+
artifactVersion: CANDIDATE_VERSION,
|
|
30
30
|
registry: OFFICIAL_NPM_REGISTRY,
|
|
31
31
|
registryRequiredBeforeAdoption: true,
|
|
32
32
|
exactVersionRequired: true,
|
|
@@ -45,8 +45,13 @@ const POLICY = Object.freeze({
|
|
|
45
45
|
"symlink",
|
|
46
46
|
"workspace",
|
|
47
47
|
],
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
rollbackRelease: {
|
|
49
|
+
packageName: PACKAGE_NAME,
|
|
50
|
+
version: "0.21.0",
|
|
51
|
+
shasum: "f9ecfa41ad2ba3140258234b49d98798675651f2",
|
|
52
|
+
integrity: "sha512-hopLyvN5vp0y3xu0H0jQbMI6DxaDSWcGYcn7tAbCa0m2OqW2G8n5kJvnr217jqPYlArQwJ2TDPRLNmp4vPEhVQ==",
|
|
53
|
+
tarballUrl: "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.21.0.tgz",
|
|
54
|
+
},
|
|
50
55
|
registryEvidenceMustBeExternal: true,
|
|
51
56
|
registryEvidenceSchemaVersion: "OwlCodaRunKitRegistryReleaseEvidenceV1",
|
|
52
57
|
embeddedAttestComponentVersion: "0.2.0",
|