audit-tools 0.30.49 → 0.30.51
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/dist/audit/cli/advanceAuditCommand.d.ts.map +1 -1
- package/dist/audit/cli/advanceAuditCommand.js +8 -4
- package/dist/audit/cli/advanceAuditCommand.js.map +1 -1
- package/dist/audit/cli/args.d.ts.map +1 -1
- package/dist/audit/cli/args.js +9 -2
- package/dist/audit/cli/args.js.map +1 -1
- package/dist/audit/cli/mergeAndIngestCommand.d.ts.map +1 -1
- package/dist/audit/cli/mergeAndIngestCommand.js +6 -22
- package/dist/audit/cli/mergeAndIngestCommand.js.map +1 -1
- package/dist/audit/cli/validateResultCommand.d.ts.map +1 -1
- package/dist/audit/cli/validateResultCommand.js +19 -6
- package/dist/audit/cli/validateResultCommand.js.map +1 -1
- package/dist/audit/cli/workerRunCommand.d.ts.map +1 -1
- package/dist/audit/cli/workerRunCommand.js +6 -21
- package/dist/audit/cli/workerRunCommand.js.map +1 -1
- package/dist/audit/contracts/workerSchemas.d.ts +27 -3
- package/dist/audit/contracts/workerSchemas.d.ts.map +1 -1
- package/dist/audit/contracts/workerSchemas.js +5 -1
- package/dist/audit/contracts/workerSchemas.js.map +1 -1
- package/dist/audit/extractors/analyzers/html.d.ts +1 -0
- package/dist/audit/extractors/analyzers/html.d.ts.map +1 -1
- package/dist/audit/extractors/analyzers/html.js +5 -3
- package/dist/audit/extractors/analyzers/html.js.map +1 -1
- package/dist/audit/extractors/browserExtension.d.ts.map +1 -1
- package/dist/audit/extractors/browserExtension.js +1 -8
- package/dist/audit/extractors/browserExtension.js.map +1 -1
- package/dist/audit/extractors/graphRoutes.d.ts.map +1 -1
- package/dist/audit/extractors/graphRoutes.js +4 -1
- package/dist/audit/extractors/graphRoutes.js.map +1 -1
- package/dist/audit/orchestrator/autoFixExecutor.d.ts +8 -0
- package/dist/audit/orchestrator/autoFixExecutor.d.ts.map +1 -1
- package/dist/audit/orchestrator/autoFixExecutor.js +68 -35
- package/dist/audit/orchestrator/autoFixExecutor.js.map +1 -1
- package/dist/audit/orchestrator/runtimeCommand.d.ts.map +1 -1
- package/dist/audit/orchestrator/runtimeCommand.js +7 -1
- package/dist/audit/orchestrator/runtimeCommand.js.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/index.d.ts.map +1 -1
- package/dist/audit/orchestrator/selectiveDeepening/index.js +12 -8
- package/dist/audit/orchestrator/selectiveDeepening/index.js.map +1 -1
- package/dist/audit/orchestrator/taskBuilder.d.ts.map +1 -1
- package/dist/audit/orchestrator/taskBuilder.js +0 -32
- package/dist/audit/orchestrator/taskBuilder.js.map +1 -1
- package/dist/audit/quota/discoveredLimits.d.ts +12 -0
- package/dist/audit/quota/discoveredLimits.d.ts.map +1 -1
- package/dist/audit/quota/discoveredLimits.js +30 -25
- package/dist/audit/quota/discoveredLimits.js.map +1 -1
- package/dist/audit/validation/auditResults.d.ts +16 -0
- package/dist/audit/validation/auditResults.d.ts.map +1 -1
- package/dist/audit/validation/auditResults.js +35 -1
- package/dist/audit/validation/auditResults.js.map +1 -1
- package/dist/remediate/phases/close.d.ts.map +1 -1
- package/dist/remediate/phases/close.js +16 -6
- package/dist/remediate/phases/close.js.map +1 -1
- package/dist/remediate/steps/contractPipeline.d.ts +4 -1
- package/dist/remediate/steps/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipeline.js +63 -47
- package/dist/remediate/steps/contractPipeline.js.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.d.ts +12 -1
- package/dist/remediate/steps/contractPipelinePrompts.d.ts.map +1 -1
- package/dist/remediate/steps/contractPipelinePrompts.js +29 -18
- package/dist/remediate/steps/contractPipelinePrompts.js.map +1 -1
- package/dist/remediate/steps/dispatch.d.ts +20 -3
- package/dist/remediate/steps/dispatch.d.ts.map +1 -1
- package/dist/remediate/steps/dispatch.js +193 -116
- package/dist/remediate/steps/dispatch.js.map +1 -1
- package/dist/remediate/steps/finalGate.d.ts +88 -0
- package/dist/remediate/steps/finalGate.d.ts.map +1 -0
- package/dist/remediate/steps/finalGate.js +171 -0
- package/dist/remediate/steps/finalGate.js.map +1 -0
- package/dist/remediate/steps/leanFastPath.d.ts.map +1 -1
- package/dist/remediate/steps/leanFastPath.js +12 -0
- package/dist/remediate/steps/leanFastPath.js.map +1 -1
- package/dist/remediate/steps/nextStep.d.ts +3 -81
- package/dist/remediate/steps/nextStep.d.ts.map +1 -1
- package/dist/remediate/steps/nextStep.js +36 -169
- package/dist/remediate/steps/nextStep.js.map +1 -1
- package/dist/remediate/validation/contractPipeline.d.ts.map +1 -1
- package/dist/remediate/validation/contractPipeline.js +17 -3
- package/dist/remediate/validation/contractPipeline.js.map +1 -1
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/io/frictionCapture.d.ts +14 -1
- package/dist/shared/io/frictionCapture.d.ts.map +1 -1
- package/dist/shared/io/frictionCapture.js +28 -3
- package/dist/shared/io/frictionCapture.js.map +1 -1
- package/dist/shared/observability/runLog.d.ts +1 -1
- package/dist/shared/observability/runLog.d.ts.map +1 -1
- package/dist/shared/observability/runLog.js.map +1 -1
- package/dist/shared/providers/providerConfirmation.d.ts +16 -1
- package/dist/shared/providers/providerConfirmation.d.ts.map +1 -1
- package/dist/shared/providers/providerConfirmation.js +13 -13
- package/dist/shared/providers/providerConfirmation.js.map +1 -1
- package/dist/shared/providers/providerFactory.d.ts.map +1 -1
- package/dist/shared/providers/providerFactory.js +10 -14
- package/dist/shared/providers/providerFactory.js.map +1 -1
- package/dist/shared/providers/providerPathGuard.d.ts +21 -0
- package/dist/shared/providers/providerPathGuard.d.ts.map +1 -0
- package/dist/shared/providers/providerPathGuard.js +69 -0
- package/dist/shared/providers/providerPathGuard.js.map +1 -0
- package/dist/shared/providers/sharedProviderConfirmation.d.ts +14 -2
- package/dist/shared/providers/sharedProviderConfirmation.d.ts.map +1 -1
- package/dist/shared/providers/sharedProviderConfirmation.js +26 -5
- package/dist/shared/providers/sharedProviderConfirmation.js.map +1 -1
- package/dist/shared/quota/apiPool.d.ts +6 -1
- package/dist/shared/quota/apiPool.d.ts.map +1 -1
- package/dist/shared/quota/apiPool.js +13 -2
- package/dist/shared/quota/apiPool.js.map +1 -1
- package/dist/shared/quota/fileLock.d.ts +17 -2
- package/dist/shared/quota/fileLock.d.ts.map +1 -1
- package/dist/shared/quota/fileLock.js +21 -19
- package/dist/shared/quota/fileLock.js.map +1 -1
- package/dist/shared/types/providerConfirmation.d.ts +9 -0
- package/dist/shared/types/providerConfirmation.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/audit/postinstall.mjs +22 -14
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ResolvedProviderName } from "../types/sessionConfig.js";
|
|
2
|
+
/**
|
|
3
|
+
* Probe PATH for a single command. Returns true if the command resolves.
|
|
4
|
+
* Routed through the injectable hook so tests can drive it deterministically.
|
|
5
|
+
*/
|
|
6
|
+
export declare function commandExists(command: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Override the PATH-detection implementation for tests. Pass `null` to restore
|
|
9
|
+
* the real `where`/`which` probe. The hook is process-global; tests MUST restore
|
|
10
|
+
* it in a `finally` so they don't leak state into sibling tests.
|
|
11
|
+
*/
|
|
12
|
+
export declare function setCommandExistsForTesting(impl: ((command: string) => boolean) | null): void;
|
|
13
|
+
/**
|
|
14
|
+
* Is `provider` self-spawn-blocked in the given environment? True iff the host
|
|
15
|
+
* is currently inside an active session of that same agent (e.g. `claude-code`
|
|
16
|
+
* while `CLAUDECODE` is set, `codex` while `CODEX` is set). Machine-readable,
|
|
17
|
+
* single-sourced, and the basis for both the auto-resolver's `*Available`
|
|
18
|
+
* guards and the Gate-0 `self_spawn_blocked` exclusion flag.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isSelfSpawnBlocked(provider: ResolvedProviderName, env?: NodeJS.ProcessEnv): boolean;
|
|
21
|
+
//# sourceMappingURL=providerPathGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerPathGuard.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/providerPathGuard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AA+BtE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,GAC1C,IAAI,CAEN;AAkBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,oBAAoB,EAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAGT"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Single-sourced PATH detection + self-spawn guard for the provider subsystem.
|
|
4
|
+
*
|
|
5
|
+
* Both `providerFactory.ts` (auto-resolution) and `providerConfirmation.ts`
|
|
6
|
+
* (Gate-0 discovery) used to carry their OWN copy of `commandExists` and their
|
|
7
|
+
* own ad-hoc `env.CLAUDECODE` / `env.CODEX` self-spawn checks. Two copies of a
|
|
8
|
+
* security-relevant guard is exactly the drift hazard the project's
|
|
9
|
+
* "single-source the guard" invariant exists to prevent — a fix to one copy
|
|
10
|
+
* silently leaves the other exploitable. This module is the ONE place that
|
|
11
|
+
* owns:
|
|
12
|
+
* - probing PATH for a command (`commandExists`),
|
|
13
|
+
* - deciding whether a provider would be self-spawn-blocked
|
|
14
|
+
* (`isSelfSpawnBlocked`) from inside an active session of that same agent.
|
|
15
|
+
*
|
|
16
|
+
* A test-injectable PATH-detection hook (`setCommandExistsForTesting`) lets
|
|
17
|
+
* tests drive discovery deterministically without a real CLI on PATH — the
|
|
18
|
+
* security obligations (self-spawn-blocked exclusion) must be testable
|
|
19
|
+
* red-before-green without depending on what happens to be installed in CI.
|
|
20
|
+
*/
|
|
21
|
+
/** The real PATH probe: `where`/`which` exits 0 iff the command resolves. */
|
|
22
|
+
function probeCommandOnPath(command) {
|
|
23
|
+
const lookupCommand = process.platform === "win32" ? "where" : "which";
|
|
24
|
+
const result = spawnSync(lookupCommand, [command], { stdio: "ignore" });
|
|
25
|
+
return result.status === 0;
|
|
26
|
+
}
|
|
27
|
+
let commandExistsImpl = probeCommandOnPath;
|
|
28
|
+
/**
|
|
29
|
+
* Probe PATH for a single command. Returns true if the command resolves.
|
|
30
|
+
* Routed through the injectable hook so tests can drive it deterministically.
|
|
31
|
+
*/
|
|
32
|
+
export function commandExists(command) {
|
|
33
|
+
return commandExistsImpl(command);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Override the PATH-detection implementation for tests. Pass `null` to restore
|
|
37
|
+
* the real `where`/`which` probe. The hook is process-global; tests MUST restore
|
|
38
|
+
* it in a `finally` so they don't leak state into sibling tests.
|
|
39
|
+
*/
|
|
40
|
+
export function setCommandExistsForTesting(impl) {
|
|
41
|
+
commandExistsImpl = impl ?? probeCommandOnPath;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The in-session env signals that mark a host as already running INSIDE an agent
|
|
45
|
+
* of a given kind — a fresh subprocess of that same agent cannot be spawned from
|
|
46
|
+
* within one (it would self-spawn). Single-sourced so the auto-resolver and the
|
|
47
|
+
* Gate-0 discovery path agree byte-for-byte on what "self-spawn-blocked" means.
|
|
48
|
+
*
|
|
49
|
+
* Only `claude-code` and `codex` have a self-spawn hazard: they are headless
|
|
50
|
+
* CLIs auto-spawned as fresh subprocesses. The other providers are either
|
|
51
|
+
* IDE/template-bound, an API pool, or the always-available local-subprocess
|
|
52
|
+
* fallback — none can self-spawn.
|
|
53
|
+
*/
|
|
54
|
+
const SELF_SPAWN_ENV_SIGNAL = {
|
|
55
|
+
"claude-code": "CLAUDECODE",
|
|
56
|
+
codex: "CODEX",
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Is `provider` self-spawn-blocked in the given environment? True iff the host
|
|
60
|
+
* is currently inside an active session of that same agent (e.g. `claude-code`
|
|
61
|
+
* while `CLAUDECODE` is set, `codex` while `CODEX` is set). Machine-readable,
|
|
62
|
+
* single-sourced, and the basis for both the auto-resolver's `*Available`
|
|
63
|
+
* guards and the Gate-0 `self_spawn_blocked` exclusion flag.
|
|
64
|
+
*/
|
|
65
|
+
export function isSelfSpawnBlocked(provider, env = process.env) {
|
|
66
|
+
const signal = SELF_SPAWN_ENV_SIGNAL[provider];
|
|
67
|
+
return signal !== undefined && Boolean(env[signal]);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=providerPathGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providerPathGuard.js","sourceRoot":"","sources":["../../../src/shared/providers/providerPathGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;GAkBG;AAEH,6EAA6E;AAC7E,SAAS,kBAAkB,CAAC,OAAe;IACzC,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,IAAI,iBAAiB,GAAiC,kBAAkB,CAAC;AAEzE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACxC,IAA2C;IAE3C,iBAAiB,GAAG,IAAI,IAAI,kBAAkB,CAAC;AACjD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,qBAAqB,GAAkD;IAC3E,aAAa,EAAE,YAAY;IAC3B,KAAK,EAAE,OAAO;CACf,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAA8B,EAC9B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,MAAM,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -89,7 +89,7 @@ export type SharedProviderConfirmationRead = {
|
|
|
89
89
|
* not surfaced unless explicitly configured), so it never spuriously perturbs
|
|
90
90
|
* the roster.
|
|
91
91
|
*/
|
|
92
|
-
export declare function currentProviderRoster(sessionConfig: SessionConfig, env?: NodeJS.ProcessEnv): ResolvedProviderName[];
|
|
92
|
+
export declare function currentProviderRoster(sessionConfig: SessionConfig, env?: NodeJS.ProcessEnv, detectCommand?: (command: string) => boolean): ResolvedProviderName[];
|
|
93
93
|
/**
|
|
94
94
|
* Build a fresh shared confirmation from auto-discovery. Guarantees the
|
|
95
95
|
* always-available `local-subprocess` fallback is present in the pool (it blocks
|
|
@@ -97,11 +97,23 @@ export declare function currentProviderRoster(sessionConfig: SessionConfig, env?
|
|
|
97
97
|
* to fall back to it) and stamps the schema version, session-level flag, and
|
|
98
98
|
* confirmation timestamp.
|
|
99
99
|
*
|
|
100
|
+
* SECURITY (self-spawn exclusion): a provider that `discoverProviders` flags as
|
|
101
|
+
* `selfSpawnBlocked` (claude-code under `CLAUDECODE`, codex under `CODEX`) is set
|
|
102
|
+
* `excluded: true` AND carries the machine-readable `self_spawn_blocked` flag, so
|
|
103
|
+
* it is OUT of the dispatchable pool by default — launching it would self-spawn a
|
|
104
|
+
* fresh agent from inside an active session of the same agent. The operator can
|
|
105
|
+
* deliberately re-include it by naming it in `include`; that overrides the
|
|
106
|
+
* exclusion (the host still always retains the local-subprocess fallback).
|
|
107
|
+
*
|
|
100
108
|
* @param sessionConfig - Current session config; may be an empty `{}`.
|
|
101
109
|
* @param env - Process env snapshot; defaults to `process.env`.
|
|
102
110
|
* @param exclude - Provider names to pre-exclude (from a prior gate).
|
|
111
|
+
* @param include - Provider names the operator explicitly opts back IN,
|
|
112
|
+
* overriding the default self-spawn-blocked exclusion for those names.
|
|
113
|
+
* @param detectCommand - Injectable PATH-detection hook, forwarded to
|
|
114
|
+
* `discoverProviders` so tests can drive discovery deterministically.
|
|
103
115
|
*/
|
|
104
|
-
export declare function buildSharedProviderConfirmation(sessionConfig?: SessionConfig, env?: NodeJS.ProcessEnv, exclude?: ResolvedProviderName[]): SharedProviderConfirmation;
|
|
116
|
+
export declare function buildSharedProviderConfirmation(sessionConfig?: SessionConfig, env?: NodeJS.ProcessEnv, exclude?: ResolvedProviderName[], include?: ResolvedProviderName[], detectCommand?: (command: string) => boolean): SharedProviderConfirmation;
|
|
105
117
|
/**
|
|
106
118
|
* Atomically write the shared confirmation to
|
|
107
119
|
* `<root>/.audit-tools/provider-confirmation.json`. The durable write goes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharedProviderConfirmation.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/sharedProviderConfirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAIrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAM3E;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,EAAG,OAAgB,CAAC;AAErE,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,+BACpB,CAAC;AAE/B,mEAAmE;AACnE,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnE;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IACzC,uDAAuD;IACvD,cAAc,EAAE,OAAO,oCAAoC,CAAC;IAC5D,0EAA0E;IAC1E,aAAa,EAAE,IAAI,CAAC;IACpB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;OAGG;IACH,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,MAAM,8BAA8B,GACtC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,YAAY,EAAE,0BAA0B,CAAA;CAAE,GACjE;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,0BAA0B,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;CAChB,GACD,IAAI,CAAC;AAMT;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,
|
|
1
|
+
{"version":3,"file":"sharedProviderConfirmation.d.ts","sourceRoot":"","sources":["../../../src/shared/providers/sharedProviderConfirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAIrF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAM3E;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,EAAG,OAAgB,CAAC;AAErE,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,+BACpB,CAAC;AAE/B,mEAAmE;AACnE,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnE;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA0B;IACzC,uDAAuD;IACvD,cAAc,EAAE,OAAO,oCAAoC,CAAC;IAC5D,0EAA0E;IAC1E,aAAa,EAAE,IAAI,CAAC;IACpB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;OAGG;IACH,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,MAAM,8BAA8B,GACtC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,YAAY,EAAE,0BAA0B,CAAA;CAAE,GACjE;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,0BAA0B,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;CAChB,GACD,IAAI,CAAC;AAMT;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAC3C,oBAAoB,EAAE,CAKxB;AAuBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,+BAA+B,CAC7C,aAAa,GAAE,aAAkB,EACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,oBAAoB,EAAO,EACpC,OAAO,GAAE,oBAAoB,EAAO,EACpC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAC3C,0BAA0B,CA2C5B;AAMD;;;;;;;GAOG;AACH,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,0BAA0B,EACxC,MAAM,CAAC,EAAE,SAAS,GACjB,OAAO,CAAC,IAAI,CAAC,CAef;AA2DD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,aAAkB,EACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,8BAA8B,CAAC,CA8BzC"}
|
|
@@ -63,8 +63,8 @@ export function sharedProviderConfirmationPath(root) {
|
|
|
63
63
|
* not surfaced unless explicitly configured), so it never spuriously perturbs
|
|
64
64
|
* the roster.
|
|
65
65
|
*/
|
|
66
|
-
export function currentProviderRoster(sessionConfig, env = process.env) {
|
|
67
|
-
const names = discoverProviders(sessionConfig, env).map((p) => p.name);
|
|
66
|
+
export function currentProviderRoster(sessionConfig, env = process.env, detectCommand) {
|
|
67
|
+
const names = discoverProviders(sessionConfig, env, detectCommand).map((p) => p.name);
|
|
68
68
|
return sortRoster(names);
|
|
69
69
|
}
|
|
70
70
|
function sortRoster(names) {
|
|
@@ -91,13 +91,26 @@ function rostersEqual(a, b) {
|
|
|
91
91
|
* to fall back to it) and stamps the schema version, session-level flag, and
|
|
92
92
|
* confirmation timestamp.
|
|
93
93
|
*
|
|
94
|
+
* SECURITY (self-spawn exclusion): a provider that `discoverProviders` flags as
|
|
95
|
+
* `selfSpawnBlocked` (claude-code under `CLAUDECODE`, codex under `CODEX`) is set
|
|
96
|
+
* `excluded: true` AND carries the machine-readable `self_spawn_blocked` flag, so
|
|
97
|
+
* it is OUT of the dispatchable pool by default — launching it would self-spawn a
|
|
98
|
+
* fresh agent from inside an active session of the same agent. The operator can
|
|
99
|
+
* deliberately re-include it by naming it in `include`; that overrides the
|
|
100
|
+
* exclusion (the host still always retains the local-subprocess fallback).
|
|
101
|
+
*
|
|
94
102
|
* @param sessionConfig - Current session config; may be an empty `{}`.
|
|
95
103
|
* @param env - Process env snapshot; defaults to `process.env`.
|
|
96
104
|
* @param exclude - Provider names to pre-exclude (from a prior gate).
|
|
105
|
+
* @param include - Provider names the operator explicitly opts back IN,
|
|
106
|
+
* overriding the default self-spawn-blocked exclusion for those names.
|
|
107
|
+
* @param detectCommand - Injectable PATH-detection hook, forwarded to
|
|
108
|
+
* `discoverProviders` so tests can drive discovery deterministically.
|
|
97
109
|
*/
|
|
98
|
-
export function buildSharedProviderConfirmation(sessionConfig = {}, env = process.env, exclude = []) {
|
|
99
|
-
const discovered = discoverProviders(sessionConfig, env);
|
|
110
|
+
export function buildSharedProviderConfirmation(sessionConfig = {}, env = process.env, exclude = [], include = [], detectCommand) {
|
|
111
|
+
const discovered = discoverProviders(sessionConfig, env, detectCommand);
|
|
100
112
|
const excludeSet = new Set(exclude);
|
|
113
|
+
const includeSet = new Set(include);
|
|
101
114
|
const pool = [];
|
|
102
115
|
// Always include local-subprocess as a fallback — it's always available and is
|
|
103
116
|
// never surfaced by PATH discovery (it blocks auto-dispatch by design).
|
|
@@ -110,10 +123,18 @@ export function buildSharedProviderConfirmation(sessionConfig = {}, env = proces
|
|
|
110
123
|
});
|
|
111
124
|
}
|
|
112
125
|
for (const provider of discovered) {
|
|
126
|
+
// Self-spawn-blocked providers are excluded from the dispatchable pool by
|
|
127
|
+
// default; the operator can opt one back in via `include`. An operator-named
|
|
128
|
+
// `exclude` always wins. The machine-readable flag rides along so downstream
|
|
129
|
+
// consumers never have to parse `reason`.
|
|
130
|
+
const blocked = provider.selfSpawnBlocked === true;
|
|
131
|
+
const operatorIncluded = includeSet.has(provider.name);
|
|
132
|
+
const excluded = excludeSet.has(provider.name) || (blocked && !operatorIncluded);
|
|
113
133
|
pool.push({
|
|
114
134
|
name: provider.name,
|
|
115
135
|
capability_tier: provider.capabilityTier,
|
|
116
|
-
excluded
|
|
136
|
+
excluded,
|
|
137
|
+
...(blocked ? { self_spawn_blocked: true } : {}),
|
|
117
138
|
reason: provider.reason,
|
|
118
139
|
});
|
|
119
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharedProviderConfirmation.js","sourceRoot":"","sources":["../../../src/shared/providers/sharedProviderConfirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EACL,iBAAiB,GAElB,MAAM,2BAA2B,CAAC;AAGnC,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,OAAgB,CAAC;AAErE,gFAAgF;AAChF,MAAM,CAAC,MAAM,qCAAqC,GAChD,4BAA4B,CAAC;AAE/B,mEAAmE;AACnE,MAAM,UAAU,8BAA8B,CAAC,IAAY;IACzD,OAAO,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,qCAAqC,CAAC,CAAC;AAC1E,CAAC;AA6CD,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAA4B,EAC5B,MAAyB,OAAO,CAAC,GAAG;
|
|
1
|
+
{"version":3,"file":"sharedProviderConfirmation.js","sourceRoot":"","sources":["../../../src/shared/providers/sharedProviderConfirmation.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,11 +32,16 @@ export declare function withSourceConfig(sessionConfig: SessionConfig, source: D
|
|
|
32
32
|
* pool-shape + quota-probe core both orchestrators' host-pool builders use, so the
|
|
33
33
|
* CapacityPool shape can't drift between them. The per-tool parts (the pool key and
|
|
34
34
|
* the discovered-limits computation) are resolved by the caller and passed in.
|
|
35
|
+
*
|
|
36
|
+
* `hostModel` is DERIVED from `poolKey` (never accepted as a separate scalar) so the
|
|
37
|
+
* pool is correct-by-construction: `pool.hostModel === parseProviderModelKey(pool.id).model`
|
|
38
|
+
* always holds. A roster builds one pool per rank with a distinct per-rank model in
|
|
39
|
+
* the key; passing a single scalar host model alongside would mis-stamp every
|
|
40
|
+
* non-primary pool, which is the leak this seam closes. See {@link buildHostModelPools}.
|
|
35
41
|
*/
|
|
36
42
|
export declare function buildHostModelPool(params: {
|
|
37
43
|
poolKey: string;
|
|
38
44
|
providerName: ResolvedProviderName;
|
|
39
|
-
hostModel: string | null;
|
|
40
45
|
rank?: DispatchModelTier;
|
|
41
46
|
hostConcurrencyLimit: HostConcurrencyLimit | null;
|
|
42
47
|
quotaStateEntry: QuotaStateEntry | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiPool.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/apiPool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,kBAAkB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAQtF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGhG;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CA4BvF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,kBAAkB,GAAG,SAAS,GACrC,aAAa,CAEf;AAED
|
|
1
|
+
{"version":3,"file":"apiPool.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/apiPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -66,13 +66,19 @@ export function withSourceConfig(sessionConfig, source) {
|
|
|
66
66
|
* pool-shape + quota-probe core both orchestrators' host-pool builders use, so the
|
|
67
67
|
* CapacityPool shape can't drift between them. The per-tool parts (the pool key and
|
|
68
68
|
* the discovered-limits computation) are resolved by the caller and passed in.
|
|
69
|
+
*
|
|
70
|
+
* `hostModel` is DERIVED from `poolKey` (never accepted as a separate scalar) so the
|
|
71
|
+
* pool is correct-by-construction: `pool.hostModel === parseProviderModelKey(pool.id).model`
|
|
72
|
+
* always holds. A roster builds one pool per rank with a distinct per-rank model in
|
|
73
|
+
* the key; passing a single scalar host model alongside would mis-stamp every
|
|
74
|
+
* non-primary pool, which is the leak this seam closes. See {@link buildHostModelPools}.
|
|
69
75
|
*/
|
|
70
76
|
export async function buildHostModelPool(params) {
|
|
71
77
|
const probe = await probeQuotaSource(params.quotaSource, params.poolKey).catch(() => ({ snapshot: null, status: "degraded" }));
|
|
72
78
|
return {
|
|
73
79
|
id: params.poolKey,
|
|
74
80
|
providerName: params.providerName,
|
|
75
|
-
hostModel: params.
|
|
81
|
+
hostModel: parseProviderModelKey(params.poolKey).model,
|
|
76
82
|
...(params.rank ? { rank: params.rank } : {}),
|
|
77
83
|
hostConcurrencyLimit: params.hostConcurrencyLimit,
|
|
78
84
|
quotaStateEntry: params.quotaStateEntry ?? null,
|
|
@@ -105,7 +111,6 @@ export async function buildHostModelPools(params) {
|
|
|
105
111
|
return buildHostModelPool({
|
|
106
112
|
poolKey,
|
|
107
113
|
providerName: params.providerName,
|
|
108
|
-
hostModel: params.hostModel,
|
|
109
114
|
rank: entry?.rank,
|
|
110
115
|
hostConcurrencyLimit: params.hostConcurrencyLimit,
|
|
111
116
|
quotaStateEntry: params.quotaEntries[poolKey] ?? null,
|
|
@@ -146,6 +151,12 @@ export async function buildSourcePool(params) {
|
|
|
146
151
|
return {
|
|
147
152
|
id: poolKey,
|
|
148
153
|
providerName: source.provider,
|
|
154
|
+
// Both the pool key (via dispatchableSourceId) and hostModel are derived from
|
|
155
|
+
// THIS one source, so they cannot leak apart: for a provider-shaped key the model
|
|
156
|
+
// segment is exactly `source.model ?? source.endpoint`; an explicit-`id` source is
|
|
157
|
+
// launched from `source.{endpoint,model,parameters}` (not from a recovered key), so
|
|
158
|
+
// its hostModel stays the source's own declared model rather than a parse of a
|
|
159
|
+
// non-provider-shaped id. The single-source derivation is the invariant here.
|
|
149
160
|
hostModel: source.model ?? null,
|
|
150
161
|
hostConcurrencyLimit: null,
|
|
151
162
|
quotaStateEntry: quotaEntries[poolKey] ?? null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiPool.js","sourceRoot":"","sources":["../../../src/shared/quota/apiPool.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAEhF;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA0B,EAAE,OAAuB;IACtF,IAAI,MAAM,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACtE,OAAO,qBAAqB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,OAAO,CAAC,CAAC;AAClG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA0B;IAC7D,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IAClC,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,mBAAmB;YACtB,OAAO;gBACL,iBAAiB,EAAE;oBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,GAAG,CAAC;iBACL;aACF,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QAC5E,KAAK,UAAU;YACb,OAAO,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QAC1D,KAAK,qBAAqB;YACxB,OAAO;gBACL,mBAAmB,EAAE;oBACnB,gBAAgB,EAAG,CAAC,CAAC,gBAAyC,IAAI,EAAE;oBACpE,GAAG,CAAC;iBACL;aACF,CAAC;QACJ,KAAK,kBAAkB;YACrB,yEAAyE;YACzE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,aAA4B,EAC5B,MAAsC;IAEtC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,EAAE,GAAG,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;AACxF,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"apiPool.js","sourceRoot":"","sources":["../../../src/shared/quota/apiPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import type { RunLogger } from "../observability/runLog.js";
|
|
2
2
|
export declare const STALE_LOCK_MS = 30000;
|
|
3
|
+
/**
|
|
4
|
+
* Injectable monotonic-ish clock for the lock. Defaults to {@link Date.now}; tests
|
|
5
|
+
* pass a controllable stub so staleness / timeout windows are exercised
|
|
6
|
+
* deterministically without sleeping real wall-clock time. Every time read inside
|
|
7
|
+
* the lock — owner-token minting, staleness comparison, deadline, backoff clamp —
|
|
8
|
+
* routes through the `now` carried on the active options, so a single injected clock
|
|
9
|
+
* governs the whole acquisition. `STALE_LOCK_MS` is unchanged (a duration, not a
|
|
10
|
+
* clock) and stays exported.
|
|
11
|
+
*/
|
|
12
|
+
export type Clock = () => number;
|
|
3
13
|
export declare class FileLockTimeoutError extends Error {
|
|
4
14
|
constructor(lockPath: string);
|
|
5
15
|
}
|
|
6
|
-
|
|
16
|
+
/** Optional seams for the lock — currently just the injectable {@link Clock}. */
|
|
17
|
+
export interface LockOptions {
|
|
18
|
+
/** Clock used for all time reads in this acquisition. Defaults to {@link Date.now}. */
|
|
19
|
+
now?: Clock;
|
|
20
|
+
}
|
|
21
|
+
export declare function acquireLock(lockPath: string, timeoutMs?: number, logger?: RunLogger, options?: LockOptions): Promise<string>;
|
|
7
22
|
export declare function releaseLock(lockPath: string, ownerToken: string): Promise<void>;
|
|
8
|
-
export declare function withFileLock<T>(lockPath: string, fn: () => Promise<T>, timeoutMs?: number, logger?: RunLogger): Promise<T>;
|
|
23
|
+
export declare function withFileLock<T>(lockPath: string, fn: () => Promise<T>, timeoutMs?: number, logger?: RunLogger, options?: LockOptions): Promise<T>;
|
|
9
24
|
//# sourceMappingURL=fileLock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,eAAO,MAAM,aAAa,QAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC;AAUjC,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,QAAQ,EAAE,MAAM;CAI7B;AAkGD,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,uFAAuF;IACvF,GAAG,CAAC,EAAE,KAAK,CAAC;CACb;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA2B,EACtC,MAAM,CAAC,EAAE,SAAS,EAClB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CA0DjB;AAED,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYrF;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,SAAS,EAClB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { writeFile, unlink, stat, readFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
export const STALE_LOCK_MS = 30_000;
|
|
4
|
+
const defaultClock = Date.now;
|
|
4
5
|
// Lock-acquire retry uses exponential backoff (initial → doubling → max) rather
|
|
5
6
|
// than a fixed poll, so a long contention window costs far fewer wakeups. The
|
|
6
7
|
// sleep is always clamped to the time left so backoff never overshoots timeoutMs.
|
|
@@ -14,17 +15,17 @@ export class FileLockTimeoutError extends Error {
|
|
|
14
15
|
this.name = "FileLockTimeoutError";
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
function generateOwnerToken() {
|
|
18
|
-
return `${process.pid}-${
|
|
18
|
+
function generateOwnerToken(now = defaultClock) {
|
|
19
|
+
return `${process.pid}-${now()}-${Math.random().toString(36).slice(2)}`;
|
|
19
20
|
}
|
|
20
21
|
// Returns the owner token of a stale lock (older than STALE_LOCK_MS), or null
|
|
21
22
|
// when the lock is fresh or already gone. Returning the token lets stale removal
|
|
22
23
|
// reuse a token-checked delete, so a lock concurrently re-created with a
|
|
23
24
|
// different token is never clobbered.
|
|
24
|
-
async function readStaleLockToken(lockPath) {
|
|
25
|
+
async function readStaleLockToken(lockPath, now) {
|
|
25
26
|
try {
|
|
26
27
|
const info = await stat(lockPath);
|
|
27
|
-
if (
|
|
28
|
+
if (now() - info.mtimeMs <= STALE_LOCK_MS)
|
|
28
29
|
return null;
|
|
29
30
|
return await readFile(lockPath, "utf8");
|
|
30
31
|
}
|
|
@@ -69,10 +70,10 @@ async function bestEffortUnlink(path) {
|
|
|
69
70
|
// reclaimed, mirroring the main lock's staleness recovery. The claim is always
|
|
70
71
|
// removed in a finally on the happy path so it lives only for the brief
|
|
71
72
|
// token-check + unlink window.
|
|
72
|
-
async function stealStaleLock(lockPath, staleToken) {
|
|
73
|
+
async function stealStaleLock(lockPath, staleToken, now) {
|
|
73
74
|
const claimPath = `${lockPath}${STEAL_CLAIM_SUFFIX}`;
|
|
74
75
|
try {
|
|
75
|
-
await writeFile(claimPath, generateOwnerToken(), { flag: "wx" });
|
|
76
|
+
await writeFile(claimPath, generateOwnerToken(now), { flag: "wx" });
|
|
76
77
|
}
|
|
77
78
|
catch (err) {
|
|
78
79
|
const code = err.code;
|
|
@@ -83,7 +84,7 @@ async function stealStaleLock(lockPath, staleToken) {
|
|
|
83
84
|
// loop retry the ordinary acquire path.
|
|
84
85
|
try {
|
|
85
86
|
const claimInfo = await stat(claimPath);
|
|
86
|
-
if (
|
|
87
|
+
if (now() - claimInfo.mtimeMs > STALE_LOCK_MS) {
|
|
87
88
|
await bestEffortUnlink(claimPath);
|
|
88
89
|
}
|
|
89
90
|
}
|
|
@@ -112,9 +113,10 @@ async function stealStaleLock(lockPath, staleToken) {
|
|
|
112
113
|
await bestEffortUnlink(claimPath);
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
|
-
export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logger) {
|
|
116
|
-
const
|
|
117
|
-
const
|
|
116
|
+
export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logger, options = {}) {
|
|
117
|
+
const now = options.now ?? defaultClock;
|
|
118
|
+
const token = generateOwnerToken(now);
|
|
119
|
+
const deadline = now() + timeoutMs;
|
|
118
120
|
let lastStaleCheckAt = 0;
|
|
119
121
|
let retryInterval = RETRY_INTERVAL_INITIAL_MS;
|
|
120
122
|
// A lock cannot be created in a directory that does not exist — the `wx` create
|
|
@@ -138,21 +140,21 @@ export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logg
|
|
|
138
140
|
}
|
|
139
141
|
// Check the deadline BEFORE any stale-check IO (stat/readFile) or sleep, so a
|
|
140
142
|
// slow filesystem cannot push the actual return time past timeoutMs.
|
|
141
|
-
if (
|
|
143
|
+
if (now() >= deadline) {
|
|
142
144
|
logger?.event({ kind: "error", note: "lock_timeout", lock_path: lockPath, timeout_ms: timeoutMs });
|
|
143
145
|
throw new FileLockTimeoutError(lockPath);
|
|
144
146
|
}
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
lastStaleCheckAt =
|
|
148
|
-
const staleToken = await readStaleLockToken(lockPath);
|
|
147
|
+
const checkAt = now();
|
|
148
|
+
if (checkAt - lastStaleCheckAt >= STALE_CHECK_INTERVAL_MS) {
|
|
149
|
+
lastStaleCheckAt = checkAt;
|
|
150
|
+
const staleToken = await readStaleLockToken(lockPath, now);
|
|
149
151
|
if (staleToken !== null) {
|
|
150
152
|
// Steal the exact stale lock we observed via a lease-style, mutually
|
|
151
153
|
// exclusive claim (see stealStaleLock). Only the single claim winner ever
|
|
152
154
|
// unlinks, and only while the lock still carries this stale token — so a
|
|
153
155
|
// fresh lock another holder created in the gap is never clobbered, and two
|
|
154
156
|
// concurrent stealers can never both end up holding the lock.
|
|
155
|
-
await stealStaleLock(lockPath, staleToken);
|
|
157
|
+
await stealStaleLock(lockPath, staleToken, now);
|
|
156
158
|
logger?.event({ kind: "step", note: "stale_lock_removed", lock_path: lockPath });
|
|
157
159
|
// Progress was made (a slot may have opened); retry promptly and reset
|
|
158
160
|
// the backoff window.
|
|
@@ -162,7 +164,7 @@ export async function acquireLock(lockPath, timeoutMs = DEFAULT_TIMEOUT_MS, logg
|
|
|
162
164
|
}
|
|
163
165
|
// Exponential backoff, clamped to the time left so we never sleep past the
|
|
164
166
|
// deadline. Doubles each idle cycle up to RETRY_INTERVAL_MAX_MS.
|
|
165
|
-
const sleepMs = Math.min(retryInterval, Math.max(0, deadline -
|
|
167
|
+
const sleepMs = Math.min(retryInterval, Math.max(0, deadline - now()));
|
|
166
168
|
await new Promise((r) => setTimeout(r, sleepMs));
|
|
167
169
|
retryInterval = Math.min(retryInterval * 2, RETRY_INTERVAL_MAX_MS);
|
|
168
170
|
}
|
|
@@ -182,8 +184,8 @@ export async function releaseLock(lockPath, ownerToken) {
|
|
|
182
184
|
// ENOENT: lock already gone — swallow silently
|
|
183
185
|
}
|
|
184
186
|
}
|
|
185
|
-
export async function withFileLock(lockPath, fn, timeoutMs, logger) {
|
|
186
|
-
const token = await acquireLock(lockPath, timeoutMs, logger);
|
|
187
|
+
export async function withFileLock(lockPath, fn, timeoutMs, logger, options = {}) {
|
|
188
|
+
const token = await acquireLock(lockPath, timeoutMs, logger, options);
|
|
187
189
|
let hasFnError = false;
|
|
188
190
|
try {
|
|
189
191
|
return await fn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/shared/quota/fileLock.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,15 @@ export interface ConfirmedPoolEntry {
|
|
|
26
26
|
* (or by self-spawn guard). Excluded entries are recorded but not dispatched.
|
|
27
27
|
*/
|
|
28
28
|
excluded: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Machine-readable self-spawn-blocked flag. True when this provider was
|
|
31
|
+
* detected on PATH but cannot be launched as a fresh subprocess from inside an
|
|
32
|
+
* active session of that same agent (claude-code under `CLAUDECODE`, codex
|
|
33
|
+
* under `CODEX`). Such an entry is `excluded: true` by default — and so out of
|
|
34
|
+
* the dispatchable pool — unless the operator explicitly re-includes it. This
|
|
35
|
+
* flag is the security signal; `reason` is advisory text only.
|
|
36
|
+
*/
|
|
37
|
+
self_spawn_blocked?: boolean;
|
|
29
38
|
/** Optional reason for exclusion or detection restriction. */
|
|
30
39
|
reason?: string;
|
|
31
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerConfirmation.d.ts","sourceRoot":"","sources":["../../../src/shared/types/providerConfirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAM3E;;;GAGG;AACH,eAAO,MAAM,oCAAoC,EAAG,OAAgB,CAAC;AAMrE,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,kDAAkD;IAClD,eAAe,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,cAAc,EAAE,OAAO,oCAAoC,CAAC;IAC5D,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"providerConfirmation.d.ts","sourceRoot":"","sources":["../../../src/shared/types/providerConfirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAM3E;;;GAGG;AACH,eAAO,MAAM,oCAAoC,EAAG,OAAgB,CAAC;AAMrE,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,kDAAkD;IAClD,eAAe,EAAE,cAAc,CAAC;IAChC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,cAAc,EAAE,OAAO,oCAAoC,CAAC;IAC5D,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;CACxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audit-tools",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.51",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Portable hybrid code auditing + remediation orchestrators for arbitrary repositories.",
|
|
6
6
|
"type": "module",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"test:remediate": "vitest run",
|
|
47
47
|
"test:single": "npm run build && node --import tsx/esm --test",
|
|
48
48
|
"verify:release": "npm run check && npm run check:deadcode && npm run check:doc-manifest && npm test && npm run verify:hosts && npm run smoke:packaged-audit-code && npm run smoke:packaged-remediate-code",
|
|
49
|
-
"check:deadcode": "knip --
|
|
49
|
+
"check:deadcode": "knip --no-config-hints",
|
|
50
50
|
"check:doc-manifest": "node scripts/check-doc-manifest.mjs",
|
|
51
51
|
"verify:hosts": "node scripts/audit/verify-hosts.mjs",
|
|
52
52
|
"smoke:linked-audit-code": "node scripts/audit/smoke-linked-audit-code.mjs",
|
|
@@ -304,22 +304,27 @@ for (const install of installs) {
|
|
|
304
304
|
|
|
305
305
|
// Install OpenCode global command and MCP via merged config
|
|
306
306
|
const opencodeGlobalConfig = join(homedir(), '.config', 'opencode', 'opencode.json');
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
307
|
+
if (!sharedOpenCodePermissions) {
|
|
308
|
+
// Expected when audit-tools/shared isn't built yet — notably during `npm ci`
|
|
309
|
+
// in CI, where postinstall runs before the shared build step. This is a SKIP,
|
|
310
|
+
// not a failure: counting it would trip the `failed > 0` exit-1 guard below and
|
|
311
|
+
// break `npm ci`. Genuine OpenCode write errors are still counted as failures.
|
|
312
|
+
console.warn(
|
|
313
|
+
'audit-code: audit-tools/shared is unavailable (build the shared workspace first); skipping OpenCode config deployment',
|
|
314
|
+
);
|
|
315
|
+
} else {
|
|
316
|
+
try {
|
|
317
|
+
const action = installMergedJson(opencodeGlobalConfig, (existing) =>
|
|
318
|
+
mergeOpenCodeGlobalConfig(existing),
|
|
311
319
|
);
|
|
320
|
+
console.log(`audit-code: ${action} global OpenCode config in ${opencodeGlobalConfig}`);
|
|
321
|
+
succeeded++;
|
|
322
|
+
} catch (err) {
|
|
323
|
+
console.warn(`audit-code: could not install global OpenCode config (${err.message})`);
|
|
324
|
+
console.warn(` To install manually, add the mcp.auditor and command["audit-code"] entries to:`);
|
|
325
|
+
console.warn(` ${opencodeGlobalConfig}`);
|
|
326
|
+
failed++;
|
|
312
327
|
}
|
|
313
|
-
const action = installMergedJson(opencodeGlobalConfig, (existing) =>
|
|
314
|
-
mergeOpenCodeGlobalConfig(existing),
|
|
315
|
-
);
|
|
316
|
-
console.log(`audit-code: ${action} global OpenCode config in ${opencodeGlobalConfig}`);
|
|
317
|
-
succeeded++;
|
|
318
|
-
} catch (err) {
|
|
319
|
-
console.warn(`audit-code: could not install global OpenCode config (${err.message})`);
|
|
320
|
-
console.warn(` To install manually, add the mcp.auditor and command["audit-code"] entries to:`);
|
|
321
|
-
console.warn(` ${opencodeGlobalConfig}`);
|
|
322
|
-
failed++;
|
|
323
328
|
}
|
|
324
329
|
|
|
325
330
|
// Install Antigravity plugin (global skill for Gemini IDE / Antigravity Hub)
|
|
@@ -383,3 +388,6 @@ try {
|
|
|
383
388
|
}
|
|
384
389
|
|
|
385
390
|
console.log(`audit-code: postinstall complete — ${succeeded} succeeded, ${failed} failed (${Date.now() - postinstallStart}ms)`);
|
|
391
|
+
if (failed > 0) {
|
|
392
|
+
process.exitCode = 1;
|
|
393
|
+
}
|