@tracehound/core 1.2.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/README.md +125 -0
- package/dist/core/agent.d.ts +89 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +141 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/audit-chain.d.ts +39 -0
- package/dist/core/audit-chain.d.ts.map +1 -0
- package/dist/core/audit-chain.js +87 -0
- package/dist/core/audit-chain.js.map +1 -0
- package/dist/core/cold-storage.d.ts +87 -0
- package/dist/core/cold-storage.d.ts.map +1 -0
- package/dist/core/cold-storage.js +53 -0
- package/dist/core/cold-storage.js.map +1 -0
- package/dist/core/evidence-factory.d.ts +85 -0
- package/dist/core/evidence-factory.d.ts.map +1 -0
- package/dist/core/evidence-factory.js +96 -0
- package/dist/core/evidence-factory.js.map +1 -0
- package/dist/core/evidence.d.ts +48 -0
- package/dist/core/evidence.d.ts.map +1 -0
- package/dist/core/evidence.js +135 -0
- package/dist/core/evidence.js.map +1 -0
- package/dist/core/fail-safe.d.ts +149 -0
- package/dist/core/fail-safe.d.ts.map +1 -0
- package/dist/core/fail-safe.js +217 -0
- package/dist/core/fail-safe.js.map +1 -0
- package/dist/core/hound-ipc.d.ts +91 -0
- package/dist/core/hound-ipc.d.ts.map +1 -0
- package/dist/core/hound-ipc.js +196 -0
- package/dist/core/hound-ipc.js.map +1 -0
- package/dist/core/hound-pool.d.ts +157 -0
- package/dist/core/hound-pool.d.ts.map +1 -0
- package/dist/core/hound-pool.js +337 -0
- package/dist/core/hound-pool.js.map +1 -0
- package/dist/core/hound-process.d.ts +14 -0
- package/dist/core/hound-process.d.ts.map +1 -0
- package/dist/core/hound-process.js +112 -0
- package/dist/core/hound-process.js.map +1 -0
- package/dist/core/hound-worker.d.ts +14 -0
- package/dist/core/hound-worker.d.ts.map +1 -0
- package/dist/core/hound-worker.js +112 -0
- package/dist/core/hound-worker.js.map +1 -0
- package/dist/core/lane-queue.d.ts +121 -0
- package/dist/core/lane-queue.d.ts.map +1 -0
- package/dist/core/lane-queue.js +181 -0
- package/dist/core/lane-queue.js.map +1 -0
- package/dist/core/license-manager.d.ts +128 -0
- package/dist/core/license-manager.d.ts.map +1 -0
- package/dist/core/license-manager.js +219 -0
- package/dist/core/license-manager.js.map +1 -0
- package/dist/core/notification-emitter.d.ts +140 -0
- package/dist/core/notification-emitter.d.ts.map +1 -0
- package/dist/core/notification-emitter.js +197 -0
- package/dist/core/notification-emitter.js.map +1 -0
- package/dist/core/process-adapter.d.ts +146 -0
- package/dist/core/process-adapter.d.ts.map +1 -0
- package/dist/core/process-adapter.js +174 -0
- package/dist/core/process-adapter.js.map +1 -0
- package/dist/core/quarantine.d.ts +95 -0
- package/dist/core/quarantine.d.ts.map +1 -0
- package/dist/core/quarantine.js +221 -0
- package/dist/core/quarantine.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +94 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +156 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/s3-cold-storage.d.ts +116 -0
- package/dist/core/s3-cold-storage.d.ts.map +1 -0
- package/dist/core/s3-cold-storage.js +198 -0
- package/dist/core/s3-cold-storage.js.map +1 -0
- package/dist/core/scheduler.d.ts +126 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +138 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/security-state.d.ts +170 -0
- package/dist/core/security-state.d.ts.map +1 -0
- package/dist/core/security-state.js +156 -0
- package/dist/core/security-state.js.map +1 -0
- package/dist/core/tier-capacity.d.ts +58 -0
- package/dist/core/tier-capacity.d.ts.map +1 -0
- package/dist/core/tier-capacity.js +89 -0
- package/dist/core/tier-capacity.js.map +1 -0
- package/dist/core/tracehound.d.ts +85 -0
- package/dist/core/tracehound.d.ts.map +1 -0
- package/dist/core/tracehound.js +90 -0
- package/dist/core/tracehound.js.map +1 -0
- package/dist/core/trust-boundary.d.ts +85 -0
- package/dist/core/trust-boundary.d.ts.map +1 -0
- package/dist/core/trust-boundary.js +71 -0
- package/dist/core/trust-boundary.js.map +1 -0
- package/dist/core/watcher.d.ts +153 -0
- package/dist/core/watcher.d.ts.map +1 -0
- package/dist/core/watcher.js +141 -0
- package/dist/core/watcher.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +112 -0
- package/dist/index.js.map +1 -0
- package/dist/types/audit.d.ts +45 -0
- package/dist/types/audit.d.ts.map +1 -0
- package/dist/types/audit.js +5 -0
- package/dist/types/audit.js.map +1 -0
- package/dist/types/common.d.ts +12 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +5 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/config.d.ts +98 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +58 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/errors.d.ts +118 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +266 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/evidence.d.ts +102 -0
- package/dist/types/evidence.d.ts.map +1 -0
- package/dist/types/evidence.js +5 -0
- package/dist/types/evidence.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/result.d.ts +62 -0
- package/dist/types/result.d.ts.map +1 -0
- package/dist/types/result.js +34 -0
- package/dist/types/result.js.map +1 -0
- package/dist/types/scent.d.ts +55 -0
- package/dist/types/scent.d.ts.map +1 -0
- package/dist/types/scent.js +5 -0
- package/dist/types/scent.js.map +1 -0
- package/dist/types/signature.d.ts +47 -0
- package/dist/types/signature.d.ts.map +1 -0
- package/dist/types/signature.js +68 -0
- package/dist/types/signature.js.map +1 -0
- package/dist/types/threat.d.ts +38 -0
- package/dist/types/threat.d.ts.map +1 -0
- package/dist/types/threat.js +18 -0
- package/dist/types/threat.js.map +1 -0
- package/dist/utils/binary-codec.d.ts +225 -0
- package/dist/utils/binary-codec.d.ts.map +1 -0
- package/dist/utils/binary-codec.js +266 -0
- package/dist/utils/binary-codec.js.map +1 -0
- package/dist/utils/compare.d.ts +26 -0
- package/dist/utils/compare.d.ts.map +1 -0
- package/dist/utils/compare.js +44 -0
- package/dist/utils/compare.js.map +1 -0
- package/dist/utils/encode.d.ts +39 -0
- package/dist/utils/encode.d.ts.map +1 -0
- package/dist/utils/encode.js +124 -0
- package/dist/utils/encode.js.map +1 -0
- package/dist/utils/hash.d.ts +19 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +25 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/id.d.ts +20 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js +47 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/utils/runtime.d.ts +24 -0
- package/dist/utils/runtime.d.ts.map +1 -0
- package/dist/utils/runtime.js +68 -0
- package/dist/utils/runtime.js.map +1 -0
- package/dist/utils/serialize.d.ts +14 -0
- package/dist/utils/serialize.d.ts.map +1 -0
- package/dist/utils/serialize.js +27 -0
- package/dist/utils/serialize.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# @tracehound/core
|
|
2
|
+
|
|
3
|
+
Security buffer system for threat quarantine.
|
|
4
|
+
Part of the Tracehound Cyberimmune System.
|
|
5
|
+
|
|
6
|
+
## Status
|
|
7
|
+
|
|
8
|
+
**Phase 1-4 Complete:** ✅
|
|
9
|
+
|
|
10
|
+
- **Phase 1:** Foundation (Types, Utils)
|
|
11
|
+
- **Phase 2:** Evidence, Quarantine, AuditChain
|
|
12
|
+
- **Phase 3:** Agent, RateLimiter
|
|
13
|
+
- **Phase 4:** HoundPool, Scheduler, Watcher, BinaryCodec
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @tracehound/core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Core Components
|
|
22
|
+
|
|
23
|
+
### 1. Agent (`IAgent`)
|
|
24
|
+
|
|
25
|
+
The main entry point. Orchestrates the threat detection flow.
|
|
26
|
+
|
|
27
|
+
- **Stateless:** Depends on injected services.
|
|
28
|
+
- **Fail-safe:** Defaults to "clean" on error.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {
|
|
32
|
+
createAgent,
|
|
33
|
+
createQuarantine,
|
|
34
|
+
createRateLimiter,
|
|
35
|
+
createEvidenceFactory,
|
|
36
|
+
} from '@tracehound/core'
|
|
37
|
+
|
|
38
|
+
const agent = createAgent({ maxPayloadSize: 1_000_000 })
|
|
39
|
+
const result = agent.intercept(scent)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Hound Pool (`IHoundPool`)
|
|
43
|
+
|
|
44
|
+
Process-separated child worker pool for evidence processing.
|
|
45
|
+
|
|
46
|
+
- **Containment-Oriented:** Uses process separation and hardening flags; OS sandboxing depends on deployment policy.
|
|
47
|
+
- **Fire-and-Forget:** Agent never awaits detection.
|
|
48
|
+
- **Resilient:** Auto-replenish on crash/timeout.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// Activate analysis (returns immediately)
|
|
52
|
+
houndPool.activate(evidence)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3. Watcher (`IWatcher`)
|
|
56
|
+
|
|
57
|
+
Pull-based observability.
|
|
58
|
+
|
|
59
|
+
- **Passive:** Does not emit events (no EventEmitter).
|
|
60
|
+
- **Snapshot:** Provides immutable view of system state.
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const snapshot = watcher.snapshot()
|
|
64
|
+
console.log(`Threats: ${snapshot.threats.total}`)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. Scheduler (`IScheduler`)
|
|
68
|
+
|
|
69
|
+
Background task management.
|
|
70
|
+
|
|
71
|
+
- **Jittered:** Prevents timing attacks.
|
|
72
|
+
- **Load-Aware:** Skips ticks if system is busy (`skipIfBusy`).
|
|
73
|
+
|
|
74
|
+
## Usage Example
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import {
|
|
78
|
+
createAgent,
|
|
79
|
+
createQuarantine,
|
|
80
|
+
createRateLimiter,
|
|
81
|
+
createEvidenceFactory,
|
|
82
|
+
createHoundPool,
|
|
83
|
+
AuditChain,
|
|
84
|
+
} from '@tracehound/core'
|
|
85
|
+
|
|
86
|
+
// 1. Setup Dependencies
|
|
87
|
+
const auditChain = new AuditChain()
|
|
88
|
+
const quarantine = createQuarantine({ maxCount: 1000 }, auditChain)
|
|
89
|
+
const rateLimiter = createRateLimiter({ windowMs: 60000, maxRequests: 100 })
|
|
90
|
+
const factory = createEvidenceFactory()
|
|
91
|
+
|
|
92
|
+
// 2. Create Agent
|
|
93
|
+
const agent = createAgent({ maxPayloadSize: 1_000_000 }, quarantine, rateLimiter, factory)
|
|
94
|
+
|
|
95
|
+
// 3. Intercept Traffic
|
|
96
|
+
const result = agent.intercept({
|
|
97
|
+
id: 'req-1',
|
|
98
|
+
source: '192.168.1.1',
|
|
99
|
+
payload: { user: 'input' },
|
|
100
|
+
timestamp: Date.now(),
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
if (result.status === 'quarantined') {
|
|
104
|
+
console.log('Threat quarantined:', result.handle.signature)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Architecture
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
[Traffic] → (Agent) → [RateLimiter]
|
|
112
|
+
│
|
|
113
|
+
▼
|
|
114
|
+
[EvidenceFactory] → (Hash/Compress) → [Evidence]
|
|
115
|
+
│
|
|
116
|
+
▼
|
|
117
|
+
[Quarantine]
|
|
118
|
+
│
|
|
119
|
+
▼
|
|
120
|
+
(HoundPool) → [Analysis]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## License
|
|
124
|
+
|
|
125
|
+
Open-Core — this package is the open-source substrate of the Tracehound ecosystem. See the root [PRICING.md](../../docs/PRICING.md) for details on the commercial satellite packages.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent - core orchestrator for Tracehound intercept flow.
|
|
3
|
+
*
|
|
4
|
+
* SECURITY: Agent does NOT perform threat detection.
|
|
5
|
+
* Agent orchestrates: rate limiting → validation → factory → quarantine.
|
|
6
|
+
*
|
|
7
|
+
* RFC Contract:
|
|
8
|
+
* - If scent.threat present → quarantine
|
|
9
|
+
* - If scent.threat absent → clean
|
|
10
|
+
* - Tracehound DOES NOT make threat decisions
|
|
11
|
+
*/
|
|
12
|
+
import type { InterceptResult } from '../types/result.js';
|
|
13
|
+
import type { Scent } from '../types/scent.js';
|
|
14
|
+
import type { IEvidenceFactory } from './evidence-factory.js';
|
|
15
|
+
import type { Quarantine } from './quarantine.js';
|
|
16
|
+
import type { IRateLimiter } from './rate-limiter.js';
|
|
17
|
+
/**
|
|
18
|
+
* Agent configuration (subset of TracehoundConfig).
|
|
19
|
+
*/
|
|
20
|
+
export interface AgentConfig {
|
|
21
|
+
/** Maximum payload size in bytes */
|
|
22
|
+
maxPayloadSize: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Agent interface.
|
|
26
|
+
*/
|
|
27
|
+
export interface IAgent {
|
|
28
|
+
/**
|
|
29
|
+
* Intercept a scent and process according to RFC.
|
|
30
|
+
*
|
|
31
|
+
* Flow:
|
|
32
|
+
* 1. Rate limit check → rate_limited
|
|
33
|
+
* 2. If no threat signal → clean
|
|
34
|
+
* 3. Validate & encode payload → payload_too_large | error
|
|
35
|
+
* 4. Generate signature via factory
|
|
36
|
+
* 5. Check duplicate → ignored
|
|
37
|
+
* 6. Create evidence & quarantine → quarantined
|
|
38
|
+
*
|
|
39
|
+
* @param scent - Input scent to process
|
|
40
|
+
* @returns Intercept result
|
|
41
|
+
*/
|
|
42
|
+
intercept(scent: Scent): InterceptResult;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Agent statistics.
|
|
46
|
+
*/
|
|
47
|
+
export interface AgentStats {
|
|
48
|
+
/** Total intercepts processed */
|
|
49
|
+
totalIntercepts: number;
|
|
50
|
+
/** Clean (no threat signal) */
|
|
51
|
+
cleanCount: number;
|
|
52
|
+
/** Rate limited */
|
|
53
|
+
rateLimitedCount: number;
|
|
54
|
+
/** Payload validation failures */
|
|
55
|
+
validationFailures: number;
|
|
56
|
+
/** Duplicates ignored */
|
|
57
|
+
ignoredCount: number;
|
|
58
|
+
/** Successfully quarantined */
|
|
59
|
+
quarantinedCount: number;
|
|
60
|
+
/** Errors */
|
|
61
|
+
errorCount: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Agent implementation.
|
|
65
|
+
*/
|
|
66
|
+
export declare class Agent implements IAgent {
|
|
67
|
+
private readonly config;
|
|
68
|
+
private readonly quarantine;
|
|
69
|
+
private readonly rateLimiter;
|
|
70
|
+
private readonly evidenceFactory;
|
|
71
|
+
private readonly stats;
|
|
72
|
+
constructor(config: AgentConfig, quarantine: Quarantine, rateLimiter: IRateLimiter, evidenceFactory: IEvidenceFactory);
|
|
73
|
+
intercept(scent: Scent): InterceptResult;
|
|
74
|
+
/**
|
|
75
|
+
* Get current agent statistics.
|
|
76
|
+
*/
|
|
77
|
+
getStats(): Readonly<AgentStats>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Create an agent instance.
|
|
81
|
+
*
|
|
82
|
+
* @param config - Agent configuration
|
|
83
|
+
* @param quarantine - Quarantine instance
|
|
84
|
+
* @param rateLimiter - Rate limiter instance
|
|
85
|
+
* @param evidenceFactory - Evidence factory instance
|
|
86
|
+
* @returns Agent instance
|
|
87
|
+
*/
|
|
88
|
+
export declare function createAgent(config: AgentConfig, quarantine: Quarantine, rateLimiter: IRateLimiter, evidenceFactory: IEvidenceFactory): IAgent;
|
|
89
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAA;AAEtE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe,CAAA;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,eAAe,EAAE,MAAM,CAAA;IACvB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,mBAAmB;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kCAAkC;IAClC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,+BAA+B;IAC/B,gBAAgB,EAAE,MAAM,CAAA;IACxB,aAAa;IACb,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,qBAAa,KAAM,YAAW,MAAM;IAYhC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAdlC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAQrB;gBAGkB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,gBAAgB;IAQpD,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,eAAe;IAmGxC;;OAEG;IACH,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC;CAGjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,YAAY,EACzB,eAAe,EAAE,gBAAgB,GAChC,MAAM,CAER"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent - core orchestrator for Tracehound intercept flow.
|
|
3
|
+
*
|
|
4
|
+
* SECURITY: Agent does NOT perform threat detection.
|
|
5
|
+
* Agent orchestrates: rate limiting → validation → factory → quarantine.
|
|
6
|
+
*
|
|
7
|
+
* RFC Contract:
|
|
8
|
+
* - If scent.threat present → quarantine
|
|
9
|
+
* - If scent.threat absent → clean
|
|
10
|
+
* - Tracehound DOES NOT make threat decisions
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Agent implementation.
|
|
14
|
+
*/
|
|
15
|
+
export class Agent {
|
|
16
|
+
config;
|
|
17
|
+
quarantine;
|
|
18
|
+
rateLimiter;
|
|
19
|
+
evidenceFactory;
|
|
20
|
+
stats = {
|
|
21
|
+
totalIntercepts: 0,
|
|
22
|
+
cleanCount: 0,
|
|
23
|
+
rateLimitedCount: 0,
|
|
24
|
+
validationFailures: 0,
|
|
25
|
+
ignoredCount: 0,
|
|
26
|
+
quarantinedCount: 0,
|
|
27
|
+
errorCount: 0,
|
|
28
|
+
};
|
|
29
|
+
constructor(config, quarantine, rateLimiter, evidenceFactory) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
this.quarantine = quarantine;
|
|
32
|
+
this.rateLimiter = rateLimiter;
|
|
33
|
+
this.evidenceFactory = evidenceFactory;
|
|
34
|
+
// Validate config
|
|
35
|
+
if (config.maxPayloadSize <= 0) {
|
|
36
|
+
throw new Error('maxPayloadSize must be positive');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
intercept(scent) {
|
|
40
|
+
this.stats.totalIntercepts++;
|
|
41
|
+
try {
|
|
42
|
+
// Step 1: Rate limit check
|
|
43
|
+
const rateResult = this.rateLimiter.check(scent.source);
|
|
44
|
+
if (!rateResult.allowed) {
|
|
45
|
+
this.stats.rateLimitedCount++;
|
|
46
|
+
return {
|
|
47
|
+
status: 'rate_limited',
|
|
48
|
+
retryAfter: rateResult.retryAfter,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Step 2: Check for threat signal
|
|
52
|
+
if (!scent.threat) {
|
|
53
|
+
// No threat signal = clean
|
|
54
|
+
// Tracehound does NOT make threat detection decisions
|
|
55
|
+
this.stats.cleanCount++;
|
|
56
|
+
return { status: 'clean' };
|
|
57
|
+
}
|
|
58
|
+
// Step 3: Create evidence via factory
|
|
59
|
+
// Factory handles: validation, encoding, hashing, signature generation
|
|
60
|
+
const creationResult = this.evidenceFactory.create(scent, scent.threat, this.config.maxPayloadSize);
|
|
61
|
+
if (!creationResult.ok) {
|
|
62
|
+
// Check if it's a payload size error
|
|
63
|
+
if (creationResult.error.code === 'AGENT_PAYLOAD_TOO_LARGE') {
|
|
64
|
+
this.stats.validationFailures++;
|
|
65
|
+
return {
|
|
66
|
+
status: 'payload_too_large',
|
|
67
|
+
limit: this.config.maxPayloadSize,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Other errors
|
|
71
|
+
this.stats.errorCount++;
|
|
72
|
+
return {
|
|
73
|
+
status: 'error',
|
|
74
|
+
error: creationResult.error,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const { evidence, signature } = creationResult;
|
|
78
|
+
// Step 4: Check for duplicate in quarantine
|
|
79
|
+
if (this.quarantine.has(signature)) {
|
|
80
|
+
// Duplicate - already have evidence for this signature
|
|
81
|
+
// Evidence was created but not needed, dispose it
|
|
82
|
+
evidence.neutralize('');
|
|
83
|
+
this.stats.ignoredCount++;
|
|
84
|
+
return {
|
|
85
|
+
status: 'ignored',
|
|
86
|
+
signature,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Step 5: Insert into quarantine
|
|
90
|
+
const insertResult = this.quarantine.insert(evidence);
|
|
91
|
+
if (insertResult.status === 'duplicate') {
|
|
92
|
+
// Race condition: became duplicate between has() and insert()
|
|
93
|
+
// Evidence already disposed by duplicate detection
|
|
94
|
+
this.stats.ignoredCount++;
|
|
95
|
+
return {
|
|
96
|
+
status: 'ignored',
|
|
97
|
+
signature,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Success
|
|
101
|
+
this.stats.quarantinedCount++;
|
|
102
|
+
return {
|
|
103
|
+
status: 'quarantined',
|
|
104
|
+
handle: evidence,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
this.stats.errorCount++;
|
|
109
|
+
const tracehoundError = {
|
|
110
|
+
state: 'agent',
|
|
111
|
+
code: 'INTERCEPT_FAILED',
|
|
112
|
+
message: error instanceof Error ? error.message : 'Unknown error during intercept',
|
|
113
|
+
context: { scentId: scent.id },
|
|
114
|
+
recoverable: false,
|
|
115
|
+
};
|
|
116
|
+
return {
|
|
117
|
+
status: 'error',
|
|
118
|
+
error: tracehoundError,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get current agent statistics.
|
|
124
|
+
*/
|
|
125
|
+
getStats() {
|
|
126
|
+
return { ...this.stats };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create an agent instance.
|
|
131
|
+
*
|
|
132
|
+
* @param config - Agent configuration
|
|
133
|
+
* @param quarantine - Quarantine instance
|
|
134
|
+
* @param rateLimiter - Rate limiter instance
|
|
135
|
+
* @param evidenceFactory - Evidence factory instance
|
|
136
|
+
* @returns Agent instance
|
|
137
|
+
*/
|
|
138
|
+
export function createAgent(config, quarantine, rateLimiter, evidenceFactory) {
|
|
139
|
+
return new Agent(config, quarantine, rateLimiter, evidenceFactory);
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0DH;;GAEG;AACH,MAAM,OAAO,KAAK;IAYG;IACA;IACA;IACA;IAdF,KAAK,GAAe;QACnC,eAAe,EAAE,CAAC;QAClB,UAAU,EAAE,CAAC;QACb,gBAAgB,EAAE,CAAC;QACnB,kBAAkB,EAAE,CAAC;QACrB,YAAY,EAAE,CAAC;QACf,gBAAgB,EAAE,CAAC;QACnB,UAAU,EAAE,CAAC;KACd,CAAA;IAED,YACmB,MAAmB,EACnB,UAAsB,EACtB,WAAyB,EACzB,eAAiC;QAHjC,WAAM,GAAN,MAAM,CAAa;QACnB,eAAU,GAAV,UAAU,CAAY;QACtB,gBAAW,GAAX,WAAW,CAAc;QACzB,oBAAe,GAAf,eAAe,CAAkB;QAElD,kBAAkB;QAClB,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;QACpD,CAAC;IACH,CAAC;IAED,SAAS,CAAC,KAAY;QACpB,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAA;QAE5B,IAAI,CAAC;YACH,2BAA2B;YAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACvD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAA;gBAC7B,OAAO;oBACL,MAAM,EAAE,cAAc;oBACtB,UAAU,EAAG,UAA2D,CAAC,UAAU;iBACpF,CAAA;YACH,CAAC;YAED,kCAAkC;YAClC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBAClB,2BAA2B;gBAC3B,sDAAsD;gBACtD,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;gBACvB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;YAC5B,CAAC;YAED,sCAAsC;YACtC,uEAAuE;YACvE,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAChD,KAAK,EACL,KAAK,CAAC,MAAM,EACZ,IAAI,CAAC,MAAM,CAAC,cAAc,CAC3B,CAAA;YAED,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC;gBACvB,qCAAqC;gBACrC,IAAI,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,yBAAyB,EAAE,CAAC;oBAC5D,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAA;oBAC/B,OAAO;wBACL,MAAM,EAAE,mBAAmB;wBAC3B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc;qBAClC,CAAA;gBACH,CAAC;gBAED,eAAe;gBACf,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;gBACvB,OAAO;oBACL,MAAM,EAAE,OAAO;oBACf,KAAK,EAAE,cAAc,CAAC,KAAK;iBAC5B,CAAA;YACH,CAAC;YAED,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,cAAc,CAAA;YAE9C,4CAA4C;YAC5C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACnC,uDAAuD;gBACvD,kDAAkD;gBAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;gBACvB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAA;gBACzB,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,SAAS;iBACV,CAAA;YACH,CAAC;YAED,iCAAiC;YACjC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YAErD,IAAI,YAAY,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACxC,8DAA8D;gBAC9D,mDAAmD;gBACnD,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAA;gBACzB,OAAO;oBACL,MAAM,EAAE,SAAS;oBACjB,SAAS;iBACV,CAAA;YACH,CAAC;YAED,UAAU;YACV,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAA;YAC7B,OAAO;gBACL,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,QAAQ;aACjB,CAAA;QACH,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;YAEvB,MAAM,eAAe,GAAoB;gBACvC,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC;gBAClF,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE;gBAC9B,WAAW,EAAE,KAAK;aACnB,CAAA;YAED,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,KAAK,EAAE,eAAe;aACvB,CAAA;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA;IAC1B,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,MAAmB,EACnB,UAAsB,EACtB,WAAyB,EACzB,eAAiC;IAEjC,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,CAAC,CAAA;AACpE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuditChain - cryptographic hash chain for evidence integrity.
|
|
3
|
+
*/
|
|
4
|
+
import type { AuditRecord, IAuditChain } from '../types/audit.js';
|
|
5
|
+
import type { EvacuateRecord, NeutralizationRecord } from '../types/evidence.js';
|
|
6
|
+
/** Genesis hash (anchor for chain) */
|
|
7
|
+
export declare const GENESIS_HASH: string;
|
|
8
|
+
/**
|
|
9
|
+
* Cryptographic hash chain for audit integrity.
|
|
10
|
+
* Each record contains hash of previous record.
|
|
11
|
+
* Tampering with any record breaks the chain.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuditChain implements IAuditChain {
|
|
14
|
+
private records;
|
|
15
|
+
private _lastHash;
|
|
16
|
+
get lastHash(): string;
|
|
17
|
+
get length(): number;
|
|
18
|
+
/**
|
|
19
|
+
* Append a record to the chain.
|
|
20
|
+
*/
|
|
21
|
+
append(record: NeutralizationRecord | EvacuateRecord): void;
|
|
22
|
+
/**
|
|
23
|
+
* Verify chain integrity.
|
|
24
|
+
*/
|
|
25
|
+
verify(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Export all records (defensive copy).
|
|
28
|
+
*/
|
|
29
|
+
export(): AuditRecord[];
|
|
30
|
+
/**
|
|
31
|
+
* Compute hash for a new record.
|
|
32
|
+
*/
|
|
33
|
+
private computeHash;
|
|
34
|
+
/**
|
|
35
|
+
* Recompute hash for verification.
|
|
36
|
+
*/
|
|
37
|
+
private recomputeHash;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=audit-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-chain.d.ts","sourceRoot":"","sources":["../../src/core/audit-chain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEhF,sCAAsC;AACtC,eAAO,MAAM,YAAY,QAAiB,CAAA;AAE1C;;;;GAIG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC5C,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,SAAS,CAAuB;IAExC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,GAAG,IAAI;IAgB3D;;OAEG;IACH,MAAM,IAAI,OAAO;IAqBjB;;OAEG;IACH,MAAM,IAAI,WAAW,EAAE;IAIvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,aAAa;CAStB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AuditChain - cryptographic hash chain for evidence integrity.
|
|
3
|
+
*/
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
/** Genesis hash (anchor for chain) */
|
|
6
|
+
export const GENESIS_HASH = '0'.repeat(64);
|
|
7
|
+
/**
|
|
8
|
+
* Cryptographic hash chain for audit integrity.
|
|
9
|
+
* Each record contains hash of previous record.
|
|
10
|
+
* Tampering with any record breaks the chain.
|
|
11
|
+
*/
|
|
12
|
+
export class AuditChain {
|
|
13
|
+
records = [];
|
|
14
|
+
_lastHash = GENESIS_HASH;
|
|
15
|
+
get lastHash() {
|
|
16
|
+
return this._lastHash;
|
|
17
|
+
}
|
|
18
|
+
get length() {
|
|
19
|
+
return this.records.length;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Append a record to the chain.
|
|
23
|
+
*/
|
|
24
|
+
append(record) {
|
|
25
|
+
const hash = this.computeHash(record, this._lastHash);
|
|
26
|
+
const auditRecord = {
|
|
27
|
+
id: record.id,
|
|
28
|
+
type: 'status' in record ? 'neutralization' : 'evacuation',
|
|
29
|
+
signature: record.signature,
|
|
30
|
+
timestamp: record.timestamp,
|
|
31
|
+
previousHash: this._lastHash,
|
|
32
|
+
hash,
|
|
33
|
+
};
|
|
34
|
+
this.records.push(auditRecord);
|
|
35
|
+
this._lastHash = hash;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Verify chain integrity.
|
|
39
|
+
*/
|
|
40
|
+
verify() {
|
|
41
|
+
let expectedPreviousHash = GENESIS_HASH;
|
|
42
|
+
for (const record of this.records) {
|
|
43
|
+
// Check chain continuity
|
|
44
|
+
if (record.previousHash !== expectedPreviousHash) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Check hash integrity
|
|
48
|
+
const computedHash = this.recomputeHash(record);
|
|
49
|
+
if (computedHash !== record.hash) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
expectedPreviousHash = record.hash;
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Export all records (defensive copy).
|
|
58
|
+
*/
|
|
59
|
+
export() {
|
|
60
|
+
return [...this.records];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Compute hash for a new record.
|
|
64
|
+
*/
|
|
65
|
+
computeHash(record, previousHash) {
|
|
66
|
+
const data = JSON.stringify({
|
|
67
|
+
id: record.id,
|
|
68
|
+
signature: record.signature,
|
|
69
|
+
timestamp: record.timestamp,
|
|
70
|
+
previousHash,
|
|
71
|
+
});
|
|
72
|
+
return createHash('sha256').update(data).digest('hex');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Recompute hash for verification.
|
|
76
|
+
*/
|
|
77
|
+
recomputeHash(record) {
|
|
78
|
+
const data = JSON.stringify({
|
|
79
|
+
id: record.id,
|
|
80
|
+
signature: record.signature,
|
|
81
|
+
timestamp: record.timestamp,
|
|
82
|
+
previousHash: record.previousHash,
|
|
83
|
+
});
|
|
84
|
+
return createHash('sha256').update(data).digest('hex');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=audit-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-chain.js","sourceRoot":"","sources":["../../src/core/audit-chain.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,sCAAsC;AACtC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAE1C;;;;GAIG;AACH,MAAM,OAAO,UAAU;IACb,OAAO,GAAkB,EAAE,CAAA;IAC3B,SAAS,GAAW,YAAY,CAAA;IAExC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;IAC5B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAA6C;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAErD,MAAM,WAAW,GAAgB;YAC/B,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,IAAI,EAAE,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY;YAC1D,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,YAAY,EAAE,IAAI,CAAC,SAAS;YAC5B,IAAI;SACL,CAAA;QAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,oBAAoB,GAAG,YAAY,CAAA;QAEvC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,yBAAyB;YACzB,IAAI,MAAM,CAAC,YAAY,KAAK,oBAAoB,EAAE,CAAC;gBACjD,OAAO,KAAK,CAAA;YACd,CAAC;YAED,uBAAuB;YACvB,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;YAC/C,IAAI,YAAY,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjC,OAAO,KAAK,CAAA;YACd,CAAC;YAED,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAA;QACpC,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,MAA6C,EAAE,YAAoB;QACrF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,YAAY;SACb,CAAC,CAAA;QACF,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACxD,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,MAAmB;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAA;QACF,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACxD,CAAC;CACF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cold Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Fire-and-forget interface for archiving evidence to external storage.
|
|
5
|
+
* Used by Quarantine.evacuate() for long-term forensic storage.
|
|
6
|
+
*
|
|
7
|
+
* RFC-0000 INVARIANTS:
|
|
8
|
+
* - write() is fire-and-forget (no blocking hot-path)
|
|
9
|
+
* - Adapter errors are logged, not thrown
|
|
10
|
+
* - Payload must be encoded with encodeWithIntegrity() before write
|
|
11
|
+
*/
|
|
12
|
+
import type { EncodedPayload } from '../utils/binary-codec.js';
|
|
13
|
+
/**
|
|
14
|
+
* Cold storage write result.
|
|
15
|
+
*/
|
|
16
|
+
export interface ColdStorageWriteResult {
|
|
17
|
+
/** Whether write succeeded */
|
|
18
|
+
success: boolean;
|
|
19
|
+
/** Storage-specific ID (e.g., S3 key, URL) */
|
|
20
|
+
id?: string;
|
|
21
|
+
/** Error message if failed */
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Cold storage read result.
|
|
26
|
+
*/
|
|
27
|
+
export interface ColdStorageReadResult {
|
|
28
|
+
/** Whether read succeeded */
|
|
29
|
+
success: boolean;
|
|
30
|
+
/** Encoded payload if found */
|
|
31
|
+
payload?: EncodedPayload;
|
|
32
|
+
/** Error message if failed */
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Cold Storage Adapter interface.
|
|
37
|
+
*
|
|
38
|
+
* Implementations: MemoryColdStorage (testing), S3Adapter, R2Adapter, etc.
|
|
39
|
+
*/
|
|
40
|
+
export interface IColdStorageAdapter {
|
|
41
|
+
/**
|
|
42
|
+
* Write encoded evidence to cold storage.
|
|
43
|
+
* Fire-and-forget semantics - caller does not wait.
|
|
44
|
+
*
|
|
45
|
+
* @param id - Unique evidence ID (signature)
|
|
46
|
+
* @param payload - Encoded and hashed payload
|
|
47
|
+
*/
|
|
48
|
+
write(id: string, payload: EncodedPayload): Promise<ColdStorageWriteResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Read evidence from cold storage.
|
|
51
|
+
* Used for forensics/evacuation only.
|
|
52
|
+
*
|
|
53
|
+
* @param id - Evidence ID to retrieve
|
|
54
|
+
*/
|
|
55
|
+
read(id: string): Promise<ColdStorageReadResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Delete evidence from cold storage.
|
|
58
|
+
* Used for policy-based cleanup.
|
|
59
|
+
*
|
|
60
|
+
* @param id - Evidence ID to delete
|
|
61
|
+
*/
|
|
62
|
+
delete(id: string): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Check if storage is available.
|
|
65
|
+
*/
|
|
66
|
+
isAvailable(): Promise<boolean>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* In-memory cold storage for testing.
|
|
70
|
+
* NOT for production use.
|
|
71
|
+
*/
|
|
72
|
+
export declare class MemoryColdStorage implements IColdStorageAdapter {
|
|
73
|
+
private readonly storage;
|
|
74
|
+
write(id: string, payload: EncodedPayload): Promise<ColdStorageWriteResult>;
|
|
75
|
+
read(id: string): Promise<ColdStorageReadResult>;
|
|
76
|
+
delete(id: string): Promise<boolean>;
|
|
77
|
+
isAvailable(): Promise<boolean>;
|
|
78
|
+
/** Get storage size (testing helper) */
|
|
79
|
+
get size(): number;
|
|
80
|
+
/** Clear all storage (testing helper) */
|
|
81
|
+
clear(): void;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create an in-memory cold storage adapter for testing.
|
|
85
|
+
*/
|
|
86
|
+
export declare function createMemoryColdStorage(): IColdStorageAdapter;
|
|
87
|
+
//# sourceMappingURL=cold-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cold-storage.d.ts","sourceRoot":"","sources":["../../src/core/cold-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6BAA6B;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAE3E;;;;;OAKG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAEhD;;;;;OAKG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAEpC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;CAChC;AAMD;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,mBAAmB;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAEtD,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAK3E,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQhD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC,wCAAwC;IACxC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,yCAAyC;IACzC,KAAK,IAAI,IAAI;CAGd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,mBAAmB,CAE7D"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cold Storage Adapter
|
|
3
|
+
*
|
|
4
|
+
* Fire-and-forget interface for archiving evidence to external storage.
|
|
5
|
+
* Used by Quarantine.evacuate() for long-term forensic storage.
|
|
6
|
+
*
|
|
7
|
+
* RFC-0000 INVARIANTS:
|
|
8
|
+
* - write() is fire-and-forget (no blocking hot-path)
|
|
9
|
+
* - Adapter errors are logged, not thrown
|
|
10
|
+
* - Payload must be encoded with encodeWithIntegrity() before write
|
|
11
|
+
*/
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
// In-Memory Implementation (Testing)
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* In-memory cold storage for testing.
|
|
17
|
+
* NOT for production use.
|
|
18
|
+
*/
|
|
19
|
+
export class MemoryColdStorage {
|
|
20
|
+
storage = new Map();
|
|
21
|
+
async write(id, payload) {
|
|
22
|
+
this.storage.set(id, payload);
|
|
23
|
+
return { success: true, id };
|
|
24
|
+
}
|
|
25
|
+
async read(id) {
|
|
26
|
+
const payload = this.storage.get(id);
|
|
27
|
+
if (payload) {
|
|
28
|
+
return { success: true, payload };
|
|
29
|
+
}
|
|
30
|
+
return { success: false, error: 'Not found' };
|
|
31
|
+
}
|
|
32
|
+
async delete(id) {
|
|
33
|
+
return this.storage.delete(id);
|
|
34
|
+
}
|
|
35
|
+
async isAvailable() {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
/** Get storage size (testing helper) */
|
|
39
|
+
get size() {
|
|
40
|
+
return this.storage.size;
|
|
41
|
+
}
|
|
42
|
+
/** Clear all storage (testing helper) */
|
|
43
|
+
clear() {
|
|
44
|
+
this.storage.clear();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create an in-memory cold storage adapter for testing.
|
|
49
|
+
*/
|
|
50
|
+
export function createMemoryColdStorage() {
|
|
51
|
+
return new MemoryColdStorage();
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=cold-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cold-storage.js","sourceRoot":"","sources":["../../src/core/cold-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiEH,gFAAgF;AAChF,qCAAqC;AACrC,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACX,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAA;IAE5D,KAAK,CAAC,KAAK,CAAC,EAAU,EAAE,OAAuB;QAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;QAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QACnC,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IAC/C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,IAAI,CAAA;IACb,CAAC;IAED,wCAAwC;IACxC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;IAC1B,CAAC;IAED,yCAAyC;IACzC,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,iBAAiB,EAAE,CAAA;AAChC,CAAC"}
|