wyrm-mcp 6.18.1 → 7.0.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.
Files changed (192) hide show
  1. package/README.md +23 -3
  2. package/dist/attribution.d.ts +51 -0
  3. package/dist/attribution.d.ts.map +1 -0
  4. package/dist/attribution.js +49 -0
  5. package/dist/attribution.js.map +1 -0
  6. package/dist/audit.d.ts +184 -8
  7. package/dist/audit.d.ts.map +1 -1
  8. package/dist/audit.js +331 -22
  9. package/dist/audit.js.map +1 -1
  10. package/dist/auto-capture.d.ts +11 -0
  11. package/dist/auto-capture.d.ts.map +1 -1
  12. package/dist/auto-capture.js +13 -0
  13. package/dist/auto-capture.js.map +1 -1
  14. package/dist/capture.js +5 -5
  15. package/dist/capture.js.map +1 -1
  16. package/dist/causality.d.ts.map +1 -1
  17. package/dist/causality.js +6 -3
  18. package/dist/causality.js.map +1 -1
  19. package/dist/daemon-write-endpoint.d.ts +112 -0
  20. package/dist/daemon-write-endpoint.d.ts.map +1 -0
  21. package/dist/daemon-write-endpoint.js +290 -0
  22. package/dist/daemon-write-endpoint.js.map +1 -0
  23. package/dist/daemon-writer.d.ts +196 -0
  24. package/dist/daemon-writer.d.ts.map +1 -0
  25. package/dist/daemon-writer.js +406 -0
  26. package/dist/daemon-writer.js.map +1 -0
  27. package/dist/database.d.ts +33 -1
  28. package/dist/database.d.ts.map +1 -1
  29. package/dist/database.js +92 -31
  30. package/dist/database.js.map +1 -1
  31. package/dist/deprecations.d.ts +41 -12
  32. package/dist/deprecations.d.ts.map +1 -1
  33. package/dist/deprecations.js +56 -27
  34. package/dist/deprecations.js.map +1 -1
  35. package/dist/event-replication.d.ts +2 -2
  36. package/dist/event-replication.d.ts.map +1 -1
  37. package/dist/event-replication.js +1 -1
  38. package/dist/events-sse.d.ts +4 -2
  39. package/dist/events-sse.d.ts.map +1 -1
  40. package/dist/events-sse.js +4 -2
  41. package/dist/events-sse.js.map +1 -1
  42. package/dist/events.d.ts +13 -0
  43. package/dist/events.d.ts.map +1 -1
  44. package/dist/events.js +17 -6
  45. package/dist/events.js.map +1 -1
  46. package/dist/failure-patterns.d.ts +416 -3
  47. package/dist/failure-patterns.d.ts.map +1 -1
  48. package/dist/failure-patterns.js +693 -46
  49. package/dist/failure-patterns.js.map +1 -1
  50. package/dist/handlers/alias-adapters.d.ts +62 -0
  51. package/dist/handlers/alias-adapters.d.ts.map +1 -0
  52. package/dist/handlers/alias-adapters.js +129 -0
  53. package/dist/handlers/alias-adapters.js.map +1 -0
  54. package/dist/handlers/aliases.d.ts +54 -0
  55. package/dist/handlers/aliases.d.ts.map +1 -0
  56. package/dist/handlers/aliases.js +170 -0
  57. package/dist/handlers/aliases.js.map +1 -0
  58. package/dist/handlers/boundary.d.ts +114 -0
  59. package/dist/handlers/boundary.d.ts.map +1 -0
  60. package/dist/handlers/boundary.js +203 -0
  61. package/dist/handlers/boundary.js.map +1 -0
  62. package/dist/handlers/capture.d.ts +25 -0
  63. package/dist/handlers/capture.d.ts.map +1 -0
  64. package/dist/handlers/capture.js +969 -0
  65. package/dist/handlers/capture.js.map +1 -0
  66. package/dist/handlers/failure.d.ts +28 -0
  67. package/dist/handlers/failure.d.ts.map +1 -0
  68. package/dist/handlers/failure.js +340 -0
  69. package/dist/handlers/failure.js.map +1 -0
  70. package/dist/handlers/goals.d.ts +21 -5
  71. package/dist/handlers/goals.d.ts.map +1 -1
  72. package/dist/handlers/goals.js +283 -52
  73. package/dist/handlers/goals.js.map +1 -1
  74. package/dist/handlers/output-schemas.d.ts +25 -0
  75. package/dist/handlers/output-schemas.d.ts.map +1 -0
  76. package/dist/handlers/output-schemas.js +24 -0
  77. package/dist/handlers/output-schemas.js.map +1 -0
  78. package/dist/handlers/prompts.d.ts +59 -0
  79. package/dist/handlers/prompts.d.ts.map +1 -0
  80. package/dist/handlers/prompts.js +156 -0
  81. package/dist/handlers/prompts.js.map +1 -0
  82. package/dist/handlers/quest.d.ts +24 -0
  83. package/dist/handlers/quest.d.ts.map +1 -0
  84. package/dist/handlers/quest.js +224 -0
  85. package/dist/handlers/quest.js.map +1 -0
  86. package/dist/handlers/recall.d.ts +20 -0
  87. package/dist/handlers/recall.d.ts.map +1 -0
  88. package/dist/handlers/recall.js +188 -0
  89. package/dist/handlers/recall.js.map +1 -0
  90. package/dist/handlers/registry.d.ts +72 -6
  91. package/dist/handlers/registry.d.ts.map +1 -1
  92. package/dist/handlers/registry.js +116 -9
  93. package/dist/handlers/registry.js.map +1 -1
  94. package/dist/handlers/review.d.ts +16 -0
  95. package/dist/handlers/review.d.ts.map +1 -0
  96. package/dist/handlers/review.js +66 -0
  97. package/dist/handlers/review.js.map +1 -0
  98. package/dist/handlers/run.d.ts +47 -0
  99. package/dist/handlers/run.d.ts.map +1 -0
  100. package/dist/handlers/run.js +498 -0
  101. package/dist/handlers/run.js.map +1 -0
  102. package/dist/handlers/search.d.ts +22 -0
  103. package/dist/handlers/search.d.ts.map +1 -0
  104. package/dist/handlers/search.js +326 -0
  105. package/dist/handlers/search.js.map +1 -0
  106. package/dist/handlers/session.d.ts +54 -0
  107. package/dist/handlers/session.d.ts.map +1 -0
  108. package/dist/handlers/session.js +623 -0
  109. package/dist/handlers/session.js.map +1 -0
  110. package/dist/handlers/shims.d.ts +84 -0
  111. package/dist/handlers/shims.d.ts.map +1 -0
  112. package/dist/handlers/shims.js +463 -0
  113. package/dist/handlers/shims.js.map +1 -0
  114. package/dist/handlers/survivors.d.ts +76 -0
  115. package/dist/handlers/survivors.d.ts.map +1 -0
  116. package/dist/handlers/survivors.js +101 -0
  117. package/dist/handlers/survivors.js.map +1 -0
  118. package/dist/handlers/types.d.ts +156 -7
  119. package/dist/handlers/types.d.ts.map +1 -1
  120. package/dist/handlers/types.js +9 -1
  121. package/dist/handlers/types.js.map +1 -1
  122. package/dist/http-fast.d.ts.map +1 -1
  123. package/dist/http-fast.js +157 -76
  124. package/dist/http-fast.js.map +1 -1
  125. package/dist/index.d.ts +0 -1
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +483 -1747
  128. package/dist/index.js.map +1 -1
  129. package/dist/intelligence.d.ts.map +1 -1
  130. package/dist/intelligence.js +7 -3
  131. package/dist/intelligence.js.map +1 -1
  132. package/dist/maintenance.d.ts +56 -0
  133. package/dist/maintenance.d.ts.map +1 -0
  134. package/dist/maintenance.js +150 -0
  135. package/dist/maintenance.js.map +1 -0
  136. package/dist/memory-artifacts.d.ts.map +1 -1
  137. package/dist/memory-artifacts.js +7 -3
  138. package/dist/memory-artifacts.js.map +1 -1
  139. package/dist/migrations.d.ts.map +1 -1
  140. package/dist/migrations.js +281 -0
  141. package/dist/migrations.js.map +1 -1
  142. package/dist/presence.d.ts +48 -8
  143. package/dist/presence.d.ts.map +1 -1
  144. package/dist/presence.js +61 -14
  145. package/dist/presence.js.map +1 -1
  146. package/dist/reindex.d.ts +28 -0
  147. package/dist/reindex.d.ts.map +1 -0
  148. package/dist/reindex.js +88 -0
  149. package/dist/reindex.js.map +1 -0
  150. package/dist/render.d.ts +240 -0
  151. package/dist/render.d.ts.map +1 -0
  152. package/dist/render.js +280 -0
  153. package/dist/render.js.map +1 -0
  154. package/dist/resilience.d.ts.map +1 -1
  155. package/dist/resilience.js +30 -4
  156. package/dist/resilience.js.map +1 -1
  157. package/dist/sqlite-busy.d.ts +134 -0
  158. package/dist/sqlite-busy.d.ts.map +1 -0
  159. package/dist/sqlite-busy.js +154 -0
  160. package/dist/sqlite-busy.js.map +1 -0
  161. package/dist/statusline.d.ts.map +1 -1
  162. package/dist/statusline.js +8 -2
  163. package/dist/statusline.js.map +1 -1
  164. package/dist/tool-annotations.d.ts +39 -0
  165. package/dist/tool-annotations.d.ts.map +1 -1
  166. package/dist/tool-annotations.js +99 -3
  167. package/dist/tool-annotations.js.map +1 -1
  168. package/dist/tool-manifest.json +1 -1
  169. package/dist/tool-profiles.d.ts +35 -27
  170. package/dist/tool-profiles.d.ts.map +1 -1
  171. package/dist/tool-profiles.js +41 -118
  172. package/dist/tool-profiles.js.map +1 -1
  173. package/dist/ulid.d.ts +26 -0
  174. package/dist/ulid.d.ts.map +1 -0
  175. package/dist/ulid.js +81 -0
  176. package/dist/ulid.js.map +1 -0
  177. package/dist/version-check.d.ts.map +1 -1
  178. package/dist/version-check.js +4 -1
  179. package/dist/version-check.js.map +1 -1
  180. package/dist/wyrm-cli.js +531 -2
  181. package/dist/wyrm-cli.js.map +1 -1
  182. package/dist/wyrm-guard.d.ts +97 -0
  183. package/dist/wyrm-guard.d.ts.map +1 -0
  184. package/dist/wyrm-guard.js +425 -0
  185. package/dist/wyrm-guard.js.map +1 -0
  186. package/dist/wyrm-manifest.json +1233 -0
  187. package/package.json +5 -6
  188. package/dist/http-server.d.ts +0 -12
  189. package/dist/http-server.d.ts.map +0 -1
  190. package/dist/http-server.js +0 -563
  191. package/dist/http-server.js.map +0 -1
  192. package/ui/index.html +0 -575
