@codyswann/lisa 4.72.6 → 4.73.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/all/copy-overwrite/scripts/lib/automation-provenance-contract.mjs +19 -0
- package/all/copy-overwrite/scripts/lib/automation-provenance-local.mjs +4 -2
- package/all/copy-overwrite/scripts/lib/history-secret-evidence-shape.mjs +398 -6
- package/all/copy-overwrite/scripts/lib/history-secret-evidence.mjs +175 -7
- package/all/copy-overwrite/scripts/lib/npm-update-cancel-origin.mjs +7 -1
- package/all/copy-overwrite/scripts/lib/npm-update-contract.mjs +11 -66
- package/all/copy-overwrite/scripts/lib/npm-update-gate.mjs +3 -0
- package/all/copy-overwrite/scripts/lib/npm-update-helper-inventory.mjs +10 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-gate.mjs +162 -121
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-hook.mjs +8 -0
- package/all/copy-overwrite/scripts/lib/npm-update-hosted-scope.mjs +177 -0
- package/all/copy-overwrite/scripts/lib/npm-update-policy.mjs +73 -0
- package/all/copy-overwrite/scripts/lib/npm-update-publish.mjs +1 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-mysql-daemon.mjs +227 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-mysql-resource.mjs +176 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-mysql-storage.mjs +201 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-mysql.mjs +220 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-runtime-contract.mjs +75 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-tool-downloads.mjs +187 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-tool-identity.mjs +288 -0
- package/all/copy-overwrite/scripts/lib/npm-update-rails-tools.mjs +292 -0
- package/all/copy-overwrite/scripts/lisa-automation-provenance.mjs +3 -0
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +1 -1
- package/all/copy-overwrite/scripts/lisa-scratch-run.sh +7 -4
- package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +148 -20
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +126 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +2 -1
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +79 -17
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/parity-safety-net.sh +1 -1
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/parity-safety-net.sh +1 -1
- package/scripts/two-channel-couplings.json +1 -1
|
@@ -9,12 +9,15 @@ import {
|
|
|
9
9
|
HistorySecretError,
|
|
10
10
|
} from "./history-secret-git.mjs";
|
|
11
11
|
import {
|
|
12
|
+
coordinateManifest,
|
|
13
|
+
coordinateMaps,
|
|
12
14
|
evidenceMaps,
|
|
13
|
-
|
|
15
|
+
paragraphNarrativeSpan,
|
|
14
16
|
safeSourcePath,
|
|
15
17
|
} from "./history-secret-evidence-shape.mjs";
|
|
16
18
|
const BUDGET = 64 * 1024 * 1024;
|
|
17
19
|
const NO_REPLACEMENTS = "--no-replace-objects";
|
|
20
|
+
const LITERAL_PATHSPECS = "--literal-pathspecs";
|
|
18
21
|
const digest = bytes => createHash("sha256").update(bytes).digest("hex");
|
|
19
22
|
const options = cwd => ({
|
|
20
23
|
cwd,
|
|
@@ -27,7 +30,7 @@ const options = cwd => ({
|
|
|
27
30
|
const readBlob = (file, commit, cwd, state) => {
|
|
28
31
|
if (!safeSourcePath(file)) return null;
|
|
29
32
|
const entries = gitRead(
|
|
30
|
-
[
|
|
33
|
+
[LITERAL_PATHSPECS, "ls-tree", "-z", commit, "--", file],
|
|
31
34
|
cwd
|
|
32
35
|
)
|
|
33
36
|
.split("\0")
|
|
@@ -116,7 +119,7 @@ const sourceVersions = (file, row, cwd, commits, cache) => {
|
|
|
116
119
|
for (let offset = 0; offset < commits.length; offset += 100) {
|
|
117
120
|
const list = gitRead(
|
|
118
121
|
[
|
|
119
|
-
|
|
122
|
+
LITERAL_PATHSPECS,
|
|
120
123
|
"log",
|
|
121
124
|
"--no-walk=unsorted",
|
|
122
125
|
"--format=%H",
|
|
@@ -224,12 +227,156 @@ const verifiedMap = (map, row, cwd, commits, heads, blob, versions) => {
|
|
|
224
227
|
return map.spans;
|
|
225
228
|
};
|
|
226
229
|
|
|
230
|
+
const coordinateKey = origin =>
|
|
231
|
+
JSON.stringify([
|
|
232
|
+
origin.commit,
|
|
233
|
+
origin.blob,
|
|
234
|
+
origin.path,
|
|
235
|
+
origin.format,
|
|
236
|
+
origin.map_pointer,
|
|
237
|
+
...origin.value_span,
|
|
238
|
+
]);
|
|
239
|
+
const blobIdentity = (bytes, width) =>
|
|
240
|
+
createHash(width === 40 ? "sha1" : "sha256")
|
|
241
|
+
.update(`blob ${bytes.length}\0`)
|
|
242
|
+
.update(bytes)
|
|
243
|
+
.digest("hex");
|
|
244
|
+
|
|
245
|
+
/** Discover only sidecar snapshots in the original selected commit set. */
|
|
246
|
+
const selectedCoordinates = (cwd, commits, blob) => {
|
|
247
|
+
const path = ".lisa/history-secret-evidence.json";
|
|
248
|
+
const candidates = new Set();
|
|
249
|
+
for (let offset = 0; offset < commits.length; offset += 100) {
|
|
250
|
+
const list = gitRead(
|
|
251
|
+
[
|
|
252
|
+
LITERAL_PATHSPECS,
|
|
253
|
+
"log",
|
|
254
|
+
"--no-walk=unsorted",
|
|
255
|
+
"--format=%H",
|
|
256
|
+
...commits.slice(offset, offset + 100),
|
|
257
|
+
"--",
|
|
258
|
+
path,
|
|
259
|
+
],
|
|
260
|
+
cwd
|
|
261
|
+
);
|
|
262
|
+
for (const commit of list.split("\n").filter(Boolean)) {
|
|
263
|
+
if (!commits.includes(commit))
|
|
264
|
+
throw new HistorySecretError(
|
|
265
|
+
"Evidence selection is invalid; safety is unproved."
|
|
266
|
+
);
|
|
267
|
+
candidates.add(commit);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (!candidates.size) return { present: false, entries: new Map() };
|
|
271
|
+
const snapshots = new Map();
|
|
272
|
+
for (const commit of candidates) {
|
|
273
|
+
const exists = gitRead(
|
|
274
|
+
[LITERAL_PATHSPECS, "ls-tree", "--name-only", commit, "--", path],
|
|
275
|
+
cwd
|
|
276
|
+
);
|
|
277
|
+
if (!exists) continue;
|
|
278
|
+
const bytes = blob(path, commit);
|
|
279
|
+
if (bytes === null) return { present: true, entries: null };
|
|
280
|
+
snapshots.set(blobIdentity(bytes, commit.length), bytes);
|
|
281
|
+
}
|
|
282
|
+
if (!snapshots.size) return { present: false, entries: new Map() };
|
|
283
|
+
if (snapshots.size !== 1) return { present: true, entries: null };
|
|
284
|
+
const entries = coordinateManifest(
|
|
285
|
+
[...snapshots.values()][0],
|
|
286
|
+
commits[0].length
|
|
287
|
+
);
|
|
288
|
+
if (entries === null) return { present: true, entries: null };
|
|
289
|
+
const indexed = new Map();
|
|
290
|
+
const spans = new Map();
|
|
291
|
+
const documents = new Set();
|
|
292
|
+
for (const entry of entries) {
|
|
293
|
+
if (!commits.includes(entry.origin.commit))
|
|
294
|
+
return { present: true, entries: null };
|
|
295
|
+
const key = coordinateKey(entry.origin);
|
|
296
|
+
const file = JSON.stringify([
|
|
297
|
+
entry.origin.commit,
|
|
298
|
+
entry.origin.blob,
|
|
299
|
+
entry.origin.path,
|
|
300
|
+
]);
|
|
301
|
+
const intervals = spans.get(file) ?? [];
|
|
302
|
+
const [start, end] = entry.origin.value_span;
|
|
303
|
+
if (indexed.has(key) || intervals.some(([a, b]) => start < b && end > a))
|
|
304
|
+
return { present: true, entries: null };
|
|
305
|
+
intervals.push([start, end]);
|
|
306
|
+
spans.set(file, intervals);
|
|
307
|
+
indexed.set(key, entry.preimage);
|
|
308
|
+
documents.add(JSON.stringify([entry.origin.commit, entry.origin.path]));
|
|
309
|
+
}
|
|
310
|
+
return { present: true, entries: indexed, documents };
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/** Explicit and typed ancestor claims require independent original commit verification. */
|
|
314
|
+
const coordinateRevision = (map, preimage, row, cwd) => {
|
|
315
|
+
const hasTyped = Object.hasOwn(map.value, "commit_parent");
|
|
316
|
+
const typed = map.value.commit_parent;
|
|
317
|
+
if (
|
|
318
|
+
hasTyped &&
|
|
319
|
+
Object.hasOwn(preimage, "commit") &&
|
|
320
|
+
typed !== preimage.commit
|
|
321
|
+
)
|
|
322
|
+
return null;
|
|
323
|
+
if (!hasTyped && !Object.hasOwn(preimage, "commit")) return row.Commit;
|
|
324
|
+
const revision = hasTyped ? typed : preimage.commit;
|
|
325
|
+
return revisionFor({ value: { source_revision: revision } }, row, cwd);
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
/** Every literal, including unflagged siblings, needs its own exact coordinate and preimage. */
|
|
329
|
+
const verifiedCoordinateMap = (
|
|
330
|
+
map,
|
|
331
|
+
row,
|
|
332
|
+
bytes,
|
|
333
|
+
coordinates,
|
|
334
|
+
cwd,
|
|
335
|
+
selected,
|
|
336
|
+
blob
|
|
337
|
+
) => {
|
|
338
|
+
if (coordinates === null) return [];
|
|
339
|
+
const identity = blobIdentity(bytes, row.Commit.length);
|
|
340
|
+
for (const span of map.spans) {
|
|
341
|
+
const preimage = coordinates.get(
|
|
342
|
+
coordinateKey({
|
|
343
|
+
commit: row.Commit,
|
|
344
|
+
blob: identity,
|
|
345
|
+
path: row.File,
|
|
346
|
+
format: map.format,
|
|
347
|
+
map_pointer: map.pointer,
|
|
348
|
+
value_span: [span.start, span.end],
|
|
349
|
+
})
|
|
350
|
+
);
|
|
351
|
+
if (
|
|
352
|
+
!preimage ||
|
|
353
|
+
bytes.subarray(span.start, span.end).toString("ascii") !== span.hash
|
|
354
|
+
)
|
|
355
|
+
return [];
|
|
356
|
+
let original;
|
|
357
|
+
if (map.kind === "proof") {
|
|
358
|
+
if (preimage.kind !== "archive" || !selected.has(preimage.commit))
|
|
359
|
+
return [];
|
|
360
|
+
original = blob(preimage.path, preimage.commit);
|
|
361
|
+
} else {
|
|
362
|
+
if (preimage.kind !== "source") return [];
|
|
363
|
+
const revision = coordinateRevision(map, preimage, row, cwd);
|
|
364
|
+
if (revision === null) return [];
|
|
365
|
+
original = blob(span.file, revision);
|
|
366
|
+
}
|
|
367
|
+
if (original === null || digest(original) !== span.hash) return [];
|
|
368
|
+
}
|
|
369
|
+
return map.spans;
|
|
370
|
+
};
|
|
371
|
+
|
|
227
372
|
/** Clear a finding only after syntax, original span and independently verified bytes agree. */
|
|
228
373
|
export const classifyEvidence = (cwd, commits, heads) => {
|
|
229
374
|
const state = { remaining: BUDGET, blobs: new Map() };
|
|
230
375
|
const refs = new Map();
|
|
231
376
|
const maps = new Map();
|
|
232
377
|
const versions = new Map();
|
|
378
|
+
const selected = new Set(commits);
|
|
379
|
+
let coordinates;
|
|
233
380
|
const blob = (file, commit) => {
|
|
234
381
|
const key = `${commit}\0${file}`;
|
|
235
382
|
if (!refs.has(key)) {
|
|
@@ -241,6 +388,7 @@ export const classifyEvidence = (cwd, commits, heads) => {
|
|
|
241
388
|
return row => {
|
|
242
389
|
if (
|
|
243
390
|
row.RuleID !== "generic-api-key" ||
|
|
391
|
+
!selected.has(row.Commit) ||
|
|
244
392
|
!safeSourcePath(row.File) ||
|
|
245
393
|
row.SymlinkFile !== "" ||
|
|
246
394
|
row.Secret !== "REDACTED" ||
|
|
@@ -256,15 +404,35 @@ export const classifyEvidence = (cwd, commits, heads) => {
|
|
|
256
404
|
if (!bytes) return false;
|
|
257
405
|
const span = attribution(row, bytes);
|
|
258
406
|
if (!span) return false;
|
|
259
|
-
const narrative =
|
|
407
|
+
const narrative = paragraphNarrativeSpan(
|
|
408
|
+
bytes,
|
|
409
|
+
span.lineStart,
|
|
410
|
+
span.lineEnd
|
|
411
|
+
);
|
|
260
412
|
if (narrative !== null && span.matches(narrative)) return true;
|
|
261
413
|
const key = `${row.Commit}\0${row.File}`;
|
|
414
|
+
if (coordinates === undefined)
|
|
415
|
+
coordinates = selectedCoordinates(cwd, commits, blob);
|
|
262
416
|
if (!maps.has(key))
|
|
263
417
|
maps.set(
|
|
264
418
|
key,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
419
|
+
coordinates.present &&
|
|
420
|
+
(coordinates.entries === null ||
|
|
421
|
+
coordinates.documents.has(JSON.stringify([row.Commit, row.File])))
|
|
422
|
+
? coordinateMaps(bytes).flatMap(map =>
|
|
423
|
+
verifiedCoordinateMap(
|
|
424
|
+
map,
|
|
425
|
+
row,
|
|
426
|
+
bytes,
|
|
427
|
+
coordinates.entries,
|
|
428
|
+
cwd,
|
|
429
|
+
selected,
|
|
430
|
+
blob
|
|
431
|
+
)
|
|
432
|
+
)
|
|
433
|
+
: evidenceMaps(bytes).flatMap(map =>
|
|
434
|
+
verifiedMap(map, row, cwd, commits, heads, blob, versions)
|
|
435
|
+
)
|
|
268
436
|
);
|
|
269
437
|
return maps.get(key).filter(span.matches).length === 1;
|
|
270
438
|
};
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import {
|
|
35
35
|
DESCRIPTOR_KEYS,
|
|
36
36
|
optionalLockFields,
|
|
37
|
+
optionalRuntimeFields,
|
|
37
38
|
} from "./automation-provenance-contract.mjs";
|
|
38
39
|
|
|
39
40
|
/** Only complete, digest-checked transport is considered; incomplete chunks grant nothing. */
|
|
@@ -181,7 +182,11 @@ export function originalDescriptor(checkpoint, old, allocation, authority) {
|
|
|
181
182
|
const preview = checkpoint.payload.preview;
|
|
182
183
|
keys(preview, ["descriptor", "message", "epoch"]);
|
|
183
184
|
const d = preview.descriptor;
|
|
184
|
-
keys(d, [
|
|
185
|
+
keys(d, [
|
|
186
|
+
...DESCRIPTOR_KEYS,
|
|
187
|
+
...optionalLockFields(old),
|
|
188
|
+
...optionalRuntimeFields(old),
|
|
189
|
+
]);
|
|
185
190
|
required(
|
|
186
191
|
d.version === 1 &&
|
|
187
192
|
d.parent === old.parent &&
|
|
@@ -193,6 +198,7 @@ export function originalDescriptor(checkpoint, old, allocation, authority) {
|
|
|
193
198
|
d.policySha256 === sha256(canonicalJson(authority)) &&
|
|
194
199
|
canonicalJson(d.files) === canonicalJson(old.hashes) &&
|
|
195
200
|
d.bunLockSha256 === old.bunLockSha256 &&
|
|
201
|
+
d.runtimeSha256 === old.runtimeSha256 &&
|
|
196
202
|
canonicalJson(d.updates) === canonicalJson(old.updates) &&
|
|
197
203
|
typeof preview.message === "string" &&
|
|
198
204
|
sha256(preview.message) === d.messageSha256 &&
|
|
@@ -12,9 +12,12 @@ import { canonicalJson } from "../lisa-automation-provenance.mjs";
|
|
|
12
12
|
import { sha256 } from "./github-attestation-verifier.mjs";
|
|
13
13
|
import {
|
|
14
14
|
optionalLockFields,
|
|
15
|
+
optionalRuntimeFields,
|
|
15
16
|
proposalFileNames,
|
|
17
|
+
signedProposalFields,
|
|
16
18
|
} from "./automation-provenance-contract.mjs";
|
|
17
19
|
export { proposalFileNames } from "./automation-provenance-contract.mjs";
|
|
20
|
+
import { runtimeBinding } from "./npm-update-rails-runtime-contract.mjs";
|
|
18
21
|
|
|
19
22
|
export const FILES = ["package-lock.json", "package.json"];
|
|
20
23
|
export const SECTIONS = [
|
|
@@ -24,72 +27,10 @@ export const SECTIONS = [
|
|
|
24
27
|
];
|
|
25
28
|
export const CLAIM =
|
|
26
29
|
"[lisa-tracker-claim] Claimed by Lisa. Starting implementation.";
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[A-Za-z0-9.-]+)?$/;
|
|
30
|
+
export { NAME, VERSION, validatePolicy } from "./npm-update-policy.mjs";
|
|
31
|
+
import { VERSION } from "./npm-update-policy.mjs";
|
|
30
32
|
export const OBJECT = /^[a-f0-9]{40}$/;
|
|
31
33
|
|
|
32
|
-
/** Configured tracking and an explicit owner are prerequisites, never inferred. */
|
|
33
|
-
export function validatePolicy(value, config) {
|
|
34
|
-
keys(value, [
|
|
35
|
-
"version",
|
|
36
|
-
"repository",
|
|
37
|
-
"directory",
|
|
38
|
-
"target",
|
|
39
|
-
"maintainer",
|
|
40
|
-
"packages",
|
|
41
|
-
"lisaOwner",
|
|
42
|
-
]);
|
|
43
|
-
required(
|
|
44
|
-
value.version === 1 && value.directory === "." && value.target === "main",
|
|
45
|
-
"only root npm on main is supported"
|
|
46
|
-
);
|
|
47
|
-
required(
|
|
48
|
-
config.tracker === "github" &&
|
|
49
|
-
value.repository === `${config.github?.org}/${config.github?.repo}`,
|
|
50
|
-
"configured repository/tracker differs"
|
|
51
|
-
);
|
|
52
|
-
required(
|
|
53
|
-
/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value.repository),
|
|
54
|
-
"invalid repository"
|
|
55
|
-
);
|
|
56
|
-
required(
|
|
57
|
-
typeof value.maintainer === "string" &&
|
|
58
|
-
/^[A-Za-z0-9][A-Za-z0-9-]{0,38}$/.test(value.maintainer),
|
|
59
|
-
"explicit assignable maintainer required"
|
|
60
|
-
);
|
|
61
|
-
required(
|
|
62
|
-
["absent", "verified-local-full-apply"].includes(value.lisaOwner),
|
|
63
|
-
"Lisa requires a verified local full-apply owner"
|
|
64
|
-
);
|
|
65
|
-
required(
|
|
66
|
-
Array.isArray(value.packages) &&
|
|
67
|
-
value.packages.length > 0 &&
|
|
68
|
-
value.packages.length <= 64,
|
|
69
|
-
"invalid package selection"
|
|
70
|
-
);
|
|
71
|
-
const names = new Set();
|
|
72
|
-
for (const selection of value.packages) {
|
|
73
|
-
keys(selection, ["name", "version"]);
|
|
74
|
-
required(
|
|
75
|
-
typeof selection.name === "string" &&
|
|
76
|
-
selection.name.length <= 214 &&
|
|
77
|
-
NAME.test(selection.name),
|
|
78
|
-
"invalid npm name"
|
|
79
|
-
);
|
|
80
|
-
required(
|
|
81
|
-
typeof selection.version === "string" && VERSION.test(selection.version),
|
|
82
|
-
"exact registry version required"
|
|
83
|
-
);
|
|
84
|
-
required(
|
|
85
|
-
!names.has(selection.name) && selection.name !== "@codyswann/lisa",
|
|
86
|
-
"duplicate selection or Lisa version-only update"
|
|
87
|
-
);
|
|
88
|
-
names.add(selection.name);
|
|
89
|
-
}
|
|
90
|
-
return structuredClone(value);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
34
|
/** Host declarations are checked before npm or lifecycle execution. */
|
|
94
35
|
export function validateHost(before) {
|
|
95
36
|
required(
|
|
@@ -221,7 +162,10 @@ export function proposalFrom(
|
|
|
221
162
|
bunLockSha256
|
|
222
163
|
) {
|
|
223
164
|
required(OBJECT.test(parent), "unsupported Git parent or object format");
|
|
224
|
-
const optional =
|
|
165
|
+
const optional = {
|
|
166
|
+
...(bunLockSha256 === undefined ? {} : { bunLockSha256 }),
|
|
167
|
+
...runtimeBinding(policy),
|
|
168
|
+
};
|
|
225
169
|
const names = proposalFileNames({ files, ...optional });
|
|
226
170
|
for (const value of Object.values(files))
|
|
227
171
|
required(
|
|
@@ -253,7 +197,7 @@ export function proposalFrom(
|
|
|
253
197
|
repository: policy.repository,
|
|
254
198
|
parent,
|
|
255
199
|
updates: ordered,
|
|
256
|
-
...optional,
|
|
200
|
+
...signedProposalFields(optional),
|
|
257
201
|
})
|
|
258
202
|
),
|
|
259
203
|
before,
|
|
@@ -280,6 +224,7 @@ export function validateProposal(value, policy) {
|
|
|
280
224
|
"files",
|
|
281
225
|
"hashes",
|
|
282
226
|
...optionalLockFields(value),
|
|
227
|
+
...optionalRuntimeFields(value),
|
|
283
228
|
]);
|
|
284
229
|
const expected = proposalFrom(
|
|
285
230
|
policy,
|
|
@@ -128,6 +128,9 @@ export async function descriptorFor({
|
|
|
128
128
|
...(proposal.bunLockSha256 === undefined
|
|
129
129
|
? {}
|
|
130
130
|
: { bunLockSha256: proposal.bunLockSha256 }),
|
|
131
|
+
...(proposal.runtimeSha256 === undefined
|
|
132
|
+
? {}
|
|
133
|
+
: { runtimeSha256: proposal.runtimeSha256 }),
|
|
131
134
|
messageSha256: sha256(message),
|
|
132
135
|
updates: proposal.updates,
|
|
133
136
|
proposalKey: proposal.bindingKey,
|
|
@@ -65,6 +65,7 @@ const PRODUCER = [
|
|
|
65
65
|
"helper-inventory",
|
|
66
66
|
"hosted-gate",
|
|
67
67
|
"hosted-hook",
|
|
68
|
+
"hosted-scope",
|
|
68
69
|
"hook-installation",
|
|
69
70
|
"hook-preload",
|
|
70
71
|
"hook-provider",
|
|
@@ -78,12 +79,21 @@ const PRODUCER = [
|
|
|
78
79
|
"object",
|
|
79
80
|
"orchestrator",
|
|
80
81
|
"owner",
|
|
82
|
+
"policy",
|
|
81
83
|
"prepare",
|
|
82
84
|
"process",
|
|
83
85
|
"process-core",
|
|
84
86
|
"publication",
|
|
85
87
|
"publish",
|
|
86
88
|
"quality",
|
|
89
|
+
"rails-mysql",
|
|
90
|
+
"rails-mysql-daemon",
|
|
91
|
+
"rails-mysql-resource",
|
|
92
|
+
"rails-mysql-storage",
|
|
93
|
+
"rails-runtime-contract",
|
|
94
|
+
"rails-tool-downloads",
|
|
95
|
+
"rails-tool-identity",
|
|
96
|
+
"rails-tools",
|
|
87
97
|
"recovery",
|
|
88
98
|
"supersession",
|
|
89
99
|
"runtime-archive",
|