@codyswann/lisa 4.29.1 → 4.29.3
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/README.md +9 -5
- package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +8 -7
- package/dist/codex/enforcement-fallback-installer.d.ts +19 -0
- package/dist/codex/enforcement-fallback-installer.d.ts.map +1 -0
- package/dist/codex/enforcement-fallback-installer.js +50 -0
- package/dist/codex/enforcement-fallback-installer.js.map +1 -0
- package/dist/codex/hooks-installer.d.ts.map +1 -1
- package/dist/codex/hooks-installer.js +5 -4
- package/dist/codex/hooks-installer.js.map +1 -1
- package/dist/codex/project-hooks-cleanup.js +1 -1
- package/dist/codex/project-hooks-cleanup.js.map +1 -1
- package/dist/codex/project-overlay.d.ts.map +1 -1
- package/dist/codex/project-overlay.js +7 -4
- package/dist/codex/project-overlay.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +2 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa.js +1 -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 +16 -5
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/lisa/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/lisa/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- 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/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/owner.mjs +96 -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/skills/lisa-secrets-access/SKILL.md +55 -0
- package/plugins/src/base/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
- package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
- package/plugins/src/base/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
- package/scripts/lisa-enforcement-fallback.sh +8 -7
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which project a credential written to this machine belongs to.
|
|
3
|
+
*
|
|
4
|
+
* Everything this skill writes outside `~/.config/<namespace>` lands in a
|
|
5
|
+
* SHARED per-user location: `~/.aws/config`, `~/.aws/credentials`, `~/.bashrc`,
|
|
6
|
+
* `~/.profile`. Those paths have no tenant in them, so two Lisa projects on one
|
|
7
|
+
* workstation wrote the same identifiers and the second silently replaced the
|
|
8
|
+
* first. Measured with two synthetic bundles declaring the same stage names:
|
|
9
|
+
* two profiles survived where four were written, the surviving `agent-dev`
|
|
10
|
+
* named the second tenant's account, and every shell on the machine sourced the
|
|
11
|
+
* second tenant's values — including the first tenant's sessions. Both runs
|
|
12
|
+
* exited 0.
|
|
13
|
+
*
|
|
14
|
+
* Nothing about the surviving profile is wrong. It is a real, working profile
|
|
15
|
+
* that belongs to someone else, which is why no property check on the profile
|
|
16
|
+
* detects it — only a comparison against the intended owner fires. So the owner
|
|
17
|
+
* has to be carried to the write point rather than inferred there.
|
|
18
|
+
*
|
|
19
|
+
* The owner is the **tenant namespace**, not the repository. That is deliberate
|
|
20
|
+
* and it is the existing model, not a new one: `~/.config/<namespace>` is
|
|
21
|
+
* already the unit of sharing, so two repositories of one tenant SHOULD see the
|
|
22
|
+
* same credentials and two tenants must not. A namespace is also already
|
|
23
|
+
* resolved and validated by the time any writer runs, so nothing has to be
|
|
24
|
+
* guessed at the point of writing.
|
|
25
|
+
*
|
|
26
|
+
* Its own module because both writers need it and neither should import the
|
|
27
|
+
* other: `aws-bootstrap` renders profile names, `materialize-secrets` writes
|
|
28
|
+
* the shell block, and this file imports nothing.
|
|
29
|
+
* @module owner
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The one shape an owner may take.
|
|
34
|
+
*
|
|
35
|
+
* Identical to the namespace rule in `surfaces.mjs`, because it IS the
|
|
36
|
+
* namespace — the same value, re-checked where it is about to become part of an
|
|
37
|
+
* ini section header and a shell filename. Anything with a bracket, newline, or
|
|
38
|
+
* path separator would either corrupt `~/.aws/config` or redirect a write.
|
|
39
|
+
*/
|
|
40
|
+
const OWNER_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Require an owner, and refuse to write anything without one.
|
|
44
|
+
*
|
|
45
|
+
* Failing closed is the whole point. A writer that fell back to an unowned name
|
|
46
|
+
* when resolution came up empty would recreate the exact collision this exists
|
|
47
|
+
* to remove, and it would do it on the machines least able to notice — the ones
|
|
48
|
+
* where nobody declared a tenant.
|
|
49
|
+
* @param {unknown} owner Candidate owner.
|
|
50
|
+
* @param {string} what What is about to be written, for the message.
|
|
51
|
+
* @returns {string} The owner, trimmed, when usable.
|
|
52
|
+
*/
|
|
53
|
+
export function assertOwner(owner, what) {
|
|
54
|
+
const trimmed = typeof owner === "string" ? owner.trim() : "";
|
|
55
|
+
if (!trimmed) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`cannot determine which project these credentials belong to, so ` +
|
|
58
|
+
`${what} was not written.\n` +
|
|
59
|
+
`Name the tenant explicitly — 'lisa environment local --tenant=<name>' ` +
|
|
60
|
+
`— or set "secrets".namespace in .lisa.config.json.\n` +
|
|
61
|
+
`Unowned names collide across projects on a shared machine, and the ` +
|
|
62
|
+
`collision is silent: the surviving credential is valid, it just ` +
|
|
63
|
+
`belongs to someone else.`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (!OWNER_SHAPE.test(trimmed) || trimmed === "..") {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`owner "${trimmed}" is not one safe name segment, so ${what} was not ` +
|
|
69
|
+
`written. Use letters, digits, dot, dash or underscore.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return trimmed;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The marker fragment that records who owns a managed block.
|
|
77
|
+
*
|
|
78
|
+
* Written inside the existing marker text rather than as a new marker, so the
|
|
79
|
+
* family recognisers keep matching blocks from every past version. A block with
|
|
80
|
+
* no `owner=` predates ownership and is handled as legacy, never as ours.
|
|
81
|
+
* @param {string} owner Validated owner.
|
|
82
|
+
* @returns {string} The fragment to embed in a marker.
|
|
83
|
+
*/
|
|
84
|
+
export function ownerTag(owner) {
|
|
85
|
+
return `owner=${owner}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Read the owner out of one marker line.
|
|
90
|
+
* @param {string} marker The matched marker text.
|
|
91
|
+
* @returns {string|null} The owner, or null when the block predates ownership.
|
|
92
|
+
*/
|
|
93
|
+
export function ownerOf(marker) {
|
|
94
|
+
const found = /\bowner=([A-Za-z0-9][A-Za-z0-9._-]*)/.exec(marker);
|
|
95
|
+
return found === null ? null : found[1];
|
|
96
|
+
}
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
# a guard, but in an environment where none existed. The guards failed open, and
|
|
16
16
|
# silently, which is the worst of the three ways they could fail.
|
|
17
17
|
#
|
|
18
|
-
# A repository hook
|
|
19
|
-
# is part of the clone, so
|
|
20
|
-
# ever installs.
|
|
18
|
+
# A repository hook removes that plugin-delivery dependency. The project hook
|
|
19
|
+
# configuration is part of the clone, so the dispatcher is available whether or
|
|
20
|
+
# not a plugin ever installs. Each harness still applies its own project-hook
|
|
21
|
+
# trust policy before firing it.
|
|
21
22
|
set -uo pipefail
|
|
22
23
|
|
|
23
24
|
payload="$(cat)"
|
|
@@ -124,7 +125,7 @@ plugin_tree="$repo_root/plugins/lisa/hooks"
|
|
|
124
125
|
# is silence rather than a fleet-wide false alarm.
|
|
125
126
|
#
|
|
126
127
|
# Bash 3.2 is the floor — macOS ships it as /bin/bash, and that is what the
|
|
127
|
-
#
|
|
128
|
+
# repository hook entry invokes — so there are no associative arrays
|
|
128
129
|
# here. There are exactly two possible trees, which is what makes plain
|
|
129
130
|
# variables enough.
|
|
130
131
|
|
|
@@ -352,7 +353,7 @@ done
|
|
|
352
353
|
# options, and the reasons are these.
|
|
353
354
|
#
|
|
354
355
|
# - The hook entry and the guards ship from the SAME `lisa apply`:
|
|
355
|
-
#
|
|
356
|
+
# `.claude/settings.json` or `.codex/hooks.json` registers this dispatcher and
|
|
356
357
|
# `all/copy-overwrite/scripts/lisa-hooks/` writes the guards. "Registered
|
|
357
358
|
# but no guards" is therefore never a configuration anyone chose; it is
|
|
358
359
|
# always drift, deletion, or a partial apply.
|
|
@@ -376,8 +377,8 @@ if [ "$guard_count" -eq 0 ]; then
|
|
|
376
377
|
Blocked: Lisa's enforcement guards are missing from this repository, so this
|
|
377
378
|
tool call was checked by nothing at all.
|
|
378
379
|
|
|
379
|
-
This hook is registered in
|
|
380
|
-
guards it dispatches: $missing
|
|
380
|
+
This hook is registered in the repository hook configuration but resolved none
|
|
381
|
+
of the guards it dispatches: $missing
|
|
381
382
|
|
|
382
383
|
Searched:
|
|
383
384
|
$host_tree/<guard>.sh
|