@codyswann/lisa 4.28.5 → 4.29.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.
Files changed (188) hide show
  1. package/all/copy-overwrite/scripts/lisa-gates.mjs +2 -1
  2. package/all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh +3 -2
  3. package/cdk/create-only/vitest.config.local.ts +5 -1
  4. package/cdk/package-lisa/package.lisa.json +14 -7
  5. package/dist/cli/lisa-test-run-bootstrap.d.ts +3 -0
  6. package/dist/cli/lisa-test-run-bootstrap.d.ts.map +1 -0
  7. package/dist/cli/lisa-test-run-bootstrap.js +201 -0
  8. package/dist/cli/lisa-test-run-bootstrap.js.map +1 -0
  9. package/dist/cli/lisa-test-run-ipc.d.ts +42 -0
  10. package/dist/cli/lisa-test-run-ipc.d.ts.map +1 -0
  11. package/dist/cli/lisa-test-run-ipc.js +200 -0
  12. package/dist/cli/lisa-test-run-ipc.js.map +1 -0
  13. package/dist/cli/lisa-test-run-process-group.d.ts +30 -0
  14. package/dist/cli/lisa-test-run-process-group.d.ts.map +1 -0
  15. package/dist/cli/lisa-test-run-process-group.js +123 -0
  16. package/dist/cli/lisa-test-run-process-group.js.map +1 -0
  17. package/dist/cli/lisa-test-run-reaper.d.ts +3 -0
  18. package/dist/cli/lisa-test-run-reaper.d.ts.map +1 -0
  19. package/dist/cli/lisa-test-run-reaper.js +195 -0
  20. package/dist/cli/lisa-test-run-reaper.js.map +1 -0
  21. package/dist/cli/lisa-test-run-runtime.d.ts +46 -0
  22. package/dist/cli/lisa-test-run-runtime.d.ts.map +1 -0
  23. package/dist/cli/lisa-test-run-runtime.js +123 -0
  24. package/dist/cli/lisa-test-run-runtime.js.map +1 -0
  25. package/dist/cli/lisa-test-run-supervisor.d.ts +13 -0
  26. package/dist/cli/lisa-test-run-supervisor.d.ts.map +1 -0
  27. package/dist/cli/lisa-test-run-supervisor.js +268 -0
  28. package/dist/cli/lisa-test-run-supervisor.js.map +1 -0
  29. package/dist/cli/lisa-test-run.d.ts +3 -0
  30. package/dist/cli/lisa-test-run.d.ts.map +1 -0
  31. package/dist/cli/lisa-test-run.js +66 -0
  32. package/dist/cli/lisa-test-run.js.map +1 -0
  33. package/dist/configs/vitest/base.d.ts.map +1 -1
  34. package/dist/configs/vitest/base.js +5 -2
  35. package/dist/configs/vitest/base.js.map +1 -1
  36. package/dist/configs/vitest/cdk.d.ts +4 -0
  37. package/dist/configs/vitest/cdk.d.ts.map +1 -1
  38. package/dist/configs/vitest/cdk.js +5 -0
  39. package/dist/configs/vitest/cdk.js.map +1 -1
  40. package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
  41. package/dist/configs/vitest/harper-fabric.js +1 -0
  42. package/dist/configs/vitest/harper-fabric.js.map +1 -1
  43. package/dist/configs/vitest/nestjs.d.ts.map +1 -1
  44. package/dist/configs/vitest/nestjs.js +1 -0
  45. package/dist/configs/vitest/nestjs.js.map +1 -1
  46. package/dist/configs/vitest/phaser.d.ts.map +1 -1
  47. package/dist/configs/vitest/phaser.js +1 -0
  48. package/dist/configs/vitest/phaser.js.map +1 -1
  49. package/dist/configs/vitest/scratch-authority.d.ts +25 -0
  50. package/dist/configs/vitest/scratch-authority.d.ts.map +1 -0
  51. package/dist/configs/vitest/scratch-authority.js +107 -0
  52. package/dist/configs/vitest/scratch-authority.js.map +1 -0
  53. package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts +5 -0
  54. package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts.map +1 -0
  55. package/dist/configs/vitest/scratch-bound-cleanup-programs.js +219 -0
  56. package/dist/configs/vitest/scratch-bound-cleanup-programs.js.map +1 -0
  57. package/dist/configs/vitest/scratch-bound-cleanup.d.ts +28 -0
  58. package/dist/configs/vitest/scratch-bound-cleanup.d.ts.map +1 -0
  59. package/dist/configs/vitest/scratch-bound-cleanup.js +155 -0
  60. package/dist/configs/vitest/scratch-bound-cleanup.js.map +1 -0
  61. package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts +17 -0
  62. package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts.map +1 -0
  63. package/dist/configs/vitest/scratch-bound-root-cleanup.js +149 -0
  64. package/dist/configs/vitest/scratch-bound-root-cleanup.js.map +1 -0
  65. package/dist/configs/vitest/scratch-global-setup.d.ts +17 -9
  66. package/dist/configs/vitest/scratch-global-setup.d.ts.map +1 -1
  67. package/dist/configs/vitest/scratch-global-setup.js +103 -35
  68. package/dist/configs/vitest/scratch-global-setup.js.map +1 -1
  69. package/dist/configs/vitest/scratch-leak-setup.d.ts +2 -0
  70. package/dist/configs/vitest/scratch-leak-setup.d.ts.map +1 -0
  71. package/dist/configs/vitest/scratch-leak-setup.js +108 -0
  72. package/dist/configs/vitest/scratch-leak-setup.js.map +1 -0
  73. package/dist/configs/vitest/scratch-namespace-authority.d.ts +80 -0
  74. package/dist/configs/vitest/scratch-namespace-authority.d.ts.map +1 -0
  75. package/dist/configs/vitest/scratch-namespace-authority.js +291 -0
  76. package/dist/configs/vitest/scratch-namespace-authority.js.map +1 -0
  77. package/dist/configs/vitest/scratch-owner.d.ts +131 -0
  78. package/dist/configs/vitest/scratch-owner.d.ts.map +1 -0
  79. package/dist/configs/vitest/scratch-owner.js +297 -0
  80. package/dist/configs/vitest/scratch-owner.js.map +1 -0
  81. package/dist/configs/vitest/scratch-route-profile.d.ts +36 -0
  82. package/dist/configs/vitest/scratch-route-profile.d.ts.map +1 -0
  83. package/dist/configs/vitest/scratch-route-profile.js +217 -0
  84. package/dist/configs/vitest/scratch-route-profile.js.map +1 -0
  85. package/dist/configs/vitest/scratch-run-root-compatibility.d.ts +33 -0
  86. package/dist/configs/vitest/scratch-run-root-compatibility.d.ts.map +1 -0
  87. package/dist/configs/vitest/scratch-run-root-compatibility.js +137 -0
  88. package/dist/configs/vitest/scratch-run-root-compatibility.js.map +1 -0
  89. package/dist/configs/vitest/scratch-run-root-intent.d.ts +66 -0
  90. package/dist/configs/vitest/scratch-run-root-intent.d.ts.map +1 -0
  91. package/dist/configs/vitest/scratch-run-root-intent.js +183 -0
  92. package/dist/configs/vitest/scratch-run-root-intent.js.map +1 -0
  93. package/dist/configs/vitest/scratch-setup.d.ts.map +1 -1
  94. package/dist/configs/vitest/scratch-setup.js +45 -15
  95. package/dist/configs/vitest/scratch-setup.js.map +1 -1
  96. package/dist/configs/vitest/scratch-supervision-intent.d.ts +8 -0
  97. package/dist/configs/vitest/scratch-supervision-intent.d.ts.map +1 -0
  98. package/dist/configs/vitest/scratch-supervision-intent.js +125 -0
  99. package/dist/configs/vitest/scratch-supervision-intent.js.map +1 -0
  100. package/dist/configs/vitest/scratch-supervision-protocol.d.ts +12 -0
  101. package/dist/configs/vitest/scratch-supervision-protocol.d.ts.map +1 -0
  102. package/dist/configs/vitest/scratch-supervision-protocol.js +230 -0
  103. package/dist/configs/vitest/scratch-supervision-protocol.js.map +1 -0
  104. package/dist/configs/vitest/scratch-supervision.d.ts +64 -0
  105. package/dist/configs/vitest/scratch-supervision.d.ts.map +1 -0
  106. package/dist/configs/vitest/scratch-supervision.js +209 -0
  107. package/dist/configs/vitest/scratch-supervision.js.map +1 -0
  108. package/dist/configs/vitest/scratch-sweep.d.ts +66 -0
  109. package/dist/configs/vitest/scratch-sweep.d.ts.map +1 -0
  110. package/dist/configs/vitest/scratch-sweep.js +82 -0
  111. package/dist/configs/vitest/scratch-sweep.js.map +1 -0
  112. package/dist/configs/vitest/scratch.d.ts +14 -187
  113. package/dist/configs/vitest/scratch.d.ts.map +1 -1
  114. package/dist/configs/vitest/scratch.js +18 -285
  115. package/dist/configs/vitest/scratch.js.map +1 -1
  116. package/dist/configs/vitest/typescript.d.ts.map +1 -1
  117. package/dist/configs/vitest/typescript.js +1 -0
  118. package/dist/configs/vitest/typescript.js.map +1 -1
  119. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  120. package/dist/core/lisa-owned-hash-ledger.js +4 -0
  121. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  122. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  123. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  124. package/dist/core/upstream-evidence-manifest.js +59 -13
  125. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  126. package/expo/package-lisa/package.lisa.json +14 -14
  127. package/harper-fabric/package-lisa/package.lisa.json +8 -3
  128. package/nestjs/create-only/vitest.config.local.ts +5 -1
  129. package/nestjs/package-lisa/package.lisa.json +14 -8
  130. package/npm-package/package-lisa/package.lisa.json +8 -0
  131. package/package.json +17 -13
  132. package/phaser/package-lisa/package.lisa.json +9 -3
  133. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  134. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  135. package/plugins/lisa/hooks/sonar-secrets.sh +3 -2
  136. package/plugins/lisa-agy/plugin.json +1 -1
  137. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  138. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  139. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  140. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  141. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  142. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  143. package/plugins/lisa-copilot/hooks/sonar-secrets.sh +3 -2
  144. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  145. package/plugins/lisa-cursor/hooks/sonar-secrets.sh +3 -2
  146. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  147. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  148. package/plugins/lisa-expo-agy/plugin.json +1 -1
  149. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  150. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  151. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  152. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  153. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  154. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  155. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  156. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  157. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  158. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  159. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  160. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  161. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  162. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  163. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  164. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  165. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  166. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  167. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  168. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  169. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  170. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  171. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  172. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  173. package/plugins/lisa-rails-agy/plugin.json +1 -1
  174. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  175. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  176. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  177. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  178. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  179. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  180. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  181. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  182. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  183. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  184. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  185. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  186. package/plugins/src/base/hooks/sonar-secrets.sh +3 -2
  187. package/typescript/create-only/vitest.config.local.ts +5 -1
  188. package/typescript/package-lisa/package.lisa.json +14 -8
