brains-mcp 1.61.2

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 (350) hide show
  1. package/README.md +95 -0
  2. package/dist/access/projectShares.d.ts +48 -0
  3. package/dist/access/projectShares.d.ts.map +1 -0
  4. package/dist/access/projectShares.js +203 -0
  5. package/dist/access/projectShares.js.map +1 -0
  6. package/dist/access/sharedInstructionsNote.d.ts +37 -0
  7. package/dist/access/sharedInstructionsNote.d.ts.map +1 -0
  8. package/dist/access/sharedInstructionsNote.js +76 -0
  9. package/dist/access/sharedInstructionsNote.js.map +1 -0
  10. package/dist/admin/seedUsers.d.ts +23 -0
  11. package/dist/admin/seedUsers.d.ts.map +1 -0
  12. package/dist/admin/seedUsers.js +168 -0
  13. package/dist/admin/seedUsers.js.map +1 -0
  14. package/dist/api/openapi.d.ts +2 -0
  15. package/dist/api/openapi.d.ts.map +1 -0
  16. package/dist/api/openapi.js +942 -0
  17. package/dist/api/openapi.js.map +1 -0
  18. package/dist/auth/clientStore.d.ts +43 -0
  19. package/dist/auth/clientStore.d.ts.map +1 -0
  20. package/dist/auth/clientStore.js +168 -0
  21. package/dist/auth/clientStore.js.map +1 -0
  22. package/dist/auth/deleteAccount.d.ts +34 -0
  23. package/dist/auth/deleteAccount.d.ts.map +1 -0
  24. package/dist/auth/deleteAccount.js +203 -0
  25. package/dist/auth/deleteAccount.js.map +1 -0
  26. package/dist/auth/oauth.d.ts +118 -0
  27. package/dist/auth/oauth.d.ts.map +1 -0
  28. package/dist/auth/oauth.js +491 -0
  29. package/dist/auth/oauth.js.map +1 -0
  30. package/dist/auth/patStore.d.ts +87 -0
  31. package/dist/auth/patStore.d.ts.map +1 -0
  32. package/dist/auth/patStore.js +308 -0
  33. package/dist/auth/patStore.js.map +1 -0
  34. package/dist/auth/supabase.d.ts +15 -0
  35. package/dist/auth/supabase.d.ts.map +1 -0
  36. package/dist/auth/supabase.js +66 -0
  37. package/dist/auth/supabase.js.map +1 -0
  38. package/dist/auth/tokenStore.d.ts +73 -0
  39. package/dist/auth/tokenStore.d.ts.map +1 -0
  40. package/dist/auth/tokenStore.js +261 -0
  41. package/dist/auth/tokenStore.js.map +1 -0
  42. package/dist/backup/drive.d.ts +24 -0
  43. package/dist/backup/drive.d.ts.map +1 -0
  44. package/dist/backup/drive.js +70 -0
  45. package/dist/backup/drive.js.map +1 -0
  46. package/dist/billing/tierStore.d.ts +59 -0
  47. package/dist/billing/tierStore.d.ts.map +1 -0
  48. package/dist/billing/tierStore.js +152 -0
  49. package/dist/billing/tierStore.js.map +1 -0
  50. package/dist/digest/activityDigest.d.ts +32 -0
  51. package/dist/digest/activityDigest.d.ts.map +1 -0
  52. package/dist/digest/activityDigest.js +299 -0
  53. package/dist/digest/activityDigest.js.map +1 -0
  54. package/dist/digest/digestCron.d.ts +40 -0
  55. package/dist/digest/digestCron.d.ts.map +1 -0
  56. package/dist/digest/digestCron.js +146 -0
  57. package/dist/digest/digestCron.js.map +1 -0
  58. package/dist/digest/digestPreferences.d.ts +25 -0
  59. package/dist/digest/digestPreferences.d.ts.map +1 -0
  60. package/dist/digest/digestPreferences.js +79 -0
  61. package/dist/digest/digestPreferences.js.map +1 -0
  62. package/dist/digest/emailSender.d.ts +20 -0
  63. package/dist/digest/emailSender.d.ts.map +1 -0
  64. package/dist/digest/emailSender.js +35 -0
  65. package/dist/digest/emailSender.js.map +1 -0
  66. package/dist/drive/client.d.ts +43 -0
  67. package/dist/drive/client.d.ts.map +1 -0
  68. package/dist/drive/client.js +282 -0
  69. package/dist/drive/client.js.map +1 -0
  70. package/dist/drive/errors.d.ts +27 -0
  71. package/dist/drive/errors.d.ts.map +1 -0
  72. package/dist/drive/errors.js +51 -0
  73. package/dist/drive/errors.js.map +1 -0
  74. package/dist/drive/fileCache.d.ts +22 -0
  75. package/dist/drive/fileCache.d.ts.map +1 -0
  76. package/dist/drive/fileCache.js +57 -0
  77. package/dist/drive/fileCache.js.map +1 -0
  78. package/dist/governance/accessControl.d.ts +87 -0
  79. package/dist/governance/accessControl.d.ts.map +1 -0
  80. package/dist/governance/accessControl.js +179 -0
  81. package/dist/governance/accessControl.js.map +1 -0
  82. package/dist/html/components.d.ts +8 -0
  83. package/dist/html/components.d.ts.map +1 -0
  84. package/dist/html/components.js +19 -0
  85. package/dist/html/components.js.map +1 -0
  86. package/dist/html/layout.d.ts +7 -0
  87. package/dist/html/layout.d.ts.map +1 -0
  88. package/dist/html/layout.js +24 -0
  89. package/dist/html/layout.js.map +1 -0
  90. package/dist/html/metricsUi.d.ts +8 -0
  91. package/dist/html/metricsUi.d.ts.map +1 -0
  92. package/dist/html/metricsUi.js +271 -0
  93. package/dist/html/metricsUi.js.map +1 -0
  94. package/dist/httpServer.d.ts +19 -0
  95. package/dist/httpServer.d.ts.map +1 -0
  96. package/dist/httpServer.js +3913 -0
  97. package/dist/httpServer.js.map +1 -0
  98. package/dist/index.d.ts +3 -0
  99. package/dist/index.d.ts.map +1 -0
  100. package/dist/index.js +40 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/jobs/asyncJobRegistry.d.ts +30 -0
  103. package/dist/jobs/asyncJobRegistry.d.ts.map +1 -0
  104. package/dist/jobs/asyncJobRegistry.js +70 -0
  105. package/dist/jobs/asyncJobRegistry.js.map +1 -0
  106. package/dist/observability/metricsQuery.d.ts +41 -0
  107. package/dist/observability/metricsQuery.d.ts.map +1 -0
  108. package/dist/observability/metricsQuery.js +106 -0
  109. package/dist/observability/metricsQuery.js.map +1 -0
  110. package/dist/observability/relevanceSignal.d.ts +26 -0
  111. package/dist/observability/relevanceSignal.d.ts.map +1 -0
  112. package/dist/observability/relevanceSignal.js +95 -0
  113. package/dist/observability/relevanceSignal.js.map +1 -0
  114. package/dist/observability/requestEvents.d.ts +31 -0
  115. package/dist/observability/requestEvents.d.ts.map +1 -0
  116. package/dist/observability/requestEvents.js +54 -0
  117. package/dist/observability/requestEvents.js.map +1 -0
  118. package/dist/observability/slowQueryAlert.d.ts +25 -0
  119. package/dist/observability/slowQueryAlert.d.ts.map +1 -0
  120. package/dist/observability/slowQueryAlert.js +67 -0
  121. package/dist/observability/slowQueryAlert.js.map +1 -0
  122. package/dist/observability/zeroResultTriage.d.ts +22 -0
  123. package/dist/observability/zeroResultTriage.d.ts.map +1 -0
  124. package/dist/observability/zeroResultTriage.js +116 -0
  125. package/dist/observability/zeroResultTriage.js.map +1 -0
  126. package/dist/search/embeddings.d.ts +31 -0
  127. package/dist/search/embeddings.d.ts.map +1 -0
  128. package/dist/search/embeddings.js +91 -0
  129. package/dist/search/embeddings.js.map +1 -0
  130. package/dist/search/fileWatcher.d.ts +28 -0
  131. package/dist/search/fileWatcher.d.ts.map +1 -0
  132. package/dist/search/fileWatcher.js +103 -0
  133. package/dist/search/fileWatcher.js.map +1 -0
  134. package/dist/search/hotQueryCache.d.ts +31 -0
  135. package/dist/search/hotQueryCache.d.ts.map +1 -0
  136. package/dist/search/hotQueryCache.js +103 -0
  137. package/dist/search/hotQueryCache.js.map +1 -0
  138. package/dist/search/postgresIndex.d.ts +439 -0
  139. package/dist/search/postgresIndex.d.ts.map +1 -0
  140. package/dist/search/postgresIndex.js +1610 -0
  141. package/dist/search/postgresIndex.js.map +1 -0
  142. package/dist/search/sqliteIndex.d.ts +66 -0
  143. package/dist/search/sqliteIndex.d.ts.map +1 -0
  144. package/dist/search/sqliteIndex.js +342 -0
  145. package/dist/search/sqliteIndex.js.map +1 -0
  146. package/dist/server.d.ts +43 -0
  147. package/dist/server.d.ts.map +1 -0
  148. package/dist/server.js +532 -0
  149. package/dist/server.js.map +1 -0
  150. package/dist/session/bundle.d.ts +53 -0
  151. package/dist/session/bundle.d.ts.map +1 -0
  152. package/dist/session/bundle.js +97 -0
  153. package/dist/session/bundle.js.map +1 -0
  154. package/dist/storage/client.d.ts +157 -0
  155. package/dist/storage/client.d.ts.map +1 -0
  156. package/dist/storage/client.js +825 -0
  157. package/dist/storage/client.js.map +1 -0
  158. package/dist/tools/addWebhookPattern.d.ts +15 -0
  159. package/dist/tools/addWebhookPattern.d.ts.map +1 -0
  160. package/dist/tools/addWebhookPattern.js +15 -0
  161. package/dist/tools/addWebhookPattern.js.map +1 -0
  162. package/dist/tools/appendLog.d.ts +18 -0
  163. package/dist/tools/appendLog.d.ts.map +1 -0
  164. package/dist/tools/appendLog.js +18 -0
  165. package/dist/tools/appendLog.js.map +1 -0
  166. package/dist/tools/auditIndex.d.ts +15 -0
  167. package/dist/tools/auditIndex.d.ts.map +1 -0
  168. package/dist/tools/auditIndex.js +165 -0
  169. package/dist/tools/auditIndex.js.map +1 -0
  170. package/dist/tools/batchDeletePages.d.ts +18 -0
  171. package/dist/tools/batchDeletePages.d.ts.map +1 -0
  172. package/dist/tools/batchDeletePages.js +143 -0
  173. package/dist/tools/batchDeletePages.js.map +1 -0
  174. package/dist/tools/coerce.d.ts +3 -0
  175. package/dist/tools/coerce.d.ts.map +1 -0
  176. package/dist/tools/coerce.js +12 -0
  177. package/dist/tools/coerce.js.map +1 -0
  178. package/dist/tools/createPage.d.ts +24 -0
  179. package/dist/tools/createPage.d.ts.map +1 -0
  180. package/dist/tools/createPage.js +99 -0
  181. package/dist/tools/createPage.js.map +1 -0
  182. package/dist/tools/createPages.d.ts +51 -0
  183. package/dist/tools/createPages.d.ts.map +1 -0
  184. package/dist/tools/createPages.js +91 -0
  185. package/dist/tools/createPages.js.map +1 -0
  186. package/dist/tools/deletePage.d.ts +19 -0
  187. package/dist/tools/deletePage.d.ts.map +1 -0
  188. package/dist/tools/deletePage.js +127 -0
  189. package/dist/tools/deletePage.js.map +1 -0
  190. package/dist/tools/exportWiki.d.ts +48 -0
  191. package/dist/tools/exportWiki.d.ts.map +1 -0
  192. package/dist/tools/exportWiki.js +233 -0
  193. package/dist/tools/exportWiki.js.map +1 -0
  194. package/dist/tools/extractLinks.d.ts +14 -0
  195. package/dist/tools/extractLinks.d.ts.map +1 -0
  196. package/dist/tools/extractLinks.js +25 -0
  197. package/dist/tools/extractLinks.js.map +1 -0
  198. package/dist/tools/generateClaudeInstructions.d.ts +27 -0
  199. package/dist/tools/generateClaudeInstructions.d.ts.map +1 -0
  200. package/dist/tools/generateClaudeInstructions.js +263 -0
  201. package/dist/tools/generateClaudeInstructions.js.map +1 -0
  202. package/dist/tools/generateGptInstructions.d.ts +27 -0
  203. package/dist/tools/generateGptInstructions.d.ts.map +1 -0
  204. package/dist/tools/generateGptInstructions.js +208 -0
  205. package/dist/tools/generateGptInstructions.js.map +1 -0
  206. package/dist/tools/getBacklinks.d.ts +12 -0
  207. package/dist/tools/getBacklinks.d.ts.map +1 -0
  208. package/dist/tools/getBacklinks.js +13 -0
  209. package/dist/tools/getBacklinks.js.map +1 -0
  210. package/dist/tools/getRelated.d.ts +12 -0
  211. package/dist/tools/getRelated.d.ts.map +1 -0
  212. package/dist/tools/getRelated.js +13 -0
  213. package/dist/tools/getRelated.js.map +1 -0
  214. package/dist/tools/healthCheck.d.ts +5 -0
  215. package/dist/tools/healthCheck.d.ts.map +1 -0
  216. package/dist/tools/healthCheck.js +167 -0
  217. package/dist/tools/healthCheck.js.map +1 -0
  218. package/dist/tools/importBrainSource.d.ts +36 -0
  219. package/dist/tools/importBrainSource.d.ts.map +1 -0
  220. package/dist/tools/importBrainSource.js +314 -0
  221. package/dist/tools/importBrainSource.js.map +1 -0
  222. package/dist/tools/importWikiZip.d.ts +60 -0
  223. package/dist/tools/importWikiZip.d.ts.map +1 -0
  224. package/dist/tools/importWikiZip.js +379 -0
  225. package/dist/tools/importWikiZip.js.map +1 -0
  226. package/dist/tools/initProject.d.ts +34 -0
  227. package/dist/tools/initProject.d.ts.map +1 -0
  228. package/dist/tools/initProject.js +443 -0
  229. package/dist/tools/initProject.js.map +1 -0
  230. package/dist/tools/instructionContext.d.ts +60 -0
  231. package/dist/tools/instructionContext.d.ts.map +1 -0
  232. package/dist/tools/instructionContext.js +210 -0
  233. package/dist/tools/instructionContext.js.map +1 -0
  234. package/dist/tools/listArchivedPages.d.ts +17 -0
  235. package/dist/tools/listArchivedPages.d.ts.map +1 -0
  236. package/dist/tools/listArchivedPages.js +51 -0
  237. package/dist/tools/listArchivedPages.js.map +1 -0
  238. package/dist/tools/listPages.d.ts +28 -0
  239. package/dist/tools/listPages.d.ts.map +1 -0
  240. package/dist/tools/listPages.js +166 -0
  241. package/dist/tools/listPages.js.map +1 -0
  242. package/dist/tools/listWebhooks.d.ts +7 -0
  243. package/dist/tools/listWebhooks.d.ts.map +1 -0
  244. package/dist/tools/listWebhooks.js +10 -0
  245. package/dist/tools/listWebhooks.js.map +1 -0
  246. package/dist/tools/movePage.d.ts +18 -0
  247. package/dist/tools/movePage.d.ts.map +1 -0
  248. package/dist/tools/movePage.js +182 -0
  249. package/dist/tools/movePage.js.map +1 -0
  250. package/dist/tools/pageHistory.d.ts +36 -0
  251. package/dist/tools/pageHistory.d.ts.map +1 -0
  252. package/dist/tools/pageHistory.js +60 -0
  253. package/dist/tools/pageHistory.js.map +1 -0
  254. package/dist/tools/patchPage.d.ts +141 -0
  255. package/dist/tools/patchPage.d.ts.map +1 -0
  256. package/dist/tools/patchPage.js +287 -0
  257. package/dist/tools/patchPage.js.map +1 -0
  258. package/dist/tools/pullSessionBundle.d.ts +34 -0
  259. package/dist/tools/pullSessionBundle.d.ts.map +1 -0
  260. package/dist/tools/pullSessionBundle.js +432 -0
  261. package/dist/tools/pullSessionBundle.js.map +1 -0
  262. package/dist/tools/purgeWiki.d.ts +23 -0
  263. package/dist/tools/purgeWiki.d.ts.map +1 -0
  264. package/dist/tools/purgeWiki.js +113 -0
  265. package/dist/tools/purgeWiki.js.map +1 -0
  266. package/dist/tools/pushSessionBundle.d.ts +139 -0
  267. package/dist/tools/pushSessionBundle.d.ts.map +1 -0
  268. package/dist/tools/pushSessionBundle.js +282 -0
  269. package/dist/tools/pushSessionBundle.js.map +1 -0
  270. package/dist/tools/readGovernanceAudit.d.ts +17 -0
  271. package/dist/tools/readGovernanceAudit.d.ts.map +1 -0
  272. package/dist/tools/readGovernanceAudit.js +21 -0
  273. package/dist/tools/readGovernanceAudit.js.map +1 -0
  274. package/dist/tools/readPage.d.ts +13 -0
  275. package/dist/tools/readPage.d.ts.map +1 -0
  276. package/dist/tools/readPage.js +46 -0
  277. package/dist/tools/readPage.js.map +1 -0
  278. package/dist/tools/removeWebhook.d.ts +14 -0
  279. package/dist/tools/removeWebhook.d.ts.map +1 -0
  280. package/dist/tools/removeWebhook.js +12 -0
  281. package/dist/tools/removeWebhook.js.map +1 -0
  282. package/dist/tools/resolveProject.d.ts +58 -0
  283. package/dist/tools/resolveProject.d.ts.map +1 -0
  284. package/dist/tools/resolveProject.js +175 -0
  285. package/dist/tools/resolveProject.js.map +1 -0
  286. package/dist/tools/restorePage.d.ts +47 -0
  287. package/dist/tools/restorePage.d.ts.map +1 -0
  288. package/dist/tools/restorePage.js +111 -0
  289. package/dist/tools/restorePage.js.map +1 -0
  290. package/dist/tools/searchPages.d.ts +28 -0
  291. package/dist/tools/searchPages.d.ts.map +1 -0
  292. package/dist/tools/searchPages.js +372 -0
  293. package/dist/tools/searchPages.js.map +1 -0
  294. package/dist/tools/setWebhook.d.ts +30 -0
  295. package/dist/tools/setWebhook.d.ts.map +1 -0
  296. package/dist/tools/setWebhook.js +30 -0
  297. package/dist/tools/setWebhook.js.map +1 -0
  298. package/dist/tools/shareProject.d.ts +25 -0
  299. package/dist/tools/shareProject.d.ts.map +1 -0
  300. package/dist/tools/shareProject.js +56 -0
  301. package/dist/tools/shareProject.js.map +1 -0
  302. package/dist/tools/suggestLinks.d.ts +29 -0
  303. package/dist/tools/suggestLinks.d.ts.map +1 -0
  304. package/dist/tools/suggestLinks.js +214 -0
  305. package/dist/tools/suggestLinks.js.map +1 -0
  306. package/dist/tools/updatePage.d.ts +27 -0
  307. package/dist/tools/updatePage.d.ts.map +1 -0
  308. package/dist/tools/updatePage.js +118 -0
  309. package/dist/tools/updatePage.js.map +1 -0
  310. package/dist/webhooks/dispatch.d.ts +49 -0
  311. package/dist/webhooks/dispatch.d.ts.map +1 -0
  312. package/dist/webhooks/dispatch.js +159 -0
  313. package/dist/webhooks/dispatch.js.map +1 -0
  314. package/dist/webhooks/webhookRules.d.ts +34 -0
  315. package/dist/webhooks/webhookRules.d.ts.map +1 -0
  316. package/dist/webhooks/webhookRules.js +129 -0
  317. package/dist/webhooks/webhookRules.js.map +1 -0
  318. package/dist/wiki/frontmatter.d.ts +45 -0
  319. package/dist/wiki/frontmatter.d.ts.map +1 -0
  320. package/dist/wiki/frontmatter.js +68 -0
  321. package/dist/wiki/frontmatter.js.map +1 -0
  322. package/dist/wiki/index.d.ts +22 -0
  323. package/dist/wiki/index.d.ts.map +1 -0
  324. package/dist/wiki/index.js +203 -0
  325. package/dist/wiki/index.js.map +1 -0
  326. package/dist/wiki/ingestPolicy.d.ts +18 -0
  327. package/dist/wiki/ingestPolicy.d.ts.map +1 -0
  328. package/dist/wiki/ingestPolicy.js +64 -0
  329. package/dist/wiki/ingestPolicy.js.map +1 -0
  330. package/dist/wiki/layoutLint.d.ts +51 -0
  331. package/dist/wiki/layoutLint.d.ts.map +1 -0
  332. package/dist/wiki/layoutLint.js +146 -0
  333. package/dist/wiki/layoutLint.js.map +1 -0
  334. package/dist/wiki/links.d.ts +6 -0
  335. package/dist/wiki/links.d.ts.map +1 -0
  336. package/dist/wiki/links.js +45 -0
  337. package/dist/wiki/links.js.map +1 -0
  338. package/dist/wiki/log.d.ts +58 -0
  339. package/dist/wiki/log.d.ts.map +1 -0
  340. package/dist/wiki/log.js +126 -0
  341. package/dist/wiki/log.js.map +1 -0
  342. package/dist/wiki/path.d.ts +8 -0
  343. package/dist/wiki/path.d.ts.map +1 -0
  344. package/dist/wiki/path.js +25 -0
  345. package/dist/wiki/path.js.map +1 -0
  346. package/dist/wiki/storageLimits.d.ts +163 -0
  347. package/dist/wiki/storageLimits.d.ts.map +1 -0
  348. package/dist/wiki/storageLimits.js +281 -0
  349. package/dist/wiki/storageLimits.js.map +1 -0
  350. package/package.json +81 -0
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Personal Access Token (PAT) store.
3
+ *
4
+ * PATs are long-lived, user-scoped bearer tokens meant for CLI / local-first
5
+ * workflows where re-authenticating every hour is impractical. They are
6
+ * distinct from the short-lived Supabase JWTs and the workspace-wide
7
+ * BRAINS_API_KEY — each PAT is tied to the Supabase/OAuth user who minted it
8
+ * and is stored alongside their wiki content under `users/<subject>/`.
9
+ *
10
+ * Two backends, auto-selected (mirrors createTokenStore):
11
+ * - LocalSQLitePATStore — adds a `pats` table to the existing oauth-tokens
12
+ * SQLite database. Good for single-instance / local runs.
13
+ * - PostgresPATStore — PostgREST-backed, stored in a `pats` table.
14
+ * Requires scripts/pats.sql to be applied once.
15
+ *
16
+ * expires_at is nullable — NULL means the token never expires.
17
+ */
18
+ import fs from "fs";
19
+ import path from "path";
20
+ import { randomUUID } from "crypto";
21
+ import { randomBytes } from "crypto";
22
+ import Database from "better-sqlite3";
23
+ // ─── Types ────────────────────────────────────────────────────────────────────
24
+ export const PAT_EXPIRY_DAYS_DEFAULT = 30;
25
+ export const PAT_EXPIRY_DAYS_MAX = 365;
26
+ export class LocalSQLitePATStore {
27
+ db;
28
+ constructor(storageLocation) {
29
+ const cacheDir = path.join(storageLocation, ".cache");
30
+ fs.mkdirSync(cacheDir, { recursive: true });
31
+ const dbPath = path.join(cacheDir, "oauth-tokens.db");
32
+ this.db = new Database(dbPath);
33
+ this.db.pragma("journal_mode = WAL");
34
+ this.db.pragma("synchronous = NORMAL");
35
+ this.initSchema();
36
+ }
37
+ initSchema() {
38
+ this.db.exec(`
39
+ CREATE TABLE IF NOT EXISTS pats (
40
+ id TEXT NOT NULL PRIMARY KEY,
41
+ token TEXT NOT NULL UNIQUE,
42
+ subject TEXT NOT NULL,
43
+ label TEXT NOT NULL DEFAULT '',
44
+ scopes TEXT NOT NULL,
45
+ expires_at INTEGER,
46
+ created_at INTEGER NOT NULL
47
+ );
48
+ CREATE INDEX IF NOT EXISTS idx_pats_token ON pats (token);
49
+ CREATE INDEX IF NOT EXISTS idx_pats_subject ON pats (subject);
50
+ CREATE INDEX IF NOT EXISTS idx_pats_expires_at ON pats (expires_at);
51
+ `);
52
+ this.migrateNullableExpiry();
53
+ }
54
+ /** Migrate existing tables that have NOT NULL on expires_at to allow NULL. */
55
+ migrateNullableExpiry() {
56
+ const colInfo = this.db.pragma("table_info(pats)");
57
+ const col = colInfo.find((c) => c.name === "expires_at");
58
+ if (!col || col.notnull === 0)
59
+ return; // already nullable or column missing
60
+ this.db.pragma("foreign_keys = off");
61
+ const migrate = this.db.transaction(() => {
62
+ this.db
63
+ .prepare(`CREATE TABLE _pats_migrate (
64
+ id TEXT NOT NULL PRIMARY KEY,
65
+ token TEXT NOT NULL UNIQUE,
66
+ subject TEXT NOT NULL,
67
+ label TEXT NOT NULL DEFAULT '',
68
+ scopes TEXT NOT NULL,
69
+ expires_at INTEGER,
70
+ created_at INTEGER NOT NULL
71
+ )`)
72
+ .run();
73
+ this.db.prepare("INSERT INTO _pats_migrate SELECT * FROM pats").run();
74
+ this.db.prepare("DROP TABLE pats").run();
75
+ this.db.prepare("ALTER TABLE _pats_migrate RENAME TO pats").run();
76
+ });
77
+ migrate();
78
+ this.db.exec(`
79
+ CREATE INDEX IF NOT EXISTS idx_pats_token ON pats (token);
80
+ CREATE INDEX IF NOT EXISTS idx_pats_subject ON pats (subject);
81
+ CREATE INDEX IF NOT EXISTS idx_pats_expires_at ON pats (expires_at);
82
+ `);
83
+ this.db.pragma("foreign_keys = on");
84
+ }
85
+ async create(subject, label, scopes, expiresAt) {
86
+ const id = randomUUID();
87
+ const token = randomBytes(32).toString("hex");
88
+ const createdAt = Date.now();
89
+ this.db
90
+ .prepare(`INSERT INTO pats (id, token, subject, label, scopes, expires_at, created_at)
91
+ VALUES (@id, @token, @subject, @label, @scopes, @expires_at, @created_at)`)
92
+ .run({
93
+ id,
94
+ token,
95
+ subject,
96
+ label,
97
+ scopes: JSON.stringify(scopes),
98
+ expires_at: expiresAt ?? null,
99
+ created_at: createdAt,
100
+ });
101
+ return { id, token, subject, label, scopes, expiresAt, createdAt };
102
+ }
103
+ async find(token) {
104
+ const row = this.db
105
+ .prepare("SELECT * FROM pats WHERE token = ? AND (expires_at IS NULL OR expires_at > ?)")
106
+ .get(token, Date.now());
107
+ if (!row)
108
+ return null;
109
+ return rowToPAT(row);
110
+ }
111
+ async list(subject) {
112
+ const rows = this.db
113
+ .prepare("SELECT * FROM pats WHERE subject = ? AND (expires_at IS NULL OR expires_at > ?) ORDER BY created_at DESC")
114
+ .all(subject, Date.now());
115
+ return rows.map(rowToPAT);
116
+ }
117
+ async revoke(id, subject) {
118
+ const result = this.db
119
+ .prepare("DELETE FROM pats WHERE id = ? AND subject = ?")
120
+ .run(id, subject);
121
+ return result.changes > 0;
122
+ }
123
+ async pruneExpired() {
124
+ this.db.prepare("DELETE FROM pats WHERE expires_at IS NOT NULL AND expires_at <= ?").run(Date.now());
125
+ }
126
+ }
127
+ /**
128
+ * Token-validation cache TTL. Matches AUTH_CACHE_TTL_MS in auth/supabase.ts,
129
+ * which has cached Supabase token auth the same way for some time.
130
+ */
131
+ const PAT_CACHE_TTL_MS = 60 * 1000;
132
+ /**
133
+ * Bound on cached tokens, so a flood of invalid bearer tokens cannot grow the
134
+ * map without limit. Evicts oldest-inserted first.
135
+ */
136
+ const PAT_CACHE_MAX_ENTRIES = 1000;
137
+ export class PostgresPATStore {
138
+ supabaseUrl;
139
+ serviceRoleKey;
140
+ /**
141
+ * Validation cache, keyed by raw token.
142
+ *
143
+ * find() runs on every bearer-authenticated request and was an uncached
144
+ * Supabase round trip — ~175ms, measured (GH #427). Worse, PATs are
145
+ * indistinguishable from OAuth tokens (both opaque hex), so PAT lookup runs
146
+ * first and every OAuth/MCP request paid that round trip for a query
147
+ * guaranteed to miss. Negative results are therefore cached too; that is
148
+ * where most of the saving is.
149
+ *
150
+ * Revocation stays immediate: revoke() and pruneExpired() clear the cache,
151
+ * and create() seeds it. Only out-of-band changes (direct SQL) wait out the
152
+ * TTL — the same tradeoff auth/supabase.ts already accepts.
153
+ */
154
+ cache = new Map();
155
+ constructor(supabaseUrl, serviceRoleKey) {
156
+ this.supabaseUrl = supabaseUrl.trim().replace(/\/$/, "");
157
+ this.serviceRoleKey = serviceRoleKey.trim();
158
+ }
159
+ cacheTtlMs() {
160
+ const raw = parseInt(process.env.BRAINS_PAT_CACHE_TTL_MS ?? "", 10);
161
+ return Number.isFinite(raw) && raw >= 0 ? raw : PAT_CACHE_TTL_MS;
162
+ }
163
+ cacheSet(token, pat) {
164
+ if (this.cache.size >= PAT_CACHE_MAX_ENTRIES) {
165
+ const oldest = this.cache.keys().next().value;
166
+ if (oldest !== undefined)
167
+ this.cache.delete(oldest);
168
+ }
169
+ this.cache.set(token, { pat, at: Date.now() });
170
+ }
171
+ /** Drop all cached validations. Called whenever a PAT is revoked or pruned. */
172
+ invalidateCache() {
173
+ this.cache.clear();
174
+ }
175
+ get baseUrl() {
176
+ return `${this.supabaseUrl}/rest/v1/pats`;
177
+ }
178
+ headers(extra) {
179
+ return {
180
+ apikey: this.serviceRoleKey,
181
+ authorization: `Bearer ${this.serviceRoleKey}`,
182
+ "content-type": "application/json",
183
+ prefer: "return=minimal",
184
+ ...extra,
185
+ };
186
+ }
187
+ async create(subject, label, scopes, expiresAt) {
188
+ const id = randomUUID();
189
+ const token = randomBytes(32).toString("hex");
190
+ const createdAt = Date.now();
191
+ const body = JSON.stringify({
192
+ id,
193
+ token,
194
+ subject,
195
+ label,
196
+ scopes: JSON.stringify(scopes),
197
+ expires_at: expiresAt, // null serializes as JSON null → Postgres NULL
198
+ created_at: createdAt,
199
+ });
200
+ const res = await fetch(this.baseUrl, { method: "POST", headers: this.headers(), body });
201
+ if (!res.ok) {
202
+ const text = await res.text().catch(() => "");
203
+ throw new Error(`PostgresPATStore.create failed (${res.status}): ${text}`);
204
+ }
205
+ // Seed the cache so a freshly minted token cannot be defeated by a negative
206
+ // entry left behind by someone probing it before it existed.
207
+ this.cacheSet(token, { id, subject, label, scopes, expiresAt, createdAt });
208
+ return { id, token, subject, label, scopes, expiresAt, createdAt };
209
+ }
210
+ async find(token) {
211
+ const now = Date.now();
212
+ const ttl = this.cacheTtlMs();
213
+ const hit = this.cache.get(token);
214
+ if (hit && ttl > 0 && now - hit.at < ttl) {
215
+ // Re-check expiry on every hit: a token can lapse mid-TTL, and the cached
216
+ // record must not outlive its own expires_at.
217
+ if (hit.pat === null || hit.pat.expiresAt === null || hit.pat.expiresAt > now) {
218
+ return hit.pat;
219
+ }
220
+ this.cache.delete(token);
221
+ }
222
+ // expires_at IS NULL (never expires) OR expires_at > now
223
+ const url = `${this.baseUrl}?token=eq.${encodeURIComponent(token)}&or=(expires_at.is.null,expires_at.gt.${now})&limit=1`;
224
+ const res = await fetch(url, { method: "GET", headers: this.headers({ prefer: "return=representation" }) }).catch(() => null);
225
+ // Do not cache transport failures — a Supabase blip would otherwise pin
226
+ // every token to "invalid" for the whole TTL and lock users out.
227
+ if (!res || !res.ok)
228
+ return null;
229
+ const rows = (await res.json().catch(() => []));
230
+ const row = rows[0];
231
+ const pat = row ? postgresRowToPAT(row) : null;
232
+ this.cacheSet(token, pat);
233
+ return pat;
234
+ }
235
+ async list(subject) {
236
+ const now = Date.now();
237
+ const url = `${this.baseUrl}?subject=eq.${encodeURIComponent(subject)}&or=(expires_at.is.null,expires_at.gt.${now})&order=created_at.desc`;
238
+ const res = await fetch(url, { method: "GET", headers: this.headers({ prefer: "return=representation" }) }).catch(() => null);
239
+ if (!res || !res.ok)
240
+ return [];
241
+ const rows = (await res.json().catch(() => []));
242
+ return rows.map(postgresRowToPAT);
243
+ }
244
+ async revoke(id, subject) {
245
+ const url = `${this.baseUrl}?id=eq.${encodeURIComponent(id)}&subject=eq.${encodeURIComponent(subject)}`;
246
+ const res = await fetch(url, { method: "DELETE", headers: this.headers({ prefer: "return=representation" }) }).catch(() => null);
247
+ // Cleared unconditionally, before checking the result: revocation is
248
+ // security-sensitive, so a cached token must never outlive an attempt to
249
+ // revoke it. The cache is keyed by raw token and revoke() identifies the
250
+ // PAT by id, so there is nothing narrower to drop.
251
+ this.invalidateCache();
252
+ if (!res || !res.ok)
253
+ return false;
254
+ const rows = (await res.json().catch(() => []));
255
+ return rows.length > 0;
256
+ }
257
+ async pruneExpired() {
258
+ // Delete rows where expires_at IS NOT NULL AND expires_at <= now
259
+ const url = `${this.baseUrl}?expires_at=not.is.null&expires_at=lte.${Date.now()}`;
260
+ await fetch(url, { method: "DELETE", headers: this.headers() }).catch(() => null);
261
+ this.invalidateCache();
262
+ }
263
+ }
264
+ // ─── Factory ──────────────────────────────────────────────────────────────────
265
+ export function createPATStore(storageLocation) {
266
+ const supabaseUrl = (process.env.SUPABASE_URL ?? "").trim();
267
+ const serviceRoleKey = (process.env.SUPABASE_SERVICE_ROLE_KEY ?? "").trim();
268
+ if (supabaseUrl && serviceRoleKey) {
269
+ return new PostgresPATStore(supabaseUrl, serviceRoleKey);
270
+ }
271
+ return new LocalSQLitePATStore(storageLocation);
272
+ }
273
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
274
+ function rowToPAT(row) {
275
+ let scopes = [];
276
+ try {
277
+ scopes = JSON.parse(row.scopes);
278
+ }
279
+ catch {
280
+ scopes = [];
281
+ }
282
+ return {
283
+ id: row.id,
284
+ subject: row.subject,
285
+ label: row.label,
286
+ scopes,
287
+ expiresAt: row.expires_at,
288
+ createdAt: row.created_at,
289
+ };
290
+ }
291
+ function postgresRowToPAT(row) {
292
+ let scopes = [];
293
+ try {
294
+ scopes = JSON.parse(row.scopes);
295
+ }
296
+ catch {
297
+ scopes = [];
298
+ }
299
+ return {
300
+ id: row.id,
301
+ subject: row.subject,
302
+ label: row.label,
303
+ scopes,
304
+ expiresAt: row.expires_at !== null ? Number(row.expires_at) : null,
305
+ createdAt: Number(row.created_at),
306
+ };
307
+ }
308
+ //# sourceMappingURL=patStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patStore.js","sourceRoot":"","sources":["../../src/auth/patStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,iFAAiF;AAEjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AA0CvC,MAAM,OAAO,mBAAmB;IACb,EAAE,CAAoB;IAEvC,YAAY,eAAuB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QACtD,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QACtD,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;KAaZ,CAAC,CAAC;QACH,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,8EAA8E;IACtE,qBAAqB;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAA6C,CAAC;QAC/F,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC;YAAE,OAAO,CAAC,qCAAqC;QAC5E,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YACvC,IAAI,CAAC,EAAE;iBACJ,OAAO,CACN;;;;;;;;YAQE,CACH;iBACA,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,EAAE,CAAC;YACtE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,GAAG,EAAE,CAAC;YACzC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAC,GAAG,EAAE,CAAC;QACpE,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,CAAC;QACV,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;KAIZ,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,KAAa,EAAE,MAAgB,EAAE,SAAwB;QACrF,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE;aACJ,OAAO,CACN;mFAC2E,CAC5E;aACA,GAAG,CAAC;YACH,EAAE;YACF,KAAK;YACL,OAAO;YACP,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAC9B,UAAU,EAAE,SAAS,IAAI,IAAI;YAC7B,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QACL,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE;aAChB,OAAO,CAAC,+EAA+E,CAAC;aACxF,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAA6B,CAAC;QACtD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CACN,0GAA0G,CAC3G;aACA,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAmB,CAAC;QAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,OAAe;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE;aACnB,OAAO,CAAC,+CAA+C,CAAC;aACxD,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACpB,OAAO,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,mEAAmE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACvG,CAAC;CACF;AAcD;;;GAGG;AACH,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC;;;GAGG;AACH,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,MAAM,OAAO,gBAAgB;IACV,WAAW,CAAS;IACpB,cAAc,CAAS;IAExC;;;;;;;;;;;;;OAaG;IACc,KAAK,GAAG,IAAI,GAAG,EAA2C,CAAC;IAE5E,YAAY,WAAmB,EAAE,cAAsB;QACrD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAEO,UAAU;QAChB,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACpE,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACnE,CAAC;IAEO,QAAQ,CAAC,KAAa,EAAE,GAAe;QAC7C,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,qBAAqB,EAAE,CAAC;YAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC9C,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,+EAA+E;IAC/E,eAAe;QACb,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAY,OAAO;QACjB,OAAO,GAAG,IAAI,CAAC,WAAW,eAAe,CAAC;IAC5C,CAAC;IAEO,OAAO,CAAC,KAA8B;QAC5C,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,cAAc;YAC3B,aAAa,EAAE,UAAU,IAAI,CAAC,cAAc,EAAE;YAC9C,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,gBAAgB;YACxB,GAAG,KAAK;SACT,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,KAAa,EAAE,MAAgB,EAAE,SAAwB;QACrF,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,EAAE;YACF,KAAK;YACL,OAAO;YACP,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;YAC9B,UAAU,EAAE,SAAS,EAAE,+CAA+C;YACtE,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,4EAA4E;QAC5E,6DAA6D;QAC7D,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC;YACzC,0EAA0E;YAC1E,8CAA8C;YAC9C,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;gBAC9E,OAAO,GAAG,CAAC,GAAG,CAAC;YACjB,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,yDAAyD;QACzD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,aAAa,kBAAkB,CAAC,KAAK,CAAC,yCAAyC,GAAG,WAAW,CAAC;QACzH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAE9H,wEAAwE;QACxE,iEAAiE;QACjE,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAEjC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAqB,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,eAAe,kBAAkB,CAAC,OAAO,CAAC,yCAAyC,GAAG,yBAAyB,CAAC;QAC3I,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC9H,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAqB,CAAC;QACpE,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,OAAe;QACtC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,CAAC,eAAe,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QACxG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QACjI,qEAAqE;QACrE,yEAAyE;QACzE,yEAAyE;QACzE,mDAAmD;QACnD,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAClC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAc,CAAC;QAC7D,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,iEAAiE;QACjE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,0CAA0C,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAClF,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAClF,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;CACF;AAED,iFAAiF;AAEjF,MAAM,UAAU,cAAc,CAAC,eAAuB;IACpD,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5E,IAAI,WAAW,IAAI,cAAc,EAAE,CAAC;QAClC,OAAO,IAAI,gBAAgB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,IAAI,mBAAmB,CAAC,eAAe,CAAC,CAAC;AAClD,CAAC;AAED,iFAAiF;AAEjF,SAAS,QAAQ,CAAC,GAAiB;IACjC,IAAI,MAAM,GAAa,EAAE,CAAC;IAC1B,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAa,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,GAAG,EAAE,CAAC;IAAC,CAAC;IAC3E,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM;QACN,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAmB;IAC3C,IAAI,MAAM,GAAa,EAAE,CAAC;IAC1B,IAAI,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAa,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,GAAG,EAAE,CAAC;IAAC,CAAC;IAC3E,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM;QACN,SAAS,EAAE,GAAG,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI;QAClE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;KAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ export declare class SupabaseAuthManager {
2
+ private readonly supabaseUrl;
3
+ private readonly anonKey;
4
+ private readonly cache;
5
+ constructor();
6
+ isEnabled(): boolean;
7
+ authenticateAccessToken(token: string): Promise<{
8
+ subject: string;
9
+ scopes: string[];
10
+ } | null>;
11
+ private fetchUser;
12
+ private resolveScopes;
13
+ private pruneExpired;
14
+ }
15
+ //# sourceMappingURL=supabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/auth/supabase.ts"],"names":[],"mappings":"AAmBA,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;;IAOvD,SAAS,IAAI,OAAO;IAId,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;YAmBrF,SAAS;IAevB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,YAAY;CAQrB"}
@@ -0,0 +1,66 @@
1
+ const AUTH_CACHE_TTL_MS = 60 * 1000;
2
+ export class SupabaseAuthManager {
3
+ supabaseUrl;
4
+ anonKey;
5
+ cache = new Map();
6
+ constructor() {
7
+ this.supabaseUrl = (process.env.SUPABASE_URL ?? "").trim().replace(/\/$/, "");
8
+ this.anonKey = (process.env.SUPABASE_ANON_KEY ?? "").trim();
9
+ }
10
+ isEnabled() {
11
+ return this.supabaseUrl.length > 0 && this.anonKey.length > 0;
12
+ }
13
+ async authenticateAccessToken(token) {
14
+ if (!this.isEnabled())
15
+ return null;
16
+ this.pruneExpired();
17
+ const cached = this.cache.get(token);
18
+ if (cached)
19
+ return cached.auth;
20
+ const user = await this.fetchUser(token);
21
+ if (!user?.id)
22
+ return null;
23
+ const scopes = this.resolveScopes(user);
24
+ const auth = { subject: user.id, scopes };
25
+ this.cache.set(token, {
26
+ expiresAt: Date.now() + AUTH_CACHE_TTL_MS,
27
+ auth,
28
+ });
29
+ return auth;
30
+ }
31
+ async fetchUser(token) {
32
+ const url = `${this.supabaseUrl}/auth/v1/user`;
33
+ const response = await fetch(url, {
34
+ method: "GET",
35
+ headers: {
36
+ apikey: this.anonKey,
37
+ authorization: `Bearer ${token}`,
38
+ },
39
+ }).catch(() => null);
40
+ if (!response || !response.ok)
41
+ return null;
42
+ return (await response.json().catch(() => null));
43
+ }
44
+ resolveScopes(user) {
45
+ const configured = user.app_metadata?.brainsScopes;
46
+ if (Array.isArray(configured) && configured.length > 0) {
47
+ const normalized = configured
48
+ .filter((v) => typeof v === "string")
49
+ .map((v) => v.trim())
50
+ .filter((v) => v === "wiki.read" || v === "wiki.write");
51
+ if (normalized.length > 0)
52
+ return Array.from(new Set(normalized));
53
+ }
54
+ // Default for first rollout: authenticated users can read/write.
55
+ return ["wiki.read", "wiki.write"];
56
+ }
57
+ pruneExpired() {
58
+ const now = Date.now();
59
+ for (const [token, cached] of this.cache.entries()) {
60
+ if (cached.expiresAt <= now) {
61
+ this.cache.delete(token);
62
+ }
63
+ }
64
+ }
65
+ }
66
+ //# sourceMappingURL=supabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../src/auth/supabase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * OAuth token persistence layer — local session sync.
3
+ *
4
+ * Provides a `TokenStore` interface with two implementations:
5
+ *
6
+ * - `LocalSQLiteTokenStore` — SQLite-backed, stored next to the search
7
+ * index under `<storageLocation>/.cache/oauth-tokens.db`. Zero extra
8
+ * dependencies (uses the already-bundled `better-sqlite3`). Suitable
9
+ * for single-instance local and Railway deployments.
10
+ *
11
+ * - `PostgresTokenStore` — Supabase PostgREST-backed, stored in an
12
+ * `oauth_tokens` table. Enables multi-instance / stateless deployments
13
+ * where the process may restart without losing active sessions. See
14
+ * `scripts/oauth-tokens.sql` for the required migration.
15
+ *
16
+ * `createTokenStore()` auto-selects the backend based on env vars:
17
+ * - `SUPABASE_URL` + `SUPABASE_SERVICE_ROLE_KEY` → PostgresTokenStore
18
+ * - otherwise → LocalSQLiteTokenStore
19
+ */
20
+ export type TokenType = "auth_code" | "access_token" | "refresh_token";
21
+ export interface StoredToken {
22
+ type: TokenType;
23
+ token: string;
24
+ clientId: string;
25
+ subject: string;
26
+ scope: string[];
27
+ expiresAt: number;
28
+ /** auth_code only */
29
+ redirectUri?: string;
30
+ codeChallenge?: string;
31
+ codeChallengeMethod?: string;
32
+ }
33
+ export interface TokenStore {
34
+ save(record: StoredToken): Promise<void>;
35
+ find(type: TokenType, token: string): Promise<StoredToken | null>;
36
+ delete(type: TokenType, token: string): Promise<void>;
37
+ /** Delete all tokens of `type` for a given subject + client pair. */
38
+ deleteAllForSubject(subject: string, clientId: string, type: TokenType): Promise<void>;
39
+ /** Delete ALL tokens (all types, all clients) for a subject — used during account deletion. */
40
+ deleteAllTokensForSubject(subject: string): Promise<void>;
41
+ pruneExpired(): Promise<void>;
42
+ }
43
+ export declare class LocalSQLiteTokenStore implements TokenStore {
44
+ private readonly db;
45
+ constructor(storageLocation: string);
46
+ private initSchema;
47
+ save(record: StoredToken): Promise<void>;
48
+ find(type: TokenType, token: string): Promise<StoredToken | null>;
49
+ delete(type: TokenType, token: string): Promise<void>;
50
+ deleteAllForSubject(subject: string, clientId: string, type: TokenType): Promise<void>;
51
+ deleteAllTokensForSubject(subject: string): Promise<void>;
52
+ pruneExpired(): Promise<void>;
53
+ }
54
+ export declare class PostgresTokenStore implements TokenStore {
55
+ private readonly supabaseUrl;
56
+ private readonly serviceRoleKey;
57
+ constructor(supabaseUrl: string, serviceRoleKey: string);
58
+ private authHeaders;
59
+ private get baseUrl();
60
+ save(record: StoredToken): Promise<void>;
61
+ find(type: TokenType, token: string): Promise<StoredToken | null>;
62
+ delete(type: TokenType, token: string): Promise<void>;
63
+ deleteAllForSubject(subject: string, clientId: string, type: TokenType): Promise<void>;
64
+ deleteAllTokensForSubject(subject: string): Promise<void>;
65
+ pruneExpired(): Promise<void>;
66
+ }
67
+ /**
68
+ * Select and instantiate a token store based on the environment:
69
+ * - SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY present → PostgresTokenStore
70
+ * - otherwise → LocalSQLiteTokenStore (stored under `storageLocation/.cache/`)
71
+ */
72
+ export declare function createTokenStore(storageLocation: string): TokenStore;
73
+ //# sourceMappingURL=tokenStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenStore.d.ts","sourceRoot":"","sources":["../../src/auth/tokenStore.ts"],"names":[],"mappings":"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"}