package/README.md CHANGED
@@ -4,10 +4,14 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/wyrm-mcp?color=00B89F&label=npm)](https://www.npmjs.com/package/wyrm-mcp)
6
6
  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-00B89F.svg)](LICENSE)
7
- [![Tests](https://img.shields.io/badge/tests-841%20passing-00B89F)](packages/mcp-server)
7
+ [![Tests](https://img.shields.io/badge/tests-1543%20passing-00B89F)](https://github.com/Ghosts-Protocol-Pvt-Ltd/Wyrm)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
9
9
  [![MCP](https://img.shields.io/badge/MCP-compatible-00B89F)](https://modelcontextprotocol.io)
10
10
 
11
+ **[wyrm.ghosts.lk](https://wyrm.ghosts.lk)**  ·  **[npm](https://www.npmjs.com/package/wyrm-mcp)**  ·  **[GitHub](https://github.com/Ghosts-Protocol-Pvt-Ltd/Wyrm)**  ·  **[Ghost Protocol](https://ghosts.lk)**  ·  `npm i -g wyrm-mcp`
12
+
13
+ Local-first persistent memory for AI agents over MCP — by [Ghost Protocol](https://ghosts.lk). Runs fully offline on your machine: no cloud, no account, no LLM required. The managed cloud tier lives at **[wyrm.ghosts.lk](https://wyrm.ghosts.lk)**.
14
+
11
15
  ---
12
16
 
13
17
  ## What Wyrm actually is
@@ -31,11 +35,27 @@ You don't ask for memory. The AI cites it on its own. Visibly, with sources.
31
35
 
32
36
  ---
33
37
 
38
+ ## New in 7.0 — "BROOD": memory for agent FLEETS
39
+
40
+ > *One agent burns its hand and a hundred siblings never touch the stove.*
41
+
42
+ The unit of cognition is now the **run** — an orchestrator fanning out structured-output subagents — and 7.0 rebuilds Wyrm around it:
43
+
44
+ - **The lean frozen surface.** Default ListTools advertises **32 tools** (≈7,993 tokens — chars/4, the F1-census convention — byte-stable across calls) instead of 6.x's 62-tool default / 137 full-load — and **every one of the 137 6.x names stays callable** through a generated alias spine routing to the same handlers. `WYRM_PROFILE=essential` = the core 4 (`session_prime` / `recall` / `capture` / `failure_check`); `WYRM_PROFILE=legacy` (or `full`, now its permanent synonym) re-advertises everything. Discovery is a hard CI gate: BM25 top-3 **100%** on 65 intent queries (threshold 90%).
45
+ - **Run-native attribution.** First-class `runs`/`run_agents` tables; every write attributable to `(agent_id, run_id)` (explicit param > `_meta['wyrm/actor']` > env > clientInfo), bound into the signed Ed25519 audit chain.
46
+ - **Fleet negative learning.** A failure recorded by one subagent **blocks the repeat for every sibling**: run-scoped quarantine with principled promotion, structured `failure_check` verdicts (`{blocked, matches[], recorded_by_agent, run_id, confidence}` — deterministic, no LLM), and **`wyrm-guard`** — a PreToolUse hook bin that enforces it harness-side (block / warn / silent when clean; measured p95 ≤70ms incl. node startup). `wyrm_stats view=failures` prints the ROI number nobody else can: *"N repeats blocked this run."*
47
+ - **The run loop.** `wyrm_run` `action=start|join|status|debrief|end` — debrief fans each agent's learnings through LOCAL-only extraction (Ollama / deterministic fallback, never a cloud LLM) into a run-scoped review queue; `end` promotes/expires quarantined failures and releases the run's claims. Fleet-mode `session_prime {run_id, role}` returns a byte-stable cached brief (≤1,200 tokens) — 12 simultaneous primes share one prompt-cache prefix. **Distribute-once**: an orchestrator that primes one `{run_id, role, for_spawn: true}` per role gets that brief back as clean embeddable markdown (+ `brief_hash` + the `run_briefs` cache key) and embeds it in each same-role agent's spawn-prompt **prefix** — so the cacheable share of the fleet's prime cost becomes never-sent bytes (measured: a 12-agent / 4-role run's prime deliveries drop 12 → 4; bench `S3b` is −38.7% vs the `S3` floor). Agent-side prime stays the byte-identical CAS-row fallback, so a forgetful orchestrator degrades to the unchanged per-agent cost, never below.
48
+ - **A typed machine wire.** The 7 hot-path domains (capture, recall, search, failure, quest, session/prime, review) return schema-validated `structuredContent`; `content[0].text` is *derived* from it (plain ASCII default, `WYRM_FANCY=1` for glyphs); SEP-1303 structured errors fleets self-correct on; 100% of advertised tools annotated; `prime`/`debrief` exposed as MCP protocol-level prompts.
49
+ - **Single-channel wire (opt-in token economy).** `WYRM_CHANNEL` (vendor-neutral, set per MCP-client config) chooses which channel(s) ride the wire. Default **`both`** = today's exact bytes (no change unless you opt in). **`structured`** keeps the full `structuredContent` body byte-identical and collapses `content[0].text` to the template's summary line + a "full body in structuredContent" pointer — **lossless by construction** (the text was always *derived* from the body) and protocol-valid, but requires that your harness forwards `structuredContent` to the model. **`text`** drops `structuredContent` and keeps the full prose (the human-complete derivation) — the lean mode for harnesses that read text only; **note:** a strict MCP client rejects a body-less response for a tool that declares an `outputSchema`, so `text` is for non-strict / text-only consumers. Measured on `bench/token-economy.mjs --channel`: an opted-in working hour drops **~40%** (`structured`) to **~49%** (`text`); recall (82% of that hour) is the lever. `session_rehydrate` is exempt (its briefing markdown *is* the payload).
50
+ - **CLI exile + deletions.** 22 operator/egress tools moved to `wyrm` subcommands — their MCP names return a structured redirect with the exact command (`wyrm_cloud_backup`/`wyrm_sync_export` keep executing through 7.0.x so scheduled backups never silently stop). The legacy `wyrm-http` server is **deleted** (its 6.18 access log measured zero traffic) — `wyrm serve` is the HTTP surface.
51
+
52
+ **Compatibility:** all 137 names callable; text output reformats (exact-string consumers pin the 6.x line — kept on the `legacy` dist-tag (`wyrm-mcp@6.18.1`): `npm i wyrm-mcp@legacy`); a v6.x database opens with 100% rows (migrations 20–24, all additive + guarded). Per-name dispositions: `specs/wyrm-v7-brood/disposition.md` in the repo.
53
+
34
54
  ## New in 6.0 — "Present"
35
55
 
36
56
  - **Live statusline** — `wyrm-statusline` binary renders Wyrm's live state into your Claude Code (or Cursor / Windsurf) statusline: `Wyrm · ProjectName · 3 ⟶ · ~12k saved · ⬢ 7`. Auto-spawned daemon, idle-times-out, privacy mode for screen-shares.
37
57
  - **✧ Cross-project memory** — `wyrm_constellation` queries FTS5 across every registered Wyrm project at once. *"Have I solved this before in any project?"* Privacy-gated: per-row `cross_project_visibility` defaults to `'within'`.
38
- - **▰ Tool profiles** — `essential` / `standard` / `full` profiles auto-detected per client. VS Code Copilot / Cursor / Antigravity see a curated 27-tool surface; Claude Code / Codex / unknown clients get all 126. No functionality removed.
58
+ - **▰ Tool profiles** — `essential` / `standard` / `full` profiles. *(7.0: client-name auto-detection removed `WYRM_PROFILE` is the one lever; `full` = `legacy`.)*
39
59
  - **⊡ Cache markers** — `wyrm_context_build` segregates a stable preamble for Anthropic prompt-caching (10× cost cut on cached portions).
40
60
  - **↺ `wyrm_migrate_prompt`** — rewrite Wyrm-managed blocks in `.cursor/rules`, `.github/copilot-instructions.md`, `CLAUDE.md` idempotently. Operator content outside the markers is preserved verbatim.
41
61
 
@@ -44,7 +64,7 @@ Enable the statusline in Claude Code:
44
64
  { "statusLine": { "type": "command", "command": "wyrm-statusline", "padding": 0 } }
45
65
  ```
46
66
 
47
- ## What's in the box (126 MCP tools)
67
+ ## What's in the box (32 advertised tools · 137 names callable)
48
68
 
49
69
  - **⌇ Memory** — projects, sessions, quests, ground truths, memory artifacts, hybrid FTS5 + vector search
50
70
  - **✖ Counter-pattern** — failure check / record / resolve, blocks repeated mistakes at suggestion time
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Wyrm attribution read helpers (v7 F2, T008).
3
+ *
4
+ * @copyright 2026 Ghost Protocol (Pvt) Ltd.
5
+ * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
6
+ *
7
+ * Migration 20 adds nullable `agent_id`/`run_id` attribution columns to 9
8
+ * tables. Every row written before v7 — and any v7 row written outside a fleet
9
+ * run — carries NULL attribution. Article VI: a v6.x DB must open under v7
10
+ * with 100% of its rows, and that history must stay legibly attributed, so at
11
+ * every READ SITE that surfaces attribution, NULL reads as actor='legacy'.
12
+ *
13
+ * Precedence when rendering "who did this" (the same order is documented in
14
+ * migration 20 next to the events.agent_id column):
15
+ * 1. agent_id — machine identity (v7 fleet writes)
16
+ * 2. actor — display identity (the existing 6.x column on
17
+ * events/audit_log; it is EXTENDED, never replaced)
18
+ * 3. LEGACY_ACTOR — 'legacy' (neither set: a pre-v7 row)
19
+ *
20
+ * Wire paths (eventsForPush, ingestRemoteEvent, replication) intentionally do
21
+ * NOT coalesce: NULL stays NULL in storage and on the wire so replication
22
+ * round-trips are byte-faithful. 'legacy' is a READ-TIME presentation value
23
+ * only — it is never written back to the database.
24
+ */
25
+ /** What NULL attribution reads as at attribution-surfacing read sites. */
26
+ export declare const LEGACY_ACTOR = "legacy";
27
+ /**
28
+ * Read a display actor from a nullable actor column.
29
+ * NULL/undefined/blank -> 'legacy'; anything else passes through trimmed.
30
+ */
31
+ export declare function readActor(actor?: string | null): string;
32
+ /** The attribution fields migration 20 adds (all nullable). */
33
+ export interface AttributedRow {
34
+ agent_id?: string | null;
35
+ run_id?: string | null;
36
+ /** Existing display-identity column on events/audit_log (6.x). */
37
+ actor?: string | null;
38
+ }
39
+ export interface ResolvedAttribution {
40
+ /** Display identity, never null: agent_id > actor > 'legacy'. */
41
+ actor: string;
42
+ agent_id: string | null;
43
+ run_id: string | null;
44
+ }
45
+ /**
46
+ * Resolve the full attribution for one row using the documented precedence.
47
+ * Use this at any read site that surfaces who/which-run produced a row
48
+ * (failure_check verdicts, wyrm_stats view=failures, event displays).
49
+ */
50
+ export declare function resolveAttribution(row: AttributedRow): ResolvedAttribution;
51
+ //# sourceMappingURL=attribution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../src/attribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGvD;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,mBAAmB,CAQ1E"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Wyrm attribution read helpers (v7 F2, T008).
3
+ *
4
+ * @copyright 2026 Ghost Protocol (Pvt) Ltd.
5
+ * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
6
+ *
7
+ * Migration 20 adds nullable `agent_id`/`run_id` attribution columns to 9
8
+ * tables. Every row written before v7 — and any v7 row written outside a fleet
9
+ * run — carries NULL attribution. Article VI: a v6.x DB must open under v7
10
+ * with 100% of its rows, and that history must stay legibly attributed, so at
11
+ * every READ SITE that surfaces attribution, NULL reads as actor='legacy'.
12
+ *
13
+ * Precedence when rendering "who did this" (the same order is documented in
14
+ * migration 20 next to the events.agent_id column):
15
+ * 1. agent_id — machine identity (v7 fleet writes)
16
+ * 2. actor — display identity (the existing 6.x column on
17
+ * events/audit_log; it is EXTENDED, never replaced)
18
+ * 3. LEGACY_ACTOR — 'legacy' (neither set: a pre-v7 row)
19
+ *
20
+ * Wire paths (eventsForPush, ingestRemoteEvent, replication) intentionally do
21
+ * NOT coalesce: NULL stays NULL in storage and on the wire so replication
22
+ * round-trips are byte-faithful. 'legacy' is a READ-TIME presentation value
23
+ * only — it is never written back to the database.
24
+ */
25
+ /** What NULL attribution reads as at attribution-surfacing read sites. */
26
+ export const LEGACY_ACTOR = 'legacy';
27
+ /**
28
+ * Read a display actor from a nullable actor column.
29
+ * NULL/undefined/blank -> 'legacy'; anything else passes through trimmed.
30
+ */
31
+ export function readActor(actor) {
32
+ const a = typeof actor === 'string' ? actor.trim() : '';
33
+ return a !== '' ? a : LEGACY_ACTOR;
34
+ }
35
+ /**
36
+ * Resolve the full attribution for one row using the documented precedence.
37
+ * Use this at any read site that surfaces who/which-run produced a row
38
+ * (failure_check verdicts, wyrm_stats view=failures, event displays).
39
+ */
40
+ export function resolveAttribution(row) {
41
+ const agentId = row.agent_id ?? null;
42
+ const runId = row.run_id ?? null;
43
+ return {
44
+ actor: agentId ?? readActor(row.actor),
45
+ agent_id: agentId,
46
+ run_id: runId,
47
+ };
48
+ }
49
+ //# sourceMappingURL=attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribution.js","sourceRoot":"","sources":["../src/attribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACrC,CAAC;AAiBD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAkB;IACnD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC;IACjC,OAAO;QACL,KAAK,EAAE,OAAO,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;QACtC,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,KAAK;KACd,CAAC;AACJ,CAAC"}
package/dist/audit.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Compliance audit trail (Tier 3.9).
2
+ * Compliance audit trail (Tier 3.9) — per-agent attribution + versioned
3
+ * Ed25519 signing (v7 F2, T010).
3
4
  *
4
5
  * Hash-chained event log: each row records sha256(prev_hash || payload ||
5
6
  * timestamp). Tampering with any historical entry breaks the chain.
@@ -10,13 +11,59 @@
10
11
  * `wyrm_audit_export(range)` produces a tamper-evident JSON bundle that
11
12
  * an external auditor can verify offline:
12
13
  * 1. Recompute the hash chain from genesis through the range.
13
- * 2. Verify Ed25519 signatures against the operator's public key.
14
+ * 2. Verify Ed25519 signatures against the operator's public key(s).
14
15
  * 3. Confirm no gaps in IDs.
15
16
  *
17
+ * ## Signed-payload versioning (v7 F2, T010)
18
+ *
19
+ * Migration 20's `agent_id`/`run_id` columns are NOT part of the hash-chain
20
+ * input — the chain rule is byte-identical to 6.x:
21
+ *
22
+ * row_hash = sha256(`${prev_hash}|${event_kind}|${payload_json}|${logged_at}`)
23
+ *
24
+ * so a 6.x DB opened under v7 keeps verifying and the v1→v2 transition can
25
+ * never break the chain (old rows verify as v1, new rows as v2, one chain).
26
+ * Attribution is instead bound TAMPER-EVIDENTLY into the Ed25519 signature
27
+ * via a payload-version byte:
28
+ *
29
+ * v1 (legacy 6.x): signed message = utf8(row_hash) — no attribution
30
+ * stored signature = bare base64 (unchanged on old rows)
31
+ * v2 (v7): signed message = 0x02 ‖ utf8(JSON.stringify(
32
+ * { row_hash, agent_id, run_id })) — attribution bound
33
+ * stored signature = `v2:<key_fp16>:<base64>`
34
+ *
35
+ * The leading 0x02 version byte domain-separates the payloads (a v1 message
36
+ * is 64 ASCII-hex bytes and can never begin with 0x02), and the canonical
37
+ * JSON body (fixed key order, NULLs preserved) makes the agent_id/run_id
38
+ * field boundaries unambiguous — no delimiter-shifting forgeries.
39
+ * `key_fp16` = first 16 hex chars of sha256(SPKI DER of the signing public
40
+ * key): the "which key" answer, claimed in the row and CONFIRMED whenever
41
+ * public keys are handed to `verify()`.
42
+ *
43
+ * ## The rule for 6.x verifiers (explicit — locked by tests/audit-attribution.test.ts)
44
+ *
45
+ * The verify structure 6.x actually shipped (`verify()` / `verifyBundle()`)
46
+ * checks ONLY the hash chain and never parses the `signature` column.
47
+ * Therefore:
48
+ * (a) a 6.x verifier verifies BOTH v1 and v2 rows exactly as today — the
49
+ * chain rule is unchanged, mixed v1/v2 chains pass, and exported
50
+ * bundles remain version-1 bundles that 6.x `verifyBundle()` accepts;
51
+ * (b) a 6.x auditor's out-of-band Ed25519 step ("signature of the
52
+ * row_hash") FAILS CLOSED on a v2 row: the stored `v2:`-prefixed value
53
+ * is not the base64 of an Ed25519 signature over the row_hash, so the
54
+ * 6.x signature check reports INVALID — it can never silently accept a
55
+ * v7 signature (and so can never silently accept forged attribution).
56
+ * The chain walk itself stays green.
57
+ *
58
+ * Signing is OPT-IN (Articles I & VII): no key configured → rows are written
59
+ * unsigned, byte-identical to 6.x behavior. `WYRM_AUDIT_SIGNING_KEY` holds a
60
+ * PEM-encoded (pkcs8) Ed25519 private key, or a path to one.
61
+ *
16
62
  * @copyright 2024-2026 Ghost Protocol (Pvt) Ltd.
17
63
  * @license AGPL-3.0-or-later — dual-licensed; commercial terms: ghosts.lk@proton.me. See LICENSE.
18
64
  */
19
65
  import type Database from 'better-sqlite3';
66
+ import { KeyObject } from 'crypto';
20
67
  export interface AuditEntry {
21
68
  id: number;
22
69
  event_kind: string;
@@ -27,13 +74,24 @@ export interface AuditEntry {
27
74
  row_hash: string;
28
75
  signature: string | null;
29
76
  logged_at: string;
77
+ /** v7 F2 (migration 20): machine attribution columns. NULL on pre-v7 rows
78
+ * (reads as actor='legacy'). NOT part of the hash chain — the v2 signed
79
+ * payload (T010) is what binds them tamper-evidently. */
80
+ agent_id: string | null;
81
+ run_id: string | null;
30
82
  }
31
83
  export interface LogInput {
32
84
  event_kind: string;
33
85
  actor?: string | null;
34
86
  project_id?: number | null;
35
87
  payload: Record<string, unknown>;
88
+ /** Explicit caller-supplied signature (stored as-is — the legacy 6.x v1
89
+ * path). When omitted and a signer is configured, the entry is auto-signed
90
+ * with a v2 attribution-binding signature. */
36
91
  signature?: string | null;
92
+ /** v7 F2 (T009): omitted → stamped from the ambient actor envelope. */
93
+ agent_id?: string | null;
94
+ run_id?: string | null;
37
95
  }
38
96
  export interface AuditBundle {
39
97
  version: 1;
@@ -49,24 +107,135 @@ export interface AuditBundle {
49
107
  final_row_hash: string;
50
108
  entries: AuditEntry[];
51
109
  }
110
+ /** v7 F2 (T010): signature-layer report — present when public keys are
111
+ * handed to verify()/verifyBundle(). Chain and signature layers are reported
112
+ * separately so a chain-intact/signature-forged DB is precisely described. */
113
+ export interface AuditSignatureReport {
114
+ /** Rows carrying any signature (v1 or v2) that were checked. */
115
+ checked: number;
116
+ valid: number;
117
+ invalid: number;
118
+ first_invalid_id?: number;
119
+ reason?: string;
120
+ }
52
121
  export interface VerificationResult {
53
122
  ok: boolean;
54
123
  total: number;
55
124
  verified: number;
56
125
  first_invalid_id?: number;
57
126
  reason?: string;
127
+ /** v7 F2 (T010): rows by signed-payload version (v1 legacy / v2 attribution
128
+ * / unsigned). Computed whenever the chain verifies. */
129
+ payload_versions?: {
130
+ v1: number;
131
+ v2: number;
132
+ unsigned: number;
133
+ };
134
+ /** v7 F2 (T010): who / which-run / which-key across the verified rows.
135
+ * `agents` are resolved display identities (NULL attribution reads as
136
+ * 'legacy' per Article VI); `keys` are signing-key fingerprints seen. */
137
+ attribution?: {
138
+ agents: string[];
139
+ runs: string[];
140
+ keys: string[];
141
+ };
142
+ /** v7 F2 (T010): only present when public keys were provided. */
143
+ signatures?: AuditSignatureReport;
144
+ }
145
+ /** Stored-signature prefix marking a v2 (attribution-binding) signature. */
146
+ export declare const AUDIT_SIG_V2_PREFIX = "v2:";
147
+ export type AuditPayloadVersion = 1 | 2;
148
+ export interface ParsedAuditSignature {
149
+ version: AuditPayloadVersion;
150
+ /** Claimed signing-key fingerprint (v2 only; null when absent/malformed). */
151
+ key_fp: string | null;
152
+ sig_b64: string;
58
153
  }
154
+ /**
155
+ * Classify a stored signature string by payload version.
156
+ * Bare base64 (anything without the `v2:` prefix) = v1 legacy; `v2:<fp>:<b64>`
157
+ * = v2. Returns null for unsigned (NULL/empty). Never throws.
158
+ */
159
+ export declare function parseAuditSignature(signature: string | null | undefined): ParsedAuditSignature | null;
160
+ /** Fingerprint of an Ed25519 public key: sha256 over the SPKI DER, first 16 hex. */
161
+ export declare function auditKeyFingerprint(publicKey: string | KeyObject): string;
162
+ /**
163
+ * Build the exact byte string an audit Ed25519 signature covers.
164
+ * v1: utf8(row_hash) — the legacy 6.x payload, no attribution.
165
+ * v2: 0x02 version byte ‖ utf8(JSON.stringify({row_hash, agent_id, run_id})).
166
+ */
167
+ export declare function buildSignedPayload(version: AuditPayloadVersion, fields: {
168
+ row_hash: string;
169
+ agent_id?: string | null;
170
+ run_id?: string | null;
171
+ }): Buffer;
172
+ /** A loaded Ed25519 signing identity (per-agent: each agent process may run
173
+ * with its own key via WYRM_AUDIT_SIGNING_KEY). */
174
+ export interface AuditSigner {
175
+ privateKey: KeyObject;
176
+ publicKeyPem: string;
177
+ key_fp: string;
178
+ }
179
+ /** Materialize a signer from a PEM (pkcs8) Ed25519 private key; the public
180
+ * half and fingerprint are derived. Throws on non-Ed25519 keys. */
181
+ export declare function createAuditSigner(privateKeyPem: string): AuditSigner;
182
+ /** Sign the v2 payload for a row. Returns the stored form `v2:<fp>:<base64>`. */
183
+ export declare function signAuditEntry(signer: AuditSigner, fields: {
184
+ row_hash: string;
185
+ agent_id?: string | null;
186
+ run_id?: string | null;
187
+ }): string;
188
+ /**
189
+ * Opt-in signer bootstrap (Articles I & VII): `WYRM_AUDIT_SIGNING_KEY` is a
190
+ * PEM string or a path to a PEM file. Absent → null (rows stay unsigned —
191
+ * exactly the 6.x behavior). Unusable → warn on STDERR (stdout is the MCP
192
+ * wire) and run unsigned; never throws.
193
+ */
194
+ export declare function loadAuditSignerFromEnv(env?: NodeJS.ProcessEnv): AuditSigner | null;
195
+ export interface AuditSignatureCheck {
196
+ ok: boolean;
197
+ /** null = the row carries no signature (not a failure). */
198
+ version: AuditPayloadVersion | null;
199
+ /** v2: the claimed fingerprint; v1-valid: the fingerprint of the key that verified. */
200
+ key_fp: string | null;
201
+ reason?: string;
202
+ }
203
+ /**
204
+ * Verify ONE row's signature against a set of public keys (PEM or KeyObject).
205
+ * Fail-closed: malformed signatures, unknown fingerprints, undecodable
206
+ * base64, and crypto-layer rejections all report ok=false. Never throws.
207
+ */
208
+ export declare function verifyAuditEntrySignature(row: Pick<AuditEntry, 'row_hash' | 'signature' | 'agent_id' | 'run_id'>, publicKeys: Array<string | KeyObject>): AuditSignatureCheck;
59
209
  export declare class AuditLog {
60
210
  private db;
61
- constructor(db: Database.Database);
211
+ private signer;
212
+ constructor(db: Database.Database, signer?: AuditSigner | null);
213
+ /** Swap or clear the signing identity (key rotation, tests). */
214
+ setSigner(signer: AuditSigner | null): void;
62
215
  /** Get the hash of the most recent entry (or 'genesis' if empty). */
63
216
  private latestHash;
64
- /** Append a hash-chained event. Returns the inserted row. */
217
+ /** Append a hash-chained event. Returns the inserted row.
218
+ *
219
+ * v7 F2 review fix: the head-read + INSERT pair runs in ONE transaction
220
+ * declared IMMEDIATE, so BEGIN takes the cross-process write lock BEFORE
221
+ * latestHash() reads the chain head. Two concurrent OS processes appending
222
+ * (the T010 per-agent-key fleet shape — audit ops are not in
223
+ * DAEMON_WRITE_OPS, so fleet agents write audit_log directly) could
224
+ * otherwise both read head H and both insert prev_hash=H, FORKING the
225
+ * chain — after which verify() reports the compliance log as tampered
226
+ * forever on legitimate writes. */
65
227
  log(input: LogInput): AuditEntry;
66
228
  get(id: number): AuditEntry | null;
67
229
  /** Verify the entire chain from the first row through the latest.
68
- * Useful for periodic self-audits. */
69
- verify(): VerificationResult;
230
+ * Useful for periodic self-audits.
231
+ *
232
+ * v7 F2 (T010): pass `publicKeys` (PEM strings) to additionally verify the
233
+ * Ed25519 signature layer; the report then answers who / which-run /
234
+ * which-key. Without keys the result is the 6.x chain-only semantics plus
235
+ * the attribution summary. */
236
+ verify(opts?: {
237
+ publicKeys?: string[];
238
+ }): VerificationResult;
70
239
  /** Export a date-ranged tamper-evident bundle. Range is inclusive on
71
240
  * both ends. Verification still walks from genesis to ensure no gaps. */
72
241
  export(opts: {
@@ -74,8 +243,15 @@ export declare class AuditLog {
74
243
  range_end?: string;
75
244
  }): AuditBundle;
76
245
  /** Statically verify a previously-exported bundle (no DB required).
77
- * Useful for the external auditor who only has the JSON file. */
78
- static verifyBundle(bundle: AuditBundle): VerificationResult;
246
+ * Useful for the external auditor who only has the JSON file.
247
+ *
248
+ * The chain walk is the unchanged 6.x structure — it never parses
249
+ * signatures, so mixed v1/v2 bundles verify exactly as they did under 6.x.
250
+ * v7 F2 (T010): optional `publicKeys` adds the signature-layer check, same
251
+ * as the instance `verify()`. */
252
+ static verifyBundle(bundle: AuditBundle, opts?: {
253
+ publicKeys?: string[];
254
+ }): VerificationResult;
79
255
  /** Slim query for recent entries — UI / dashboards. */
80
256
  recent(limit?: number, kind?: string): AuditEntry[];
81
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,QAAQ;IACP,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,qEAAqE;IACrE,OAAO,CAAC,UAAU;IAOlB,6DAA6D;IAC7D,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU;IAwBhC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAMlC;0CACsC;IACtC,MAAM,IAAI,kBAAkB;IA8B5B;6EACyE;IACzE,MAAM,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW;IA+BvE;qEACiE;IACjE,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,kBAAkB;IAoC5D,uDAAuD;IACvD,MAAM,CAAC,KAAK,SAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;CAUjD"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}