@runcore-sh/runcore 0.1.8 → 0.1.10

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 (225) hide show
  1. package/dist/access/manifest.d.ts +59 -0
  2. package/dist/access/manifest.d.ts.map +1 -0
  3. package/dist/access/manifest.js +251 -0
  4. package/dist/access/manifest.js.map +1 -0
  5. package/dist/activity/log.d.ts +1 -1
  6. package/dist/activity/log.d.ts.map +1 -1
  7. package/dist/agents/autonomous.d.ts.map +1 -1
  8. package/dist/agents/autonomous.js +38 -0
  9. package/dist/agents/autonomous.js.map +1 -1
  10. package/dist/agents/governance.d.ts +70 -0
  11. package/dist/agents/governance.d.ts.map +1 -0
  12. package/dist/agents/governance.js +220 -0
  13. package/dist/agents/governance.js.map +1 -0
  14. package/dist/agents/governed-spawn.d.ts +83 -0
  15. package/dist/agents/governed-spawn.d.ts.map +1 -0
  16. package/dist/agents/governed-spawn.js +186 -0
  17. package/dist/agents/governed-spawn.js.map +1 -0
  18. package/dist/agents/heartbeat.d.ts +91 -0
  19. package/dist/agents/heartbeat.d.ts.map +1 -0
  20. package/dist/agents/heartbeat.js +323 -0
  21. package/dist/agents/heartbeat.js.map +1 -0
  22. package/dist/agents/index.d.ts +4 -1
  23. package/dist/agents/index.d.ts.map +1 -1
  24. package/dist/agents/index.js +6 -1
  25. package/dist/agents/index.js.map +1 -1
  26. package/dist/agents/spawn-policy.d.ts +45 -0
  27. package/dist/agents/spawn-policy.d.ts.map +1 -0
  28. package/dist/agents/spawn-policy.js +202 -0
  29. package/dist/agents/spawn-policy.js.map +1 -0
  30. package/dist/alert.d.ts +16 -0
  31. package/dist/alert.d.ts.map +1 -0
  32. package/dist/alert.js +70 -0
  33. package/dist/alert.js.map +1 -0
  34. package/dist/cli.js +261 -32
  35. package/dist/cli.js.map +1 -1
  36. package/dist/credentials/store.d.ts +1 -1
  37. package/dist/credentials/store.d.ts.map +1 -1
  38. package/dist/credentials/store.js +14 -3
  39. package/dist/credentials/store.js.map +1 -1
  40. package/dist/crystallizer.d.ts +56 -0
  41. package/dist/crystallizer.d.ts.map +1 -0
  42. package/dist/crystallizer.js +159 -0
  43. package/dist/crystallizer.js.map +1 -0
  44. package/dist/distiller.d.ts +48 -0
  45. package/dist/distiller.d.ts.map +1 -0
  46. package/dist/distiller.js +140 -0
  47. package/dist/distiller.js.map +1 -0
  48. package/dist/files/deep-index.d.ts +59 -0
  49. package/dist/files/deep-index.d.ts.map +1 -0
  50. package/dist/files/deep-index.js +337 -0
  51. package/dist/files/deep-index.js.map +1 -0
  52. package/dist/files/import.d.ts +44 -0
  53. package/dist/files/import.d.ts.map +1 -0
  54. package/dist/files/import.js +213 -0
  55. package/dist/files/import.js.map +1 -0
  56. package/dist/files/index-local.d.ts +37 -0
  57. package/dist/files/index-local.d.ts.map +1 -0
  58. package/dist/files/index-local.js +198 -0
  59. package/dist/files/index-local.js.map +1 -0
  60. package/dist/google/auth.d.ts +2 -0
  61. package/dist/google/auth.d.ts.map +1 -1
  62. package/dist/google/auth.js +2 -0
  63. package/dist/google/auth.js.map +1 -1
  64. package/dist/integrations/gate.d.ts +40 -0
  65. package/dist/integrations/gate.d.ts.map +1 -0
  66. package/dist/integrations/gate.js +100 -0
  67. package/dist/integrations/gate.js.map +1 -0
  68. package/dist/lib/audit.d.ts +43 -0
  69. package/dist/lib/audit.d.ts.map +1 -0
  70. package/dist/lib/audit.js +120 -0
  71. package/dist/lib/audit.js.map +1 -0
  72. package/dist/lib/brain-io.d.ts.map +1 -1
  73. package/dist/lib/brain-io.js +52 -0
  74. package/dist/lib/brain-io.js.map +1 -1
  75. package/dist/lib/dpapi.d.ts +14 -0
  76. package/dist/lib/dpapi.d.ts.map +1 -0
  77. package/dist/lib/dpapi.js +104 -0
  78. package/dist/lib/dpapi.js.map +1 -0
  79. package/dist/lib/glob-match.d.ts +22 -0
  80. package/dist/lib/glob-match.d.ts.map +1 -0
  81. package/dist/lib/glob-match.js +64 -0
  82. package/dist/lib/glob-match.js.map +1 -0
  83. package/dist/lib/locked.d.ts +40 -0
  84. package/dist/lib/locked.d.ts.map +1 -0
  85. package/dist/lib/locked.js +130 -0
  86. package/dist/lib/locked.js.map +1 -0
  87. package/dist/llm/complete.d.ts.map +1 -1
  88. package/dist/llm/complete.js +5 -2
  89. package/dist/llm/complete.js.map +1 -1
  90. package/dist/llm/fetch-guard.d.ts +16 -0
  91. package/dist/llm/fetch-guard.d.ts.map +1 -0
  92. package/dist/llm/fetch-guard.js +61 -0
  93. package/dist/llm/fetch-guard.js.map +1 -0
  94. package/dist/llm/guard.d.ts +40 -0
  95. package/dist/llm/guard.d.ts.map +1 -0
  96. package/dist/llm/guard.js +88 -0
  97. package/dist/llm/guard.js.map +1 -0
  98. package/dist/llm/membrane.d.ts +46 -0
  99. package/dist/llm/membrane.d.ts.map +1 -0
  100. package/dist/llm/membrane.js +123 -0
  101. package/dist/llm/membrane.js.map +1 -0
  102. package/dist/llm/providers/index.d.ts +5 -1
  103. package/dist/llm/providers/index.d.ts.map +1 -1
  104. package/dist/llm/providers/index.js +8 -1
  105. package/dist/llm/providers/index.js.map +1 -1
  106. package/dist/llm/redact.d.ts +39 -0
  107. package/dist/llm/redact.d.ts.map +1 -0
  108. package/dist/llm/redact.js +155 -0
  109. package/dist/llm/redact.js.map +1 -0
  110. package/dist/llm/sensitive-registry.d.ts +33 -0
  111. package/dist/llm/sensitive-registry.d.ts.map +1 -0
  112. package/dist/llm/sensitive-registry.js +106 -0
  113. package/dist/llm/sensitive-registry.js.map +1 -0
  114. package/dist/mcp-server.d.ts +11 -0
  115. package/dist/mcp-server.d.ts.map +1 -0
  116. package/dist/mcp-server.js +520 -0
  117. package/dist/mcp-server.js.map +1 -0
  118. package/dist/mdns.d.ts +17 -0
  119. package/dist/mdns.d.ts.map +1 -0
  120. package/dist/mdns.js +110 -0
  121. package/dist/mdns.js.map +1 -0
  122. package/dist/nerve/push.d.ts +26 -0
  123. package/dist/nerve/push.d.ts.map +1 -0
  124. package/dist/nerve/push.js +170 -0
  125. package/dist/nerve/push.js.map +1 -0
  126. package/dist/nerve/state.d.ts +35 -0
  127. package/dist/nerve/state.d.ts.map +1 -0
  128. package/dist/nerve/state.js +257 -0
  129. package/dist/nerve/state.js.map +1 -0
  130. package/dist/posture/engine.d.ts +41 -0
  131. package/dist/posture/engine.d.ts.map +1 -0
  132. package/dist/posture/engine.js +217 -0
  133. package/dist/posture/engine.js.map +1 -0
  134. package/dist/posture/index.d.ts +11 -0
  135. package/dist/posture/index.d.ts.map +1 -0
  136. package/dist/posture/index.js +10 -0
  137. package/dist/posture/index.js.map +1 -0
  138. package/dist/posture/middleware.d.ts +30 -0
  139. package/dist/posture/middleware.d.ts.map +1 -0
  140. package/dist/posture/middleware.js +92 -0
  141. package/dist/posture/middleware.js.map +1 -0
  142. package/dist/posture/types.d.ts +61 -0
  143. package/dist/posture/types.d.ts.map +1 -0
  144. package/dist/posture/types.js +48 -0
  145. package/dist/posture/types.js.map +1 -0
  146. package/dist/resend/inbox.d.ts +23 -0
  147. package/dist/resend/inbox.d.ts.map +1 -0
  148. package/dist/resend/inbox.js +198 -0
  149. package/dist/resend/inbox.js.map +1 -0
  150. package/dist/resend/webhooks.d.ts +30 -0
  151. package/dist/resend/webhooks.d.ts.map +1 -0
  152. package/dist/resend/webhooks.js +244 -0
  153. package/dist/resend/webhooks.js.map +1 -0
  154. package/dist/server.d.ts +5 -1
  155. package/dist/server.d.ts.map +1 -1
  156. package/dist/server.js +773 -58
  157. package/dist/server.js.map +1 -1
  158. package/dist/settings.d.ts +14 -1
  159. package/dist/settings.d.ts.map +1 -1
  160. package/dist/settings.js +32 -1
  161. package/dist/settings.js.map +1 -1
  162. package/dist/tier/bond.d.ts +51 -0
  163. package/dist/tier/bond.d.ts.map +1 -0
  164. package/dist/tier/bond.js +154 -0
  165. package/dist/tier/bond.js.map +1 -0
  166. package/dist/tier/freeze.d.ts +21 -0
  167. package/dist/tier/freeze.d.ts.map +1 -0
  168. package/dist/tier/freeze.js +73 -0
  169. package/dist/tier/freeze.js.map +1 -0
  170. package/dist/tier/gate.d.ts +11 -0
  171. package/dist/tier/gate.d.ts.map +1 -0
  172. package/dist/tier/gate.js +25 -0
  173. package/dist/tier/gate.js.map +1 -0
  174. package/dist/tier/heartbeat.d.ts +22 -0
  175. package/dist/tier/heartbeat.d.ts.map +1 -0
  176. package/dist/tier/heartbeat.js +128 -0
  177. package/dist/tier/heartbeat.js.map +1 -0
  178. package/dist/tier/token.d.ts +22 -0
  179. package/dist/tier/token.d.ts.map +1 -0
  180. package/dist/tier/token.js +100 -0
  181. package/dist/tier/token.js.map +1 -0
  182. package/dist/tier/types.d.ts +44 -0
  183. package/dist/tier/types.d.ts.map +1 -0
  184. package/dist/tier/types.js +61 -0
  185. package/dist/tier/types.js.map +1 -0
  186. package/dist/updater.d.ts +32 -0
  187. package/dist/updater.d.ts.map +1 -0
  188. package/dist/updater.js +145 -0
  189. package/dist/updater.js.map +1 -0
  190. package/dist/vault/policy.d.ts +42 -0
  191. package/dist/vault/policy.d.ts.map +1 -0
  192. package/dist/vault/policy.js +159 -0
  193. package/dist/vault/policy.js.map +1 -0
  194. package/dist/vault/store.d.ts +6 -0
  195. package/dist/vault/store.d.ts.map +1 -1
  196. package/dist/vault/store.js +15 -5
  197. package/dist/vault/store.js.map +1 -1
  198. package/dist/vault/transfer.d.ts +33 -0
  199. package/dist/vault/transfer.d.ts.map +1 -0
  200. package/dist/vault/transfer.js +187 -0
  201. package/dist/vault/transfer.js.map +1 -0
  202. package/dist/voucher.d.ts +39 -0
  203. package/dist/voucher.d.ts.map +1 -0
  204. package/dist/voucher.js +105 -0
  205. package/dist/voucher.js.map +1 -0
  206. package/dist/webhooks/handlers.d.ts +10 -0
  207. package/dist/webhooks/handlers.d.ts.map +1 -1
  208. package/dist/webhooks/handlers.js +53 -0
  209. package/dist/webhooks/handlers.js.map +1 -1
  210. package/dist/webhooks/index.d.ts +2 -2
  211. package/dist/webhooks/index.d.ts.map +1 -1
  212. package/dist/webhooks/index.js +2 -2
  213. package/dist/webhooks/index.js.map +1 -1
  214. package/dist/webhooks/verify.d.ts +8 -0
  215. package/dist/webhooks/verify.d.ts.map +1 -1
  216. package/dist/webhooks/verify.js +56 -0
  217. package/dist/webhooks/verify.js.map +1 -1
  218. package/package.json +8 -2
  219. package/public/board.html +8 -3
  220. package/public/browser.html +8 -3
  221. package/public/library.html +8 -3
  222. package/public/observatory.html +8 -3
  223. package/public/ops.html +8 -3
  224. package/public/registry.html +627 -0
  225. package/public/roadmap.html +975 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Audit logging for brain file access.
