@jungjaehoon/mama-os 0.21.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +12 -4
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +76 -11
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
- package/dist/agent/code-act/host-bridge.js +74 -0
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/codex-mcp-process.d.ts +1 -0
- package/dist/agent/codex-mcp-process.d.ts.map +1 -1
- package/dist/agent/codex-mcp-process.js +3 -2
- package/dist/agent/codex-mcp-process.js.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +16 -1
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +148 -2
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +6 -1
- package/dist/agent/model-runner.d.ts +8 -0
- package/dist/agent/model-runner.d.ts.map +1 -1
- package/dist/agent/model-runner.js.map +1 -1
- package/dist/agent/persistent-cli-adapter.d.ts +6 -0
- package/dist/agent/persistent-cli-adapter.d.ts.map +1 -1
- package/dist/agent/persistent-cli-adapter.js +21 -10
- package/dist/agent/persistent-cli-adapter.js.map +1 -1
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +32 -1
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +26 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +15 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/operator-handler.d.ts +2 -0
- package/dist/api/operator-handler.d.ts.map +1 -1
- package/dist/api/operator-handler.js +23 -5
- package/dist/api/operator-handler.js.map +1 -1
- package/dist/api/operator-summary.d.ts +3 -0
- package/dist/api/operator-summary.d.ts.map +1 -0
- package/dist/api/operator-summary.js +72 -0
- package/dist/api/operator-summary.js.map +1 -0
- package/dist/api/operator-tasks-handler.d.ts +7 -0
- package/dist/api/operator-tasks-handler.d.ts.map +1 -0
- package/dist/api/operator-tasks-handler.js +165 -0
- package/dist/api/operator-tasks-handler.js.map +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +62 -12
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts +2 -1
- package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
- package/dist/cli/runtime/agent-loop-init.js +16 -8
- package/dist/cli/runtime/agent-loop-init.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +196 -158
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-init.js +3 -1
- package/dist/cli/runtime/gateway-init.js.map +1 -1
- package/dist/cli/runtime/gateway-wiring.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-wiring.js +6 -0
- package/dist/cli/runtime/gateway-wiring.js.map +1 -1
- package/dist/cli/runtime/memory-agent-init.d.ts +2 -1
- package/dist/cli/runtime/memory-agent-init.d.ts.map +1 -1
- package/dist/cli/runtime/memory-agent-init.js +15 -3
- package/dist/cli/runtime/memory-agent-init.js.map +1 -1
- package/dist/connectors/framework/types.d.ts +8 -0
- package/dist/connectors/framework/types.d.ts.map +1 -1
- package/dist/connectors/slack/index.d.ts.map +1 -1
- package/dist/connectors/slack/index.js +3 -1
- package/dist/connectors/slack/index.js.map +1 -1
- package/dist/connectors/trello/index.d.ts.map +1 -1
- package/dist/connectors/trello/index.js +6 -2
- package/dist/connectors/trello/index.js.map +1 -1
- package/dist/db/agent-store.d.ts +5 -0
- package/dist/db/agent-store.d.ts.map +1 -1
- package/dist/db/agent-store.js +6 -3
- package/dist/db/agent-store.js.map +1 -1
- package/dist/db/migrations/agent-activity-tool-name.d.ts +8 -0
- package/dist/db/migrations/agent-activity-tool-name.d.ts.map +1 -0
- package/dist/db/migrations/agent-activity-tool-name.js +24 -0
- package/dist/db/migrations/agent-activity-tool-name.js.map +1 -0
- package/dist/envelope/run-guard.d.ts +10 -0
- package/dist/envelope/run-guard.d.ts.map +1 -0
- package/dist/envelope/run-guard.js +19 -0
- package/dist/envelope/run-guard.js.map +1 -0
- package/dist/gateways/telegram.d.ts +1 -0
- package/dist/gateways/telegram.d.ts.map +1 -1
- package/dist/gateways/telegram.js +25 -1
- package/dist/gateways/telegram.js.map +1 -1
- package/dist/memory/history-extractor.d.ts.map +1 -1
- package/dist/memory/history-extractor.js +10 -5
- package/dist/memory/history-extractor.js.map +1 -1
- package/dist/multi-agent/agent-event-bus.d.ts +4 -0
- package/dist/multi-agent/agent-event-bus.d.ts.map +1 -1
- package/dist/multi-agent/agent-event-bus.js.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.js +18 -5
- package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
- package/dist/multi-agent/runtime-process.d.ts +4 -2
- package/dist/multi-agent/runtime-process.d.ts.map +1 -1
- package/dist/multi-agent/runtime-process.js +7 -4
- package/dist/multi-agent/runtime-process.js.map +1 -1
- package/dist/observability/code-audit.d.ts +83 -0
- package/dist/observability/code-audit.d.ts.map +1 -0
- package/dist/observability/code-audit.js +334 -0
- package/dist/observability/code-audit.js.map +1 -0
- package/dist/operator/action-verifier.d.ts +50 -0
- package/dist/operator/action-verifier.d.ts.map +1 -0
- package/dist/operator/action-verifier.js +68 -0
- package/dist/operator/action-verifier.js.map +1 -0
- package/dist/operator/board-reconcile.d.ts +62 -0
- package/dist/operator/board-reconcile.d.ts.map +1 -0
- package/dist/operator/board-reconcile.js +160 -0
- package/dist/operator/board-reconcile.js.map +1 -0
- package/dist/operator/board-slot-instructions.d.ts +8 -0
- package/dist/operator/board-slot-instructions.d.ts.map +1 -1
- package/dist/operator/board-slot-instructions.js +25 -1
- package/dist/operator/board-slot-instructions.js.map +1 -1
- package/dist/operator/operator-trigger-loop.d.ts +15 -2
- package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
- package/dist/operator/operator-trigger-loop.js +40 -1
- package/dist/operator/operator-trigger-loop.js.map +1 -1
- package/dist/operator/report-scheduler.d.ts +23 -0
- package/dist/operator/report-scheduler.d.ts.map +1 -1
- package/dist/operator/report-scheduler.js +56 -8
- package/dist/operator/report-scheduler.js.map +1 -1
- package/dist/operator/situation-report.d.ts +5 -1
- package/dist/operator/situation-report.d.ts.map +1 -1
- package/dist/operator/situation-report.js +14 -3
- package/dist/operator/situation-report.js.map +1 -1
- package/dist/operator/task-ledger.d.ts +96 -0
- package/dist/operator/task-ledger.d.ts.map +1 -0
- package/dist/operator/task-ledger.js +277 -0
- package/dist/operator/task-ledger.js.map +1 -0
- package/dist/security/security-monitor.d.ts +12 -0
- package/dist/security/security-monitor.d.ts.map +1 -1
- package/dist/security/security-monitor.js +51 -14
- package/dist/security/security-monitor.js.map +1 -1
- package/dist/utils/untrusted-content.d.ts +18 -0
- package/dist/utils/untrusted-content.d.ts.map +1 -0
- package/dist/utils/untrusted-content.js +34 -0
- package/dist/utils/untrusted-content.js.map +1 -0
- package/package.json +1 -1
- package/public/ui/assets/index-CKOJQYXA.css +1 -0
- package/public/ui/assets/index-OSgiwL24.js +62 -0
- package/public/ui/index.html +3 -2
- package/public/ui/theme-init.js +20 -0
- package/public/viewer/viewer.html +12 -28
- package/public/ui/assets/index-BDsaQNGd.js +0 -62
- package/public/ui/assets/index-C4URnm_X.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"situation-report.d.ts","sourceRoot":"","sources":["../../src/operator/situation-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"situation-report.d.ts","sourceRoot":"","sources":["../../src/operator/situation-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,2BAA2B,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChD;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAqB3C,MAAM,WAAW,wBAAwB;IACvC;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;IAC9C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CACnD;AAKD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,eAAe,CAAoC;IAC3D,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,IAAI,CAA2B;gBAE3B,IAAI,GAAE,wBAA6B;IAI/C,0EAA0E;IAC1E,YAAY,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG,IAAI;IAgBlD,2FAA2F;IAC3F,UAAU,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;IAmBxC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAInC,uFAAuF;IACvF,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACG,MAAM,CACV,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAChC,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,OAAO,CAAC;IA2CnB,OAAO,CAAC,KAAK;IAQb,kGAAkG;IAClG,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;CAuHtC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SituationReporter = exports.OPERATOR_FULL_REPORT_TAG = void 0;
|
|
4
|
+
const untrusted_content_js_1 = require("../utils/untrusted-content.js");
|
|
4
5
|
/**
|
|
5
6
|
* Machine frame tag prepended to the FULL report prompt so the report-run wiring can tell a full
|
|
6
7
|
* report from a digest for tool-use auditing (report-run.ts). Kagemusha frames its scheduled full
|
|
@@ -126,6 +127,16 @@ class SituationReporter {
|
|
|
126
127
|
}
|
|
127
128
|
const fireLines = [...this.fireAgg.values()].map((f) => `- trigger "${f.kind}" [id: ${f.triggerId}] fired ${f.count}x on ${f.channelId}; recalled: ${[...f.topics].join(', ') || '(none)'}`);
|
|
128
129
|
const memoryLines = [...this.recalled.entries()].map(([topic, content]) => `- ${topic}: ${content}`);
|
|
130
|
+
// Resolve the gather lines only for the FULL report - the digest framing never renders
|
|
131
|
+
// them, so a zero-arg PROVIDER must not be invoked (it may do real gather work) just to
|
|
132
|
+
// build a digest prompt. The guard below stays anchored on the RESOLVED array: a zero-arg
|
|
133
|
+
// provider's `.length` is its arity (0), so guarding on the raw opts value would compile
|
|
134
|
+
// cleanly and silently drop the ENTIRE gather block on every production report.
|
|
135
|
+
const gatherLines = mode === 'full'
|
|
136
|
+
? typeof this.opts.selfGatherLines === 'function'
|
|
137
|
+
? this.opts.selfGatherLines()
|
|
138
|
+
: (this.opts.selfGatherLines ?? [])
|
|
139
|
+
: [];
|
|
129
140
|
// M2.1 posture: the full report is a DUTY report (always arrives - a quiet window is
|
|
130
141
|
// reported as quiet, the aliveness signal owners rely on); the digest defaults to briefing
|
|
131
142
|
// and keeps NOTHING only for pure noise.
|
|
@@ -140,7 +151,7 @@ class SituationReporter {
|
|
|
140
151
|
"Structure the report with these sections (render the headings in the owner's language;",
|
|
141
152
|
'omit a section only when it is truly empty):',
|
|
142
153
|
'1) Key situation 2) Action required 3) Decisions needed 4) Pipeline 5) Next actions',
|
|
143
|
-
...(
|
|
154
|
+
...(gatherLines.length > 0
|
|
144
155
|
? [
|
|
145
156
|
'',
|
|
146
157
|
'Before writing, ACTIVELY gather current context by CALLING your gateway tools.',
|
|
@@ -150,7 +161,7 @@ class SituationReporter {
|
|
|
150
161
|
'{"name": "kagemusha_tasks", "input": {"status": "in_progress"}}',
|
|
151
162
|
'```',
|
|
152
163
|
'Gather with these gateway tool calls:',
|
|
153
|
-
...
|
|
164
|
+
...gatherLines.map((line) => `- ${line}`),
|
|
154
165
|
'These gateway tools are NOT native or deferred CLI tools: ToolSearch cannot',
|
|
155
166
|
'load them and will find nothing. Invoke them ONLY as fenced tool_call JSON',
|
|
156
167
|
'blocks in your reply text - do not search for them, and do not fall back to',
|
|
@@ -196,7 +207,7 @@ class SituationReporter {
|
|
|
196
207
|
`Current local time: ${new Date().toLocaleString()}. Use LOCAL time in the report, never UTC.`,
|
|
197
208
|
'',
|
|
198
209
|
'Window (per channel; excerpts truncated):',
|
|
199
|
-
|
|
210
|
+
(0, untrusted_content_js_1.wrapUntrustedContent)('connector-window', windowLines.length > 0 ? windowLines.join('\n') : '- (no channel messages this window)'),
|
|
200
211
|
'',
|
|
201
212
|
`Triggers newly authored this window: ${this.authored}`,
|
|
202
213
|
'Fire activity:',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"situation-report.js","sourceRoot":"","sources":["../../src/operator/situation-report.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"situation-report.js","sourceRoot":"","sources":["../../src/operator/situation-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskLedger - the operator-owned native work-item ledger (M8 Task 0.1).
|
|
3
|
+
*
|
|
4
|
+
* Ports the SHAPE of Kagemusha's proven task store (11 columns: id/title/status/
|
|
5
|
+
* priority/deadline/source/auto_created/confirmed/timestamps) plus `assignee`
|
|
6
|
+
* and an idempotency key. Implements the pre-existing `TaskSource` interface
|
|
7
|
+
* (operator-interfaces.ts) so the board projects ONE task model, not two.
|
|
8
|
+
*
|
|
9
|
+
* Reconcile runs create/update rows through the task_create/task_update gateway
|
|
10
|
+
* tools; the pipeline board slot is a projection of `list({order:
|
|
11
|
+
* 'deadline_priority'})`. The AGENT makes every judgment about what becomes a
|
|
12
|
+
* task; this store only persists.
|
|
13
|
+
*
|
|
14
|
+
* Schema-extension note: CREATE TABLE IF NOT EXISTS is a no-op on existing
|
|
15
|
+
* tables. Any post-ship column addition needs an explicit ALTER TABLE guarded
|
|
16
|
+
* by a PRAGMA table_info check, added to runMigration().
|
|
17
|
+
*
|
|
18
|
+
* The db handle is SHARED with TriggerRegistry and owned by the caller
|
|
19
|
+
* (start.ts opens and closes it once) - deliberately no close() here.
|
|
20
|
+
*/
|
|
21
|
+
import type { SQLiteDatabase } from '../sqlite.js';
|
|
22
|
+
import type { OperatorTask, TaskSource } from './operator-interfaces.js';
|
|
23
|
+
export declare const TASK_STATUSES: readonly ["pending", "in_progress", "review", "blocked", "done", "cancelled"];
|
|
24
|
+
export type TaskStatus = (typeof TASK_STATUSES)[number];
|
|
25
|
+
export declare const TASK_PRIORITIES: readonly ["high", "normal", "low"];
|
|
26
|
+
export type TaskPriority = (typeof TASK_PRIORITIES)[number];
|
|
27
|
+
/** Extended record: satisfies OperatorTask (numeric deadline) and carries the ISO original. */
|
|
28
|
+
export interface TaskRecord extends OperatorTask {
|
|
29
|
+
status: TaskStatus;
|
|
30
|
+
priority: TaskPriority;
|
|
31
|
+
/** ISO YYYY-MM-DD as stored; `deadline` (OperatorTask) is its UTC-midnight epoch ms. */
|
|
32
|
+
deadlineIso: string | null;
|
|
33
|
+
assignee: string | null;
|
|
34
|
+
sourceChannel: string | null;
|
|
35
|
+
sourceEventId: string | null;
|
|
36
|
+
latestEvent: string | null;
|
|
37
|
+
autoCreated: boolean;
|
|
38
|
+
confirmed: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface CreateTaskInput {
|
|
41
|
+
title: string;
|
|
42
|
+
status?: TaskStatus;
|
|
43
|
+
priority?: TaskPriority;
|
|
44
|
+
assignee?: string;
|
|
45
|
+
/** ISO YYYY-MM-DD */
|
|
46
|
+
deadline?: string;
|
|
47
|
+
/** channelKey: "<connector>:<channelId>" */
|
|
48
|
+
source_channel?: string;
|
|
49
|
+
/** Idempotency key from the connector event; duplicate (channel, event) UPSERTS. */
|
|
50
|
+
source_event_id?: string;
|
|
51
|
+
latest_event?: string;
|
|
52
|
+
confirmed?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface UpdateTaskInput {
|
|
55
|
+
status?: TaskStatus;
|
|
56
|
+
priority?: TaskPriority;
|
|
57
|
+
assignee?: string | null;
|
|
58
|
+
deadline?: string | null;
|
|
59
|
+
latest_event?: string;
|
|
60
|
+
confirmed?: boolean;
|
|
61
|
+
title?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface ListTasksFilter {
|
|
64
|
+
status?: TaskStatus;
|
|
65
|
+
channel?: string;
|
|
66
|
+
search?: string;
|
|
67
|
+
limit?: number;
|
|
68
|
+
/** 'deadline_priority' = deadline asc NULLS LAST, then high>normal>low, then id. */
|
|
69
|
+
order?: 'deadline_priority' | 'updated';
|
|
70
|
+
}
|
|
71
|
+
export declare class TaskLedger implements TaskSource {
|
|
72
|
+
private db;
|
|
73
|
+
constructor(db: SQLiteDatabase);
|
|
74
|
+
private runMigration;
|
|
75
|
+
/** TaskSource conformance: open items in canonical board order. */
|
|
76
|
+
getTasks(): OperatorTask[];
|
|
77
|
+
countOpenUnconfirmed(): number;
|
|
78
|
+
list(filter?: ListTasksFilter): TaskRecord[];
|
|
79
|
+
getById(id: number): TaskRecord | null;
|
|
80
|
+
/**
|
|
81
|
+
* Create a task. Idempotent under at-least-once delivery: a duplicate
|
|
82
|
+
* (source_channel, source_event_id) UPSERTS - the existing row gets the new
|
|
83
|
+
* latest_event (and title stays) instead of a near-duplicate row appearing.
|
|
84
|
+
*/
|
|
85
|
+
create(input: CreateTaskInput): TaskRecord;
|
|
86
|
+
update(id: number, patch: UpdateTaskInput): TaskRecord;
|
|
87
|
+
/** Stable hash over ordered rows - the Phase-2 verifier's ledger snapshot. */
|
|
88
|
+
payloadHash(): string;
|
|
89
|
+
/** contract_no_update: silence as a verifiable judgment, scoped to one reconcile run. */
|
|
90
|
+
recordNoUpdate(scope: string, reason: string): {
|
|
91
|
+
id: number;
|
|
92
|
+
};
|
|
93
|
+
/** Max no-update note id, optionally scoped - the verifier's note snapshot. */
|
|
94
|
+
maxNoUpdateId(scope?: string): number;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=task-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-ledger.d.ts","sourceRoot":"","sources":["../../src/operator/task-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TaskLedger - the operator-owned native work-item ledger (M8 Task 0.1).
|
|
4
|
+
*
|
|
5
|
+
* Ports the SHAPE of Kagemusha's proven task store (11 columns: id/title/status/
|
|
6
|
+
* priority/deadline/source/auto_created/confirmed/timestamps) plus `assignee`
|
|
7
|
+
* and an idempotency key. Implements the pre-existing `TaskSource` interface
|
|
8
|
+
* (operator-interfaces.ts) so the board projects ONE task model, not two.
|
|
9
|
+
*
|
|
10
|
+
* Reconcile runs create/update rows through the task_create/task_update gateway
|
|
11
|
+
* tools; the pipeline board slot is a projection of `list({order:
|
|
12
|
+
* 'deadline_priority'})`. The AGENT makes every judgment about what becomes a
|
|
13
|
+
* task; this store only persists.
|
|
14
|
+
*
|
|
15
|
+
* Schema-extension note: CREATE TABLE IF NOT EXISTS is a no-op on existing
|
|
16
|
+
* tables. Any post-ship column addition needs an explicit ALTER TABLE guarded
|
|
17
|
+
* by a PRAGMA table_info check, added to runMigration().
|
|
18
|
+
*
|
|
19
|
+
* The db handle is SHARED with TriggerRegistry and owned by the caller
|
|
20
|
+
* (start.ts opens and closes it once) - deliberately no close() here.
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.TaskLedger = exports.TASK_PRIORITIES = exports.TASK_STATUSES = void 0;
|
|
24
|
+
const node_crypto_1 = require("node:crypto");
|
|
25
|
+
exports.TASK_STATUSES = [
|
|
26
|
+
'pending',
|
|
27
|
+
'in_progress',
|
|
28
|
+
'review',
|
|
29
|
+
'blocked',
|
|
30
|
+
'done',
|
|
31
|
+
'cancelled',
|
|
32
|
+
];
|
|
33
|
+
exports.TASK_PRIORITIES = ['high', 'normal', 'low'];
|
|
34
|
+
const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
35
|
+
function isoToEpochMs(iso) {
|
|
36
|
+
if (!iso)
|
|
37
|
+
return null;
|
|
38
|
+
const ms = Date.parse(`${iso}T00:00:00Z`);
|
|
39
|
+
return Number.isNaN(ms) ? null : ms;
|
|
40
|
+
}
|
|
41
|
+
function assertEnum(value, allowed, field) {
|
|
42
|
+
if (!allowed.includes(value)) {
|
|
43
|
+
throw new Error(`${field} must be one of ${allowed.join('|')}, got: ${value}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function assertIsoDate(value, field) {
|
|
47
|
+
const match = ISO_DATE_PATTERN.exec(value);
|
|
48
|
+
if (!match) {
|
|
49
|
+
throw new Error(`${field} must be an ISO date (YYYY-MM-DD), got: ${value}`);
|
|
50
|
+
}
|
|
51
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
52
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
53
|
+
const isRoundTrip = date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
54
|
+
if (!isRoundTrip) {
|
|
55
|
+
throw new Error(`${field} must be an ISO date (YYYY-MM-DD), got: ${value}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function rowToRecord(row) {
|
|
59
|
+
return {
|
|
60
|
+
id: row.id,
|
|
61
|
+
title: row.title,
|
|
62
|
+
status: row.status,
|
|
63
|
+
priority: row.priority,
|
|
64
|
+
deadline: isoToEpochMs(row.deadline),
|
|
65
|
+
deadlineIso: row.deadline,
|
|
66
|
+
assignee: row.assignee,
|
|
67
|
+
sourceChannel: row.source_channel,
|
|
68
|
+
sourceEventId: row.source_event_id,
|
|
69
|
+
latestEvent: row.latest_event,
|
|
70
|
+
autoCreated: row.auto_created === 1,
|
|
71
|
+
confirmed: row.confirmed === 1,
|
|
72
|
+
createdAt: row.created_at,
|
|
73
|
+
updatedAt: row.updated_at,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
class TaskLedger {
|
|
77
|
+
db;
|
|
78
|
+
constructor(db) {
|
|
79
|
+
this.db = db;
|
|
80
|
+
this.runMigration();
|
|
81
|
+
}
|
|
82
|
+
runMigration() {
|
|
83
|
+
this.db.exec(`
|
|
84
|
+
CREATE TABLE IF NOT EXISTS operator_tasks (
|
|
85
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
86
|
+
title TEXT NOT NULL,
|
|
87
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
88
|
+
CHECK (status IN ('pending','in_progress','review','blocked','done','cancelled')),
|
|
89
|
+
priority TEXT NOT NULL DEFAULT 'normal' CHECK (priority IN ('high','normal','low')),
|
|
90
|
+
assignee TEXT,
|
|
91
|
+
deadline TEXT,
|
|
92
|
+
source_channel TEXT,
|
|
93
|
+
source_event_id TEXT,
|
|
94
|
+
latest_event TEXT,
|
|
95
|
+
auto_created INTEGER NOT NULL DEFAULT 1,
|
|
96
|
+
confirmed INTEGER NOT NULL DEFAULT 0,
|
|
97
|
+
created_at INTEGER NOT NULL,
|
|
98
|
+
updated_at INTEGER NOT NULL
|
|
99
|
+
);
|
|
100
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_operator_tasks_source
|
|
101
|
+
ON operator_tasks(source_channel, source_event_id)
|
|
102
|
+
WHERE source_event_id IS NOT NULL;
|
|
103
|
+
CREATE INDEX IF NOT EXISTS idx_operator_tasks_status ON operator_tasks(status);
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_operator_tasks_deadline ON operator_tasks(deadline);
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS operator_no_update_notes (
|
|
107
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
108
|
+
scope TEXT NOT NULL,
|
|
109
|
+
reason TEXT NOT NULL,
|
|
110
|
+
created_at INTEGER NOT NULL
|
|
111
|
+
);
|
|
112
|
+
CREATE INDEX IF NOT EXISTS idx_operator_no_update_scope
|
|
113
|
+
ON operator_no_update_notes(scope, id);
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
/** TaskSource conformance: open items in canonical board order. */
|
|
117
|
+
getTasks() {
|
|
118
|
+
return this.list({ order: 'deadline_priority' });
|
|
119
|
+
}
|
|
120
|
+
countOpenUnconfirmed() {
|
|
121
|
+
const row = this.db
|
|
122
|
+
.prepare(`SELECT COUNT(*) AS count
|
|
123
|
+
FROM operator_tasks
|
|
124
|
+
WHERE auto_created = 1
|
|
125
|
+
AND confirmed = 0
|
|
126
|
+
AND status NOT IN ('done', 'cancelled')`)
|
|
127
|
+
.get();
|
|
128
|
+
return row.count;
|
|
129
|
+
}
|
|
130
|
+
list(filter = {}) {
|
|
131
|
+
const where = [];
|
|
132
|
+
const params = [];
|
|
133
|
+
if (filter.status) {
|
|
134
|
+
where.push('status = ?');
|
|
135
|
+
params.push(filter.status);
|
|
136
|
+
}
|
|
137
|
+
if (filter.channel) {
|
|
138
|
+
where.push('source_channel = ?');
|
|
139
|
+
params.push(filter.channel);
|
|
140
|
+
}
|
|
141
|
+
if (filter.search) {
|
|
142
|
+
where.push('(title LIKE ? OR latest_event LIKE ? OR assignee LIKE ?)');
|
|
143
|
+
const like = `%${filter.search}%`;
|
|
144
|
+
params.push(like, like, like);
|
|
145
|
+
}
|
|
146
|
+
const order = filter.order === 'updated'
|
|
147
|
+
? 'updated_at DESC, id DESC'
|
|
148
|
+
: // deadline asc NULLS LAST, then priority high>normal>low, then id.
|
|
149
|
+
// LIMIT applies AFTER ordering so the true top-N is returned.
|
|
150
|
+
`CASE WHEN deadline IS NULL THEN 1 ELSE 0 END ASC, deadline ASC,
|
|
151
|
+
CASE priority WHEN 'high' THEN 0 WHEN 'normal' THEN 1 ELSE 2 END ASC, id ASC`;
|
|
152
|
+
const rawLimit = Number(filter.limit);
|
|
153
|
+
const limit = Number.isFinite(rawLimit) ? Math.max(1, Math.min(200, Math.floor(rawLimit))) : 50;
|
|
154
|
+
const rows = this.db
|
|
155
|
+
.prepare(`SELECT * FROM operator_tasks
|
|
156
|
+
${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}
|
|
157
|
+
ORDER BY ${order}
|
|
158
|
+
LIMIT ?`)
|
|
159
|
+
.all(...params, limit);
|
|
160
|
+
return rows.map(rowToRecord);
|
|
161
|
+
}
|
|
162
|
+
getById(id) {
|
|
163
|
+
const row = this.db.prepare(`SELECT * FROM operator_tasks WHERE id = ?`).get(id);
|
|
164
|
+
return row ? rowToRecord(row) : null;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create a task. Idempotent under at-least-once delivery: a duplicate
|
|
168
|
+
* (source_channel, source_event_id) UPSERTS - the existing row gets the new
|
|
169
|
+
* latest_event (and title stays) instead of a near-duplicate row appearing.
|
|
170
|
+
*/
|
|
171
|
+
create(input) {
|
|
172
|
+
if (!input.title || input.title.trim() === '') {
|
|
173
|
+
throw new Error('task title must be a non-empty string');
|
|
174
|
+
}
|
|
175
|
+
if (input.status !== undefined)
|
|
176
|
+
assertEnum(input.status, exports.TASK_STATUSES, 'status');
|
|
177
|
+
if (input.priority !== undefined)
|
|
178
|
+
assertEnum(input.priority, exports.TASK_PRIORITIES, 'priority');
|
|
179
|
+
if (input.deadline !== undefined)
|
|
180
|
+
assertIsoDate(input.deadline, 'deadline');
|
|
181
|
+
const now = Date.now();
|
|
182
|
+
if (input.source_channel && input.source_event_id) {
|
|
183
|
+
const existing = this.db
|
|
184
|
+
.prepare(`SELECT * FROM operator_tasks WHERE source_channel = ? AND source_event_id = ?`)
|
|
185
|
+
.get(input.source_channel, input.source_event_id);
|
|
186
|
+
if (existing) {
|
|
187
|
+
// Upsert carries every provided field EXCEPT title (the original naming
|
|
188
|
+
// stays stable across retries; movement and state updates flow through).
|
|
189
|
+
return this.update(existing.id, {
|
|
190
|
+
...(input.status !== undefined ? { status: input.status } : {}),
|
|
191
|
+
...(input.priority !== undefined ? { priority: input.priority } : {}),
|
|
192
|
+
...(input.assignee !== undefined ? { assignee: input.assignee } : {}),
|
|
193
|
+
...(input.deadline !== undefined ? { deadline: input.deadline } : {}),
|
|
194
|
+
...(input.confirmed !== undefined ? { confirmed: input.confirmed } : {}),
|
|
195
|
+
...(input.latest_event !== undefined ? { latest_event: input.latest_event } : {}),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const result = this.db
|
|
200
|
+
.prepare(`INSERT INTO operator_tasks
|
|
201
|
+
(title, status, priority, assignee, deadline, source_channel, source_event_id,
|
|
202
|
+
latest_event, auto_created, confirmed, created_at, updated_at)
|
|
203
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
204
|
+
.run(input.title.trim(), input.status ?? 'pending', input.priority ?? 'normal', input.assignee ?? null, input.deadline ?? null, input.source_channel ?? null, input.source_event_id ?? null, input.latest_event ?? null, 1, input.confirmed ? 1 : 0, now, now);
|
|
205
|
+
const created = this.getById(Number(result.lastInsertRowid));
|
|
206
|
+
if (!created)
|
|
207
|
+
throw new Error('task_create: inserted row could not be read back');
|
|
208
|
+
return created;
|
|
209
|
+
}
|
|
210
|
+
update(id, patch) {
|
|
211
|
+
const existing = this.getById(id);
|
|
212
|
+
if (!existing)
|
|
213
|
+
throw new Error(`task_update: no task with id ${id}`);
|
|
214
|
+
if (patch.status !== undefined)
|
|
215
|
+
assertEnum(patch.status, exports.TASK_STATUSES, 'status');
|
|
216
|
+
if (patch.priority !== undefined)
|
|
217
|
+
assertEnum(patch.priority, exports.TASK_PRIORITIES, 'priority');
|
|
218
|
+
if (patch.deadline !== undefined && patch.deadline !== null) {
|
|
219
|
+
assertIsoDate(patch.deadline, 'deadline');
|
|
220
|
+
}
|
|
221
|
+
if (patch.title !== undefined && patch.title.trim() === '') {
|
|
222
|
+
throw new Error('task title must be a non-empty string');
|
|
223
|
+
}
|
|
224
|
+
const sets = ['updated_at = ?'];
|
|
225
|
+
const params = [Date.now()];
|
|
226
|
+
const assign = (column, value) => {
|
|
227
|
+
sets.push(`${column} = ?`);
|
|
228
|
+
params.push(value);
|
|
229
|
+
};
|
|
230
|
+
if (patch.title !== undefined)
|
|
231
|
+
assign('title', patch.title.trim());
|
|
232
|
+
if (patch.status !== undefined)
|
|
233
|
+
assign('status', patch.status);
|
|
234
|
+
if (patch.priority !== undefined)
|
|
235
|
+
assign('priority', patch.priority);
|
|
236
|
+
if (patch.assignee !== undefined)
|
|
237
|
+
assign('assignee', patch.assignee);
|
|
238
|
+
if (patch.deadline !== undefined)
|
|
239
|
+
assign('deadline', patch.deadline);
|
|
240
|
+
if (patch.latest_event !== undefined)
|
|
241
|
+
assign('latest_event', patch.latest_event);
|
|
242
|
+
if (patch.confirmed !== undefined)
|
|
243
|
+
assign('confirmed', patch.confirmed ? 1 : 0);
|
|
244
|
+
this.db.prepare(`UPDATE operator_tasks SET ${sets.join(', ')} WHERE id = ?`).run(...params, id);
|
|
245
|
+
return this.getById(id);
|
|
246
|
+
}
|
|
247
|
+
/** Stable hash over ordered rows - the Phase-2 verifier's ledger snapshot. */
|
|
248
|
+
payloadHash() {
|
|
249
|
+
const rows = this.db
|
|
250
|
+
.prepare(`SELECT id, title, status, priority, assignee, deadline, latest_event, confirmed,
|
|
251
|
+
updated_at
|
|
252
|
+
FROM operator_tasks ORDER BY id ASC`)
|
|
253
|
+
.all();
|
|
254
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(rows)).digest('hex');
|
|
255
|
+
}
|
|
256
|
+
/** contract_no_update: silence as a verifiable judgment, scoped to one reconcile run. */
|
|
257
|
+
recordNoUpdate(scope, reason) {
|
|
258
|
+
if (!scope || !reason) {
|
|
259
|
+
throw new Error('contract_no_update requires both scope and reason');
|
|
260
|
+
}
|
|
261
|
+
const result = this.db
|
|
262
|
+
.prepare(`INSERT INTO operator_no_update_notes (scope, reason, created_at) VALUES (?, ?, ?)`)
|
|
263
|
+
.run(scope, reason, Date.now());
|
|
264
|
+
return { id: Number(result.lastInsertRowid) };
|
|
265
|
+
}
|
|
266
|
+
/** Max no-update note id, optionally scoped - the verifier's note snapshot. */
|
|
267
|
+
maxNoUpdateId(scope) {
|
|
268
|
+
const row = (scope
|
|
269
|
+
? this.db
|
|
270
|
+
.prepare(`SELECT MAX(id) AS max_id FROM operator_no_update_notes WHERE scope = ?`)
|
|
271
|
+
.get(scope)
|
|
272
|
+
: this.db.prepare(`SELECT MAX(id) AS max_id FROM operator_no_update_notes`).get());
|
|
273
|
+
return row.max_id ?? 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
exports.TaskLedger = TaskLedger;
|
|
277
|
+
//# sourceMappingURL=task-ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-ledger.js","sourceRoot":"","sources":["../../src/operator/task-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,18 @@ declare function getDenylistTxtPath(): string;
|
|
|
28
28
|
declare function getCloudflareCustomListCsvPath(): string;
|
|
29
29
|
declare function getCloudflareWafExpressionPath(): string;
|
|
30
30
|
export declare function setSecurityAlertSender(sender: SecurityAlertSender | null): void;
|
|
31
|
+
export declare function hasSecurityAlertSender(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Deliver an alert through the registered sender WITHOUT the incident pipeline.
|
|
34
|
+
*
|
|
35
|
+
* recordSecurityEvent() preserves evidence, writes denylist candidates, and
|
|
36
|
+
* runs RDAP attribution - correct for real client events, but self-generated
|
|
37
|
+
* alerts (system audit findings) must not fabricate incident/denylist/WAF
|
|
38
|
+
* artifacts for a pseudo client. This path only appends the event to the
|
|
39
|
+
* security log (durable record) and AWAITS delivery so the caller can retry:
|
|
40
|
+
* it throws when no sender is registered or when the sender fails.
|
|
41
|
+
*/
|
|
42
|
+
export declare function dispatchSecurityAlertDirect(event: SecurityEvent): Promise<void>;
|
|
31
43
|
export declare function resetSecurityMonitorForTests(): void;
|
|
32
44
|
export declare function flushSecurityMonitor(): Promise<void>;
|
|
33
45
|
export declare function formatSecurityAlert(event: SecurityEvent): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-monitor.d.ts","sourceRoot":"","sources":["../../src/security/security-monitor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAuD/D,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAO5E;AAED,wBAAgB,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAuBhF;AAiBD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,KAAK,mBAAmB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAgHnE,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAcjF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;
|
|
1
|
+
{"version":3,"file":"security-monitor.d.ts","sourceRoot":"","sources":["../../src/security/security-monitor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAuD/D,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAO5E;AAED,wBAAgB,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAuBhF;AAiBD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAaD,KAAK,mBAAmB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAgHnE,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAcjF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AA0OD,iBAAS,kBAAkB,IAAI,MAAM,CAEpC;AAED,iBAAS,iBAAiB,IAAI,MAAM,CAEnC;AAED,iBAAS,mBAAmB,IAAI,MAAM,CAErC;AAED,iBAAS,kBAAkB,IAAI,MAAM,CAEpC;AAED,iBAAS,8BAA8B,IAAI,MAAM,CAEhD;AAED,iBAAS,8BAA8B,IAAI,MAAM,CAEhD;AAuND,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAK/E;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrF;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CASnD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK1D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAmChE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAoC9D;AAED,wBAAgB,wBAAwB,KACxB,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAgD9E;AAED,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,CAAC"}
|
|
@@ -39,6 +39,8 @@ exports.recordAuthFailure = recordAuthFailure;
|
|
|
39
39
|
exports.getTarpitDelayMs = getTarpitDelayMs;
|
|
40
40
|
exports.isHoneypotPath = isHoneypotPath;
|
|
41
41
|
exports.setSecurityAlertSender = setSecurityAlertSender;
|
|
42
|
+
exports.hasSecurityAlertSender = hasSecurityAlertSender;
|
|
43
|
+
exports.dispatchSecurityAlertDirect = dispatchSecurityAlertDirect;
|
|
42
44
|
exports.resetSecurityMonitorForTests = resetSecurityMonitorForTests;
|
|
43
45
|
exports.flushSecurityMonitor = flushSecurityMonitor;
|
|
44
46
|
exports.formatSecurityAlert = formatSecurityAlert;
|
|
@@ -405,7 +407,10 @@ function formatAbuseReport(incidentId, incidentSummary) {
|
|
|
405
407
|
].join('\n');
|
|
406
408
|
}
|
|
407
409
|
function getSecurityLogDir() {
|
|
408
|
-
|
|
410
|
+
// MAMA_SECURITY_LOG_DIR redirects ALL security telemetry (events, incidents,
|
|
411
|
+
// denylist artifacts). Test suites MUST set this (tests/setup.ts does) so
|
|
412
|
+
// fixture events never pollute the live operator telemetry.
|
|
413
|
+
return process.env.MAMA_SECURITY_LOG_DIR || (0, node_path_1.join)((0, node_os_1.homedir)(), '.mama', 'logs');
|
|
409
414
|
}
|
|
410
415
|
function getSecurityLogPath() {
|
|
411
416
|
return (0, node_path_1.join)(getSecurityLogDir(), 'security-events.jsonl');
|
|
@@ -613,6 +618,33 @@ function setSecurityAlertSender(sender) {
|
|
|
613
618
|
logger.info('Security alert sender registered');
|
|
614
619
|
}
|
|
615
620
|
}
|
|
621
|
+
function hasSecurityAlertSender() {
|
|
622
|
+
return alertSender !== null;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Deliver an alert through the registered sender WITHOUT the incident pipeline.
|
|
626
|
+
*
|
|
627
|
+
* recordSecurityEvent() preserves evidence, writes denylist candidates, and
|
|
628
|
+
* runs RDAP attribution - correct for real client events, but self-generated
|
|
629
|
+
* alerts (system audit findings) must not fabricate incident/denylist/WAF
|
|
630
|
+
* artifacts for a pseudo client. This path only appends the event to the
|
|
631
|
+
* security log (durable record) and AWAITS delivery so the caller can retry:
|
|
632
|
+
* it throws when no sender is registered or when the sender fails.
|
|
633
|
+
*/
|
|
634
|
+
async function dispatchSecurityAlertDirect(event) {
|
|
635
|
+
const normalized = {
|
|
636
|
+
...event,
|
|
637
|
+
timestamp: event.timestamp || new Date().toISOString(),
|
|
638
|
+
};
|
|
639
|
+
logger.warn(`[SECURITY] ${normalized.message}`, normalized);
|
|
640
|
+
trackBackgroundTask(appendSecurityLog(normalized).catch((error) => {
|
|
641
|
+
logger.error('Failed to append security event log', error);
|
|
642
|
+
}));
|
|
643
|
+
if (!alertSender) {
|
|
644
|
+
throw new Error('No security alert sender registered (MAMA_SECURITY_ALERT_CHANNELS unset?)');
|
|
645
|
+
}
|
|
646
|
+
await alertSender(normalized);
|
|
647
|
+
}
|
|
616
648
|
function resetSecurityMonitorForTests() {
|
|
617
649
|
banMap.clear();
|
|
618
650
|
alertSender = null;
|
|
@@ -630,14 +662,12 @@ async function flushSecurityMonitor() {
|
|
|
630
662
|
await Promise.allSettled([...pendingTasks]);
|
|
631
663
|
}
|
|
632
664
|
function formatSecurityAlert(event) {
|
|
633
|
-
const
|
|
634
|
-
const
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
`
|
|
638
|
-
|
|
639
|
-
`client: ${event.clientAddress || event.remoteAddress || 'unknown'}`,
|
|
640
|
-
];
|
|
665
|
+
const client = event.clientAddress || event.remoteAddress;
|
|
666
|
+
const lines = [`🚨 [Security] ${event.message}`, `type: ${event.type}`];
|
|
667
|
+
lines.push(`severity: ${event.severity}`);
|
|
668
|
+
if (client) {
|
|
669
|
+
lines.push(`client: ${client}`);
|
|
670
|
+
}
|
|
641
671
|
if (event.path) {
|
|
642
672
|
lines.push(`path: ${event.path}`);
|
|
643
673
|
}
|
|
@@ -650,11 +680,18 @@ function formatSecurityAlert(event) {
|
|
|
650
680
|
if (event.details && Object.keys(event.details).length > 0) {
|
|
651
681
|
lines.push(`details: ${JSON.stringify(event.details)}`);
|
|
652
682
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
683
|
+
// Incident artifacts exist only for client-attributed events that went
|
|
684
|
+
// through the evidence pipeline; self-generated alerts (system audit) have
|
|
685
|
+
// no client and must not point the owner at files that were never written.
|
|
686
|
+
if (client) {
|
|
687
|
+
const incidentId = getIncidentId(event);
|
|
688
|
+
const incidentDir = (0, node_path_1.join)(getIncidentLogDir(), incidentId);
|
|
689
|
+
lines.push(`evidence: ${(0, node_path_1.join)(incidentDir, 'incident.json')}`);
|
|
690
|
+
lines.push(`abuse_draft: ${(0, node_path_1.join)(incidentDir, 'abuse-report.md')}`);
|
|
691
|
+
lines.push(`denylist: ${getDenylistJsonPath()}`);
|
|
692
|
+
lines.push(`cloudflare_csv: ${getCloudflareCustomListCsvPath()}`);
|
|
693
|
+
lines.push(`cloudflare_waf: ${getCloudflareWafExpressionPath()}`);
|
|
694
|
+
}
|
|
658
695
|
return lines.join('\n');
|
|
659
696
|
}
|
|
660
697
|
function recordSecurityEvent(event) {
|