@codyswann/lisa 3.11.9 → 3.13.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/lisa-command-envelope.mjs +10 -0
- package/all/copy-overwrite/scripts/lisa-destructive-guard.mjs +267 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +15 -2
- package/all/create-only/scripts/remote-agent-aws-setup.sh +3 -0
- package/cdk/create-only/.github/workflows/deploy.yml +2 -1
- package/cdk/create-only/vitest.config.local.ts +3 -0
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts +11 -2
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -1
- package/dist/cli/doctor-lisa-owned-artifacts.js +60 -15
- package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -1
- package/dist/core/config.d.ts +21 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/guard-capabilities.d.ts +60 -0
- package/dist/core/guard-capabilities.d.ts.map +1 -0
- package/dist/core/guard-capabilities.js +102 -0
- package/dist/core/guard-capabilities.js.map +1 -0
- package/dist/core/lisa-owned-hash-ledger.d.ts +11 -0
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -0
- package/dist/core/lisa-owned-hash-ledger.js +127 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -0
- package/dist/core/lisa-owned-provenance.d.ts +75 -0
- package/dist/core/lisa-owned-provenance.d.ts.map +1 -0
- package/dist/core/lisa-owned-provenance.js +127 -0
- package/dist/core/lisa-owned-provenance.js.map +1 -0
- package/dist/core/lisa.d.ts +18 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +38 -0
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +66 -53
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/strategies/copy-overwrite.d.ts +28 -1
- package/dist/strategies/copy-overwrite.d.ts.map +1 -1
- package/dist/strategies/copy-overwrite.js +53 -3
- package/dist/strategies/copy-overwrite.js.map +1 -1
- package/dist/strategies/strategy.interface.d.ts +13 -0
- package/dist/strategies/strategy.interface.d.ts.map +1 -1
- package/expo/create-only/.github/workflows/ci.yml +3 -0
- package/expo/create-only/.github/workflows/deploy.yml +2 -1
- package/expo/create-only/.github/workflows/maestro-e2e.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-health.yml +3 -0
- package/expo/create-only/.github/workflows/nightly-e2e-report.yml +3 -0
- package/expo/create-only/babel.config.js +3 -0
- package/expo/create-only/jest.config.local.ts +3 -0
- package/expo/create-only/jest.config.react-native-mock.js +3 -0
- package/expo/create-only/jest.setup.local.ts +3 -0
- package/expo/create-only/jest.setup.pre.local.js +3 -0
- package/expo/create-only/scripts/zap-baseline.sh +3 -0
- package/harper-fabric/create-only/.github/workflows/deploy.yml +3 -0
- package/harper-fabric/create-only/.github/workflows/zap-baseline.yml +3 -0
- package/harper-fabric/create-only/scripts/zap-baseline.sh +3 -0
- package/nestjs/create-only/.github/workflows/deploy.yml +3 -0
- package/nestjs/create-only/scripts/zap-baseline.sh +3 -0
- package/nestjs/create-only/vitest.config.local.ts +3 -0
- package/npm-package/create-only/.github/workflows/publish-to-npm.yml +2 -1
- package/package.json +3 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/block-no-verify.sh +15 -2
- package/plugins/lisa/rules/eager/reset-seed-coverage.md +2 -0
- 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/block-no-verify.sh +15 -2
- package/plugins/lisa-copilot/rules/eager/reset-seed-coverage.md +2 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +15 -2
- package/plugins/lisa-cursor/rules/reset-seed-coverage.mdc +2 -0
- 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/block-no-verify.sh +15 -2
- package/plugins/src/base/rules/eager/reset-seed-coverage.md +2 -0
- package/rails/create-only/.github/workflows/claude-code-review-response.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-code-complexity.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-test-coverage.yml +2 -1
- package/rails/create-only/.github/workflows/claude-nightly-test-improvement.yml +2 -1
- package/rails/create-only/.github/workflows/claude-sync-down-branches.yml +2 -1
- package/rails/create-only/.github/workflows/deploy.yml +2 -1
- package/rails/create-only/.mutant.yml +3 -0
- package/rails/create-only/.reek.yml +3 -0
- package/rails/create-only/.rubocop_todo.yml +3 -0
- package/rails/create-only/mutation.gate.yml +3 -0
- package/rails/create-only/rubocop.thresholds.yml +3 -0
- package/rails/create-only/spec/rails_helper.rb +2 -0
- package/rails/create-only/spec/spec_helper.rb +2 -0
- package/scripts/generate-lisa-owned-hash-ledger.mjs +226 -0
- package/typescript/create-only/.github/workflows/auto-update-pr-branches-dispatch.yml +2 -1
- package/typescript/create-only/.github/workflows/auto-update-pr-branches.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-ci-auto-fix.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-code-review-response.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-deploy-auto-fix.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-code-complexity.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-test-coverage.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-nightly-test-improvement.yml +2 -1
- package/typescript/create-only/.github/workflows/claude-sync-down-branches.yml +2 -1
- package/typescript/create-only/.github/workflows/claude.yml +2 -1
- package/typescript/create-only/.github/workflows/required-checks-drift.yml +2 -1
- package/typescript/create-only/eslint.config.local.ts +3 -0
- package/typescript/create-only/jest.config.local.ts +3 -0
- package/typescript/create-only/vitest.config.local.ts +3 -0
|
@@ -25,6 +25,7 @@ import * as fs from "node:fs";
|
|
|
25
25
|
import * as path from "node:path";
|
|
26
26
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
27
27
|
|
|
28
|
+
import { destructiveDenial } from "./lisa-destructive-guard.mjs";
|
|
28
29
|
import { validateAgainstSchema } from "./lisa-schema-validate.mjs";
|
|
29
30
|
|
|
30
31
|
/** Pinned envelope schema version. */
|
|
@@ -126,6 +127,15 @@ export function validateEnvelope(envelope) {
|
|
|
126
127
|
if (envelope.mode === "declared-noop" && envelope.status !== "no-op") {
|
|
127
128
|
errors.push('mode "declared-noop" requires status "no-op"');
|
|
128
129
|
}
|
|
130
|
+
// The production boundary lives here, at the one interface every reset, seed,
|
|
131
|
+
// and verify adapter must pass through, rather than in each adapter. A
|
|
132
|
+
// destructive run against a production-resolved (or unresolvable) environment
|
|
133
|
+
// has no representable success envelope, so it can never exit 0 — reporting
|
|
134
|
+
// the refusal stays available, which is the only outcome that should be.
|
|
135
|
+
const denial = destructiveDenial(envelope);
|
|
136
|
+
if (denial && SUCCESS_STATUSES.includes(envelope.status)) {
|
|
137
|
+
errors.push(`${denial.code}: ${denial.message}`);
|
|
138
|
+
}
|
|
129
139
|
return { valid: errors.length === 0, errors };
|
|
130
140
|
}
|
|
131
141
|
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lisa-destructive-guard — the executable arm of `production-fails-closed`.
|
|
4
|
+
*
|
|
5
|
+
* The `reset-seed-coverage` contract already says the right thing: production
|
|
6
|
+
* is refused "with no override, escape hatch, or environment variable that
|
|
7
|
+
* changes the answer", `--dry-run` is mandatory before anything destructive,
|
|
8
|
+
* and a caller-supplied `--stage` is a *request* to be checked against
|
|
9
|
+
* server-resolved identity rather than the source of truth. Until this module
|
|
10
|
+
* existed, all three were prose — an agent reading a rule and choosing to stop.
|
|
11
|
+
* Measured conformance for that rung in this codebase was approximately zero,
|
|
12
|
+
* including by the agent that authored the rule. For a destructive,
|
|
13
|
+
* irreversible operation that is the wrong rung, so the decision moves here.
|
|
14
|
+
*
|
|
15
|
+
* Three properties make this a control rather than a suggestion:
|
|
16
|
+
*
|
|
17
|
+
* 1. **No override exists to be found.** There is no `force` parameter, no
|
|
18
|
+
* `allowProduction` field, and no environment-variable read anywhere in this
|
|
19
|
+
* file — a test greps the shipped source for the latter, so the claim cannot
|
|
20
|
+
* rot. A caller cannot pass the wrong thing because there is no right thing
|
|
21
|
+
* to pass. The tests assert the absence structurally, not behaviourally.
|
|
22
|
+
* 2. **Ambiguity resolves to refusal.** An environment identity that cannot be
|
|
23
|
+
* read is treated exactly like production. "I could not tell" must never be
|
|
24
|
+
* the cheaper answer than "it is production".
|
|
25
|
+
* 3. **A dry run is not a pass.** `dryRun: true` does not soften a production
|
|
26
|
+
* denial. Enumerating production state is still reaching into production,
|
|
27
|
+
* and allowing it would hand every caller a one-flag override.
|
|
28
|
+
*
|
|
29
|
+
* What this module deliberately does NOT claim: it cannot verify that the
|
|
30
|
+
* `environment` an adapter reports is the environment it actually connected to.
|
|
31
|
+
* An adapter that resolves its stage from a caller-supplied string and reports
|
|
32
|
+
* `"dev"` while pointed at production defeats every in-process check by
|
|
33
|
+
* construction. That hole is why the contract says platform enforcement beats
|
|
34
|
+
* process enforcement, and why the durable answer is a capability that is not
|
|
35
|
+
* deployed to production at all — see `docs/decisions/`. This module closes the
|
|
36
|
+
* narrower hole Lisa can close: an honest adapter can no longer report a
|
|
37
|
+
* successful destructive production run, in any repo, by any path.
|
|
38
|
+
* @module scripts/lisa-destructive-guard
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Capabilities that mutate persistent state by definition.
|
|
43
|
+
*
|
|
44
|
+
* Membership is by capability name because a destructive adapter that fails
|
|
45
|
+
* before it deletes anything still reports zeroes, and a guard that keyed only
|
|
46
|
+
* on the counts would wave it through on the attempt that mattered.
|
|
47
|
+
*/
|
|
48
|
+
export const DESTRUCTIVE_CAPABILITIES = Object.freeze([
|
|
49
|
+
"reset",
|
|
50
|
+
"reseed",
|
|
51
|
+
"reset-seed",
|
|
52
|
+
"seed",
|
|
53
|
+
"teardown",
|
|
54
|
+
"truncate",
|
|
55
|
+
"purge",
|
|
56
|
+
"drop",
|
|
57
|
+
"restore",
|
|
58
|
+
"migrate-down",
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Substring marking an environment segment as production.
|
|
63
|
+
*
|
|
64
|
+
* Deliberately a substring rather than an exact match, so `preprod`,
|
|
65
|
+
* `prod-blue`, and `acme-prod-1` all classify as production. That
|
|
66
|
+
* over-includes: a genuine pre-production environment is refused too. For a
|
|
67
|
+
* control over irreversible operations, over-refusal is the correct direction
|
|
68
|
+
* to be wrong in, and a project that needs the distinction names its
|
|
69
|
+
* environments so the word does not appear.
|
|
70
|
+
*/
|
|
71
|
+
const PRODUCTION_SUBSTRING = "prod";
|
|
72
|
+
|
|
73
|
+
/** Whole segments that mark production without containing the substring. */
|
|
74
|
+
const PRODUCTION_SEGMENTS = Object.freeze(["prd", "live"]);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Values that carry no environment identity.
|
|
78
|
+
*
|
|
79
|
+
* Each of these is something a resolver returns when it failed, and every one
|
|
80
|
+
* of them classifies as `unresolved`, which the guard then treats exactly as it
|
|
81
|
+
* treats production.
|
|
82
|
+
*/
|
|
83
|
+
const UNRESOLVED_SENTINELS = new Set([
|
|
84
|
+
"",
|
|
85
|
+
"unknown",
|
|
86
|
+
"unresolved",
|
|
87
|
+
"undefined",
|
|
88
|
+
"null",
|
|
89
|
+
"n/a",
|
|
90
|
+
"na",
|
|
91
|
+
"none",
|
|
92
|
+
"-",
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
/** Flags that explicitly opt out of the mandatory dry run. */
|
|
96
|
+
const EXECUTE_FLAGS = Object.freeze(["--no-dry-run", "--execute"]);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Normalize an environment identity for comparison.
|
|
100
|
+
* @param {unknown} value - Candidate environment identity
|
|
101
|
+
* @returns {string} Lowercased, trimmed text, or "" when there is no text
|
|
102
|
+
*/
|
|
103
|
+
function normalize(value) {
|
|
104
|
+
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Classify a server-resolved environment identity.
|
|
109
|
+
*
|
|
110
|
+
* Returns `unresolved` rather than guessing whenever the value is not text, is
|
|
111
|
+
* blank, or is one of the sentinels a failed resolver produces. Callers must
|
|
112
|
+
* treat `unresolved` as production; this function does not make that decision
|
|
113
|
+
* for them so that the two cases stay separately reportable.
|
|
114
|
+
* @param {unknown} value - The environment identity to classify
|
|
115
|
+
* @returns {"production"|"non-production"|"unresolved"} The classification
|
|
116
|
+
*/
|
|
117
|
+
export function classifyEnvironment(value) {
|
|
118
|
+
const text = normalize(value);
|
|
119
|
+
if (typeof value !== "string" || UNRESOLVED_SENTINELS.has(text)) {
|
|
120
|
+
return "unresolved";
|
|
121
|
+
}
|
|
122
|
+
const segments = text.split(/[^a-z0-9]+/u).filter(Boolean);
|
|
123
|
+
if (segments.length === 0) {
|
|
124
|
+
return "unresolved";
|
|
125
|
+
}
|
|
126
|
+
const production = segments.some(
|
|
127
|
+
segment =>
|
|
128
|
+
segment.includes(PRODUCTION_SUBSTRING) ||
|
|
129
|
+
PRODUCTION_SEGMENTS.includes(segment)
|
|
130
|
+
);
|
|
131
|
+
return production ? "production" : "non-production";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Whether a run mutates persistent state.
|
|
136
|
+
*
|
|
137
|
+
* True when the capability is destructive by name, and also when a run of any
|
|
138
|
+
* capability reports rows deleted or created — a read-only adapter that mutated
|
|
139
|
+
* is still a mutation, and the guard should not depend on it being named
|
|
140
|
+
* honestly.
|
|
141
|
+
* @param {object} fields - An envelope or envelope-shaped object
|
|
142
|
+
* @returns {boolean} True when the run is destructive
|
|
143
|
+
*/
|
|
144
|
+
export function isDestructive(fields) {
|
|
145
|
+
const capability = normalize(fields?.capability);
|
|
146
|
+
if (DESTRUCTIVE_CAPABILITIES.includes(capability)) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
const summary = fields?.summary ?? {};
|
|
150
|
+
return Number(summary.deleted) > 0 || Number(summary.created) > 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Build the denial for a resolved environment, or null when it is permitted.
|
|
155
|
+
* @param {unknown} environment - Server-resolved environment identity
|
|
156
|
+
* @returns {{code: string, message: string}|null} The denial, if any
|
|
157
|
+
*/
|
|
158
|
+
function denyByEnvironment(environment) {
|
|
159
|
+
const classification = classifyEnvironment(environment);
|
|
160
|
+
if (classification === "unresolved") {
|
|
161
|
+
return {
|
|
162
|
+
code: "unresolved-environment",
|
|
163
|
+
message:
|
|
164
|
+
"the server-resolved environment could not be read, which fails closed exactly as production does — resolve the environment from deployment identity before any destructive operation",
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (classification === "production") {
|
|
168
|
+
return {
|
|
169
|
+
code: "production-forbidden",
|
|
170
|
+
message: `production is refused by the reset-seed contract with no override, and "${normalize(environment)}" classifies as production — a dry run is not an exemption`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The denial implied by an envelope, or null when the envelope is permitted.
|
|
178
|
+
*
|
|
179
|
+
* This is the check the command envelope itself applies, so a destructive
|
|
180
|
+
* production run cannot be *reported* as a success by any adapter in any repo.
|
|
181
|
+
* @param {object} fields - An envelope or envelope-shaped object
|
|
182
|
+
* @returns {{code: string, message: string}|null} The denial, if any
|
|
183
|
+
*/
|
|
184
|
+
export function destructiveDenial(fields) {
|
|
185
|
+
return isDestructive(fields) ? denyByEnvironment(fields?.environment) : null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Decide whether a destructive invocation may proceed.
|
|
190
|
+
*
|
|
191
|
+
* Adapter-time counterpart of {@link destructiveDenial}, adding the two checks
|
|
192
|
+
* that need the caller's request alongside the resolved identity. The requested
|
|
193
|
+
* stage is never trusted: it is compared against server-resolved identity, and
|
|
194
|
+
* a production request is refused even when the resolver disagrees, because the
|
|
195
|
+
* disagreement itself means one of the two is wrong.
|
|
196
|
+
* @param {object} request - capability, summary, resolvedEnvironment, requestedStage, dryRun
|
|
197
|
+
* @returns {{allowed: boolean, denial: ({code: string, message: string}|null)}} The decision
|
|
198
|
+
*/
|
|
199
|
+
export function assertDestructiveAllowed(request) {
|
|
200
|
+
if (!isDestructive(request)) {
|
|
201
|
+
return { allowed: true, denial: null };
|
|
202
|
+
}
|
|
203
|
+
const resolved = request?.resolvedEnvironment;
|
|
204
|
+
const environmentDenial = denyByEnvironment(resolved);
|
|
205
|
+
if (environmentDenial) {
|
|
206
|
+
return { allowed: false, denial: environmentDenial };
|
|
207
|
+
}
|
|
208
|
+
const requested = request?.requestedStage;
|
|
209
|
+
if (requested === undefined || requested === null) {
|
|
210
|
+
return { allowed: true, denial: null };
|
|
211
|
+
}
|
|
212
|
+
if (classifyEnvironment(requested) === "production") {
|
|
213
|
+
return {
|
|
214
|
+
allowed: false,
|
|
215
|
+
denial: {
|
|
216
|
+
code: "production-requested",
|
|
217
|
+
message: `the caller requested "${normalize(requested)}", which classifies as production; a requested stage never authorizes a destructive operation`,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (normalize(requested) !== normalize(resolved)) {
|
|
222
|
+
return {
|
|
223
|
+
allowed: false,
|
|
224
|
+
denial: {
|
|
225
|
+
code: "stage-mismatch",
|
|
226
|
+
message: `the caller requested "${normalize(requested)}" but deployment identity resolved to "${normalize(resolved)}"; a stage is a request to be checked, never the source of truth`,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return { allowed: true, denial: null };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Read one `--flag value` / `--flag=value` option out of argv.
|
|
235
|
+
* @param {readonly string[]} argv - Arguments after the script name
|
|
236
|
+
* @param {string} flag - The long flag to read, including leading dashes
|
|
237
|
+
* @returns {string|null} The value, or null when the flag is absent or empty
|
|
238
|
+
*/
|
|
239
|
+
function readOption(argv, flag) {
|
|
240
|
+
const inline = argv.find(entry => entry.startsWith(`${flag}=`));
|
|
241
|
+
if (inline) {
|
|
242
|
+
return inline.slice(flag.length + 1) || null;
|
|
243
|
+
}
|
|
244
|
+
const index = argv.indexOf(flag);
|
|
245
|
+
return index === -1 ? null : (argv[index + 1] ?? null);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Parse the arguments every destructive adapter accepts.
|
|
250
|
+
*
|
|
251
|
+
* `--dry-run` is the default rather than an opt-in: an adapter that forgets to
|
|
252
|
+
* parse anything, or is handed arguments it does not understand, enumerates
|
|
253
|
+
* instead of mutating. Mutating requires an explicit `--no-dry-run` or
|
|
254
|
+
* `--execute`, and passing `--dry-run` alongside either one keeps the dry run,
|
|
255
|
+
* so a stray flag can never silently upgrade a rehearsal into a real run.
|
|
256
|
+
* @param {readonly string[]} argv - Arguments after the script name
|
|
257
|
+
* @returns {{dryRun: boolean, requestedStage: (string|null), idempotencyKey: (string|null)}} Parsed arguments
|
|
258
|
+
*/
|
|
259
|
+
export function parseDestructiveArgs(argv) {
|
|
260
|
+
const args = [...(argv ?? [])];
|
|
261
|
+
const optedOut = EXECUTE_FLAGS.some(flag => args.includes(flag));
|
|
262
|
+
return {
|
|
263
|
+
dryRun: args.includes("--dry-run") || !optedOut,
|
|
264
|
+
requestedStage: readOption(args, "--stage"),
|
|
265
|
+
idempotencyKey: readOption(args, "--idempotency-key"),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -5,9 +5,22 @@
|
|
|
5
5
|
# check. See feedback_never_no_verify in user memory.
|
|
6
6
|
#
|
|
7
7
|
# Blocked bypass vectors:
|
|
8
|
-
# 1.
|
|
8
|
+
# 1. --no-verify, and any prefix abbreviation git would accept for it;
|
|
9
9
|
# 2. HUSKY=0 / HUSKY_SKIP_HOOKS=... — disables husky-managed git hooks;
|
|
10
|
-
# 3. core.hooksPath pointed
|
|
10
|
+
# 3. core.hooksPath pointed anywhere but an allowlisted in-repo hooks dir;
|
|
11
|
+
# 4. --config-env=core.hooksPath=VAR, in both the one- and two-token spellings;
|
|
12
|
+
# 5. GIT_CONFIG_KEY_<n>=core.hooksPath env-var-style command-scope config.
|
|
13
|
+
#
|
|
14
|
+
# The line below is what lets `lisa apply` tell a downstream copy of this guard
|
|
15
|
+
# that is BEHIND from one that is AHEAD. Byte comparison cannot: both look like
|
|
16
|
+
# "differs from mine", and guessing "behind" is how a fork's stronger guard gets
|
|
17
|
+
# silently replaced by a weaker upstream one. Refresh compares the two declared
|
|
18
|
+
# sets, and refuses to overwrite a copy declaring anything this one does not.
|
|
19
|
+
#
|
|
20
|
+
# Add a name here in the same commit that closes a vector. A hardening that
|
|
21
|
+
# forgets to is invisible to refresh, and shows up as an unexplained diff at
|
|
22
|
+
# review time instead of a named capability.
|
|
23
|
+
# lisa-guard-capabilities: no-verify-abbrev, husky-env, hookspath-allowlist, config-env, git-config-key
|
|
11
24
|
#
|
|
12
25
|
# Shell-token matching avoids false positives from issue bodies, heredocs, and
|
|
13
26
|
# commit-message prose while still catching quoted real argv values such as
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# Seeded by Lisa on first setup — this file is YOURS.
|
|
3
|
+
# Lisa will not overwrite it. (copy-overwrite assets ARE replaced each run.)
|
|
4
|
+
|
|
2
5
|
# Installed by Lisa. The authoritative implementation is shipped by the
|
|
3
6
|
# lisa-setup-remote-aws skill and the @codyswann/lisa package.
|
|
4
7
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { HashLedger } from "../core/lisa-owned-provenance.js";
|
|
1
2
|
/** One doctor check result, structurally identical to `DoctorCheck`. */
|
|
2
3
|
interface ArtifactCheck {
|
|
3
4
|
name: string;
|
|
@@ -5,14 +6,22 @@ interface ArtifactCheck {
|
|
|
5
6
|
detail: string;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
|
-
* Report Lisa-owned enforcement artifacts
|
|
9
|
+
* Report Lisa-owned enforcement artifacts that differ from what Lisa ships.
|
|
10
|
+
*
|
|
11
|
+
* Two different findings, deliberately not merged. An *outdated* copy is fixed
|
|
12
|
+
* by running apply. A *modified* copy is one apply will now refuse to touch, so
|
|
13
|
+
* telling the operator to run apply would send them round a loop that never
|
|
14
|
+
* terminates and make the protection look like a bug. Both still warn — a guard
|
|
15
|
+
* nobody can account for is worth a line either way, and staying silent about a
|
|
16
|
+
* downstream edit would let a project quietly swap a guard for a stub.
|
|
9
17
|
*
|
|
10
18
|
* Only artifacts the project already has are considered: a missing one means
|
|
11
19
|
* the stack does not apply here, not that something drifted.
|
|
12
20
|
* @param targetPath - Project path to inspect
|
|
13
21
|
* @param lisaRoot - Installed Lisa package root (injected by tests)
|
|
22
|
+
* @param ledger - Known-good hashes, defaulting to Lisa's shipping history
|
|
14
23
|
* @returns Doctor check result
|
|
15
24
|
*/
|
|
16
|
-
export declare function checkLisaOwnedArtifacts(targetPath: string, lisaRoot?: string): Promise<ArtifactCheck>;
|
|
25
|
+
export declare function checkLisaOwnedArtifacts(targetPath: string, lisaRoot?: string, ledger?: HashLedger): Promise<ArtifactCheck>;
|
|
17
26
|
export {};
|
|
18
27
|
//# sourceMappingURL=doctor-lisa-owned-artifacts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-lisa-owned-artifacts.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor-lisa-owned-artifacts.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAoBnE,wEAAwE;AACxE,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAkHD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,MAA0B,EACpC,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,aAAa,CAAC,CA+CxB"}
|
|
@@ -20,6 +20,7 @@ import * as path from "node:path";
|
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import * as fse from "fs-extra";
|
|
22
22
|
import { PROJECT_TYPE_ORDER } from "../core/config.js";
|
|
23
|
+
import { classifyHostCopy, mayRefreshLisaOwned, } from "../core/lisa-owned-provenance.js";
|
|
23
24
|
import { isLisaOwnedTemplate } from "../core/lisa-owned-templates.js";
|
|
24
25
|
import { isLisaSourceRepo } from "../core/self-apply.js";
|
|
25
26
|
import { listFilesRecursive } from "../utils/file-operations.js";
|
|
@@ -112,15 +113,23 @@ function reExportsShippedTemplate(installed, installedPath, sources) {
|
|
|
112
113
|
return [...installed.toString("utf8").matchAll(RELATIVE_SPECIFIER)].some(match => shipped.has(path.resolve(directory, match[1] ?? "")));
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
115
|
-
* Report Lisa-owned enforcement artifacts
|
|
116
|
+
* Report Lisa-owned enforcement artifacts that differ from what Lisa ships.
|
|
117
|
+
*
|
|
118
|
+
* Two different findings, deliberately not merged. An *outdated* copy is fixed
|
|
119
|
+
* by running apply. A *modified* copy is one apply will now refuse to touch, so
|
|
120
|
+
* telling the operator to run apply would send them round a loop that never
|
|
121
|
+
* terminates and make the protection look like a bug. Both still warn — a guard
|
|
122
|
+
* nobody can account for is worth a line either way, and staying silent about a
|
|
123
|
+
* downstream edit would let a project quietly swap a guard for a stub.
|
|
116
124
|
*
|
|
117
125
|
* Only artifacts the project already has are considered: a missing one means
|
|
118
126
|
* the stack does not apply here, not that something drifted.
|
|
119
127
|
* @param targetPath - Project path to inspect
|
|
120
128
|
* @param lisaRoot - Installed Lisa package root (injected by tests)
|
|
129
|
+
* @param ledger - Known-good hashes, defaulting to Lisa's shipping history
|
|
121
130
|
* @returns Doctor check result
|
|
122
131
|
*/
|
|
123
|
-
export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisaRoot()) {
|
|
132
|
+
export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisaRoot(), ledger) {
|
|
124
133
|
const shipped = await shippedArtifacts(lisaRoot);
|
|
125
134
|
if (shipped.size === 0) {
|
|
126
135
|
return {
|
|
@@ -145,24 +154,60 @@ export async function checkLisaOwnedArtifacts(targetPath, lisaRoot = defaultLisa
|
|
|
145
154
|
return undefined;
|
|
146
155
|
if (await matchesAnyShipped(installed, sources))
|
|
147
156
|
return undefined;
|
|
148
|
-
|
|
149
|
-
reExportsShippedTemplate(installed, installedPath, sources)
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
if (selfHost &&
|
|
158
|
+
reExportsShippedTemplate(installed, installedPath, sources))
|
|
159
|
+
return undefined;
|
|
160
|
+
const outdated = await isProvablyStale(installed, destination, sources, ledger);
|
|
161
|
+
return [destination, outdated ? "stale" : "modified"];
|
|
152
162
|
}));
|
|
153
|
-
|
|
154
|
-
|
|
163
|
+
return summarise(results.filter((item) => item !== undefined));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Turn the per-artifact findings into one doctor line.
|
|
167
|
+
* @param findings - Destination paths paired with what was found
|
|
168
|
+
* @returns Doctor check result
|
|
169
|
+
*/
|
|
170
|
+
function summarise(findings) {
|
|
171
|
+
const pick = (wanted) => findings
|
|
172
|
+
.filter(([, finding]) => finding === wanted)
|
|
173
|
+
.map(([destination]) => destination)
|
|
155
174
|
.sort((left, right) => left.localeCompare(right));
|
|
156
|
-
|
|
157
|
-
|
|
175
|
+
const stale = pick("stale");
|
|
176
|
+
const modified = pick("modified");
|
|
177
|
+
if (stale.length === 0 && modified.length === 0) {
|
|
178
|
+
return {
|
|
158
179
|
name: CHECK_NAME,
|
|
159
180
|
status: "ok",
|
|
160
181
|
detail: "Enforcement guards match the installed Lisa version",
|
|
161
|
-
}
|
|
162
|
-
: {
|
|
163
|
-
name: CHECK_NAME,
|
|
164
|
-
status: "warn",
|
|
165
|
-
detail: `Outdated Lisa-owned guards (run \`npx lisa apply .\` to refresh): ${stale.join(", ")}`,
|
|
166
182
|
};
|
|
183
|
+
}
|
|
184
|
+
const parts = [
|
|
185
|
+
stale.length > 0
|
|
186
|
+
? `Outdated Lisa-owned guards (run \`npx lisa apply .\` to refresh): ${stale.join(", ")}`
|
|
187
|
+
: "",
|
|
188
|
+
modified.length > 0
|
|
189
|
+
? `Lisa-owned guards edited in this project, so apply will keep yours rather than overwrite them: ${modified.join(", ")}`
|
|
190
|
+
: "",
|
|
191
|
+
].filter(part => part.length > 0);
|
|
192
|
+
return { name: CHECK_NAME, status: "warn", detail: parts.join(". ") };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Whether a differing installed guard is genuinely behind Lisa's.
|
|
196
|
+
*
|
|
197
|
+
* Doctor and apply have to agree, or the operator gets contradictory
|
|
198
|
+
* instructions: doctor telling somebody to run `lisa apply .` to fix a file
|
|
199
|
+
* apply will then deliberately refuse to touch is a loop with no exit, and it
|
|
200
|
+
* reads as a broken tool rather than as the protection it is. So a copy apply
|
|
201
|
+
* would preserve is not reported here either — it is not outdated, and calling
|
|
202
|
+
* it outdated invites the operator to discard their own hardening.
|
|
203
|
+
* @param installed - Bytes currently installed in the project
|
|
204
|
+
* @param destination - Repo-relative destination path
|
|
205
|
+
* @param sources - Absolute paths of the shipped variants
|
|
206
|
+
* @param ledger - Known-good hashes, defaulting to Lisa's shipping history
|
|
207
|
+
* @returns True when every shipped variant considers the installed copy stale
|
|
208
|
+
*/
|
|
209
|
+
async function isProvablyStale(installed, destination, sources, ledger) {
|
|
210
|
+
const shipped = await Promise.all(sources.map(async (source) => readFile(source)));
|
|
211
|
+
return shipped.every(candidate => mayRefreshLisaOwned(classifyHostCopy(destination, installed, candidate, ledger)));
|
|
167
212
|
}
|
|
168
213
|
//# sourceMappingURL=doctor-lisa-owned-artifacts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-lisa-owned-artifacts.js","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"doctor-lisa-owned-artifacts.js","sourceRoot":"","sources":["../../src/cli/doctor-lisa-owned-artifacts.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -158,8 +158,26 @@ export interface FileOperationResult {
|
|
|
158
158
|
* let template changes — including fixes to the enforcement guards —
|
|
159
159
|
* go undelivered while the summary read exactly like a clean no-op.
|
|
160
160
|
*/
|
|
161
|
-
| "stale"
|
|
161
|
+
| "stale"
|
|
162
|
+
/**
|
|
163
|
+
* A Lisa-owned artifact whose installed copy could not be proved to be
|
|
164
|
+
* behind Lisa's, so it was preserved rather than overwritten.
|
|
165
|
+
*
|
|
166
|
+
* Emphatically not "stale" — that word says the file is out of date, and
|
|
167
|
+
* here the likeliest reason it differs is that it is *ahead*. Filing the two
|
|
168
|
+
* under one label would reproduce the original defect in the reporting: an
|
|
169
|
+
* operator reading "out of date" about a guard they deliberately hardened
|
|
170
|
+
* would fix the wrong thing.
|
|
171
|
+
*/
|
|
172
|
+
| "host-ahead" | "overwritten" | "appended" | "merged" | "created";
|
|
162
173
|
readonly linesAdded?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Operator-readable explanation of a non-obvious outcome, shown verbatim.
|
|
176
|
+
*
|
|
177
|
+
* Carries the "why" for `host-ahead`, where the path alone tells an operator
|
|
178
|
+
* nothing actionable and the whole point is to say what would have been lost.
|
|
179
|
+
*/
|
|
180
|
+
readonly note?: string;
|
|
163
181
|
}
|
|
164
182
|
/**
|
|
165
183
|
* Counters for operation summary
|
|
@@ -169,6 +187,8 @@ export interface OperationCounters {
|
|
|
169
187
|
skipped: number;
|
|
170
188
|
/** Managed files left out of date because this apply could not overwrite them. */
|
|
171
189
|
stale: number;
|
|
190
|
+
/** Lisa-owned artifacts preserved because the installed copy may be ahead. */
|
|
191
|
+
hostAhead: number;
|
|
172
192
|
overwritten: number;
|
|
173
193
|
appended: number;
|
|
174
194
|
merged: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.js
CHANGED
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAwBA;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAE/B;IACF,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,YAAY;IACpB,GAAG,EAAE,YAAY;IACjB,eAAe,EAAE,YAAY;IAC7B,MAAM,EAAE,YAAY;IACpB,aAAa,EAAE,YAAY;IAC3B,UAAU,EAAE,SAAS;IACrB,KAAK,EAAE,SAAS;CACR,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,YAAY;IACZ,aAAa;IACb,eAAe;IACf,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,KAAK;IACL,OAAO;CACC,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAA4B;IACtD,gBAAgB;IAChB,eAAe;IACf,aAAa;IACb,OAAO;IACP,cAAc;IACd,cAAc;CACN,CAAC;AAyBX;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAuB;IAChD,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,KAAK;IACL,SAAS;IACT,UAAU;IACV,OAAO;CACC,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsC;IAChE,GAAG,EAAE,OAAO;CACb,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,GAAG,cAAc;IACjB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;CAChC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsC;IACvE,IAAI,EAAE,OAAO;CACd,CAAC;AASF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAgB,EAChB,KAAgB;IAEhB,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,OAAO,KAAK,KAAK,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAY,QAAQ,CAAC;AAsDjD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,YAAoB,EACpB,OAAqC;IAErC,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACxC,8EAA8E;IAC9E,0CAA0C;IAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC9B,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC9D,OAAO,KAAK,KAAK,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,oBAAoB,CAAC,KAAa;IACzC,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAChF,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The capability marker a Lisa-owned guard uses to declare what it defends
|
|
3
|
+
* against, so refresh can compare two copies by *what they stop* rather than by
|
|
4
|
+
* bytes.
|
|
5
|
+
*
|
|
6
|
+
* A byte comparison answers "are these the same?" and nothing else. It cannot
|
|
7
|
+
* answer the only question refresh actually needs answered — "is the host's copy
|
|
8
|
+
* behind mine, or ahead of it?" — and guessing "behind" is how a host's stronger
|
|
9
|
+
* guard gets silently replaced by a weaker upstream one.
|
|
10
|
+
*
|
|
11
|
+
* The marker is one comment line in the guard's header:
|
|
12
|
+
*
|
|
13
|
+
* ```
|
|
14
|
+
* # lisa-guard-capabilities: no-verify-abbrev, hookspath-allowlist, config-env
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Deliberately a *set*, not a version number. A monotonic `lisa-guard-version: N`
|
|
18
|
+
* is easier to compare but lies the moment two hosts harden different vectors
|
|
19
|
+
* independently — which is exactly what happened: `propswapllc/frontend` closed
|
|
20
|
+
* the `GIT_CONFIG_KEY_<n>` bypass while `tunnl-infrastructure` closed a different
|
|
21
|
+
* one. Both would have bumped to the same number and one would have silently
|
|
22
|
+
* won. Two sets stay two sets, and set difference names precisely what each copy
|
|
23
|
+
* has that the other does not.
|
|
24
|
+
*
|
|
25
|
+
* Only the header window is scanned. A guard whose *body* greps for the marker
|
|
26
|
+
* string, or a test fixture that quotes one, must not be read as declaring it.
|
|
27
|
+
* @module core/guard-capabilities
|
|
28
|
+
*/
|
|
29
|
+
/** A guard's declared capability set, normalised for comparison. */
|
|
30
|
+
export type CapabilitySet = ReadonlySet<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Read the capabilities a guard's header declares.
|
|
33
|
+
*
|
|
34
|
+
* Absence is not an error and not a failure signal — it means the artifact has
|
|
35
|
+
* not been enrolled, and every caller treats that as "no declaration made"
|
|
36
|
+
* rather than "declares nothing dangerous". That is what lets the marker roll
|
|
37
|
+
* out one guard at a time with no flag day.
|
|
38
|
+
* Scanned line by line with plain string operations rather than a regular
|
|
39
|
+
* expression. A header is untrusted input — it arrives from whatever repository
|
|
40
|
+
* the "host" copy came from — and a linear scan cannot be made to backtrack.
|
|
41
|
+
* @param bytes - Full contents of the guard file
|
|
42
|
+
* @returns The declared capabilities, lower-cased and de-duplicated
|
|
43
|
+
*/
|
|
44
|
+
export declare function readGuardCapabilities(bytes: Buffer): CapabilitySet;
|
|
45
|
+
/**
|
|
46
|
+
* The capabilities the host declares that Lisa's copy does not.
|
|
47
|
+
*
|
|
48
|
+
* A non-empty result is the whole signal: the host copy defends something
|
|
49
|
+
* upstream does not, so overwriting it removes protection. This is set
|
|
50
|
+
* *difference*, not a strict-superset test, on purpose — a host that hardened
|
|
51
|
+
* vector A while upstream hardened vector B is not a superset of upstream, yet
|
|
52
|
+
* overwriting it still deletes A. Asking only "is the host a superset?" would
|
|
53
|
+
* clobber precisely the divergent-hardening case the set representation exists
|
|
54
|
+
* to handle.
|
|
55
|
+
* @param host - Capabilities declared by the installed copy
|
|
56
|
+
* @param lisa - Capabilities declared by the packaged copy
|
|
57
|
+
* @returns Capabilities present on the host and absent upstream, sorted
|
|
58
|
+
*/
|
|
59
|
+
export declare function capabilitiesOnlyOnHost(host: CapabilitySet, lisa: CapabilitySet): readonly string[];
|
|
60
|
+
//# sourceMappingURL=guard-capabilities.d.ts.map
|