3
+ * Appends access records to brain/ops/audit.jsonl.
4
+ * Uses AsyncLocalStorage to track caller identity (MCP tool, HTTP route, etc.).
5
+ *
6
+ * Fire-and-forget — audit failures never block or crash the caller.
7
+ */
8
+ import { AsyncLocalStorage } from "node:async_hooks";
9
+ import { appendFile } from "node:fs/promises";
10
+ import { appendFileSync, mkdirSync, existsSync } from "node:fs";
11
+ import { join, relative } from "node:path";
12
+ import { createLogger } from "../utils/logger.js";
13
+ const log = createLogger("audit");
14
+ // ── Caller context via AsyncLocalStorage ─────────────────────────────────────
15
+ const auditContextStore = new AsyncLocalStorage();
16
+ /**
17
+ * Run a function with audit context. All brain file reads within the callback
18
+ * will be tagged with the given caller and channel.
19
+ */
20
+ export function runWithAuditContext(ctx, fn) {
21
+ return auditContextStore.run(ctx, fn);
22
+ }
23
+ /** Get the current audit context (if set). */
24
+ export function getAuditContext() {
25
+ return auditContextStore.getStore();
26
+ }
27
+ // ── File setup ───────────────────────────────────────────────────────────────
28
+ const BRAIN_DIR = join(process.cwd(), "brain");
29
+ const OPS_DIR = join(BRAIN_DIR, "ops");
30
+ const AUDIT_FILE = join(OPS_DIR, "audit.jsonl");
31
+ const SCHEMA_LINE = JSON.stringify({
32
+ _schema: "audit",
33
+ _version: "1.0",
34
+ _fields: "timestamp,file,method,caller,channel",
35
+ });
36
+ let fileEnsured = false;
37
+ function ensureFile() {
38
+ if (fileEnsured)
39
+ return;
40
+ try {
41
+ if (!existsSync(OPS_DIR)) {
42
+ mkdirSync(OPS_DIR, { recursive: true });
43
+ }
44
+ if (!existsSync(AUDIT_FILE)) {
45
+ appendFileSync(AUDIT_FILE, SCHEMA_LINE + "\n", "utf-8");
46
+ }
47
+ fileEnsured = true;
48
+ }
49
+ catch (err) {
50
+ log.debug(`Failed to ensure audit file: ${err instanceof Error ? err.message : String(err)}`);
51
+ }
52
+ }
53
+ // ── Core logging ─────────────────────────────────────────────────────────────
54
+ /**
55
+ * Resolve a full path to a relative brain path for cleaner logs.
56
+ * Returns the path as-is if it's not under brain/.
57
+ */
58
+ function toBrainRelative(filePath) {
59
+ try {
60
+ const rel = relative(BRAIN_DIR, filePath);
61
+ // If the relative path escapes brain/, return the original
62
+ if (rel.startsWith("..") || rel.startsWith("/"))
63
+ return filePath;
64
+ return rel.replace(/\\/g, "/");
65
+ }
66
+ catch {
67
+ return filePath;
68
+ }
69
+ }
70
+ /**
71
+ * Log a brain file read. Fire-and-forget (async).
72
+ * Skips logging reads of the audit file itself to avoid recursion.
73
+ */
74
+ export function logAccess(filePath, method) {
75
+ // Prevent recursive audit of the audit file
76
+ if (filePath === AUDIT_FILE)
77
+ return;
78
+ const ctx = auditContextStore.getStore();
79
+ const entry = {
80
+ timestamp: new Date().toISOString(),
81
+ file: toBrainRelative(filePath),
82
+ method,
83
+ caller: ctx?.caller,
84
+ channel: ctx?.channel,
85
+ };
86
+ try {
87
+ ensureFile();
88
+ const line = JSON.stringify(entry);
89
+ // Async append — fire-and-forget
90
+ appendFile(AUDIT_FILE, line + "\n", "utf-8").catch((err) => {
91
+ log.debug(`Audit write failed: ${err instanceof Error ? err.message : String(err)}`);
92
+ });
93
+ }
94
+ catch (err) {
95
+ log.debug(`Audit log error: ${err instanceof Error ? err.message : String(err)}`);
96
+ }
97
+ }
98
+ /**
99
+ * Synchronous variant for use in readBrainLinesSync.
100
+ */
101
+ export function logAccessSync(filePath, method) {
102
+ if (filePath === AUDIT_FILE)
103
+ return;
104
+ const ctx = auditContextStore.getStore();
105
+ const entry = {
106
+ timestamp: new Date().toISOString(),
107
+ file: toBrainRelative(filePath),
108
+ method,
109
+ caller: ctx?.caller,
110
+ channel: ctx?.channel,
111
+ };
112
+ try {
113
+ ensureFile();
114
+ appendFileSync(AUDIT_FILE, JSON.stringify(entry) + "\n", "utf-8");
115
+ }
116
+ catch (err) {
117
+ log.debug(`Audit sync write failed: ${err instanceof Error ? err.message : String(err)}`);
118
+ }
119
+ }
120
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/lib/audit.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"brain-io.d.ts","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAyCH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBxE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1F;AAID;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrF;AAID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAInD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAO9E;AAID;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1F"}
1
+ {"version":3,"file":"brain-io.d.ts","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA+EH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BxE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ1F;AAID;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrF;AAID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAM5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAInD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAO9E;AAID;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1F"}
@@ -16,6 +16,10 @@ import { readFileSync, appendFileSync, mkdirSync, existsSync, } from "node:fs";
16
16
  import { dirname } from "node:path";
