@codyswann/lisa 4.73.7 → 4.73.9

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.
Files changed (63) hide show
  1. package/all/copy-overwrite/scripts/lib/github-attestation-recovery.mjs +48 -35
  2. package/all/copy-overwrite/scripts/lib/npm-update-hosted-gate.mjs +15 -1
  3. package/all/copy-overwrite/scripts/lib/npm-update-hosted-hook.mjs +56 -27
  4. package/all/copy-overwrite/scripts/lib/npm-update-invariants.mjs +78 -1
  5. package/all/copy-overwrite/scripts/lib/npm-update-native-process.mjs +29 -10
  6. package/all/copy-overwrite/scripts/lisa-automation-provenance.mjs +86 -37
  7. package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +11 -8
  8. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  9. package/dist/core/lisa-owned-hash-ledger.js +14 -0
  10. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  11. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  12. package/dist/core/upstream-evidence-manifest.js +7 -7
  13. package/package.json +4 -4
  14. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-agy/plugin.json +1 -1
  17. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-agy/plugin.json +1 -1
  27. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  37. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  42. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  47. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-agy/plugin.json +1 -1
  52. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  57. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  62. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
@@ -8,6 +8,7 @@ import {
8
8
  verifyAssignable,
9
9
  } from "./github-attestation-provider.mjs";
10
10
  import { boundedSpawnSync } from "./bounded-spawn.mjs";