@@ -0,0 +1,80 @@
1
+ import { parseScratchRunRootName, scratchRunRootName, type ScratchPathIdentity } from "./scratch-owner.js";
2
+ /** Public compatibility name for the exact managed namespace. */
3
+ export declare const SCRATCH_NAMESPACE = "lisa-scratch";
4
+ /** Prefix identifying a per-process run root inside the namespace. */
5
+ export declare const RUN_ROOT_PREFIX = "run-";
6
+ /** Legacy default retained for callers; age alone never authorizes deletion. */
7
+ export declare const DEFAULT_RECLAIM_AGE_MS: number;
8
+ /** Absolute cap shared by startup inspection and destructive sweeps. */
9
+ export declare const MAX_SCRATCH_NAMESPACE_SCAN_ENTRIES = 120000;
10
+ /** Maximum UTF-8 bytes accepted in one direct namespace basename. */
11
+ export declare const MAX_SCRATCH_NAMESPACE_NAME_BYTES = 1024;
12
+ /** Maximum direct entries one already-authorized suite audit may retain. */
13
+ export declare const SCRATCH_DIRECT_ENTRY_LIMIT = 100000;
14
+ /** Maximum UTF-8 bytes in one authorized direct-child basename. */
15
+ export declare const SCRATCH_DIRECT_NAME_BYTES = 1024;
16
+ /** Recognisable quarantine prefix, with a random suffix per removal. */
17
+ export declare const SCRATCH_QUARANTINE_PREFIX = ".lisa-quarantine-";
18
+ /** Namespace identity plus local ownership facts. */
19
+ export interface ScratchNamespaceIdentity extends ScratchPathIdentity {
20
+ readonly uid: number | undefined;
21
+ }
22
+ /** Authority required before any destructive scratch operation. */
23
+ export interface ScratchNamespaceAuthority {
24
+ readonly baseCanonicalPath: string;
25
+ readonly namespace: ScratchNamespaceIdentity;
26
+ }
27
+ /**
28
+ * Resolve the only public platform-temp authority.
29
+ * @returns Logical platform temp root
30
+ */
31
+ export declare const scratchBaseDir: () => string;
32
+ /**
33
+ * Resolve the shared namespace directory.
34
+ * @returns Managed namespace path
35
+ */
36
+ export declare const scratchNamespaceDir: () => string;
37
+ /** Build one unique direct run-root basename. */
38
+ export declare const runRootName: typeof scratchRunRootName;
39
+ /** Parse one recognized direct run-root basename. */
40
+ export declare const parseRunRootName: typeof parseScratchRunRootName;
41
+ /**
42
+ * Consume injected direct namespace basenames under the 120k hard bound.
43
+ * @param names - Direct namespace basenames
44
+ * @returns Deterministically sorted names
45
+ */
46
+ export declare function collectBoundedScratchNamespaceNames(names: Iterable<string>): readonly string[];
47
+ /**
48
+ * Stream one real namespace without following direct children.
49
+ * @param dir - Namespace path
50
+ * @returns Validated direct basenames
51
+ */
52
+ export declare function readBoundedScratchNamespace(dir: string): readonly string[];
53
+ /**
54
+ * Validate one direct-name stream under the distinct 100k suite bound.
55
+ * @param names - Direct basename stream
56
+ * @returns Validated names in source order
57
+ */
58
+ export declare function collectBoundedScratchNames(names: Iterable<string>): readonly string[];
59
+ /**
60
+ * Stream one already-authorized directory under the 100k suite bound.
61
+ * @param directory - Authorized suite directory
62
+ * @returns Validated direct basenames
63
+ */
64
+ export declare function readBoundedScratchNames(directory: string): readonly string[];
65
+ /**
66
+ * Establish and pin the canonical scratch namespace.
67
+ * @returns Filesystem authority for its exact direct `lisa-scratch` child
68
+ */
69
+ export declare function createScratchNamespaceAuthority(): ScratchNamespaceAuthority;
70
+ /**
71
+ * Revalidate that the namespace is still the directory authority pinned.
72
+ * @param authority - Captured namespace authority
73
+ */
74
+ export declare function assertScratchNamespaceAuthority(authority: ScratchNamespaceAuthority): void;
75
+ /**
76
+ * Resolve authority for an existing exact namespace without creating it.
77
+ * @returns Captured authority, or undefined when absent
78
+ */
79
+ export declare function authorityForExistingScratchNamespace(): ScratchNamespaceAuthority | undefined;
80
+ //# sourceMappingURL=scratch-namespace-authority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scratch-namespace-authority.d.ts","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-namespace-authority.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,uBAAuB,EACvB,kBAAkB,EAElB,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAK5B,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,iBAA+B,CAAC;AAE9D,sEAAsE;AACtE,eAAO,MAAM,eAAe,SAA0B,CAAC;AAEvD,gFAAgF;AAChF,eAAO,MAAM,sBAAsB,QAAqB,CAAC;AAEzD,wEAAwE;AACxE,eAAO,MAAM,kCAAkC,SAAU,CAAC;AAE1D,qEAAqE;AACrE,eAAO,MAAM,gCAAgC,OAAQ,CAAC;AAEtD,4EAA4E;AAC5E,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAElD,mEAAmE;AACnE,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,wEAAwE;AACxE,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D,qDAAqD;AACrD,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,mEAAmE;AACnE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,wBAAwB,CAAC;CAC9C;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,MAAqB,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAO,MACS,CAAC;AAEjD,iDAAiD;AACjD,eAAO,MAAM,WAAW,2BAAqB,CAAC;AAE9C,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,gCAA0B,CAAC;AAWxD;;;;GAIG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GACtB,SAAS,MAAM,EAAE,CA0BnB;AAoBD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAgB1E;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GACtB,SAAS,MAAM,EAAE,CAiBnB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAe5E;AAiFD;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,yBAAyB,CAiB3E;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,yBAAyB,GACnC,IAAI,CAqBN;AAED;;;GAGG;AACH,wBAAgB,oCAAoC,IAChD,yBAAyB,GACzB,SAAS,CAuBZ"}
@@ -0,0 +1,291 @@
1
+ /** Canonical platform-temp namespace capture and immutable identity authority. */
2
+ import * as fs from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import { SCRATCH_RUN_ROOT_PREFIX, parseScratchRunRootName, scratchRunRootName, scratchPathIdentity, } from "./scratch-owner.js";
6
+ /** Exact shared namespace basename used by the authority implementation. */
7
+ const AUTHORIZED_SCRATCH_NAMESPACE = "lisa-scratch";
8
+ /** Public compatibility name for the exact managed namespace. */
9
+ export const SCRATCH_NAMESPACE = AUTHORIZED_SCRATCH_NAMESPACE;
10
+ /** Prefix identifying a per-process run root inside the namespace. */
11
+ export const RUN_ROOT_PREFIX = SCRATCH_RUN_ROOT_PREFIX;
12
+ /** Legacy default retained for callers; age alone never authorizes deletion. */
13
+ export const DEFAULT_RECLAIM_AGE_MS = 6 * 60 * 60 * 1000;
14
+ /** Absolute cap shared by startup inspection and destructive sweeps. */
15
+ export const MAX_SCRATCH_NAMESPACE_SCAN_ENTRIES = 120_000;
16
+ /** Maximum UTF-8 bytes accepted in one direct namespace basename. */
17
+ export const MAX_SCRATCH_NAMESPACE_NAME_BYTES = 1_024;
18
+ /** Maximum direct entries one already-authorized suite audit may retain. */
19
+ export const SCRATCH_DIRECT_ENTRY_LIMIT = 100_000;
20
+ /** Maximum UTF-8 bytes in one authorized direct-child basename. */
21
+ export const SCRATCH_DIRECT_NAME_BYTES = 1_024;
22
+ /** Recognisable quarantine prefix, with a random suffix per removal. */
23
+ export const SCRATCH_QUARANTINE_PREFIX = ".lisa-quarantine-";
24
+ /**
25
+ * Resolve the only public platform-temp authority.
26
+ * @returns Logical platform temp root
27
+ */
28
+ export const scratchBaseDir = () => os.tmpdir();
29
+ /**
30
+ * Resolve the shared namespace directory.
31
+ * @returns Managed namespace path
32
+ */
33
+ export const scratchNamespaceDir = () => path.join(scratchBaseDir(), SCRATCH_NAMESPACE);
34
+ /** Build one unique direct run-root basename. */
35
+ export const runRootName = scratchRunRootName;
36
+ /** Parse one recognized direct run-root basename. */
37
+ export const parseRunRootName = parseScratchRunRootName;
38
+ /**
39
+ * Stable code-point ordering independent of host locale.
40
+ * @param left - Left basename
41
+ * @param right - Right basename
42
+ * @returns Sort comparator result
43
+ */
44
+ const codePointCompare = (left, right) => left === right ? 0 : left < right ? -1 : 1;
45
+ /**
46
+ * Consume injected direct namespace basenames under the 120k hard bound.
47
+ * @param names - Direct namespace basenames
48
+ * @returns Deterministically sorted names
49
+ */
50
+ export function collectBoundedScratchNamespaceNames(names) {
51
+ const collected = [];
52
+ for (const name of names) {
53
+ if (name === "" ||
54
+ name === "." ||
55
+ name === ".." ||
56
+ name.includes("/") ||
57
+ name.includes("\\")) {
58
+ throw new Error(`Scratch namespace scan refused non-basename: ${name}`);
59
+ }
60
+ if (Buffer.byteLength(name, "utf8") > MAX_SCRATCH_NAMESPACE_NAME_BYTES) {
61
+ throw new Error(`Scratch namespace name exceeds ${String(MAX_SCRATCH_NAMESPACE_NAME_BYTES)} bytes`);
62
+ }
63
+ if (collected.length >= MAX_SCRATCH_NAMESPACE_SCAN_ENTRIES) {
64
+ throw new Error(`Scratch namespace scan exceeds ${String(MAX_SCRATCH_NAMESPACE_SCAN_ENTRIES)} entries`);
65
+ }
66
+ // eslint-disable-next-line functional/immutable-data -- bounded streaming avoids attacker-sized materialization
67
+ collected.push(name);
68
+ }
69
+ return [...collected].sort(codePointCompare);
70
+ }
71
+ /**
72
+ * Open one real namespace directory while preserving absence.
73
+ * @param dir - Namespace path
74
+ * @returns Open handle, or undefined when absent
75
+ */
76
+ function openScratchNamespace(dir) {
77
+ try {
78
+ const stat = fs.lstatSync(dir);
79
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
80
+ throw new Error(`Scratch namespace is not a real directory: ${dir}`);
81
+ }
82
+ return fs.opendirSync(dir);
83
+ }
84
+ catch (error) {
85
+ if (error.code === "ENOENT")
86
+ return undefined;
87
+ throw error;
88
+ }
89
+ }
90
+ /**
91
+ * Stream one real namespace without following direct children.
92
+ * @param dir - Namespace path
93
+ * @returns Validated direct basenames
94
+ */
95
+ export function readBoundedScratchNamespace(dir) {
96
+ const directory = openScratchNamespace(dir);
97
+ if (directory === undefined)
98
+ return [];
99
+ try {
100
+ return collectBoundedScratchNamespaceNames((function* entries() {
101
+ for (;;) {
102
+ const entry = directory.readSync();
103
+ if (entry === null)
104
+ return;
105
+ yield entry.name;
106
+ }
107
+ })());
108
+ }
109
+ finally {
110
+ directory.closeSync();
111
+ }
112
+ }
113
+ /**
114
+ * Validate one direct-name stream under the distinct 100k suite bound.
115
+ * @param names - Direct basename stream
116
+ * @returns Validated names in source order
117
+ */
118
+ export function collectBoundedScratchNames(names) {
119
+ const collected = [];
120
+ for (const name of names) {
121
+ if (Buffer.byteLength(name, "utf8") > SCRATCH_DIRECT_NAME_BYTES) {
122
+ throw new Error(`Scratch direct basename exceeds ${String(SCRATCH_DIRECT_NAME_BYTES)} bytes`);
123
+ }
124
+ // eslint-disable-next-line functional/immutable-data -- refuse before retaining the 100001st entry
125
+ collected.push(name);
126
+ if (collected.length > SCRATCH_DIRECT_ENTRY_LIMIT) {
127
+ throw new Error(`Scratch direct entry count exceeds ${String(SCRATCH_DIRECT_ENTRY_LIMIT)}`);
128
+ }
129
+ }
130
+ return collected;
131
+ }
132
+ /**
133
+ * Stream one already-authorized directory under the 100k suite bound.
134
+ * @param directory - Authorized suite directory
135
+ * @returns Validated direct basenames
136
+ */
137
+ export function readBoundedScratchNames(directory) {
138
+ const handle = fs.opendirSync(directory);
139
+ try {
140
+ return collectBoundedScratchNames({
141
+ *[Symbol.iterator]() {
142
+ for (;;) {
143
+ const entry = handle.readSync();
144
+ if (entry === null)
145
+ return;
146
+ yield entry.name;
147
+ }
148
+ },
149
+ });
150
+ }
151
+ finally {
152
+ handle.closeSync();
153
+ }
154
+ }
155
+ /**
156
+ * Return the current uid where the platform supplies one.
157
+ * @returns Current uid or undefined on platforms without uid ownership
158
+ */
159
+ const currentUid = () => process.getuid?.();
160
+ /**
161
+ * Ensure the namespace path exists as a real directory.
162
+ * @param namespacePath - Exact namespace path
163
+ */
164
+ function assertRealDirectory(namespacePath) {
165
+ const existing = fs.lstatSync(namespacePath);
166
+ if (existing.isSymbolicLink()) {
167
+ throw new Error(`Scratch namespace must not be a symlink: ${namespacePath}`);
168
+ }
169
+ if (!existing.isDirectory()) {
170
+ throw new Error(`Scratch namespace is not a directory: ${namespacePath}`);
171
+ }
172
+ }
173
+ /**
174
+ * Create the namespace or accept a concurrent creator only after revalidation.
175
+ * @param namespacePath - Exact namespace path
176
+ */
177
+ function ensureNamespaceDirectory(namespacePath) {
178
+ try {
179
+ assertRealDirectory(namespacePath);
180
+ }
181
+ catch (error) {
182
+ if (error.code !== "ENOENT")
183
+ throw error;
184
+ try {
185
+ fs.mkdirSync(namespacePath, { mode: 0o700 });
186
+ }
187
+ catch (mkdirError) {
188
+ if (mkdirError.code !== "EEXIST") {
189
+ throw mkdirError;
190
+ }
191
+ assertRealDirectory(namespacePath);
192
+ }
193
+ }
194
+ }
195
+ /**
196
+ * Assert local namespace ownership without silently broadening authority.
197
+ * @param namespacePath - Exact namespace path
198
+ */
199
+ function enforceNamespaceOwnership(namespacePath) {
200
+ const stat = fs.lstatSync(namespacePath);
201
+ const uid = currentUid();
202
+ if (uid !== undefined && stat.uid !== uid) {
203
+ throw new Error(`Scratch namespace uid ${String(stat.uid)} does not match current uid ${String(uid)}`);
204
+ }
205
+ if ((stat.mode & 0o777) !== 0o700) {
206
+ throw new Error(`Scratch namespace mode must be 0700: ${namespacePath}`);
207
+ }
208
+ }
209
+ /**
210
+ * Capture the namespace identity after its creation and mode repair.
211
+ * @param namespacePath - Exact namespace path
212
+ * @param baseCanonicalPath - Pinned physical temp base
213
+ * @returns Captured authority
214
+ */
215
+ function captureNamespaceAuthority(namespacePath, baseCanonicalPath) {
216
+ const uid = currentUid();
217
+ const identity = scratchPathIdentity(namespacePath);
218
+ if (path.dirname(identity.canonicalPath) !== baseCanonicalPath) {
219
+ throw new Error("Scratch namespace escaped its canonical temp base");
220
+ }
221
+ return {
222
+ baseCanonicalPath,
223
+ namespace: { ...identity, uid },
224
+ };
225
+ }
226
+ /**
227
+ * Establish and pin the canonical scratch namespace.
228
+ * @returns Filesystem authority for its exact direct `lisa-scratch` child
229
+ */
230
+ export function createScratchNamespaceAuthority() {
231
+ const baseDir = os.tmpdir();
232
+ const baseStat = fs.lstatSync(baseDir);
233
+ if (baseStat.isSymbolicLink()) {
234
+ throw new Error(`Scratch temp base must not be a symlink: ${baseDir}`);
235
+ }
236
+ if (!baseStat.isDirectory()) {
237
+ throw new Error(`Scratch temp base is not a directory: ${baseDir}`);
238
+ }
239
+ const baseCanonicalPath = fs.realpathSync(baseDir);
240
+ const namespacePath = path.join(baseCanonicalPath, AUTHORIZED_SCRATCH_NAMESPACE);
241
+ ensureNamespaceDirectory(namespacePath);
242
+ enforceNamespaceOwnership(namespacePath);
243
+ return captureNamespaceAuthority(namespacePath, baseCanonicalPath);
244
+ }
245
+ /**
246
+ * Revalidate that the namespace is still the directory authority pinned.
247
+ * @param authority - Captured namespace authority
248
+ */
249
+ export function assertScratchNamespaceAuthority(authority) {
250
+ const current = scratchPathIdentity(authority.namespace.canonicalPath);
251
+ if (current.dev !== authority.namespace.dev ||
252
+ current.ino !== authority.namespace.ino ||
253
+ current.canonicalPath !== authority.namespace.canonicalPath) {
254
+ throw new Error("Scratch namespace identity changed after authority capture");
255
+ }
256
+ const stat = fs.lstatSync(authority.namespace.canonicalPath);
257
+ if ((stat.mode & 0o777) !== 0o700) {
258
+ throw new Error("Scratch namespace mode changed after authority capture");
259
+ }
260
+ if (authority.namespace.uid !== undefined &&
261
+ stat.uid !== authority.namespace.uid) {
262
+ throw new Error("Scratch namespace uid changed after authority capture");
263
+ }
264
+ }
265
+ /**
266
+ * Resolve authority for an existing exact namespace without creating it.
267
+ * @returns Captured authority, or undefined when absent
268
+ */
269
+ export function authorityForExistingScratchNamespace() {
270
+ const dir = path.join(os.tmpdir(), AUTHORIZED_SCRATCH_NAMESPACE);
271
+ try {
272
+ const stat = fs.lstatSync(dir);
273
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
274
+ throw new Error(`Scratch namespace must be a real directory: ${dir}`);
275
+ }
276
+ }
277
+ catch (error) {
278
+ if (error.code === "ENOENT")
279
+ return undefined;
280
+ throw error;
281
+ }
282
+ if (path.basename(dir) !== AUTHORIZED_SCRATCH_NAMESPACE) {
283
+ throw new Error(`Scratch namespace must be the exact ${AUTHORIZED_SCRATCH_NAMESPACE} child`);
284
+ }
285
+ const authority = createScratchNamespaceAuthority();
286
+ if (fs.realpathSync(dir) !== authority.namespace.canonicalPath) {
287
+ throw new Error("Scratch namespace path does not match canonical authority");
288
+ }
289
+ return authority;
290
+ }
291
+ //# sourceMappingURL=scratch-namespace-authority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scratch-namespace-authority.js","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-namespace-authority.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /** Owner-marker filename stored directly inside every run root. */
2
+ export declare const SCRATCH_OWNER_FILE = ".lisa-scratch-owner.json";
3
+ /** Prefix identifying a per-process run root inside the namespace. */
4
+ export declare const SCRATCH_RUN_ROOT_PREFIX = "run-";
5
+ /** Filesystem identity pinned into an owner record. */
6
+ export interface ScratchPathIdentity {
7
+ readonly canonicalPath: string;
8
+ readonly dev: number;
9
+ readonly ino: number;
10
+ }
11
+ /** Version-one durable owner marker. */
12
+ export interface ScratchOwnerRecordV1 {
13
+ readonly schema: 1;
14
+ readonly pid: number;
15
+ readonly processBirthFingerprint: string;
16
+ readonly createdAt: string;
17
+ readonly token: string;
18
+ readonly suiteLabel: string;
19
+ readonly registeredPrefixes: readonly string[];
20
+ readonly namespace: ScratchPathIdentity;
21
+ readonly root: ScratchPathIdentity;
22
+ }
23
+ /** Minimal namespace authority consumed while constructing a record. */
24
+ interface OwnerAuthority {
25
+ readonly namespace: ScratchPathIdentity;
26
+ }
27
+ /** Inputs for a new owner record. */
28
+ export interface CreateScratchOwnerRecordOptions {
29
+ readonly authority: OwnerAuthority;
30
+ readonly root: string;
31
+ readonly pid?: number;
32
+ readonly processBirthFingerprint?: string;
33
+ readonly suiteLabel: string;
34
+ readonly registeredPrefixes: readonly string[];
35
+ /** Precommitted 128-bit ownership token, when a supervisor armed it first. */
36
+ readonly token?: string;
37
+ readonly now?: Date;
38
+ }
39
+ /** Probes used to classify a persisted owner. */
40
+ export interface ScratchOwnerProbes {
41
+ readonly isProcessAlive: (pid: number) => boolean;
42
+ readonly processBirthFingerprint: (pid: number) => string | undefined;
43
+ }
44
+ /** Safe reclaim verdict for an owner record. */
45
+ export type ScratchOwnerDisposition = "reclaim" | "preserve";
46
+ /** Injectable seams for one bulk process-birth snapshot. */
47
+ export interface ProcessBirthFingerprintSnapshotOptions {
48
+ /** Platform contract to exercise; defaults to the current platform. */
49
+ readonly platform?: NodeJS.Platform;
50
+ /** Bounded macOS batch runner, injectable for deterministic call-count tests. */
51
+ readonly runDarwinBatch?: (pids: readonly number[]) => string | undefined;
52
+ }
53
+ /**
54
+ * Capture process birth once for a bounded pid set.
55
+ *
56
+ * Darwin has no `/proc`, so namespace audits must not launch one `ps` process
57
+ * per live scratch root. This snapshot deduplicates pids and reads them in
58
+ * bounded 256-pid batches; callers reuse the returned map throughout one
59
+ * sweep/inspection transaction.
60
+ * @param pids - Process ids needed by one audit transaction
61
+ * @param options - Platform and deterministic batch seam
62
+ * @returns A complete lookup whose missing observations remain undefined
63
+ */
64
+ export declare function processBirthFingerprintSnapshot(pids: readonly number[], options?: ProcessBirthFingerprintSnapshotOptions): ReadonlyMap<number, string | undefined>;
65
+ /**
66
+ * Read the OS-authoritative birth fingerprint for a process.
67
+ * @param pid - Process id to inspect
68
+ * @returns Fingerprint, or undefined on an unsupported/ambiguous platform
69
+ */
70
+ export declare function processBirthFingerprint(pid: number): string | undefined;
71
+ /**
72
+ * Fingerprint the current process for a newly-created marker.
73
+ *
74
+ * Unsupported platforms still need an opaque value to make the marker
75
+ * complete. Reclaim never treats this fallback as authoritative: a live pid on
76
+ * such a platform yields an ambiguous observation and is preserved.
77
+ * @returns Current process birth fingerprint
78
+ */
79
+ export declare function currentProcessBirthFingerprint(): string;
80
+ /** Ownership encoded in a legacy or current run-root basename. */
81
+ export interface RunRootOwner {
82
+ readonly pid: number;
83
+ readonly startedAt: number;
84
+ }
85
+ /**
86
+ * Build a run-root basename.
87
+ * @param pid - Owning process id
88
+ * @param startedAt - Creation epoch milliseconds
89
+ * @param suffix - Opaque random suffix
90
+ * @returns Direct namespace-child basename
91
+ */
92
+ export declare function scratchRunRootName(pid: number, startedAt: number, suffix: string): string;
93
+ /**
94
+ * Parse the owner fields encoded in a run-root basename.
95
+ * @param name - Direct namespace-child basename
96
+ * @returns Parsed owner, or undefined for an unrelated name
97
+ */
98
+ export declare function parseScratchRunRootName(name: string): RunRootOwner | undefined;
99
+ /**
100
+ * Decide whether a valid owner may be reclaimed.
101
+ * @param record - Persisted owner marker
102
+ * @param probes - Kernel probes, injectable for deterministic tests
103
+ * @returns Fail-closed reclaim disposition
104
+ */
105
+ export declare function classifyScratchOwner(record: ScratchOwnerRecordV1, probes: ScratchOwnerProbes): ScratchOwnerDisposition;
106
+ /**
107
+ * Capture an immutable filesystem identity without following a final symlink.
108
+ * @param candidate - Existing regular file or directory
109
+ * @returns Canonical path plus device/inode identity
110
+ */
111
+ export declare function scratchPathIdentity(candidate: string): ScratchPathIdentity;
112
+ /**
113
+ * Construct a version-one owner marker from live filesystem state.
114
+ * @param options - Owner and path facts
115
+ * @returns Immutable owner record
116
+ */
117
+ export declare function createScratchOwnerRecord(options: CreateScratchOwnerRecordOptions): ScratchOwnerRecordV1;
118
+ /**
119
+ * Write an owner marker without permitting a pre-existing file or symlink.
120
+ * @param root - Owned run root
121
+ * @param record - Marker to persist
122
+ */
123
+ export declare function writeScratchOwnerRecord(root: string, record: ScratchOwnerRecordV1): void;
124
+ /**
125
+ * Read and validate an owner marker without following a marker symlink.
126
+ * @param root - Run root containing the marker
127
+ * @returns Validated owner marker
128
+ */
129
+ export declare function readScratchOwnerRecord(root: string): ScratchOwnerRecordV1;
130
+ export {};
131
+ //# sourceMappingURL=scratch-owner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scratch-owner.d.ts","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-owner.ts"],"names":[],"mappings":"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"}