@codyswann/lisa 4.28.5 → 4.29.1
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-gates.mjs +2 -1
- package/all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh +3 -2
- package/cdk/create-only/vitest.config.local.ts +5 -1
- package/cdk/package-lisa/package.lisa.json +14 -7
- package/dist/cli/lisa-test-run-bootstrap.d.ts +3 -0
- package/dist/cli/lisa-test-run-bootstrap.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-bootstrap.js +201 -0
- package/dist/cli/lisa-test-run-bootstrap.js.map +1 -0
- package/dist/cli/lisa-test-run-ipc.d.ts +42 -0
- package/dist/cli/lisa-test-run-ipc.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-ipc.js +200 -0
- package/dist/cli/lisa-test-run-ipc.js.map +1 -0
- package/dist/cli/lisa-test-run-process-group.d.ts +30 -0
- package/dist/cli/lisa-test-run-process-group.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-process-group.js +123 -0
- package/dist/cli/lisa-test-run-process-group.js.map +1 -0
- package/dist/cli/lisa-test-run-reaper.d.ts +3 -0
- package/dist/cli/lisa-test-run-reaper.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-reaper.js +195 -0
- package/dist/cli/lisa-test-run-reaper.js.map +1 -0
- package/dist/cli/lisa-test-run-runtime.d.ts +46 -0
- package/dist/cli/lisa-test-run-runtime.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-runtime.js +123 -0
- package/dist/cli/lisa-test-run-runtime.js.map +1 -0
- package/dist/cli/lisa-test-run-supervisor.d.ts +13 -0
- package/dist/cli/lisa-test-run-supervisor.d.ts.map +1 -0
- package/dist/cli/lisa-test-run-supervisor.js +268 -0
- package/dist/cli/lisa-test-run-supervisor.js.map +1 -0
- package/dist/cli/lisa-test-run.d.ts +3 -0
- package/dist/cli/lisa-test-run.d.ts.map +1 -0
- package/dist/cli/lisa-test-run.js +66 -0
- package/dist/cli/lisa-test-run.js.map +1 -0
- package/dist/configs/vitest/base.d.ts.map +1 -1
- package/dist/configs/vitest/base.js +5 -2
- package/dist/configs/vitest/base.js.map +1 -1
- package/dist/configs/vitest/cdk.d.ts +4 -0
- package/dist/configs/vitest/cdk.d.ts.map +1 -1
- package/dist/configs/vitest/cdk.js +5 -0
- package/dist/configs/vitest/cdk.js.map +1 -1
- package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
- package/dist/configs/vitest/harper-fabric.js +1 -0
- package/dist/configs/vitest/harper-fabric.js.map +1 -1
- package/dist/configs/vitest/nestjs.d.ts.map +1 -1
- package/dist/configs/vitest/nestjs.js +1 -0
- package/dist/configs/vitest/nestjs.js.map +1 -1
- package/dist/configs/vitest/phaser.d.ts.map +1 -1
- package/dist/configs/vitest/phaser.js +1 -0
- package/dist/configs/vitest/phaser.js.map +1 -1
- package/dist/configs/vitest/scratch-authority.d.ts +25 -0
- package/dist/configs/vitest/scratch-authority.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-authority.js +107 -0
- package/dist/configs/vitest/scratch-authority.js.map +1 -0
- package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts +5 -0
- package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-bound-cleanup-programs.js +219 -0
- package/dist/configs/vitest/scratch-bound-cleanup-programs.js.map +1 -0
- package/dist/configs/vitest/scratch-bound-cleanup.d.ts +28 -0
- package/dist/configs/vitest/scratch-bound-cleanup.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-bound-cleanup.js +155 -0
- package/dist/configs/vitest/scratch-bound-cleanup.js.map +1 -0
- package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts +17 -0
- package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-bound-root-cleanup.js +149 -0
- package/dist/configs/vitest/scratch-bound-root-cleanup.js.map +1 -0
- package/dist/configs/vitest/scratch-global-setup.d.ts +17 -9
- package/dist/configs/vitest/scratch-global-setup.d.ts.map +1 -1
- package/dist/configs/vitest/scratch-global-setup.js +103 -35
- package/dist/configs/vitest/scratch-global-setup.js.map +1 -1
- package/dist/configs/vitest/scratch-leak-setup.d.ts +2 -0
- package/dist/configs/vitest/scratch-leak-setup.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-leak-setup.js +108 -0
- package/dist/configs/vitest/scratch-leak-setup.js.map +1 -0
- package/dist/configs/vitest/scratch-namespace-authority.d.ts +80 -0
- package/dist/configs/vitest/scratch-namespace-authority.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-namespace-authority.js +291 -0
- package/dist/configs/vitest/scratch-namespace-authority.js.map +1 -0
- package/dist/configs/vitest/scratch-owner.d.ts +131 -0
- package/dist/configs/vitest/scratch-owner.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-owner.js +297 -0
- package/dist/configs/vitest/scratch-owner.js.map +1 -0
- package/dist/configs/vitest/scratch-route-profile.d.ts +36 -0
- package/dist/configs/vitest/scratch-route-profile.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-route-profile.js +217 -0
- package/dist/configs/vitest/scratch-route-profile.js.map +1 -0
- package/dist/configs/vitest/scratch-run-root-compatibility.d.ts +33 -0
- package/dist/configs/vitest/scratch-run-root-compatibility.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-run-root-compatibility.js +137 -0
- package/dist/configs/vitest/scratch-run-root-compatibility.js.map +1 -0
- package/dist/configs/vitest/scratch-run-root-intent.d.ts +66 -0
- package/dist/configs/vitest/scratch-run-root-intent.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-run-root-intent.js +183 -0
- package/dist/configs/vitest/scratch-run-root-intent.js.map +1 -0
- package/dist/configs/vitest/scratch-setup.d.ts.map +1 -1
- package/dist/configs/vitest/scratch-setup.js +45 -15
- package/dist/configs/vitest/scratch-setup.js.map +1 -1
- package/dist/configs/vitest/scratch-supervision-intent.d.ts +8 -0
- package/dist/configs/vitest/scratch-supervision-intent.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-supervision-intent.js +125 -0
- package/dist/configs/vitest/scratch-supervision-intent.js.map +1 -0
- package/dist/configs/vitest/scratch-supervision-protocol.d.ts +12 -0
- package/dist/configs/vitest/scratch-supervision-protocol.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-supervision-protocol.js +230 -0
- package/dist/configs/vitest/scratch-supervision-protocol.js.map +1 -0
- package/dist/configs/vitest/scratch-supervision.d.ts +64 -0
- package/dist/configs/vitest/scratch-supervision.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-supervision.js +209 -0
- package/dist/configs/vitest/scratch-supervision.js.map +1 -0
- package/dist/configs/vitest/scratch-sweep.d.ts +66 -0
- package/dist/configs/vitest/scratch-sweep.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-sweep.js +82 -0
- package/dist/configs/vitest/scratch-sweep.js.map +1 -0
- package/dist/configs/vitest/scratch.d.ts +14 -187
- package/dist/configs/vitest/scratch.d.ts.map +1 -1
- package/dist/configs/vitest/scratch.js +18 -285
- package/dist/configs/vitest/scratch.js.map +1 -1
- package/dist/configs/vitest/typescript.d.ts.map +1 -1
- package/dist/configs/vitest/typescript.js +1 -0
- package/dist/configs/vitest/typescript.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +4 -0
- package/dist/core/lisa-owned-hash-ledger.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 +59 -13
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/package-lisa/package.lisa.json +14 -14
- package/harper-fabric/package-lisa/package.lisa.json +8 -3
- package/nestjs/create-only/vitest.config.local.ts +5 -1
- package/nestjs/package-lisa/package.lisa.json +14 -8
- package/npm-package/package-lisa/package.lisa.json +8 -0
- package/package.json +17 -13
- package/phaser/package-lisa/package.lisa.json +9 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/sonar-secrets.sh +3 -2
- 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/sonar-secrets.sh +3 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/sonar-secrets.sh +3 -2
- 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/sonar-secrets.sh +3 -2
- package/typescript/create-only/vitest.config.local.ts +5 -1
- 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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"}
|