pm-orchestrator-runner 1.0.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.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/cli/cli-interface.d.ts +150 -0
- package/dist/cli/cli-interface.d.ts.map +1 -0
- package/dist/cli/cli-interface.js +606 -0
- package/dist/cli/cli-interface.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +243 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/llm-sentinel.d.ts +15 -0
- package/dist/cli/llm-sentinel.d.ts.map +1 -0
- package/dist/cli/llm-sentinel.js +184 -0
- package/dist/cli/llm-sentinel.js.map +1 -0
- package/dist/config/configuration-manager.d.ts +149 -0
- package/dist/config/configuration-manager.d.ts.map +1 -0
- package/dist/config/configuration-manager.js +241 -0
- package/dist/config/configuration-manager.js.map +1 -0
- package/dist/continuation/continuation-control-manager.d.ts +154 -0
- package/dist/continuation/continuation-control-manager.d.ts.map +1 -0
- package/dist/continuation/continuation-control-manager.js +303 -0
- package/dist/continuation/continuation-control-manager.js.map +1 -0
- package/dist/core/runner-core.d.ts +474 -0
- package/dist/core/runner-core.d.ts.map +1 -0
- package/dist/core/runner-core.js +1311 -0
- package/dist/core/runner-core.js.map +1 -0
- package/dist/errors/error-codes.d.ts +105 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +198 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/errors/runner-error.d.ts +14 -0
- package/dist/errors/runner-error.d.ts.map +1 -0
- package/dist/errors/runner-error.js +33 -0
- package/dist/errors/runner-error.js.map +1 -0
- package/dist/evidence/evidence-manager.d.ts +112 -0
- package/dist/evidence/evidence-manager.d.ts.map +1 -0
- package/dist/evidence/evidence-manager.js +337 -0
- package/dist/evidence/evidence-manager.js.map +1 -0
- package/dist/executor/claude-code-executor.d.ts +136 -0
- package/dist/executor/claude-code-executor.d.ts.map +1 -0
- package/dist/executor/claude-code-executor.js +643 -0
- package/dist/executor/claude-code-executor.js.map +1 -0
- package/dist/executor/deterministic-executor.d.ts +40 -0
- package/dist/executor/deterministic-executor.d.ts.map +1 -0
- package/dist/executor/deterministic-executor.js +269 -0
- package/dist/executor/deterministic-executor.js.map +1 -0
- package/dist/lifecycle/lifecycle-controller.d.ts +270 -0
- package/dist/lifecycle/lifecycle-controller.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-controller.js +596 -0
- package/dist/lifecycle/lifecycle-controller.js.map +1 -0
- package/dist/limits/resource-limit-manager.d.ts +200 -0
- package/dist/limits/resource-limit-manager.d.ts.map +1 -0
- package/dist/limits/resource-limit-manager.js +376 -0
- package/dist/limits/resource-limit-manager.js.map +1 -0
- package/dist/locks/lock-manager.d.ts +116 -0
- package/dist/locks/lock-manager.d.ts.map +1 -0
- package/dist/locks/lock-manager.js +306 -0
- package/dist/locks/lock-manager.js.map +1 -0
- package/dist/logging/index.d.ts +8 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +22 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/sensitive-data-masker.d.ts +90 -0
- package/dist/logging/sensitive-data-masker.d.ts.map +1 -0
- package/dist/logging/sensitive-data-masker.js +228 -0
- package/dist/logging/sensitive-data-masker.js.map +1 -0
- package/dist/logging/task-log-manager.d.ts +215 -0
- package/dist/logging/task-log-manager.d.ts.map +1 -0
- package/dist/logging/task-log-manager.js +743 -0
- package/dist/logging/task-log-manager.js.map +1 -0
- package/dist/mediation/fail-closed-runner.d.ts +131 -0
- package/dist/mediation/fail-closed-runner.d.ts.map +1 -0
- package/dist/mediation/fail-closed-runner.js +245 -0
- package/dist/mediation/fail-closed-runner.js.map +1 -0
- package/dist/mediation/llm-client-with-evidence.d.ts +123 -0
- package/dist/mediation/llm-client-with-evidence.d.ts.map +1 -0
- package/dist/mediation/llm-client-with-evidence.js +245 -0
- package/dist/mediation/llm-client-with-evidence.js.map +1 -0
- package/dist/mediation/llm-client.d.ts +102 -0
- package/dist/mediation/llm-client.d.ts.map +1 -0
- package/dist/mediation/llm-client.js +206 -0
- package/dist/mediation/llm-client.js.map +1 -0
- package/dist/mediation/llm-evidence-manager.d.ts +108 -0
- package/dist/mediation/llm-evidence-manager.d.ts.map +1 -0
- package/dist/mediation/llm-evidence-manager.js +230 -0
- package/dist/mediation/llm-evidence-manager.js.map +1 -0
- package/dist/mediation/llm-mediation-layer.d.ts +175 -0
- package/dist/mediation/llm-mediation-layer.d.ts.map +1 -0
- package/dist/mediation/llm-mediation-layer.js +315 -0
- package/dist/mediation/llm-mediation-layer.js.map +1 -0
- package/dist/mediation/llm-sentinel.d.ts +107 -0
- package/dist/mediation/llm-sentinel.d.ts.map +1 -0
- package/dist/mediation/llm-sentinel.js +187 -0
- package/dist/mediation/llm-sentinel.js.map +1 -0
- package/dist/mediation/real-llm-mediation-layer.d.ts +104 -0
- package/dist/mediation/real-llm-mediation-layer.d.ts.map +1 -0
- package/dist/mediation/real-llm-mediation-layer.js +322 -0
- package/dist/mediation/real-llm-mediation-layer.js.map +1 -0
- package/dist/mediation/verdict-reporter.d.ts +61 -0
- package/dist/mediation/verdict-reporter.d.ts.map +1 -0
- package/dist/mediation/verdict-reporter.js +178 -0
- package/dist/mediation/verdict-reporter.js.map +1 -0
- package/dist/models/enums.d.ts +133 -0
- package/dist/models/enums.d.ts.map +1 -0
- package/dist/models/enums.js +201 -0
- package/dist/models/enums.js.map +1 -0
- package/dist/models/evidence.d.ts +60 -0
- package/dist/models/evidence.d.ts.map +1 -0
- package/dist/models/evidence.js +135 -0
- package/dist/models/evidence.js.map +1 -0
- package/dist/models/execution-result.d.ts +89 -0
- package/dist/models/execution-result.d.ts.map +1 -0
- package/dist/models/execution-result.js +197 -0
- package/dist/models/execution-result.js.map +1 -0
- package/dist/models/file-lock.d.ts +62 -0
- package/dist/models/file-lock.d.ts.map +1 -0
- package/dist/models/file-lock.js +133 -0
- package/dist/models/file-lock.js.map +1 -0
- package/dist/models/index.d.ts +12 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +91 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/repl/index.d.ts +7 -0
- package/dist/models/repl/index.d.ts.map +1 -0
- package/dist/models/repl/index.js +32 -0
- package/dist/models/repl/index.js.map +1 -0
- package/dist/models/repl/model-registry.d.ts +73 -0
- package/dist/models/repl/model-registry.d.ts.map +1 -0
- package/dist/models/repl/model-registry.js +116 -0
- package/dist/models/repl/model-registry.js.map +1 -0
- package/dist/models/repl/repl-state.d.ts +86 -0
- package/dist/models/repl/repl-state.d.ts.map +1 -0
- package/dist/models/repl/repl-state.js +152 -0
- package/dist/models/repl/repl-state.js.map +1 -0
- package/dist/models/repl/task-log.d.ts +247 -0
- package/dist/models/repl/task-log.d.ts.map +1 -0
- package/dist/models/repl/task-log.js +178 -0
- package/dist/models/repl/task-log.js.map +1 -0
- package/dist/models/session.d.ts +71 -0
- package/dist/models/session.d.ts.map +1 -0
- package/dist/models/session.js +140 -0
- package/dist/models/session.js.map +1 -0
- package/dist/models/supporting.d.ts +97 -0
- package/dist/models/supporting.d.ts.map +1 -0
- package/dist/models/supporting.js +208 -0
- package/dist/models/supporting.js.map +1 -0
- package/dist/models/task.d.ts +77 -0
- package/dist/models/task.d.ts.map +1 -0
- package/dist/models/task.js +170 -0
- package/dist/models/task.js.map +1 -0
- package/dist/output/output-control-manager.d.ts +217 -0
- package/dist/output/output-control-manager.d.ts.map +1 -0
- package/dist/output/output-control-manager.js +378 -0
- package/dist/output/output-control-manager.js.map +1 -0
- package/dist/pool/agent-pool.d.ts +284 -0
- package/dist/pool/agent-pool.d.ts.map +1 -0
- package/dist/pool/agent-pool.js +451 -0
- package/dist/pool/agent-pool.js.map +1 -0
- package/dist/repl/commands/index.d.ts +12 -0
- package/dist/repl/commands/index.d.ts.map +1 -0
- package/dist/repl/commands/index.js +26 -0
- package/dist/repl/commands/index.js.map +1 -0
- package/dist/repl/commands/init.d.ts +31 -0
- package/dist/repl/commands/init.d.ts.map +1 -0
- package/dist/repl/commands/init.js +234 -0
- package/dist/repl/commands/init.js.map +1 -0
- package/dist/repl/commands/keys.d.ts +63 -0
- package/dist/repl/commands/keys.d.ts.map +1 -0
- package/dist/repl/commands/keys.js +114 -0
- package/dist/repl/commands/keys.js.map +1 -0
- package/dist/repl/commands/logs.d.ts +91 -0
- package/dist/repl/commands/logs.d.ts.map +1 -0
- package/dist/repl/commands/logs.js +200 -0
- package/dist/repl/commands/logs.js.map +1 -0
- package/dist/repl/commands/model.d.ts +85 -0
- package/dist/repl/commands/model.d.ts.map +1 -0
- package/dist/repl/commands/model.js +225 -0
- package/dist/repl/commands/model.js.map +1 -0
- package/dist/repl/commands/models.d.ts +50 -0
- package/dist/repl/commands/models.d.ts.map +1 -0
- package/dist/repl/commands/models.js +180 -0
- package/dist/repl/commands/models.js.map +1 -0
- package/dist/repl/commands/provider.d.ts +79 -0
- package/dist/repl/commands/provider.d.ts.map +1 -0
- package/dist/repl/commands/provider.js +291 -0
- package/dist/repl/commands/provider.js.map +1 -0
- package/dist/repl/commands/session.d.ts +50 -0
- package/dist/repl/commands/session.d.ts.map +1 -0
- package/dist/repl/commands/session.js +152 -0
- package/dist/repl/commands/session.js.map +1 -0
- package/dist/repl/commands/status.d.ts +55 -0
- package/dist/repl/commands/status.d.ts.map +1 -0
- package/dist/repl/commands/status.js +182 -0
- package/dist/repl/commands/status.js.map +1 -0
- package/dist/repl/index.d.ts +6 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +25 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl/repl-interface.d.ts +371 -0
- package/dist/repl/repl-interface.d.ts.map +1 -0
- package/dist/repl/repl-interface.js +1214 -0
- package/dist/repl/repl-interface.js.map +1 -0
- package/dist/session/session-manager.d.ts +85 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +217 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/supervisor/executor-supervisor.d.ts +90 -0
- package/dist/supervisor/executor-supervisor.d.ts.map +1 -0
- package/dist/supervisor/executor-supervisor.js +223 -0
- package/dist/supervisor/executor-supervisor.js.map +1 -0
- package/dist/supervisor/index.d.ts +5 -0
- package/dist/supervisor/index.d.ts.map +1 -0
- package/dist/supervisor/index.js +9 -0
- package/dist/supervisor/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lock Manager
|
|
3
|
+
* Based on 04_COMPONENTS.md L178-201
|
|
4
|
+
*
|
|
5
|
+
* Responsible for:
|
|
6
|
+
* - Lock acquisition and release
|
|
7
|
+
* - Deadlock detection
|
|
8
|
+
* - Lock ordering (sorted acquisition)
|
|
9
|
+
* - Global semaphore management (max 4 executors)
|
|
10
|
+
*
|
|
11
|
+
* IMPORTANT: expires_at is INFORMATIONAL ONLY
|
|
12
|
+
* Auto-release based on expires_at is forbidden (E405)
|
|
13
|
+
*/
|
|
14
|
+
import { FileLock } from '../models/file-lock';
|
|
15
|
+
import { LockType } from '../models/enums';
|
|
16
|
+
import { ErrorCode } from '../errors/error-codes';
|
|
17
|
+
/**
|
|
18
|
+
* Lock Manager Error
|
|
19
|
+
*/
|
|
20
|
+
export declare class LockManagerError extends Error {
|
|
21
|
+
readonly code: ErrorCode;
|
|
22
|
+
readonly details?: Record<string, unknown>;
|
|
23
|
+
constructor(code: ErrorCode, message?: string, details?: Record<string, unknown>);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Wait graph entry for deadlock detection
|
|
27
|
+
*/
|
|
28
|
+
interface WaitGraphEntry {
|
|
29
|
+
executor_id: string;
|
|
30
|
+
holds: string[];
|
|
31
|
+
wants: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Lock Manager class
|
|
35
|
+
*/
|
|
36
|
+
export declare class LockManager {
|
|
37
|
+
private readonly baseDir;
|
|
38
|
+
private readonly locks;
|
|
39
|
+
private readonly fileLocks;
|
|
40
|
+
private readonly executorSemaphores;
|
|
41
|
+
private readonly maxExecutors;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new LockManager
|
|
44
|
+
* @param baseDir Base directory for lock storage
|
|
45
|
+
*/
|
|
46
|
+
constructor(baseDir: string);
|
|
47
|
+
/**
|
|
48
|
+
* Acquire a lock on a file
|
|
49
|
+
* @throws LockManagerError with E401 if lock cannot be acquired
|
|
50
|
+
*/
|
|
51
|
+
acquireLock(filePath: string, executorId: string, lockType: LockType): FileLock;
|
|
52
|
+
/**
|
|
53
|
+
* Release a lock
|
|
54
|
+
* @throws LockManagerError with E402 if lock not found
|
|
55
|
+
*/
|
|
56
|
+
releaseLock(lockId: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Acquire multiple locks in sorted order (to prevent deadlocks)
|
|
59
|
+
*/
|
|
60
|
+
acquireMultipleLocks(files: string[], executorId: string, lockType: LockType): FileLock[];
|
|
61
|
+
/**
|
|
62
|
+
* Acquire global semaphore for an executor
|
|
63
|
+
* @throws LockManagerError with E404 if executor limit exceeded
|
|
64
|
+
*/
|
|
65
|
+
acquireGlobalSemaphore(executorId: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Release global semaphore for an executor
|
|
68
|
+
*/
|
|
69
|
+
releaseGlobalSemaphore(executorId: string): void;
|
|
70
|
+
/**
|
|
71
|
+
* Detect deadlock from wait graph
|
|
72
|
+
* Uses cycle detection in the wait-for graph
|
|
73
|
+
*/
|
|
74
|
+
detectDeadlock(waitGraph: WaitGraphEntry[]): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Acquire lock with deadlock check
|
|
77
|
+
* @throws LockManagerError with E403 if deadlock would occur
|
|
78
|
+
*/
|
|
79
|
+
acquireLockWithDeadlockCheck(filePath: string, executorId: string, lockType: LockType, holdingFiles: string[]): FileLock;
|
|
80
|
+
/**
|
|
81
|
+
* Update lock expiry (informational only)
|
|
82
|
+
*/
|
|
83
|
+
updateLockExpiry(lockId: string, newExpiry: string): void;
|
|
84
|
+
/**
|
|
85
|
+
* Get a lock by ID
|
|
86
|
+
*/
|
|
87
|
+
getLock(lockId: string): FileLock | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Get lock age in milliseconds
|
|
90
|
+
*/
|
|
91
|
+
getLockAge(lockId: string): number;
|
|
92
|
+
/**
|
|
93
|
+
* Auto-release expired locks - FORBIDDEN
|
|
94
|
+
* expires_at is INFORMATIONAL ONLY
|
|
95
|
+
* @throws LockManagerError with E405 always
|
|
96
|
+
*/
|
|
97
|
+
autoReleaseExpiredLocks(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Get all active locks
|
|
100
|
+
*/
|
|
101
|
+
getActiveLocks(): FileLock[];
|
|
102
|
+
/**
|
|
103
|
+
* Get locks by executor
|
|
104
|
+
*/
|
|
105
|
+
getLocksByExecutor(executorId: string): FileLock[];
|
|
106
|
+
/**
|
|
107
|
+
* Get locks by file
|
|
108
|
+
*/
|
|
109
|
+
getLocksByFile(filePath: string): FileLock[];
|
|
110
|
+
/**
|
|
111
|
+
* Check if a file is locked
|
|
112
|
+
*/
|
|
113
|
+
isFileLocked(filePath: string): boolean;
|
|
114
|
+
}
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=lock-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-manager.d.ts","sourceRoot":"","sources":["../../src/locks/lock-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAoC,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAmB,MAAM,uBAAuB,CAAC;AAEnE;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,SAAgB,IAAI,EAAE,SAAS,CAAC;IAChC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEtC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAMjF;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2B;IACrD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAc;IACjD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAE1C;;;OAGG;gBACS,OAAO,EAAE,MAAM;IAO3B;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ;IAiC/E;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAwBjC;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE;IAwBzF;;;OAGG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAanD;;OAEG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAIhD;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO;IAuDpD;;;OAGG;IACH,4BAA4B,CAC1B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,MAAM,EAAE,GACrB,QAAQ;IAwCX;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAWzD;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI7C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAUlC;;;;OAIG;IACH,uBAAuB,IAAI,IAAI;IAe/B;;OAEG;IACH,cAAc,IAAI,QAAQ,EAAE;IAI5B;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,EAAE;IAMlD;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE;IAW5C;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAIxC"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Lock Manager
|
|
4
|
+
* Based on 04_COMPONENTS.md L178-201
|
|
5
|
+
*
|
|
6
|
+
* Responsible for:
|
|
7
|
+
* - Lock acquisition and release
|
|
8
|
+
* - Deadlock detection
|
|
9
|
+
* - Lock ordering (sorted acquisition)
|
|
10
|
+
* - Global semaphore management (max 4 executors)
|
|
11
|
+
*
|
|
12
|
+
* IMPORTANT: expires_at is INFORMATIONAL ONLY
|
|
13
|
+
* Auto-release based on expires_at is forbidden (E405)
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.LockManager = exports.LockManagerError = void 0;
|
|
17
|
+
const file_lock_1 = require("../models/file-lock");
|
|
18
|
+
const error_codes_1 = require("../errors/error-codes");
|
|
19
|
+
/**
|
|
20
|
+
* Lock Manager Error
|
|
21
|
+
*/
|
|
22
|
+
class LockManagerError extends Error {
|
|
23
|
+
code;
|
|
24
|
+
details;
|
|
25
|
+
constructor(code, message, details) {
|
|
26
|
+
super(message || (0, error_codes_1.getErrorMessage)(code));
|
|
27
|
+
this.name = 'LockManagerError';
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.details = details;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.LockManagerError = LockManagerError;
|
|
33
|
+
/**
|
|
34
|
+
* Lock Manager class
|
|
35
|
+
*/
|
|
36
|
+
class LockManager {
|
|
37
|
+
baseDir;
|
|
38
|
+
locks;
|
|
39
|
+
fileLocks; // file_path -> Set<lock_id>
|
|
40
|
+
executorSemaphores;
|
|
41
|
+
maxExecutors = 4;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new LockManager
|
|
44
|
+
* @param baseDir Base directory for lock storage
|
|
45
|
+
*/
|
|
46
|
+
constructor(baseDir) {
|
|
47
|
+
this.baseDir = baseDir;
|
|
48
|
+
this.locks = new Map();
|
|
49
|
+
this.fileLocks = new Map();
|
|
50
|
+
this.executorSemaphores = new Set();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Acquire a lock on a file
|
|
54
|
+
* @throws LockManagerError with E401 if lock cannot be acquired
|
|
55
|
+
*/
|
|
56
|
+
acquireLock(filePath, executorId, lockType) {
|
|
57
|
+
// Check existing locks on this file
|
|
58
|
+
const existingLockIds = this.fileLocks.get(filePath);
|
|
59
|
+
if (existingLockIds && existingLockIds.size > 0) {
|
|
60
|
+
// Check if any existing lock conflicts
|
|
61
|
+
for (const lockId of existingLockIds) {
|
|
62
|
+
const existingLock = this.locks.get(lockId);
|
|
63
|
+
if (existingLock && !(0, file_lock_1.isLockCompatible)(existingLock, lockType)) {
|
|
64
|
+
throw new LockManagerError(error_codes_1.ErrorCode.E401_LOCK_ACQUISITION_FAILURE, `Cannot acquire ${lockType} lock on ${filePath}: conflicting lock exists`, { filePath, executorId, lockType, conflictingLockId: lockId });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Create the lock
|
|
69
|
+
const lock = (0, file_lock_1.createFileLock)(filePath, executorId, lockType);
|
|
70
|
+
// Store the lock
|
|
71
|
+
this.locks.set(lock.lock_id, lock);
|
|
72
|
+
// Track file -> locks mapping
|
|
73
|
+
if (!this.fileLocks.has(filePath)) {
|
|
74
|
+
this.fileLocks.set(filePath, new Set());
|
|
75
|
+
}
|
|
76
|
+
this.fileLocks.get(filePath).add(lock.lock_id);
|
|
77
|
+
return lock;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Release a lock
|
|
81
|
+
* @throws LockManagerError with E402 if lock not found
|
|
82
|
+
*/
|
|
83
|
+
releaseLock(lockId) {
|
|
84
|
+
const lock = this.locks.get(lockId);
|
|
85
|
+
if (!lock) {
|
|
86
|
+
throw new LockManagerError(error_codes_1.ErrorCode.E402_LOCK_RELEASE_FAILURE, `Lock not found: ${lockId}`, { lockId });
|
|
87
|
+
}
|
|
88
|
+
// Remove from file -> locks mapping
|
|
89
|
+
const fileLockIds = this.fileLocks.get(lock.file_path);
|
|
90
|
+
if (fileLockIds) {
|
|
91
|
+
fileLockIds.delete(lockId);
|
|
92
|
+
if (fileLockIds.size === 0) {
|
|
93
|
+
this.fileLocks.delete(lock.file_path);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Remove the lock
|
|
97
|
+
this.locks.delete(lockId);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Acquire multiple locks in sorted order (to prevent deadlocks)
|
|
101
|
+
*/
|
|
102
|
+
acquireMultipleLocks(files, executorId, lockType) {
|
|
103
|
+
// Sort files to ensure consistent lock acquisition order
|
|
104
|
+
const sortedFiles = [...files].sort();
|
|
105
|
+
const acquiredLocks = [];
|
|
106
|
+
try {
|
|
107
|
+
for (const filePath of sortedFiles) {
|
|
108
|
+
const lock = this.acquireLock(filePath, executorId, lockType);
|
|
109
|
+
acquiredLocks.push(lock);
|
|
110
|
+
}
|
|
111
|
+
return acquiredLocks;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// Rollback: release all acquired locks in reverse order
|
|
115
|
+
for (const lock of acquiredLocks.reverse()) {
|
|
116
|
+
try {
|
|
117
|
+
this.releaseLock(lock.lock_id);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Ignore release errors during rollback
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Acquire global semaphore for an executor
|
|
128
|
+
* @throws LockManagerError with E404 if executor limit exceeded
|
|
129
|
+
*/
|
|
130
|
+
acquireGlobalSemaphore(executorId) {
|
|
131
|
+
if (this.executorSemaphores.size >= this.maxExecutors) {
|
|
132
|
+
throw new LockManagerError(error_codes_1.ErrorCode.E404_EXECUTOR_LIMIT_EXCEEDED, `Executor limit exceeded: max ${this.maxExecutors} executors allowed`, { executorId, currentCount: this.executorSemaphores.size });
|
|
133
|
+
}
|
|
134
|
+
this.executorSemaphores.add(executorId);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Release global semaphore for an executor
|
|
139
|
+
*/
|
|
140
|
+
releaseGlobalSemaphore(executorId) {
|
|
141
|
+
this.executorSemaphores.delete(executorId);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Detect deadlock from wait graph
|
|
145
|
+
* Uses cycle detection in the wait-for graph
|
|
146
|
+
*/
|
|
147
|
+
detectDeadlock(waitGraph) {
|
|
148
|
+
// Build adjacency list: executor -> set of executors it's waiting for
|
|
149
|
+
const adjacencyList = new Map();
|
|
150
|
+
// Initialize all executors
|
|
151
|
+
for (const entry of waitGraph) {
|
|
152
|
+
adjacencyList.set(entry.executor_id, new Set());
|
|
153
|
+
}
|
|
154
|
+
// Build the wait-for graph
|
|
155
|
+
for (const entry of waitGraph) {
|
|
156
|
+
for (const wantedFile of entry.wants) {
|
|
157
|
+
// Find who holds this file
|
|
158
|
+
for (const other of waitGraph) {
|
|
159
|
+
if (other.executor_id !== entry.executor_id && other.holds.includes(wantedFile)) {
|
|
160
|
+
adjacencyList.get(entry.executor_id).add(other.executor_id);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Detect cycle using DFS
|
|
166
|
+
const visited = new Set();
|
|
167
|
+
const recursionStack = new Set();
|
|
168
|
+
const hasCycle = (node) => {
|
|
169
|
+
visited.add(node);
|
|
170
|
+
recursionStack.add(node);
|
|
171
|
+
const neighbors = adjacencyList.get(node) || new Set();
|
|
172
|
+
for (const neighbor of neighbors) {
|
|
173
|
+
if (!visited.has(neighbor)) {
|
|
174
|
+
if (hasCycle(neighbor)) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else if (recursionStack.has(neighbor)) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
recursionStack.delete(node);
|
|
183
|
+
return false;
|
|
184
|
+
};
|
|
185
|
+
for (const executor of adjacencyList.keys()) {
|
|
186
|
+
if (!visited.has(executor)) {
|
|
187
|
+
if (hasCycle(executor)) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Acquire lock with deadlock check
|
|
196
|
+
* @throws LockManagerError with E403 if deadlock would occur
|
|
197
|
+
*/
|
|
198
|
+
acquireLockWithDeadlockCheck(filePath, executorId, lockType, holdingFiles) {
|
|
199
|
+
// Check if acquiring this lock would cause a deadlock
|
|
200
|
+
const existingLockIds = this.fileLocks.get(filePath);
|
|
201
|
+
if (existingLockIds && existingLockIds.size > 0) {
|
|
202
|
+
// Get the executor holding the wanted file
|
|
203
|
+
for (const lockId of existingLockIds) {
|
|
204
|
+
const existingLock = this.locks.get(lockId);
|
|
205
|
+
if (existingLock && existingLock.holder_executor_id !== executorId) {
|
|
206
|
+
// Check if that executor wants any file we're holding
|
|
207
|
+
const otherExecutorId = existingLock.holder_executor_id;
|
|
208
|
+
// Check all locks to see if the other executor wants our files
|
|
209
|
+
for (const [lId, lock] of this.locks) {
|
|
210
|
+
if (lock.holder_executor_id === otherExecutorId) {
|
|
211
|
+
// The other executor holds some file, check if they're waiting for our files
|
|
212
|
+
// This is a simplified deadlock check - in reality would need more context
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Build wait graph to check for deadlock
|
|
216
|
+
const waitGraph = [
|
|
217
|
+
{ executor_id: executorId, holds: holdingFiles, wants: [filePath] },
|
|
218
|
+
{ executor_id: otherExecutorId, holds: [filePath], wants: holdingFiles },
|
|
219
|
+
];
|
|
220
|
+
if (this.detectDeadlock(waitGraph)) {
|
|
221
|
+
throw new LockManagerError(error_codes_1.ErrorCode.E403_DEADLOCK_DETECTED, `Deadlock detected: ${executorId} waiting for ${filePath} held by ${otherExecutorId}`, { executorId, filePath, otherExecutorId, holdingFiles });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return this.acquireLock(filePath, executorId, lockType);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Update lock expiry (informational only)
|
|
230
|
+
*/
|
|
231
|
+
updateLockExpiry(lockId, newExpiry) {
|
|
232
|
+
const lock = this.locks.get(lockId);
|
|
233
|
+
if (lock) {
|
|
234
|
+
const updatedLock = {
|
|
235
|
+
...lock,
|
|
236
|
+
expires_at: newExpiry,
|
|
237
|
+
};
|
|
238
|
+
this.locks.set(lockId, updatedLock);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get a lock by ID
|
|
243
|
+
*/
|
|
244
|
+
getLock(lockId) {
|
|
245
|
+
return this.locks.get(lockId);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get lock age in milliseconds
|
|
249
|
+
*/
|
|
250
|
+
getLockAge(lockId) {
|
|
251
|
+
const lock = this.locks.get(lockId);
|
|
252
|
+
if (!lock) {
|
|
253
|
+
return -1;
|
|
254
|
+
}
|
|
255
|
+
const acquiredAt = new Date(lock.acquired_at);
|
|
256
|
+
return Date.now() - acquiredAt.getTime();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Auto-release expired locks - FORBIDDEN
|
|
260
|
+
* expires_at is INFORMATIONAL ONLY
|
|
261
|
+
* @throws LockManagerError with E405 always
|
|
262
|
+
*/
|
|
263
|
+
autoReleaseExpiredLocks() {
|
|
264
|
+
// Check if there are any expired locks
|
|
265
|
+
for (const [lockId, lock] of this.locks) {
|
|
266
|
+
const expiresAt = new Date(lock.expires_at);
|
|
267
|
+
if (expiresAt < new Date()) {
|
|
268
|
+
// Auto-release is forbidden
|
|
269
|
+
throw new LockManagerError(error_codes_1.ErrorCode.E405_RESOURCE_RELEASE_FAILURE, 'Auto-release based on expires_at is forbidden. Locks must be explicitly released.', { lockId, expires_at: lock.expires_at });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get all active locks
|
|
275
|
+
*/
|
|
276
|
+
getActiveLocks() {
|
|
277
|
+
return Array.from(this.locks.values());
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Get locks by executor
|
|
281
|
+
*/
|
|
282
|
+
getLocksByExecutor(executorId) {
|
|
283
|
+
return Array.from(this.locks.values()).filter(lock => lock.holder_executor_id === executorId);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Get locks by file
|
|
287
|
+
*/
|
|
288
|
+
getLocksByFile(filePath) {
|
|
289
|
+
const lockIds = this.fileLocks.get(filePath);
|
|
290
|
+
if (!lockIds) {
|
|
291
|
+
return [];
|
|
292
|
+
}
|
|
293
|
+
return Array.from(lockIds)
|
|
294
|
+
.map(lockId => this.locks.get(lockId))
|
|
295
|
+
.filter((lock) => lock !== undefined);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if a file is locked
|
|
299
|
+
*/
|
|
300
|
+
isFileLocked(filePath) {
|
|
301
|
+
const lockIds = this.fileLocks.get(filePath);
|
|
302
|
+
return lockIds !== undefined && lockIds.size > 0;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
exports.LockManager = LockManager;
|
|
306
|
+
//# sourceMappingURL=lock-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-manager.js","sourceRoot":"","sources":["../../src/locks/lock-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging Module Index
|
|
3
|
+
*
|
|
4
|
+
* Per spec 13_LOGGING_AND_OBSERVABILITY.md
|
|
5
|
+
*/
|
|
6
|
+
export { maskSensitiveData, containsSensitiveData, maskSensitiveObject, getApiKeyStatus, checkApiKeyForProvider, MASKING_PATTERNS, } from './sensitive-data-masker';
|
|
7
|
+
export { TaskLogManager, CompleteTaskOptions, LOG_DIR, INDEX_FILE, TASKS_DIR, RAW_DIR, } from './task-log-manager';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,OAAO,EACP,UAAU,EACV,SAAS,EACT,OAAO,GACR,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Logging Module Index
|
|
4
|
+
*
|
|
5
|
+
* Per spec 13_LOGGING_AND_OBSERVABILITY.md
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.RAW_DIR = exports.TASKS_DIR = exports.INDEX_FILE = exports.LOG_DIR = exports.TaskLogManager = exports.MASKING_PATTERNS = exports.checkApiKeyForProvider = exports.getApiKeyStatus = exports.maskSensitiveObject = exports.containsSensitiveData = exports.maskSensitiveData = void 0;
|
|
9
|
+
var sensitive_data_masker_1 = require("./sensitive-data-masker");
|
|
10
|
+
Object.defineProperty(exports, "maskSensitiveData", { enumerable: true, get: function () { return sensitive_data_masker_1.maskSensitiveData; } });
|
|
11
|
+
Object.defineProperty(exports, "containsSensitiveData", { enumerable: true, get: function () { return sensitive_data_masker_1.containsSensitiveData; } });
|
|
12
|
+
Object.defineProperty(exports, "maskSensitiveObject", { enumerable: true, get: function () { return sensitive_data_masker_1.maskSensitiveObject; } });
|
|
13
|
+
Object.defineProperty(exports, "getApiKeyStatus", { enumerable: true, get: function () { return sensitive_data_masker_1.getApiKeyStatus; } });
|
|
14
|
+
Object.defineProperty(exports, "checkApiKeyForProvider", { enumerable: true, get: function () { return sensitive_data_masker_1.checkApiKeyForProvider; } });
|
|
15
|
+
Object.defineProperty(exports, "MASKING_PATTERNS", { enumerable: true, get: function () { return sensitive_data_masker_1.MASKING_PATTERNS; } });
|
|
16
|
+
var task_log_manager_1 = require("./task-log-manager");
|
|
17
|
+
Object.defineProperty(exports, "TaskLogManager", { enumerable: true, get: function () { return task_log_manager_1.TaskLogManager; } });
|
|
18
|
+
Object.defineProperty(exports, "LOG_DIR", { enumerable: true, get: function () { return task_log_manager_1.LOG_DIR; } });
|
|
19
|
+
Object.defineProperty(exports, "INDEX_FILE", { enumerable: true, get: function () { return task_log_manager_1.INDEX_FILE; } });
|
|
20
|
+
Object.defineProperty(exports, "TASKS_DIR", { enumerable: true, get: function () { return task_log_manager_1.TASKS_DIR; } });
|
|
21
|
+
Object.defineProperty(exports, "RAW_DIR", { enumerable: true, get: function () { return task_log_manager_1.RAW_DIR; } });
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,iEAOiC;AAN/B,0HAAA,iBAAiB,OAAA;AACjB,8HAAA,qBAAqB,OAAA;AACrB,4HAAA,mBAAmB,OAAA;AACnB,wHAAA,eAAe,OAAA;AACf,+HAAA,sBAAsB,OAAA;AACtB,yHAAA,gBAAgB,OAAA;AAGlB,uDAO4B;AAN1B,kHAAA,cAAc,OAAA;AAEd,2GAAA,OAAO,OAAA;AACP,8GAAA,UAAU,OAAA;AACV,6GAAA,SAAS,OAAA;AACT,2GAAA,OAAO,OAAA"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensitive Data Masker
|
|
3
|
+
*
|
|
4
|
+
* Per spec 13_LOGGING_AND_OBSERVABILITY.md Section 4:
|
|
5
|
+
* Per spec 06_CORRECTNESS_PROPERTIES.md Property 24/25:
|
|
6
|
+
*
|
|
7
|
+
* 11 Masking Patterns across 4 Priority Levels:
|
|
8
|
+
*
|
|
9
|
+
* Priority 1 - Critical Secrets:
|
|
10
|
+
* 1. OpenAI API Key: sk-[A-Za-z0-9]{20,}
|
|
11
|
+
* 2. Anthropic API Key: sk-ant-[A-Za-z0-9-]{20,}
|
|
12
|
+
* 3. Private Key blocks: -----BEGIN.*PRIVATE KEY-----
|
|
13
|
+
*
|
|
14
|
+
* Priority 2 - Tokens and Auth Headers:
|
|
15
|
+
* 4. JWT Token: eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+
|
|
16
|
+
* 5. Authorization Header: Authorization:\s*\S+
|
|
17
|
+
* 6. Cookie: Cookie:\s*.+
|
|
18
|
+
* 7. Set-Cookie: Set-Cookie:\s*.+
|
|
19
|
+
*
|
|
20
|
+
* Priority 3 - Credentials:
|
|
21
|
+
* 8. JSON Credential: "(?:apiKey|password|secret|token)":\s*"[^"]+"
|
|
22
|
+
* 9. Environment Credential: [A-Z_]+(?:PASSWORD|SECRET|KEY|TOKEN)=[^\s]+
|
|
23
|
+
* 10. Bearer Token: Bearer\s+[A-Za-z0-9._-]+
|
|
24
|
+
*
|
|
25
|
+
* Priority 4 - Generic Secrets:
|
|
26
|
+
* 11. Generic Secret: (?:password|secret|token)\s*[=:]\s*["']?[^\s"']+
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Masking pattern definition with priority
|
|
30
|
+
*/
|
|
31
|
+
interface MaskingPattern {
|
|
32
|
+
name: string;
|
|
33
|
+
regex: RegExp;
|
|
34
|
+
mask: string;
|
|
35
|
+
priority: 1 | 2 | 3 | 4;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Masking patterns ordered by priority (higher priority first)
|
|
39
|
+
* Per spec 06_CORRECTNESS_PROPERTIES.md Property 25 Section 3
|
|
40
|
+
*/
|
|
41
|
+
declare const MASKING_PATTERNS: MaskingPattern[];
|
|
42
|
+
/**
|
|
43
|
+
* Mask sensitive data in a string
|
|
44
|
+
* Per spec 13_LOGGING_AND_OBSERVABILITY.md Section 4.3
|
|
45
|
+
*
|
|
46
|
+
* Patterns are applied in priority order (1 first, then 2, etc.)
|
|
47
|
+
*
|
|
48
|
+
* @param content - Content to mask
|
|
49
|
+
* @returns Masked content
|
|
50
|
+
*/
|
|
51
|
+
export declare function maskSensitiveData(content: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* Check if content contains sensitive data
|
|
54
|
+
*
|
|
55
|
+
* @param content - Content to check
|
|
56
|
+
* @returns true if sensitive data is detected
|
|
57
|
+
*/
|
|
58
|
+
export declare function containsSensitiveData(content: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Mask sensitive data in an object (recursive)
|
|
61
|
+
*
|
|
62
|
+
* @param obj - Object to mask
|
|
63
|
+
* @returns Masked object
|
|
64
|
+
*/
|
|
65
|
+
export declare function maskSensitiveObject<T>(obj: T): T;
|
|
66
|
+
/**
|
|
67
|
+
* Get API key status (SET/NOT SET) without revealing the value
|
|
68
|
+
* Per spec 06_CORRECTNESS_PROPERTIES.md Property 24
|
|
69
|
+
*
|
|
70
|
+
* @param envVar - Environment variable name
|
|
71
|
+
* @returns 'SET' or 'NOT SET'
|
|
72
|
+
*/
|
|
73
|
+
export declare function getApiKeyStatus(envVar: string): 'SET' | 'NOT SET';
|
|
74
|
+
/**
|
|
75
|
+
* Check API key availability for a provider
|
|
76
|
+
*
|
|
77
|
+
* @param provider - Provider identifier
|
|
78
|
+
* @returns Object with status and env variable name
|
|
79
|
+
*/
|
|
80
|
+
export declare function checkApiKeyForProvider(provider: string): {
|
|
81
|
+
required: boolean;
|
|
82
|
+
envVar: string | null;
|
|
83
|
+
status: 'SET' | 'NOT SET' | 'NOT_REQUIRED';
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Get list of pattern names by priority
|
|
87
|
+
*/
|
|
88
|
+
export declare function getPatternsByPriority(priority: 1 | 2 | 3 | 4): string[];
|
|
89
|
+
export { MASKING_PATTERNS };
|
|
90
|
+
//# sourceMappingURL=sensitive-data-masker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitive-data-masker.d.ts","sourceRoot":"","sources":["../../src/logging/sensitive-data-masker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;GAEG;AACH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACzB;AAED;;;GAGG;AACH,QAAA,MAAM,gBAAgB,EAAE,cAAc,EA0ErC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsBzD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAY9D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAsBhD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAGjE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,KAAK,GAAG,SAAS,GAAG,cAAc,CAAC;CAC5C,CAkBA;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE,CAIvE;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|