17
17
  import { createLogger } from "../utils/logger.js";
18
18
  import { getEncryptionKey, getWriteEncryptionKey } from "./key-store.js";
19
+ import { logAccess, logAccessSync } from "./audit.js";
20
+ import { assertNotLocked, toBrainRelativePath } from "./locked.js";
21
+ import { getAuditContext } from "./audit.js";
22
+ import { getManifest, canRead, canWrite } from "../access/manifest.js";
19
23
  const log = createLogger("brain-io");
20
24
  import { shouldEncryptFile } from "./encryption-config.js";
21
25
  import { encryptLine, decryptLine, isEncryptedLine, encryptFile, decryptFile, isEncryptedFile, } from "./encryption.js";
@@ -32,6 +36,37 @@ function writeKey(filePath) {
32
36
  return null;
33
37
  return getWriteEncryptionKey();
34
38
  }
39
+ // ── Access enforcement ───────────────────────────────────────────────────────
40
+ /**
41
+ * Assert that the current instance (from AuditContext) has access to the path.
42
+ * No-op when instanceName is undefined (backward compatible).
43
+ * Checks the instance's access manifest; logs denied access to audit.
44
+ *
45
+ * @param absolutePath - Absolute file path
46
+ * @param operation - "read" or "write"
47
+ */
48
+ function assertAccess(absolutePath, operation) {
49
+ const ctx = getAuditContext();
50
+ if (!ctx?.instanceName)
51
+ return; // No instance context — skip check
52
+ const relPath = toBrainRelativePath(absolutePath);
53
+ if (relPath === null)
54
+ return; // Not a brain path
55
+ const manifest = getManifest(ctx.instanceName);
56
+ if (!manifest)
57
+ return; // No manifest loaded — skip (permissive for unknown instances)
58
+ const allowed = operation === "read"
59
+ ? canRead(manifest, relPath)
60
+ : canWrite(manifest, relPath);
61
+ if (!allowed) {
62
+ log.warn("Access denied by manifest", {
63
+ instance: ctx.instanceName,
64
+ path: relPath,
65
+ operation,
66
+ });
67
+ throw new Error(`Access denied: ${ctx.instanceName} cannot ${operation} ${relPath}`);
68
+ }
69
+ }
35
70
  // ── Async JSONL (per-line) I/O ───────────────────────────────────────────────
