@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.
Files changed (99) hide show
  1. package/README.md +9 -5
  2. package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +8 -7
  3. package/dist/codex/enforcement-fallback-installer.d.ts +19 -0
  4. package/dist/codex/enforcement-fallback-installer.d.ts.map +1 -0
  5. package/dist/codex/enforcement-fallback-installer.js +50 -0
  6. package/dist/codex/enforcement-fallback-installer.js.map +1 -0
  7. package/dist/codex/hooks-installer.d.ts.map +1 -1
  8. package/dist/codex/hooks-installer.js +5 -4
  9. package/dist/codex/hooks-installer.js.map +1 -1
  10. package/dist/codex/project-hooks-cleanup.js +1 -1
  11. package/dist/codex/project-hooks-cleanup.js.map +1 -1
  12. package/dist/codex/project-overlay.d.ts.map +1 -1
  13. package/dist/codex/project-overlay.js +7 -4
  14. package/dist/codex/project-overlay.js.map +1 -1
  15. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  16. package/dist/core/lisa-owned-hash-ledger.js +2 -0
  17. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  18. package/dist/core/lisa.js +1 -1
  19. package/dist/core/lisa.js.map +1 -1
  20. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  21. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  22. package/dist/core/upstream-evidence-manifest.js +16 -5
  23. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  24. package/package.json +4 -3
  25. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +55 -0
  28. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  29. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  30. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  31. package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +55 -0
  32. package/plugins/lisa/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  33. package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  34. package/plugins/lisa/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  35. package/plugins/lisa-agy/plugin.json +1 -1
  36. package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +55 -0
  37. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  38. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  39. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  40. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  43. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +55 -0
  47. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  48. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  49. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  50. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +55 -0
  52. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  53. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  54. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  55. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-expo-agy/plugin.json +1 -1
  58. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  63. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  68. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  73. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  77. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  78. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  82. package/plugins/lisa-rails-agy/plugin.json +1 -1
  83. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  87. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  88. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  92. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  93. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  95. package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +55 -0
  96. package/plugins/src/base/skills/lisa-secrets-access/scripts/aws-bootstrap.mjs +202 -16
  97. package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +589 -100
  98. package/plugins/src/base/skills/lisa-secrets-access/scripts/owner.mjs +96 -0
  99. 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 is the delivery that cannot fail this way. `.claude/settings.json`
19
- # is part of the clone, so it reaches a cloud session whether or not a plugin
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
- # `.claude/settings.json` entry invokes — so there are no associative arrays
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
- # `all/merge/.claude/settings.json` registers this dispatcher and
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 .claude/settings.json but resolved none of the
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