@trenchwork/erosolar 1.1.36 → 1.1.38
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 +219 -170
- package/SECURITY.md +28 -6
- package/agents/engagement-delivery.rules.json +7 -0
- package/agents/variant-research.rules.json +7 -0
- package/dist/bin/erosolar.js +192 -85
- package/dist/bin/erosolar.js.map +1 -1
- package/dist/capabilities/_opsContext.d.ts +65 -1
- package/dist/capabilities/_opsContext.d.ts.map +1 -1
- package/dist/capabilities/_opsContext.js +43 -0
- package/dist/capabilities/_opsContext.js.map +1 -1
- package/dist/capabilities/heliaCapability.d.ts +15 -0
- package/dist/capabilities/heliaCapability.d.ts.map +1 -0
- package/dist/capabilities/heliaCapability.js +34 -0
- package/dist/capabilities/heliaCapability.js.map +1 -0
- package/dist/capabilities/index.d.ts +1 -0
- package/dist/capabilities/index.d.ts.map +1 -1
- package/dist/capabilities/index.js +1 -0
- package/dist/capabilities/index.js.map +1 -1
- package/dist/capabilities/llmRedteamCapability.d.ts.map +1 -1
- package/dist/capabilities/llmRedteamCapability.js +47 -0
- package/dist/capabilities/llmRedteamCapability.js.map +1 -1
- package/dist/core/artifactLog.d.ts +82 -0
- package/dist/core/artifactLog.d.ts.map +1 -0
- package/dist/core/artifactLog.js +224 -0
- package/dist/core/artifactLog.js.map +1 -0
- package/dist/core/artifactStore.d.ts +17 -0
- package/dist/core/artifactStore.d.ts.map +1 -1
- package/dist/core/artifactStore.js +22 -0
- package/dist/core/artifactStore.js.map +1 -1
- package/dist/core/cliTriggerHandlers.d.ts +15 -0
- package/dist/core/cliTriggerHandlers.d.ts.map +1 -0
- package/dist/core/cliTriggerHandlers.js +60 -0
- package/dist/core/cliTriggerHandlers.js.map +1 -0
- package/dist/core/hitl.d.ts +4 -1
- package/dist/core/hitl.d.ts.map +1 -1
- package/dist/core/hitl.js +60 -171
- package/dist/core/hitl.js.map +1 -1
- package/dist/core/portalPresence.d.ts +74 -0
- package/dist/core/portalPresence.d.ts.map +1 -0
- package/dist/core/portalPresence.js +187 -0
- package/dist/core/portalPresence.js.map +1 -0
- package/dist/core/updateChecker.d.ts.map +1 -1
- package/dist/core/updateChecker.js +8 -6
- package/dist/core/updateChecker.js.map +1 -1
- package/dist/headless/interactiveShell.js +23 -0
- package/dist/headless/interactiveShell.js.map +1 -1
- package/dist/plugins/tools/mcp/mcpClient.js +1 -1
- package/dist/plugins/tools/mcp/mcpClient.js.map +1 -1
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +2 -2
- package/dist/runtime/node.js.map +1 -1
- package/dist/runtime/phaseEmitter.d.ts +6 -0
- package/dist/runtime/phaseEmitter.d.ts.map +1 -1
- package/dist/runtime/phaseEmitter.js +0 -0
- package/dist/runtime/phaseEmitter.js.map +1 -1
- package/dist/tools/engagementTools.d.ts.map +1 -1
- package/dist/tools/engagementTools.js +73 -1
- package/dist/tools/engagementTools.js.map +1 -1
- package/dist/tools/heliaControl.d.ts +17 -0
- package/dist/tools/heliaControl.d.ts.map +1 -1
- package/dist/tools/heliaControl.js +108 -2
- package/dist/tools/heliaControl.js.map +1 -1
- package/dist/tools/heliaTools.d.ts +22 -0
- package/dist/tools/heliaTools.d.ts.map +1 -0
- package/dist/tools/heliaTools.js +125 -0
- package/dist/tools/heliaTools.js.map +1 -0
- package/dist/tools/interactionTools.d.ts.map +1 -1
- package/dist/tools/interactionTools.js +31 -15
- package/dist/tools/interactionTools.js.map +1 -1
- package/dist/tools/scheduleTools.d.ts.map +1 -1
- package/dist/tools/scheduleTools.js +5 -2
- package/dist/tools/scheduleTools.js.map +1 -1
- package/dist/tools/webTools.js +1 -1
- package/dist/tools/webTools.js.map +1 -1
- package/dist/ui/ink/AskUserMenu.d.ts +16 -0
- package/dist/ui/ink/AskUserMenu.d.ts.map +1 -0
- package/dist/ui/ink/AskUserMenu.js +85 -0
- package/dist/ui/ink/AskUserMenu.js.map +1 -0
- package/dist/ui/ink/HitlDecisionMenu.d.ts +23 -0
- package/dist/ui/ink/HitlDecisionMenu.d.ts.map +1 -0
- package/dist/ui/ink/HitlDecisionMenu.js +124 -0
- package/dist/ui/ink/HitlDecisionMenu.js.map +1 -0
- package/dist/ui/ink/oneShot.d.ts +33 -0
- package/dist/ui/ink/oneShot.d.ts.map +1 -0
- package/dist/ui/ink/oneShot.js +70 -0
- package/dist/ui/ink/oneShot.js.map +1 -0
- package/dist/utils/heliaClient.d.ts +23 -0
- package/dist/utils/heliaClient.d.ts.map +1 -0
- package/dist/utils/heliaClient.js +79 -0
- package/dist/utils/heliaClient.js.map +1 -0
- package/dist/utils/lambdaClient.d.ts.map +1 -1
- package/dist/utils/lambdaClient.js +9 -0
- package/dist/utils/lambdaClient.js.map +1 -1
- package/dist/utils/statusReporter.d.ts +13 -0
- package/dist/utils/statusReporter.d.ts.map +1 -1
- package/dist/utils/statusReporter.js +26 -0
- package/dist/utils/statusReporter.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append-only artifact transparency log.
|
|
3
|
+
*
|
|
4
|
+
* Every artifact registered in the artifact store fires a metadata
|
|
5
|
+
* row to Firestore at `artifact_log/{uid}/entries/{entryId}`. The log
|
|
6
|
+
* carries the sha256 + tags + size + timestamp + profile + cli
|
|
7
|
+
* version + operator uid/email — NEVER the artifact contents. If the
|
|
8
|
+
* artifact later surfaces in the wild, you can prove "this hash was
|
|
9
|
+
* produced at this time, under this profile, by this operator,
|
|
10
|
+
* tagged for this engagement."
|
|
11
|
+
*
|
|
12
|
+
* Threat model addressed:
|
|
13
|
+
*
|
|
14
|
+
* - Endpoint compromise / lost laptop. Even if `~/.erosolar/` is
|
|
15
|
+
* exfiltrated, the metadata trail is server-side and replicated
|
|
16
|
+
* out of the operator's control.
|
|
17
|
+
* - Accidental/sloppy delivery. Distinguishes "shipped through the
|
|
18
|
+
* sanctioned path" (logged) from "escaped" (not logged).
|
|
19
|
+
* - Provenance disputes. Backdating a leaked exploit becomes
|
|
20
|
+
* provably false against the Firestore server-timestamp.
|
|
21
|
+
*
|
|
22
|
+
* Threats NOT addressed (be honest):
|
|
23
|
+
*
|
|
24
|
+
* - Determined insider with operator rights can simply not register
|
|
25
|
+
* the artifact, or modify the CLI source to bypass this writer.
|
|
26
|
+
* The log makes good-faith use auditable; it doesn't stop a
|
|
27
|
+
* malicious operator who decides to bypass the tooling. That gap
|
|
28
|
+
* is what hardware co-sign / threshold signing would close, and
|
|
29
|
+
* is intentionally out of scope for the budget-startup baseline.
|
|
30
|
+
* - Once an artifact is decrypted in process memory, it's leakable.
|
|
31
|
+
* Encryption at rest with KMS-wrapped DEKs would close the
|
|
32
|
+
* "stolen laptop yields plaintext" gap; out of scope here.
|
|
33
|
+
*
|
|
34
|
+
* Failure mode: a Firestore call failure does NOT block the artifact
|
|
35
|
+
* write. The agent has to keep working when the operator is offline.
|
|
36
|
+
* Failed writes are queued at `~/.erosolar/artifact_log_pending/` and
|
|
37
|
+
* flushed on the next CLI boot via `flushPendingArtifactLog()`.
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the same pattern as `userApproval.ts:writeUsageLog` and
|
|
40
|
+
* `userApproval.ts:writeReviewerLog` — same Firestore REST surface,
|
|
41
|
+
* same append-only Firestore rule on the receiving end.
|
|
42
|
+
*/
|
|
43
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
44
|
+
import { homedir } from 'node:os';
|
|
45
|
+
import { join } from 'node:path';
|
|
46
|
+
import { FIREBASE_PROJECT_ID, getAuthStatus, getValidIdToken } from './auth.js';
|
|
47
|
+
import { logDebug } from '../utils/debugLogger.js';
|
|
48
|
+
const FIRESTORE_BASE = `https://firestore.googleapis.com/v1/projects/${FIREBASE_PROJECT_ID}/databases/(default)/documents`;
|
|
49
|
+
// Resolved at call time (not module load) so EROSOLAR_HOME / HOME
|
|
50
|
+
// overrides from tests + custom installs are honoured. Same pattern
|
|
51
|
+
// secretStore.ts uses for ~/.erosolar/secrets.json.
|
|
52
|
+
function pendingDir() {
|
|
53
|
+
const root = process.env['EROSOLAR_HOME']?.trim() || homedir();
|
|
54
|
+
return join(root, '.erosolar', 'artifact_log_pending');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Append one row to `artifact_log/{uid}/entries/{entryId}`. Best-effort:
|
|
58
|
+
* a Firestore failure (offline, expired token, rule denial) writes the
|
|
59
|
+
* entry to the pending queue and returns `{ ok: false, queued: true }`.
|
|
60
|
+
* Caller MUST NOT block on this — it's fire-and-forget by contract.
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* Test seam — when a tap is installed, every entry passed to
|
|
64
|
+
* `writeArtifactLog` is ALSO surfaced through it before the normal
|
|
65
|
+
* Firestore-or-queue routing runs. Production never installs a tap;
|
|
66
|
+
* tests use it to assert on the entry shape without caring whether
|
|
67
|
+
* the runtime took the Firestore path or the queue path. The tap
|
|
68
|
+
* cannot suppress or alter the real write — it observes only.
|
|
69
|
+
*/
|
|
70
|
+
let entryTap = null;
|
|
71
|
+
export function __setArtifactLogTap(fn) {
|
|
72
|
+
entryTap = fn;
|
|
73
|
+
}
|
|
74
|
+
export async function writeArtifactLog(entry) {
|
|
75
|
+
if (entryTap) {
|
|
76
|
+
try {
|
|
77
|
+
entryTap(entry);
|
|
78
|
+
}
|
|
79
|
+
catch { /* tap errors are observation-only */ }
|
|
80
|
+
}
|
|
81
|
+
const status = getAuthStatus();
|
|
82
|
+
if (!status.authenticated || !status.uid) {
|
|
83
|
+
queuePendingEntry(entry, 'not signed in at write time');
|
|
84
|
+
return { ok: false, queued: true, reason: 'not signed in' };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const idToken = await getValidIdToken();
|
|
88
|
+
const result = await postEntry(status.uid, status.email ?? '', entry, idToken);
|
|
89
|
+
if (!result.ok) {
|
|
90
|
+
queuePendingEntry(entry, result.reason ?? 'firestore error');
|
|
91
|
+
return { ok: false, queued: true, reason: result.reason };
|
|
92
|
+
}
|
|
93
|
+
return { ok: true };
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
97
|
+
queuePendingEntry(entry, reason);
|
|
98
|
+
return { ok: false, queued: true, reason };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function postEntry(uid, email, entry, idToken) {
|
|
102
|
+
const entryId = `${Date.now()}-${entry.sha256.slice(0, 12)}`;
|
|
103
|
+
const url = `${FIRESTORE_BASE}/artifact_log/${encodeURIComponent(uid)}/entries?documentId=${encodeURIComponent(entryId)}`;
|
|
104
|
+
const fields = {
|
|
105
|
+
uid: { stringValue: uid },
|
|
106
|
+
email: { stringValue: email },
|
|
107
|
+
sha256: { stringValue: entry.sha256 },
|
|
108
|
+
size: { integerValue: String(entry.size) },
|
|
109
|
+
clientCreatedAt: { timestampValue: entry.clientCreatedAt },
|
|
110
|
+
serverLoggedAt: { timestampValue: new Date().toISOString() },
|
|
111
|
+
};
|
|
112
|
+
if (entry.tags && entry.tags.length) {
|
|
113
|
+
fields['tags'] = {
|
|
114
|
+
arrayValue: { values: entry.tags.slice(0, 32).map((t) => ({ stringValue: t.slice(0, 64) })) },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (entry.source)
|
|
118
|
+
fields['source'] = { stringValue: entry.source.slice(0, 200) };
|
|
119
|
+
if (entry.description)
|
|
120
|
+
fields['description'] = { stringValue: entry.description.slice(0, 500) };
|
|
121
|
+
if (entry.profile)
|
|
122
|
+
fields['profile'] = { stringValue: entry.profile.slice(0, 64) };
|
|
123
|
+
if (entry.cliVersion)
|
|
124
|
+
fields['cliVersion'] = { stringValue: entry.cliVersion.slice(0, 32) };
|
|
125
|
+
if (entry.engagementId)
|
|
126
|
+
fields['engagementId'] = { stringValue: entry.engagementId.slice(0, 200) };
|
|
127
|
+
const res = await fetch(url, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: { Authorization: `Bearer ${idToken}`, 'Content-Type': 'application/json' },
|
|
130
|
+
body: JSON.stringify({ fields }),
|
|
131
|
+
});
|
|
132
|
+
if (!res.ok) {
|
|
133
|
+
const txt = await res.text().catch(() => '<no body>');
|
|
134
|
+
return { ok: false, reason: `Firestore ${res.status}: ${txt.slice(0, 200)}` };
|
|
135
|
+
}
|
|
136
|
+
logDebug(`[artifactLog] wrote ${entry.sha256.slice(0, 12)}…`);
|
|
137
|
+
return { ok: true };
|
|
138
|
+
}
|
|
139
|
+
function queuePendingEntry(entry, reason) {
|
|
140
|
+
try {
|
|
141
|
+
if (!existsSync(pendingDir()))
|
|
142
|
+
mkdirSync(pendingDir(), { recursive: true, mode: 0o700 });
|
|
143
|
+
const file = join(pendingDir(), `${Date.now()}-${entry.sha256.slice(0, 12)}.json`);
|
|
144
|
+
writeFileSync(file, JSON.stringify({ entry, queuedAt: new Date().toISOString(), reason }, null, 2), {
|
|
145
|
+
mode: 0o600,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
logDebug(`[artifactLog] failed to queue pending entry: ${err instanceof Error ? err.message : err}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Drain the pending queue at boot. Called once from the CLI bootstrap
|
|
154
|
+
* after `requireAuth()` succeeds. Each successful flush deletes the
|
|
155
|
+
* pending file; failures stay queued for the next boot. Returns
|
|
156
|
+
* `{ flushed, remaining }` for the optional caller log line.
|
|
157
|
+
*/
|
|
158
|
+
export async function flushPendingArtifactLog() {
|
|
159
|
+
if (!existsSync(pendingDir()))
|
|
160
|
+
return { flushed: 0, remaining: 0 };
|
|
161
|
+
const status = getAuthStatus();
|
|
162
|
+
if (!status.authenticated || !status.uid)
|
|
163
|
+
return { flushed: 0, remaining: 0 };
|
|
164
|
+
let files;
|
|
165
|
+
try {
|
|
166
|
+
files = readdirSync(pendingDir()).filter((f) => f.endsWith('.json'));
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return { flushed: 0, remaining: 0 };
|
|
170
|
+
}
|
|
171
|
+
if (!files.length)
|
|
172
|
+
return { flushed: 0, remaining: 0 };
|
|
173
|
+
let idToken;
|
|
174
|
+
try {
|
|
175
|
+
idToken = await getValidIdToken();
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return { flushed: 0, remaining: files.length };
|
|
179
|
+
}
|
|
180
|
+
let flushed = 0;
|
|
181
|
+
for (const file of files) {
|
|
182
|
+
const path = join(pendingDir(), file);
|
|
183
|
+
let payload = null;
|
|
184
|
+
try {
|
|
185
|
+
payload = JSON.parse(readFileSync(path, 'utf8'));
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
try {
|
|
189
|
+
unlinkSync(path);
|
|
190
|
+
}
|
|
191
|
+
catch { /* ignore */ }
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (!payload?.entry?.sha256) {
|
|
195
|
+
try {
|
|
196
|
+
unlinkSync(path);
|
|
197
|
+
}
|
|
198
|
+
catch { /* ignore */ }
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const result = await postEntry(status.uid, status.email ?? '', payload.entry, idToken);
|
|
202
|
+
if (result.ok) {
|
|
203
|
+
try {
|
|
204
|
+
unlinkSync(path);
|
|
205
|
+
}
|
|
206
|
+
catch { /* ignore */ }
|
|
207
|
+
flushed++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const remaining = (() => {
|
|
211
|
+
try {
|
|
212
|
+
return readdirSync(pendingDir()).filter((f) => f.endsWith('.json')).length;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
return 0;
|
|
216
|
+
}
|
|
217
|
+
})();
|
|
218
|
+
return { flushed, remaining };
|
|
219
|
+
}
|
|
220
|
+
/** Test seam — overrideable so unit tests can point at a temp dir. */
|
|
221
|
+
export function getPendingDir() {
|
|
222
|
+
return pendingDir();
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=artifactLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifactLog.js","sourceRoot":"","sources":["../../src/core/artifactLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,22 @@ export interface ArtifactPutResult {
|
|
|
12
12
|
size: number;
|
|
13
13
|
summary: string;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Context bound by the CLI bootstrap so every artifact write carries
|
|
17
|
+
* the active profile + CLI version + engagement id into the
|
|
18
|
+
* transparency log. Kept module-local so the ArtifactStore class
|
|
19
|
+
* itself stays decoupled from auth/profile state.
|
|
20
|
+
*/
|
|
21
|
+
interface ArtifactLogContext {
|
|
22
|
+
profile?: string;
|
|
23
|
+
cliVersion?: string;
|
|
24
|
+
engagementId?: string;
|
|
25
|
+
/** Set to false to disable the transparency log (tests, --self-test). */
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function setArtifactLogContext(ctx: Partial<Omit<ArtifactLogContext, 'enabled'>> & {
|
|
29
|
+
enabled?: boolean;
|
|
30
|
+
}): void;
|
|
15
31
|
export declare class ArtifactStore {
|
|
16
32
|
private readonly root;
|
|
17
33
|
private indexCache;
|
|
@@ -32,4 +48,5 @@ export declare class ArtifactStore {
|
|
|
32
48
|
private buildSummary;
|
|
33
49
|
}
|
|
34
50
|
export declare function getSharedArtifactStore(): ArtifactStore;
|
|
51
|
+
export {};
|
|
35
52
|
//# sourceMappingURL=artifactStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifactStore.d.ts","sourceRoot":"","sources":["../../src/core/artifactStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifactStore.d.ts","sourceRoot":"","sources":["../../src/core/artifactStore.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAErH;AAKD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAiD;gBAEvD,IAAI,GAAE,MAAqB;IAOvC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,iBAAiB;IAsCtF,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAMvB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAI7B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAIzC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB,EAAE;IAOpE,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,YAAY;CAQrB;AAID,wBAAgB,sBAAsB,IAAI,aAAa,CAGtD"}
|
|
@@ -2,6 +2,11 @@ import { createHash } from 'node:crypto';
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
|
+
import { writeArtifactLog } from './artifactLog.js';
|
|
6
|
+
let logContext = { enabled: true };
|
|
7
|
+
export function setArtifactLogContext(ctx) {
|
|
8
|
+
logContext = { ...logContext, ...ctx };
|
|
9
|
+
}
|
|
5
10
|
const DEFAULT_ROOT = join(homedir(), '.erosolar', 'artifacts');
|
|
6
11
|
const INDEX_FILE = 'index.json';
|
|
7
12
|
export class ArtifactStore {
|
|
@@ -35,6 +40,23 @@ export class ArtifactStore {
|
|
|
35
40
|
if (meta.description !== undefined)
|
|
36
41
|
record.description = meta.description;
|
|
37
42
|
this.writeMeta(record);
|
|
43
|
+
if (logContext.enabled) {
|
|
44
|
+
// Fire-and-forget transparency log. Failures queue locally in
|
|
45
|
+
// ~/.erosolar/artifact_log_pending/ and flush on next boot.
|
|
46
|
+
// The artifact write completes regardless of the log outcome —
|
|
47
|
+
// a Firestore outage must not break offsec workflow continuity.
|
|
48
|
+
void writeArtifactLog({
|
|
49
|
+
sha256: id,
|
|
50
|
+
size: buf.length,
|
|
51
|
+
clientCreatedAt: record.createdAt,
|
|
52
|
+
...(record.tags ? { tags: record.tags } : {}),
|
|
53
|
+
...(record.source ? { source: record.source } : {}),
|
|
54
|
+
...(record.description ? { description: record.description } : {}),
|
|
55
|
+
...(logContext.profile ? { profile: logContext.profile } : {}),
|
|
56
|
+
...(logContext.cliVersion ? { cliVersion: logContext.cliVersion } : {}),
|
|
57
|
+
...(logContext.engagementId ? { engagementId: logContext.engagementId } : {}),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
38
60
|
return { id, size: buf.length, summary: this.buildSummary(record, buf) };
|
|
39
61
|
}
|
|
40
62
|
get(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifactStore.js","sourceRoot":"","sources":["../../src/core/artifactStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"artifactStore.js","sourceRoot":"","sources":["../../src/core/artifactStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch table for portal-queued cli_triggers.
|
|
3
|
+
*
|
|
4
|
+
* Each kind maps to a handler that runs the work and returns a
|
|
5
|
+
* structured outcome. The consumer in portalPresence.ts records the
|
|
6
|
+
* outcome via `cliTriggerComplete` so the portal can surface "done /
|
|
7
|
+
* failed / cancelled" in its trigger ledger.
|
|
8
|
+
*/
|
|
9
|
+
import type { PendingTrigger } from './portalPresence.js';
|
|
10
|
+
export interface TriggerOutcome {
|
|
11
|
+
status: 'done' | 'failed';
|
|
12
|
+
result?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export declare function handleCliTrigger(t: PendingTrigger): Promise<TriggerOutcome>;
|
|
15
|
+
//# sourceMappingURL=cliTriggerHandlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliTriggerHandlers.d.ts","sourceRoot":"","sources":["../../src/core/cliTriggerHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAUjF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch table for portal-queued cli_triggers.
|
|
3
|
+
*
|
|
4
|
+
* Each kind maps to a handler that runs the work and returns a
|
|
5
|
+
* structured outcome. The consumer in portalPresence.ts records the
|
|
6
|
+
* outcome via `cliTriggerComplete` so the portal can surface "done /
|
|
7
|
+
* failed / cancelled" in its trigger ledger.
|
|
8
|
+
*/
|
|
9
|
+
import { callLambda } from '../utils/lambdaClient.js';
|
|
10
|
+
export async function handleCliTrigger(t) {
|
|
11
|
+
switch (t.kind) {
|
|
12
|
+
case 'exploit-retest':
|
|
13
|
+
return await handleExploitRetest(t);
|
|
14
|
+
default:
|
|
15
|
+
// Unknown trigger kinds shouldn't crash the consumer — record a
|
|
16
|
+
// failed status with a reason so the portal can show "no
|
|
17
|
+
// handler" instead of leaving the row spinning.
|
|
18
|
+
return { status: 'failed', result: { error: `no handler for kind=${t.kind}` } };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Re-runs the original tool against the original target and writes a
|
|
23
|
+
* fresh exploit run with the appropriate verdict. The portal's
|
|
24
|
+
* canonical exploit doc carries enough metadata (targetHost,
|
|
25
|
+
* vulnClass, payloadSignature, tool) for us to reconstruct an upsert
|
|
26
|
+
* call without needing the trigger row to repeat all of it.
|
|
27
|
+
*
|
|
28
|
+
* For now we issue the upsert with verdict='inconclusive' — the real
|
|
29
|
+
* retest path that actually fires the original tool wires up under a
|
|
30
|
+
* dedicated capability later. Even an inconclusive run bumps
|
|
31
|
+
* `lastVerifiedAt` so the operator can see the portal "Retest now"
|
|
32
|
+
* button actually did something.
|
|
33
|
+
*/
|
|
34
|
+
async function handleExploitRetest(t) {
|
|
35
|
+
const args = t.args ?? {};
|
|
36
|
+
const exploitId = typeof args.exploitId === 'string' ? args.exploitId : '';
|
|
37
|
+
if (!exploitId) {
|
|
38
|
+
return { status: 'failed', result: { error: 'exploitId missing in trigger args' } };
|
|
39
|
+
}
|
|
40
|
+
const r = await callLambda('cliExploitUpsert', {
|
|
41
|
+
exploitId,
|
|
42
|
+
identity: {
|
|
43
|
+
targetHost: typeof args.target === 'string' ? args.target : 'unknown',
|
|
44
|
+
vulnClass: 'retest-pending',
|
|
45
|
+
payloadSignature: typeof args.payload === 'string' ? args.payload : '',
|
|
46
|
+
},
|
|
47
|
+
classification: { noteOneApplies: true },
|
|
48
|
+
run: {
|
|
49
|
+
verdict: 'inconclusive',
|
|
50
|
+
tool: typeof t.tool === 'string' ? t.tool : 'portal-retest',
|
|
51
|
+
cmd: null,
|
|
52
|
+
evidenceDelta: { source: 'portal-retest-trigger', triggerId: t.id },
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
if (!r.ok) {
|
|
56
|
+
return { status: 'failed', result: { error: r.error || 'cliExploitUpsert failed' } };
|
|
57
|
+
}
|
|
58
|
+
return { status: 'done', result: { exploitId, status: r.result?.status ?? null } };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=cliTriggerHandlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cliTriggerHandlers.js","sourceRoot":"","sources":["../../src/core/cliTriggerHandlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAOtD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,CAAiB;IACtD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,gBAAgB;YACnB,OAAO,MAAM,mBAAmB,CAAC,CAAC,CAAC,CAAC;QACtC;YACE,gEAAgE;YAChE,yDAAyD;YACzD,gDAAgD;YAChD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,uBAAuB,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IACpF,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,UAAU,mBAAmB,CAAC,CAAiB;IAClD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAC1B,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,mCAAmC,EAAE,EAAE,CAAC;IACtF,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,UAAU,CACxB,kBAAkB,EAClB;QACE,SAAS;QACT,QAAQ,EAAE;YACR,UAAU,EAAE,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACrE,SAAS,EAAE,gBAAgB;YAC3B,gBAAgB,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;SACvE;QACD,cAAc,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;QACxC,GAAG,EAAE;YACH,OAAO,EAAE,cAAc;YACvB,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe;YAC3D,GAAG,EAAE,IAAI;YACT,aAAa,EAAE,EAAE,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;SACpE;KACF,CACF,CAAC;IACF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACV,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,yBAAyB,EAAE,EAAE,CAAC;IACvF,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;AACrF,CAAC"}
|
package/dist/core/hitl.d.ts
CHANGED
|
@@ -71,7 +71,10 @@ export declare class HITLSystem {
|
|
|
71
71
|
*/
|
|
72
72
|
requestDecision(request: DecisionRequest): Promise<string>;
|
|
73
73
|
/**
|
|
74
|
-
* Present decision
|
|
74
|
+
* Present the decision via the Ink-rendered HitlDecisionMenu.
|
|
75
|
+
* Replaces the prior chalk + raw-mode arrow-key implementation;
|
|
76
|
+
* Ink owns the alternate-screen frame, the keypress loop, and the
|
|
77
|
+
* custom-input flow.
|
|
75
78
|
*/
|
|
76
79
|
private promptUserForDecision;
|
|
77
80
|
private cleanupReadline;
|
package/dist/core/hitl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hitl.d.ts","sourceRoot":"","sources":["../../src/core/hitl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,mBAAqB,CAAC;AAK7C,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;CAC3C;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,EAAE,CAAC,CAAqB;gBAEpB,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;IASxC;;;OAGG;IACG,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAoChE
|
|
1
|
+
{"version":3,"file":"hitl.d.ts","sourceRoot":"","sources":["../../src/core/hitl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,mBAAqB,CAAC;AAK7C,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;CAC3C;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,EAAE,CAAC,CAAqB;gBAEpB,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;IASxC;;;OAGG;IACG,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAoChE;;;;;OAKG;YACW,qBAAqB;IA0EnC,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,cAAc;IAgBtB;;OAEG;IACH,UAAU,IAAI,gBAAgB,EAAE;IAIhC;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI;CAGhD;AAKD;;GAEG;AACH,wBAAgB,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAUhE;AAED;;GAEG;AACH,eAAO,MAAM,IAAI;IACf;;OAEG;oBACmB,MAAM,eAAe,MAAM,YAAW,MAAM,eAAmB,OAAO,GAAU,OAAO,CAAC,OAAO,CAAC;IA6BtH;;OAEG;wBACuB,MAAM,eAAe,MAAM,WAAW,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC,YAAW,MAAM,oBAAyB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBzL;;OAEG;2BAC0B,MAAM,mBAAmB,MAAM,oBAAoB,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAQ1G,CAAC"}
|