11
+ import { withProvenancePhase } from "./npm-update-invariants.mjs";
11
12
  import {
12
13
  requireProof,
13
14
  verifiedRole,
@@ -251,45 +252,57 @@ export function verifyRecoveryOrigin(
251
252
  scope,
252
253
  execute = boundedSpawnSync
253
254
  ) {
254
- validateRecovery(recovery, descriptor, digest, policy);
255
- for (const key of [
256
- "npmPolicySha256",
257
- "proposalKey",
258
- "leafBodySha256",
259
- "commit",
260
- ])
255
+ withProvenancePhase("recovery-local", () => {
256
+ validateRecovery(recovery, descriptor, digest, policy);
257
+ for (const key of [
258
+ "npmPolicySha256",
259
+ "proposalKey",
260
+ "leafBodySha256",
261
+ "commit",
262
+ ])
263
+ requireProof(
264
+ recovery[key] === scope[key],
265
+ `current recovery ${key} differs`
266
+ );
261
267
  requireProof(
262
- recovery[key] === scope[key],
263
- `current recovery ${key} differs`
268
+ process.env.GITHUB_RUN_ID === recovery.runId &&
269
+ process.env.GITHUB_RUN_ATTEMPT === recovery.runAttempt,
270
+ "recovery replayed into different current invocation"
264
271
  );
265
- requireProof(
266
- process.env.GITHUB_RUN_ID === recovery.runId &&
267
- process.env.GITHUB_RUN_ATTEMPT === recovery.runAttempt,
268
- "recovery replayed into different current invocation"
272
+ });
273
+ const origin = withProvenancePhase("historical-provider", () =>
274
+ verifyHistoricalProvider(policy, descriptor, execute)
269
275
  );
270
- const origin = verifyHistoricalProvider(policy, descriptor, execute);
271
- verifyHistoricalDescriptor(
272
- policy,
273
- descriptor,
274
- paths,
275
- digest,
276
- origin.run,
277
- origin.claim,
278
- execute
276
+ withProvenancePhase("historical-signature", () =>
277
+ verifyHistoricalDescriptor(
278
+ policy,
279
+ descriptor,
280
+ paths,
281
+ digest,
282
+ origin.run,
283
+ origin.claim,
284
+ execute
285
+ )
279
286
  );
280
- verifyRecoveryAttestation(
281
- policy,
282
- recovery,
283
- paths,
284
- scope.recoverySha256,
285
- execute
287
+ withProvenancePhase("recovery-signature", () =>
288
+ verifyRecoveryAttestation(
289
+ policy,
290
+ recovery,
291
+ paths,
292
+ scope.recoverySha256,
293
+ execute
294
+ )
286
295
  );
287
- verifyRecoveryProvider(
288
- policy,
289
- descriptor,
290
- recovery,
291
- scope.maintainer,
292
- execute
296
+ withProvenancePhase("recovery-provider", () =>
297
+ verifyRecoveryProvider(
298
+ policy,
299
+ descriptor,
300
+ recovery,
301
+ scope.maintainer,
302
+ execute
303
+ )
304
+ );
305
+ withProvenancePhase("assignable", () =>
306
+ verifyAssignable(policy, scope.maintainer, execute)
293
307
  );
294
- verifyAssignable(policy, scope.maintainer, execute);
295
308
  }
@@ -17,7 +17,10 @@ import { affirmRuntimeProfile } from "./npm-update-rails-runtime-contract.mjs";
17
17
  import { prepareRailsTools } from "./npm-update-rails-tools.mjs";
18
18
  import { openRailsMysqlRuntime } from "./npm-update-rails-mysql.mjs";
19
19
  import { installOriginalManager } from "./npm-update-hook-installation.mjs";
20
- import { withStage } from "./npm-update-invariants.mjs";
20
+ import {
21
+ withStage,
22
+ inheritProvenanceFailure,
23
+ } from "./npm-update-invariants.mjs";
21
24
 
22
25
  const INSTALL_STAGE = "gate-install";
23
26
  const VALIDATE_STAGE = "gate-validate";
@@ -66,6 +69,17 @@ function nativeStep(context, env, command, args, maximum = 3_145_728) {
66
69
  env,
67
70
  timeout: remainingGateTime(context.deadline),
68
71
  maximum,
72
+ }).catch(error => {
73
+ if (
74
+ command === "node" &&
75
+ env.LISA_NPM_HOOK_ROLE === "commit" &&
76
+ typeof env.HOME === "string" &&
77
+ args.length === 2 &&
78
+ args[0] === "scripts/lisa-automation-provenance.mjs" &&
79
+ args[1] === join(env.HOME, "message")
80
+ )
81
+ inheritProvenanceFailure(error);
82
+ throw error;
69
83
  });
70
84
  }
71
85
 
@@ -9,6 +9,11 @@ import { realpathSync, lstatSync } from "node:fs";
9
9
  import { resolve, join, basename } from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "node:url";
11
11
  import { binaryDigest } from "./npm-update-isolation.mjs";
12
+ import {
13
+ withProvenancePhase,
14
+ recordProvenancePhase,
15
+ provenanceFailure,
16
+ } from "./npm-update-invariants.mjs";
12
17
 
13
18
  const ENTRY = fileURLToPath(import.meta.url);
14
19
  const PRELOAD = fileURLToPath(
@@ -111,55 +116,79 @@ export function tokenFreeHookEnvironment(source) {
111
116
  return env;
112
117
  }
113
118
 
119
+ /** Input consumes the same fixed bound and one original deadline observation before native execution. */
120
+ async function originalHookInput(context) {
121
+ const chunks = [];
122
+ let size = 0;
123
+ try {
124
+ for await (const chunk of process.stdin) {
125
+ size += chunk.length;
126
+ required(size <= 4_194_304, "original hook stdin exceeded");
127
+ chunks.push(chunk);
128
+ }
129
+ const timeout = Math.min(1_800_000, context.deadline - Date.now());
130
+ required(timeout > 0, "original hook phase expired");
131
+ return { input: Buffer.concat(chunks), timeout };
132
+ } catch (error) {
133
+ recordProvenancePhase(error, "gateway-input");
134
+ throw error;
135
+ }
136
+ }
137
+
114
138
  async function main() {
115
139
  const args = process.argv.slice(2);
116
- required(
117
- args.length >= 3 && args[0] === "--context" && args[2] === "--",
118
- "invalid hosted Node gateway"
140
+ withProvenancePhase("gateway-context", () =>
141
+ required(
142
+ args.length >= 3 && args[0] === "--context" && args[2] === "--",
143
+ "invalid hosted Node gateway"
144
+ )
145
+ );
146
+ const context = withProvenancePhase("gateway-context", () =>
147
+ hostedHookContext(args[1])
119
148
  );
120
- const context = hostedHookContext(args[1]);
121
149
  const original = args.slice(3);
122
- const entry = hookEntry(context, original, realpathSync(process.cwd()));
123
- if (entry)
124
- required(
125
- !original.some(arg =>
126
- /^(?:-r|--require|--import|--(?:experimental-)?loader)(?:=|$)/.test(arg)
127
- ) &&
128
- !process.env.NODE_OPTIONS &&
129
- !process.env.NODE_PATH,
130
- "unqualified original canonical hook loader"
131
- );
150
+ const entry = withProvenancePhase("gateway-entry", () =>
151
+ hookEntry(context, original, realpathSync(process.cwd()))
152
+ );
153
+ withProvenancePhase("gateway-entry", () => {
154
+ if (entry)
155
+ required(
156
+ !original.some(arg =>
157
+ /^(?:-r|--require|--import|--(?:experimental-)?loader)(?:=|$)/.test(
158
+ arg
159
+ )
160
+ ) &&
161
+ !process.env.NODE_OPTIONS &&
162
+ !process.env.NODE_PATH,
163
+ "unqualified original canonical hook loader"
164
+ );
165
+ });
132
166
  const env = tokenFreeHookEnvironment(process.env);
133
167
  if (entry) env.LISA_NPM_HOSTED_HOOK_CONTEXT = context.file;
134
168
  else delete env.LISA_NPM_HOSTED_HOOK_CONTEXT;
135
- const chunks = [];
136
- let size = 0;
137
- for await (const chunk of process.stdin) {
138
- size += chunk.length;
139
- required(size <= 4_194_304, "original hook stdin exceeded");
140
- chunks.push(chunk);
141
- }
142
- const timeout = Math.min(1_800_000, context.deadline - Date.now());
143
- required(timeout > 0, "original hook phase expired");
169
+ const { input, timeout } = await originalHookInput(context);
144
170
  const result = await runProcess(
145
171
  context.native.node.path,
146
172
  entry ? ["--import", pathToFileURL(PRELOAD).href, ...original] : original,
147
173
  {
148
174
  cwd: process.cwd(),
149
175
  env,
150
- input: Buffer.concat(chunks),
176
+ input,
151
177
  timeout,
152
178
  maximum: 8_388_608,
153
179
  allowed: Array.from({ length: 256 }, (_, code) => code),
154
180
  }
155
- );
181
+ ).catch(error => {
182
+ recordProvenancePhase(error, "gateway-child");
183
+ throw error;
184
+ });
156
185
  process.stdout.write(result.stdout);
157
186
  process.stderr.write(result.stderr);
158
187
  process.exitCode = result.code;
159
188
  }
160
189
 
161
190
  if (process.argv[1] && resolve(process.argv[1]) === ENTRY)
162
- main().catch(() => {
163
- process.stderr.write("original hosted hook command failed\n");
191
+ main().catch(error => {
192
+ process.stderr.write(`${provenanceFailure(error)}\n`);
164
193
  process.exitCode = 1;
165
194
  });
@@ -29,6 +29,73 @@ const stages = new Set([
29
29
  "gate-output",
30
30
  ]);
31
31
  const diagnostics = new WeakMap();
32
+ const capturedErrors = new WeakMap();
33
+ const provenancePhases = new Set([
34
+ "local-proof",
35
+ "configuration",
36
+ "verifier",
37
+ "canonical-context",
38
+ "recovery-local",
39
+ "historical-provider",
40
+ "historical-signature",
41
+ "recovery-signature",
42
+ "recovery-provider",
43
+ "assignable",
44
+ "ordinary-signature",
45
+ "ordinary-provider",
46
+ "final-proof",
47
+ "gateway-context",
48
+ "gateway-entry",
49
+ "gateway-input",
50
+ "gateway-child",
51
+ ]);
52
+ const provenancePrefix =
53
+ "Invalid automation provenance: required proof, policy or provider evidence failed";
54
+
55
+ /** A synchronous verifier keeps its original exception and innermost source-selected phase. */
56
+ export function withProvenancePhase(phase, operation) {
57
+ required(provenancePhases.has(phase), "invalid provenance diagnostic phase");
58
+ try {
59
+ return operation();
60
+ } catch (error) {
61
+ recordProvenancePhase(error, phase);
62
+ throw error;
63
+ }
64
+ }
65
+
66
+ /** Shared sync/async catches never inspect exception properties, including hostile getters. */
67
+ export function recordProvenancePhase(error, phase) {
68
+ required(provenancePhases.has(phase), "invalid provenance diagnostic phase");
69
+ if (
70
+ error !== null &&
71
+ (typeof error === "object" || typeof error === "function")
72
+ ) {
73
+ const prior = diagnostics.get(error) ?? {};
74
+ diagnostics.set(error, { ...prior, provenance: prior.provenance ?? phase });
75
+ }
76
+ }
77
+
78
+ /** Canonical CLI and gateway failures expose one closed label, never provider or exception text. */
79
+ export function provenanceFailure(error) {
80
+ return `${provenancePrefix} (phase=${diagnostics.get(error)?.provenance ?? "unknown"})`;
81
+ }
82
+
83
+ /** Only a complete fixed diagnostic from an observed native exit-one can add a phase, never authority. */
84
+ export function inheritProvenanceFailure(error) {
85
+ const facts = diagnostics.get(error);
86
+ const bytes = capturedErrors.get(error);
87
+ if (
88
+ facts?.native !== "exit" ||
89
+ facts.status !== 1 ||
90
+ !bytes ||
91
+ bytes.length > 256
92
+ )
93
+ return;
94
+ const text = bytes.toString("utf8");
95
+ for (const phase of provenancePhases)
96
+ if (text === `${provenancePrefix} (phase=${phase})\n`)
97
+ recordProvenancePhase(error, phase);
98
+ }
32
99
  const signals = new Set([
33
100
  "SIGTERM",
34
101
  "SIGINT",
@@ -81,7 +148,16 @@ export async function withStage(stage, operation) {
81
148
  }
82
149
 
83
150
  /** Only native capture registers observed close facts; exception properties never establish provenance. */
84
- export function recordNativeFailure(error, category, status, signal, errno) {
151
+ export function recordNativeFailure(
152
+ error,
153
+ category,
154
+ status,
155
+ signal,
156
+ errno,
157
+ stderr
158
+ ) {
159
+ if (Buffer.isBuffer(stderr) && stderr.length <= 256)
160
+ capturedErrors.set(error, Buffer.from(stderr));
85
161
  diagnostics.set(error, {
86
162
  ...diagnostics.get(error),
87
163
  native: categories.has(category) ? category : "unknown",
@@ -101,6 +177,7 @@ export function publicFailure(error) {
101
177
  if (facts.signal) parts.push(`signal=${facts.signal}`);
102
178
  if (facts.errno) parts.push(`errno=${facts.errno}`);
103
179
  }
180
+ if (facts?.provenance) parts.push(`provenance=${facts.provenance}`);
104
181
  return `npm updater failed: required policy, authorization, installation, gate or exact publication evidence was unavailable (${parts.join(" ")})`;
105
182
  }
106
183
 
@@ -95,6 +95,29 @@ export function runProcess(
95
95
  });
96
96
  }
97
97
 
98
+ /** Retain the original native error and captured bytes while registering only observed close facts. */
99
+ function observedFailure(error, observation) {
100
+ const {
101
+ chunks,
102
+ errors,
103
+ command,
104
+ code,
105
+ nativeCompleted,
106
+ category,
107
+ signal,
108
+ errno,
109
+ } = observation;
110
+ const stderr = Buffer.concat(errors);
111
+ recordNativeFailure(error, category, code, signal, errno, stderr);
112
+ return Object.assign(error, {
113
+ stdout: Buffer.concat(chunks),
114
+ stderr,
115
+ command,
116
+ code,
117
+ nativeCompleted,
118
+ });
119
+ }
120
+
98
121
  /** Native close, not cancellation delivery, completes an owned child. */
99
122
  function captureProcess(
100
123
  child,
@@ -145,20 +168,16 @@ function captureProcess(
145
168
  if (failure || signal || !allowed.includes(code)) {
146
169
  const error =
147
170
  failure ?? new Error(`npm updater: child failed (${code ?? signal})`);
148
- recordNativeFailure(
149
- error,
150
- category ?? (signal ? "signal" : "exit"),
151
- code,
152
- signal,
153
- errno
154
- );
155
171
  reject(
156
- Object.assign(error, {
157
- stdout: Buffer.concat(chunks),
158
- stderr: Buffer.concat(errors),
172
+ observedFailure(error, {
173
+ chunks,
174
+ errors,
159
175
  command,
160
176
  code,
161
177
  nativeCompleted: !failure && !signal,
178
+ category: category ?? (signal ? "signal" : "exit"),
179
+ signal,
180
+ errno,
162
181
  })
163
182
  );
164
183
  return;
@@ -7,6 +7,10 @@ import {
7
7
  verifyRecoveryOrigin,
8
8
  } from "./lib/github-attestation-recovery.mjs";
9
9
  import { invokedAsScript } from "./lib/invoked-as-script.mjs";
10
+ import {
11
+ withProvenancePhase,
12
+ provenanceFailure,
13
+ } from "./lib/npm-update-invariants.mjs";
10
14
  import {
11
15
  assertPinnedVerifier,
12
16
  requireProof,
@@ -29,6 +33,8 @@ import {
29
33
  } from "./lib/automation-provenance-local.mjs";
30
34
  export { canonicalJson } from "./lib/automation-provenance-contract.mjs";
31
35
 
36
+ const LOCAL_PROOF = "local-proof";
37
+
32
38
  /** A present but malformed reference is a failure, even with ordinary AI trailers. */
33
39
  export function automationReference(message) {
34
40
  const lines = message
@@ -88,14 +94,8 @@ function recoveryPermission(
88
94
  );
89
95
  }
90
96
 
91
- /** Verify fixed private proof against the final message, tree, binding and provider. */
92
- export function verifyAutomationProvenance(messageFile) {
93
- const messageBytes = privateBytes(messageFile, 65_536, false);
94
- const message = messageBytes.toString("utf8");
95
- const reference = automationReference(message);
96
- if (!reference) return false;
97
- const { config, policy } = trustedConfiguration(git);
98
- const { paths, optional, bytes, bundleBytes, descriptor } = proofSnapshot();
97
+ /** Keep unchanged local authorization together without obscuring the canonical phase. */
98
+ function verifyLocalProposal(descriptor, messageBytes, reference, policy) {
99
99
  localDescriptor(descriptor, messageBytes, reference, policy);
100
100
  npmProposal(descriptor, git);
101
101
  requireProof(
@@ -110,30 +110,18 @@ export function verifyAutomationProvenance(messageFile) {
110
110
  ),
111
111
  "deterministic proposal key differs"
112
112
  );
113
- assertPinnedVerifier(policy);
114
- const context = canonicalContext(message, config, policy, descriptor);
115
- const recoveryBytes = optional[0]
116
- ? privateBytes(paths.recovery, 65_536)
117
- : null;
118
- const recoveryBundle = optional[0]
119
- ? privateBytes(paths.recoveryBundle, 1_048_576)
120
- : null;
121
- if (recoveryBytes) {
122
- recoveryPermission(
123
- policy,
124
- descriptor,
125
- context,
126
- config,
127
- bytes,
128
- paths,
129
- recoveryBytes,
130
- recoveryBundle,
131
- messageBytes
132
- );
133
- } else {
134
- verifyDescriptorAttestation(policy, descriptor, paths, sha256(bytes));
135
- verifyCurrentProvider(policy, descriptor);
136
- }
113
+ }
114
+
115
+ /** Final rereads preserve the original mutation checks after all provider verification. */
116
+ function verifyFinalSnapshot(
117
+ paths,
118
+ bundleBytes,
119
+ bytes,
120
+ descriptor,
121
+ messageFile,
122
+ reference,
123
+ policy
124
+ ) {
137
125
  requireProof(
138
126
  privateBytes(paths.bundle, 1_048_576).equals(bundleBytes),
139
127
  "origin bundle changed during verification"
@@ -148,17 +136,78 @@ export function verifyAutomationProvenance(messageFile) {
148
136
  reference,
149
137
  policy
150
138
  );
151
- return true;
139
+ }
140
+
141
+ /** Verify fixed private proof against the final message, tree, binding and provider. */
142
+ export function verifyAutomationProvenance(messageFile) {
143
+ const messageBytes = withProvenancePhase(LOCAL_PROOF, () =>
144
+ privateBytes(messageFile, 65_536, false)
145
+ );
146
+ const message = messageBytes.toString("utf8");
147
+ const reference = withProvenancePhase(LOCAL_PROOF, () =>
148
+ automationReference(message)
149
+ );
150
+ if (!reference) return false;
151
+ const { config, policy } = withProvenancePhase("configuration", () =>
152
+ trustedConfiguration(git)
153
+ );
154
+ const { paths, optional, bytes, bundleBytes, descriptor } =
155
+ withProvenancePhase(LOCAL_PROOF, proofSnapshot);
156
+ withProvenancePhase(LOCAL_PROOF, () =>
157
+ verifyLocalProposal(descriptor, messageBytes, reference, policy)
158
+ );
159
+ withProvenancePhase("verifier", () => assertPinnedVerifier(policy));
160
+ const context = withProvenancePhase("canonical-context", () =>
161
+ canonicalContext(message, config, policy, descriptor)
162
+ );
163
+ return withProvenancePhase("final-proof", () => {
164
+ const recoveryBytes = optional[0]
165
+ ? privateBytes(paths.recovery, 65_536)
166
+ : null;
167
+ const recoveryBundle = optional[0]
168
+ ? privateBytes(paths.recoveryBundle, 1_048_576)
169
+ : null;
170
+ if (recoveryBytes) {
171
+ withProvenancePhase("recovery-local", () =>
172
+ recoveryPermission(
173
+ policy,
174
+ descriptor,
175
+ context,
176
+ config,
177
+ bytes,
178
+ paths,
179
+ recoveryBytes,
180
+ recoveryBundle,
181
+ messageBytes
182
+ )
183
+ );
184
+ } else {
185
+ withProvenancePhase("ordinary-signature", () =>
186
+ verifyDescriptorAttestation(policy, descriptor, paths, sha256(bytes))
187
+ );
188
+ withProvenancePhase("ordinary-provider", () =>
189
+ verifyCurrentProvider(policy, descriptor)
190
+ );
191
+ }
192
+ verifyFinalSnapshot(
193
+ paths,
194
+ bundleBytes,
195
+ bytes,
196
+ descriptor,
197
+ messageFile,
198
+ reference,
199
+ policy
200
+ );
201
+ return true;
202
+ });
152
203
  }
153
204
 
154
205
  if (invokedAsScript(import.meta.url)) {
155
206
  try {
156
207
  const verified = verifyAutomationProvenance(process.argv[2]);
157
208
  process.exitCode = verified ? 0 : 10;
158
- } catch {
159
- console.error(
160
- "Invalid automation provenance: required proof, policy or provider evidence failed"
161
- );
209
+ } catch (error) {
210
+ console.error(provenanceFailure(error));
162
211
  process.exitCode = 1;
163
212
  }
164
213
  }
@@ -92,12 +92,13 @@
92
92
  "children": []
93
93
  },
94
94
  "lib/github-attestation-recovery.mjs": {
95
- "sha256": "ff89d72300035a2554cf3e406b1054ca3c8a494d6a5768ea4981f4c87c50e981",
95
+ "sha256": "aa97fbc52f58aba1cc93e105a9ee7a32a0ae184259c10ab55e23589b593207f9",
96
96
  "staticImports": [
97
97
  "lib/automation-provenance-local.mjs",
98
98
  "lib/bounded-spawn.mjs",
99
99
  "lib/github-attestation-provider.mjs",
100
- "lib/github-attestation-verifier.mjs"
100
+ "lib/github-attestation-verifier.mjs",
101
+ "lib/npm-update-invariants.mjs"
101
102
  ],
102
103
  "dynamicImports": [],
103
104
  "children": []
@@ -588,7 +589,7 @@
588
589
  "children": []
589
590
  },
590
591
  "lib/npm-update-hosted-gate.mjs": {
591
- "sha256": "0c54442f27521c989783cdf5bf975739f99c9f46c8e67deee4da0eefb9b327b9",
592
+ "sha256": "b9ced911733ab9c6afd06c9451bb9d9cc9363e0a6fd1059ef659aba0107065cc",
592
593
  "staticImports": [
593
594
  "lib/npm-update-bun.mjs",
594
595
  "lib/npm-update-contract.mjs",
@@ -608,9 +609,10 @@
608
609
  "children": []
609
610
  },
610
611
  "lib/npm-update-hosted-hook.mjs": {
611
- "sha256": "ef468e94c148b8d81125d3d374c2350b44abcb48ef9037639f0ba4a8ea9ecf03",
612
+ "sha256": "0e9cf3bf55b9b979d22553f01ad4d17c0a85058b2b87657bd3126b9034e9f8c1",
612
613
  "staticImports": [
613
614
  "lib/npm-update-contract.mjs",
615
+ "lib/npm-update-invariants.mjs",
614
616
  "lib/npm-update-isolation.mjs",
615
617
  "lib/npm-update-orchestrator.mjs",
616
618
  "lib/npm-update-process.mjs",
@@ -642,7 +644,7 @@
642
644
  ]
643
645
  },
644
646
  "lib/npm-update-invariants.mjs": {
645
- "sha256": "136cb22396d33252494c4df1e35d13ff58c58a0ca34fbe5c68954b077cb3f30b",
647
+ "sha256": "e91f3f85bcce92eba8fb0a6a544a9ef3d60985828e6b8e5265e3d44e42bfe09b",
646
648
  "staticImports": [],
647
649
  "dynamicImports": [],
648
650
  "children": []
@@ -681,7 +683,7 @@
681
683
  "children": []
682
684
  },
683
685
  "lib/npm-update-native-process.mjs": {
684
- "sha256": "295d69d90f32aad9d757060ea6d3f66787a00e24c19e01e5beaf2ba752fec8da",
686
+ "sha256": "1dec7d3392289203a99db38db1501a6282d436e779c720250aaf8fbfdd18bd16",
685
687
  "staticImports": [
686
688
  "lib/npm-update-contract.mjs",
687
689
  "lib/npm-update-invariants.mjs",
@@ -1124,13 +1126,14 @@
1124
1126
  "children": []
1125
1127
  },
1126
1128
  "lisa-automation-provenance.mjs": {
1127
- "sha256": "01bdecb447fe6ffa8e961846306a7839bce970e1a6ebacc9179e2d3cf662fce3",
1129
+ "sha256": "d3d2ad9769b47ac988ff2bb4514ad37901cf5de854cf536cf1acf38fab9f94a0",
1128
1130
  "staticImports": [
1129
1131
  "lib/automation-provenance-contract.mjs",
1130
1132
  "lib/automation-provenance-local.mjs",
1131
1133
  "lib/github-attestation-recovery.mjs",
1132
1134
  "lib/github-attestation-verifier.mjs",
1133
- "lib/invoked-as-script.mjs"
1135
+ "lib/invoked-as-script.mjs",
1136
+ "lib/npm-update-invariants.mjs"
1134
1137
  ],
1135
1138
  "dynamicImports": [],
1136
1139
  "children": []
@@ -1 +1 @@
1
- {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CA09DjC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,+BAA+B,EAAE,QAAQ,CACpD,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CA63DjC,CAAC"}
1
+ {"version":3,"file":"lisa-owned-hash-ledger.d.ts","sourceRoot":"","sources":["../../src/core/lisa-owned-hash-ledger.ts"],"names":[],"mappings":"AACA,6EAA6E;AAE7E;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAi+DjC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,+BAA+B,EAAE,QAAQ,CACpD,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAo4DjC,CAAC"}