36
71
  /**
37
72
  * Read a JSONL file, decrypting each line if needed.
@@ -39,6 +74,9 @@ function writeKey(filePath) {
39
74
  * Empty/whitespace lines are filtered out.
40
75
  */
41
76
  export async function readBrainLines(filePath) {
77
+ assertNotLocked(filePath);
78
+ assertAccess(filePath, "read");
79
+ logAccess(filePath, "readBrainLines");
42
80
  let raw;
43
81
  try {
44
82
  raw = await readFile(filePath, "utf-8");
@@ -68,6 +106,8 @@ export async function readBrainLines(filePath) {
68
106
  * The line should be a JSON string (not newline-terminated).
69
107
  */
70
108
  export async function appendBrainLine(filePath, jsonLine) {
109
+ assertNotLocked(filePath);
110
+ assertAccess(filePath, "write");
71
111
  const key = writeKey(filePath);
72
112
  const line = key ? encryptLine(jsonLine, key) : jsonLine;
73
113
  await appendFile(filePath, line + "\n", "utf-8");
@@ -77,6 +117,8 @@ export async function appendBrainLine(filePath, jsonLine) {
77
117
  * Used for compaction/rotation where the whole file is rewritten.
78
118
  */
79
119
  export async function writeBrainLines(filePath, jsonLines) {
120
+ assertNotLocked(filePath);
121
+ assertAccess(filePath, "write");
80
122
  const key = writeKey(filePath);
81
123
  const output = jsonLines
82
124
  .map((l) => (key ? encryptLine(l, key) : l))
@@ -89,6 +131,9 @@ export async function writeBrainLines(filePath, jsonLines) {
89
131
  * Returns the plaintext content. Falls back to raw content if not encrypted.
90
132
  */
91
133
  export async function readBrainFile(filePath) {
134
+ assertNotLocked(filePath);
135
+ assertAccess(filePath, "read");
136
+ logAccess(filePath, "readBrainFile");
92
137
  const raw = await readFile(filePath, "utf-8");
93
138
  const key = readKey(filePath);
94
139
  if (key && isEncryptedFile(raw)) {
@@ -101,6 +146,8 @@ export async function readBrainFile(filePath) {
101
146
  * Creates parent directories if needed.
102
147
  */
103
148
  export async function writeBrainFile(filePath, content) {
149
+ assertNotLocked(filePath);
150
+ assertAccess(filePath, "write");
104
151
  await mkdir(dirname(filePath), { recursive: true });
105
152
  const key = writeKey(filePath);
106
153
  const output = key ? encryptFile(content, key) : content;
@@ -111,6 +158,9 @@ export async function writeBrainFile(filePath, content) {
111
158
  * Synchronously read a JSONL file, decrypting each line if needed.
112
159
  */
113
160
  export function readBrainLinesSync(filePath) {
161
+ assertNotLocked(filePath);
162
+ assertAccess(filePath, "read");
163
+ logAccessSync(filePath, "readBrainLinesSync");
114
164
  let raw;
115
165
  try {
116
166
  raw = readFileSync(filePath, "utf-8");
@@ -139,6 +189,8 @@ export function readBrainLinesSync(filePath) {
139
189
  * Synchronously append a single line to a JSONL file, encrypting if enabled.
140
190
  */
141
191
  export function appendBrainLineSync(filePath, jsonLine) {
192
+ assertNotLocked(filePath);
193
+ assertAccess(filePath, "write");
142
194
  const key = writeKey(filePath);
143
195
  const line = key ? encryptLine(jsonLine, key) : jsonLine;
144
196
  appendFileSync(filePath, line + "\n", "utf-8");
@@ -1 +1 @@
1
- {"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
3
+ * Keys are tied to the current Windows user account.
4
+ * Falls back to plaintext on non-Windows or if DPAPI is unavailable.
5
+ */
6
+ /**
7
+ * Read a session key file. Tries DPAPI-protected format first (.dpapi),
8
+ * falls back to plaintext hex. If plaintext found, migrates to DPAPI.
9
+ * Returns the raw key as a Buffer, or null if not found.
10
+ */
11
+ export declare function readSessionKey(keyPath: string): Promise<Buffer | null>;
12
+ /** Check if DPAPI is available on this system. */
13
+ export declare function isDpapiAvailable(): boolean;
14
+ //# sourceMappingURL=dpapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpapi.d.ts","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkDH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuC5E;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,OAAO,CAQ1C"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
3
+ * Keys are tied to the current Windows user account.
4
+ * Falls back to plaintext on non-Windows or if DPAPI is unavailable.
5
+ */
6
+ import { execSync } from "node:child_process";
7
+ import { readFile, writeFile, realpath } from "node:fs/promises";
8
+ import { existsSync } from "node:fs";
9
+ const IS_WINDOWS = process.platform === "win32";
10
+ /** Encode a PowerShell script as base64 UTF-16LE for -EncodedCommand. */
11
+ function encodePS(script) {
12
+ return Buffer.from(script, "utf16le").toString("base64");
13
+ }
14
+ /** Run a PowerShell script reliably via -EncodedCommand. */
15
+ function runPS(script) {
16
+ const encoded = encodePS(script);
17
+ return execSync(`powershell -NoProfile -EncodedCommand ${encoded}`, { encoding: "utf-8", windowsHide: true }).trim();
18
+ }
19
+ /** DPAPI-protect a Buffer, returns base64-encoded ciphertext. */
20
+ function dpapiProtect(data) {
21
+ const b64Input = data.toString("base64");
22
+ return runPS(`
23
+ Add-Type -AssemblyName System.Security
24
+ $bytes = [Convert]::FromBase64String("${b64Input}")
25
+ $enc = [System.Security.Cryptography.ProtectedData]::Protect(
26
+ $bytes, [byte[]]@(),
27
+ [System.Security.Cryptography.DataProtectionScope]::CurrentUser
28
+ )
29
+ [Convert]::ToBase64String($enc)
30
+ `);
31
+ }
32
+ /** DPAPI-unprotect a base64-encoded ciphertext, returns Buffer. */
33
+ function dpapiUnprotect(b64Ciphertext) {
34
+ const result = runPS(`
35
+ Add-Type -AssemblyName System.Security
36
+ $enc = [Convert]::FromBase64String("${b64Ciphertext}")
37
+ $dec = [System.Security.Cryptography.ProtectedData]::Unprotect(
38
+ $enc, [byte[]]@(),
39
+ [System.Security.Cryptography.DataProtectionScope]::CurrentUser
40
+ )
41
+ [Convert]::ToBase64String($dec)
42
+ `);
43
+ return Buffer.from(result, "base64");
44
+ }
45
+ /**
46
+ * Read a session key file. Tries DPAPI-protected format first (.dpapi),
47
+ * falls back to plaintext hex. If plaintext found, migrates to DPAPI.
48
+ * Returns the raw key as a Buffer, or null if not found.
49
+ */
50
+ export async function readSessionKey(keyPath) {
51
+ // Resolve symlinks so .dpapi file lands next to the real key
52
+ let resolvedPath = keyPath;
53
+ try {
54
+ resolvedPath = await realpath(keyPath);
55
+ }
56
+ catch {
57
+ // realpath fails if file doesn't exist — use original
58
+ }
59
+ const dpapiPath = resolvedPath + ".dpapi";
60
+ // Try DPAPI-protected version first
61
+ if (IS_WINDOWS && existsSync(dpapiPath)) {
62
+ try {
63
+ const b64 = (await readFile(dpapiPath, "utf-8")).trim();
64
+ if (b64.length > 0)
65
+ return dpapiUnprotect(b64);
66
+ }
67
+ catch {
68
+ // DPAPI decrypt failed — fall through to plaintext
69
+ }
70
+ }
71
+ // Try plaintext hex file
72
+ if (!existsSync(resolvedPath))
73
+ return null;
74
+ const hex = (await readFile(resolvedPath, "utf-8")).trim();
75
+ if (!/^[0-9a-f]{64}$/i.test(hex))
76
+ return null;
77
+ const key = Buffer.from(hex, "hex");
78
+ // Migrate: protect with DPAPI and save
79
+ if (IS_WINDOWS) {
80
+ try {
81
+ const protected64 = dpapiProtect(key);
82
+ await writeFile(dpapiPath, protected64, "utf-8");
83
+ // Don't delete the plaintext yet — Dash may still need it
84
+ // until Dash also uses this reader
85
+ }
86
+ catch {
87
+ // DPAPI not available — keep using plaintext
88
+ }
89
+ }
90
+ return key;
91
+ }
92
+ /** Check if DPAPI is available on this system. */
93
+ export function isDpapiAvailable() {
94
+ if (!IS_WINDOWS)
95
+ return false;
96
+ try {
97
+ dpapiProtect(Buffer.from("test"));
98
+ return true;
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ }
104
+ //# sourceMappingURL=dpapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpapi.js","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Minimal glob matcher for brain-relative paths.
3
+ *
4
+ * Supports:
5
+ * - `**` — match any number of path segments (including zero)
6
+ * - `*` — match a single path segment (no slashes)
7
+ * - exact — literal string match
8
+ *
9
+ * No external dependencies. Used by vault policy + access manifests.
10
+ */
11
+ /**
12
+ * Test whether a brain-relative path matches a glob pattern.
13
+ *
14
+ * @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
15
+ * @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
16
+ */
17
+ export declare function matchGlob(pattern: string, path: string): boolean;
18
+ /**
19
+ * Test whether a path matches ANY of the given glob patterns.
20
+ */
21
+ export declare function matchAnyGlob(patterns: string[], path: string): boolean;
22
+ //# sourceMappingURL=glob-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-match.d.ts","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqCH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtE"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Minimal glob matcher for brain-relative paths.
3
+ *
4
+ * Supports:
5
+ * - `**` — match any number of path segments (including zero)
6
+ * - `*` — match a single path segment (no slashes)
7
+ * - exact — literal string match
8
+ *
9
+ * No external dependencies. Used by vault policy + access manifests.
10
+ */
11
+ /**
12
+ * Convert a glob pattern to a RegExp.
13
+ * Patterns are matched against forward-slash-normalized brain-relative paths.
14
+ */
15
+ function globToRegex(pattern) {
16
+ // Normalize
17
+ const p = pattern.replace(/\\/g, "/").replace(/\/+$/, "");
18
+ let regex = "^";
19
+ let i = 0;
20
+ while (i < p.length) {
21
+ if (p[i] === "*" && p[i + 1] === "*") {
22
+ // ** — match any depth (including zero segments)
23
+ // Consume trailing slash if present
24
+ i += 2;
25
+ if (p[i] === "/")
26
+ i++;
27
+ regex += "(?:.+/)?";
28
+ }
29
+ else if (p[i] === "*") {
30
+ // * — match single segment (no slashes)
31
+ regex += "[^/]+";
32
+ i++;
33
+ }
34
+ else if (".+?^${}()|[]\\".includes(p[i])) {
35
+ // Escape regex special chars
36
+ regex += "\\" + p[i];
37
+ i++;
38
+ }
39
+ else {
40
+ regex += p[i];
41
+ i++;
42
+ }
43
+ }
44
+ regex += "$";
45
+ return new RegExp(regex);
46
+ }
47
+ /**
48
+ * Test whether a brain-relative path matches a glob pattern.
49
+ *
50
+ * @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
51
+ * @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
52
+ */
53
+ export function matchGlob(pattern, path) {
54
+ const normalized = path.replace(/\\/g, "/");
55
+ const re = globToRegex(pattern);
56
+ return re.test(normalized);
57
+ }
58
+ /**
59
+ * Test whether a path matches ANY of the given glob patterns.
60
+ */
61
+ export function matchAnyGlob(patterns, path) {
62
+ return patterns.some((p) => matchGlob(p, path));
63
+ }
64
+ //# sourceMappingURL=glob-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob-match.js","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,YAAY;IACZ,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACrC,iDAAiD;YACjD,oCAAoC;YACpC,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,CAAC,EAAE,CAAC;YACtB,KAAK,IAAI,UAAU,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACxB,wCAAwC;YACxC,KAAK,IAAI,OAAO,CAAC;YACjB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,6BAA6B;YAC7B,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACd,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,KAAK,IAAI,GAAG,CAAC;IAEb,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,IAAY;IAC3D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Centralized .locked file enforcement for brain paths.
3
+ *
4
+ * Shared by both MCP server (stdio) and direct file access (brain-io).
5
+ * Ensures locked paths are consistently protected regardless of access channel.
6
+ *
7
+ * Lock rules:
8
+ * - Exact path match (e.g. "identity/human.json")
9
+ * - Filename-only match (e.g. ".session-key" matches "identity/.session-key")
10
+ * - Directory prefix match (e.g. "identity/" matches "identity/foo.md")
11
+ */
12
+ /**
13
+ * Read brain/.locked and merge with hardcoded minimums. Caches result.
14
+ * Safe to call multiple times — returns cached paths after first load.
15
+ */
16
+ export declare function loadLockedPaths(): Promise<string[]>;
17
+ /**
18
+ * Synchronous variant — reads .locked file on first call, caches after.
19
+ */
20
+ export declare function loadLockedPathsSync(): string[];
21
+ /** Force reload of locked paths (e.g. when listing current locks). */
22
+ export declare function reloadLockedPaths(): Promise<string[]>;
23
+ /** Get the currently cached locked paths. Loads synchronously if not yet cached. */
24
+ export declare function getLockedPaths(): string[];
25
+ /**
26
+ * Check if a brain-relative path (forward slashes) is locked.
27
+ * Matches exact paths, filename-only, and directory prefixes.
28
+ */
29
+ export declare function isLocked(relPath: string): boolean;
30
+ /**
31
+ * Convert an absolute file path to a brain-relative path.
32
+ * Returns null if the path is not under brain/.
33
+ */
34
+ export declare function toBrainRelativePath(absolutePath: string): string | null;
35
+ /**
36
+ * Assert that an absolute path is not locked. Throws if locked.
37
+ * No-op for paths outside brain/.
38
+ */
39
+ export declare function assertNotLocked(absolutePath: string): void;
40
+ //# sourceMappingURL=locked.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locked.d.ts","sourceRoot":"","sources":["../../src/lib/locked.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAezD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAkB9C;AAED,sEAAsE;AACtE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3D;AAED,oFAAoF;AACpF,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAGzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAajD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAM1D"}