mrplex 0.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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +284 -0
  3. package/dist/cli/config.d.ts +28 -0
  4. package/dist/cli/config.js +48 -0
  5. package/dist/cli/config.js.map +1 -0
  6. package/dist/cli/exit-codes.d.ts +13 -0
  7. package/dist/cli/exit-codes.js +39 -0
  8. package/dist/cli/exit-codes.js.map +1 -0
  9. package/dist/cli/format.d.ts +22 -0
  10. package/dist/cli/format.js +148 -0
  11. package/dist/cli/format.js.map +1 -0
  12. package/dist/cli/main.d.ts +16 -0
  13. package/dist/cli/main.js +1518 -0
  14. package/dist/cli/main.js.map +1 -0
  15. package/dist/client/kernel-client.d.ts +97 -0
  16. package/dist/client/kernel-client.js +14 -0
  17. package/dist/client/kernel-client.js.map +1 -0
  18. package/dist/client/local.d.ts +26 -0
  19. package/dist/client/local.js +103 -0
  20. package/dist/client/local.js.map +1 -0
  21. package/dist/client/remote-mcp.d.ts +35 -0
  22. package/dist/client/remote-mcp.js +174 -0
  23. package/dist/client/remote-mcp.js.map +1 -0
  24. package/dist/embed/backfill.d.ts +24 -0
  25. package/dist/embed/backfill.js +33 -0
  26. package/dist/embed/backfill.js.map +1 -0
  27. package/dist/embed/chunker.d.ts +31 -0
  28. package/dist/embed/chunker.js +121 -0
  29. package/dist/embed/chunker.js.map +1 -0
  30. package/dist/embed/cmd-hook.d.ts +21 -0
  31. package/dist/embed/cmd-hook.js +100 -0
  32. package/dist/embed/cmd-hook.js.map +1 -0
  33. package/dist/embed/config.d.ts +61 -0
  34. package/dist/embed/config.js +109 -0
  35. package/dist/embed/config.js.map +1 -0
  36. package/dist/embed/hook.d.ts +38 -0
  37. package/dist/embed/hook.js +56 -0
  38. package/dist/embed/hook.js.map +1 -0
  39. package/dist/embed/http-hook.d.ts +13 -0
  40. package/dist/embed/http-hook.js +39 -0
  41. package/dist/embed/http-hook.js.map +1 -0
  42. package/dist/embed/worker.d.ts +62 -0
  43. package/dist/embed/worker.js +228 -0
  44. package/dist/embed/worker.js.map +1 -0
  45. package/dist/fixtures/hwe/characters/albion-ever.md +12 -0
  46. package/dist/fixtures/hwe/characters/cent.md +11 -0
  47. package/dist/fixtures/hwe/concepts/cent-demiurge-resonance.md +10 -0
  48. package/dist/fixtures/hwe/concepts/phase-looper.md +10 -0
  49. package/dist/fixtures/hwe/entities/demiurge.md +11 -0
  50. package/dist/fixtures/hwe/entities/monad.md +11 -0
  51. package/dist/fixtures/hwe/moc/globocorp-network.md +19 -0
  52. package/dist/fixtures/hwe/organizations/globocorp.md +11 -0
  53. package/dist/fixtures/hwe/readme.md +24 -0
  54. package/dist/fixtures/starship/crew/aria-okonkwo.md +14 -0
  55. package/dist/fixtures/starship/crew/bexley-orr.md +14 -0
  56. package/dist/fixtures/starship/crew/dax-thorne.md +14 -0
  57. package/dist/fixtures/starship/crew/isolde-marsh.md +16 -0
  58. package/dist/fixtures/starship/crew/kestrel-vance.md +15 -0
  59. package/dist/fixtures/starship/crew/quill-vasquez.md +14 -0
  60. package/dist/fixtures/starship/crew/soren-halloway.md +16 -0
  61. package/dist/fixtures/starship/encounters/the-drift-choir.md +14 -0
  62. package/dist/fixtures/starship/encounters/the-hollow-signal.md +16 -0
  63. package/dist/fixtures/starship/encounters/the-wandering-buoy.md +14 -0
  64. package/dist/fixtures/starship/equipment/coolant-loop-b.md +13 -0
  65. package/dist/fixtures/starship/equipment/emergency-ration-bars.md +12 -0
  66. package/dist/fixtures/starship/equipment/long-range-sensors.md +13 -0
  67. package/dist/fixtures/starship/equipment/plasma-manifold-3.md +15 -0
  68. package/dist/fixtures/starship/equipment/shuttle-corvid.md +13 -0
  69. package/dist/fixtures/starship/logs/marsh-4419-1.md +13 -0
  70. package/dist/fixtures/starship/logs/okonkwo-4415-1.md +13 -0
  71. package/dist/fixtures/starship/logs/orr-4413-1.md +13 -0
  72. package/dist/fixtures/starship/logs/orr-4420-1.md +12 -0
  73. package/dist/fixtures/starship/logs/thorne-4413-2.md +13 -0
  74. package/dist/fixtures/starship/logs/vance-4419-2.md +13 -0
  75. package/dist/fixtures/starship/misc/the-galley-ficus.md +11 -0
  76. package/dist/fixtures/starship/missions/the-cinder-run.md +17 -0
  77. package/dist/fixtures/starship/missions/the-drift-choir.md +17 -0
  78. package/dist/fixtures/starship/missions/the-hollow-signal.md +17 -0
  79. package/dist/fixtures/starship/missions/the-silent-beacon.md +17 -0
  80. package/dist/fixtures/starship/moc/crew.md +19 -0
  81. package/dist/fixtures/starship/moc/encounters.md +14 -0
  82. package/dist/fixtures/starship/moc/missions.md +15 -0
  83. package/dist/fixtures/starship/readme.md +60 -0
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.js +3 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/kernel/auth/glob.d.ts +46 -0
  88. package/dist/kernel/auth/glob.js +112 -0
  89. package/dist/kernel/auth/glob.js.map +1 -0
  90. package/dist/kernel/auth/scope.d.ts +53 -0
  91. package/dist/kernel/auth/scope.js +83 -0
  92. package/dist/kernel/auth/scope.js.map +1 -0
  93. package/dist/kernel/casefold.d.ts +37 -0
  94. package/dist/kernel/casefold.js +44 -0
  95. package/dist/kernel/casefold.js.map +1 -0
  96. package/dist/kernel/constants.d.ts +21 -0
  97. package/dist/kernel/constants.js +22 -0
  98. package/dist/kernel/constants.js.map +1 -0
  99. package/dist/kernel/context.d.ts +70 -0
  100. package/dist/kernel/context.js +114 -0
  101. package/dist/kernel/context.js.map +1 -0
  102. package/dist/kernel/deletion.d.ts +50 -0
  103. package/dist/kernel/deletion.js +83 -0
  104. package/dist/kernel/deletion.js.map +1 -0
  105. package/dist/kernel/diff.d.ts +36 -0
  106. package/dist/kernel/diff.js +61 -0
  107. package/dist/kernel/diff.js.map +1 -0
  108. package/dist/kernel/errors.d.ts +37 -0
  109. package/dist/kernel/errors.js +55 -0
  110. package/dist/kernel/errors.js.map +1 -0
  111. package/dist/kernel/frontmatter-input.d.ts +32 -0
  112. package/dist/kernel/frontmatter-input.js +85 -0
  113. package/dist/kernel/frontmatter-input.js.map +1 -0
  114. package/dist/kernel/graph.d.ts +34 -0
  115. package/dist/kernel/graph.js +559 -0
  116. package/dist/kernel/graph.js.map +1 -0
  117. package/dist/kernel/history.d.ts +74 -0
  118. package/dist/kernel/history.js +143 -0
  119. package/dist/kernel/history.js.map +1 -0
  120. package/dist/kernel/kernel.d.ts +162 -0
  121. package/dist/kernel/kernel.js +675 -0
  122. package/dist/kernel/kernel.js.map +1 -0
  123. package/dist/kernel/path-config.d.ts +101 -0
  124. package/dist/kernel/path-config.js +171 -0
  125. package/dist/kernel/path-config.js.map +1 -0
  126. package/dist/kernel/query/ast.d.ts +24 -0
  127. package/dist/kernel/query/ast.js +52 -0
  128. package/dist/kernel/query/ast.js.map +1 -0
  129. package/dist/kernel/query/cel-parse.d.ts +37 -0
  130. package/dist/kernel/query/cel-parse.js +88 -0
  131. package/dist/kernel/query/cel-parse.js.map +1 -0
  132. package/dist/kernel/query/degrees.d.ts +31 -0
  133. package/dist/kernel/query/degrees.js +135 -0
  134. package/dist/kernel/query/degrees.js.map +1 -0
  135. package/dist/kernel/query/graph-ast.d.ts +51 -0
  136. package/dist/kernel/query/graph-ast.js +139 -0
  137. package/dist/kernel/query/graph-ast.js.map +1 -0
  138. package/dist/kernel/query/query.d.ts +56 -0
  139. package/dist/kernel/query/query.js +276 -0
  140. package/dist/kernel/query/query.js.map +1 -0
  141. package/dist/kernel/validation.d.ts +64 -0
  142. package/dist/kernel/validation.js +183 -0
  143. package/dist/kernel/validation.js.map +1 -0
  144. package/dist/kernel/version-id.d.ts +10 -0
  145. package/dist/kernel/version-id.js +21 -0
  146. package/dist/kernel/version-id.js.map +1 -0
  147. package/dist/kernel/wire.d.ts +148 -0
  148. package/dist/kernel/wire.js +6 -0
  149. package/dist/kernel/wire.js.map +1 -0
  150. package/dist/links/backfill.d.ts +28 -0
  151. package/dist/links/backfill.js +33 -0
  152. package/dist/links/backfill.js.map +1 -0
  153. package/dist/links/extract.d.ts +29 -0
  154. package/dist/links/extract.js +233 -0
  155. package/dist/links/extract.js.map +1 -0
  156. package/dist/links/link-config.d.ts +70 -0
  157. package/dist/links/link-config.js +107 -0
  158. package/dist/links/link-config.js.map +1 -0
  159. package/dist/links/maintain.d.ts +37 -0
  160. package/dist/links/maintain.js +91 -0
  161. package/dist/links/maintain.js.map +1 -0
  162. package/dist/links/repair.d.ts +46 -0
  163. package/dist/links/repair.js +96 -0
  164. package/dist/links/repair.js.map +1 -0
  165. package/dist/links/resolve.d.ts +41 -0
  166. package/dist/links/resolve.js +121 -0
  167. package/dist/links/resolve.js.map +1 -0
  168. package/dist/links/stale.d.ts +32 -0
  169. package/dist/links/stale.js +73 -0
  170. package/dist/links/stale.js.map +1 -0
  171. package/dist/markdown/content-hash.d.ts +34 -0
  172. package/dist/markdown/content-hash.js +46 -0
  173. package/dist/markdown/content-hash.js.map +1 -0
  174. package/dist/markdown/frontmatter.d.ts +69 -0
  175. package/dist/markdown/frontmatter.js +147 -0
  176. package/dist/markdown/frontmatter.js.map +1 -0
  177. package/dist/markdown/hash-backfill.d.ts +22 -0
  178. package/dist/markdown/hash-backfill.js +43 -0
  179. package/dist/markdown/hash-backfill.js.map +1 -0
  180. package/dist/mcp/query-syntax.d.ts +20 -0
  181. package/dist/mcp/query-syntax.js +194 -0
  182. package/dist/mcp/query-syntax.js.map +1 -0
  183. package/dist/mcp/render.d.ts +31 -0
  184. package/dist/mcp/render.js +110 -0
  185. package/dist/mcp/render.js.map +1 -0
  186. package/dist/mcp/server.d.ts +60 -0
  187. package/dist/mcp/server.js +170 -0
  188. package/dist/mcp/server.js.map +1 -0
  189. package/dist/mcp/tools.d.ts +93 -0
  190. package/dist/mcp/tools.js +1218 -0
  191. package/dist/mcp/tools.js.map +1 -0
  192. package/dist/rest/conditional.d.ts +37 -0
  193. package/dist/rest/conditional.js +58 -0
  194. package/dist/rest/conditional.js.map +1 -0
  195. package/dist/rest/negotiate.d.ts +33 -0
  196. package/dist/rest/negotiate.js +54 -0
  197. package/dist/rest/negotiate.js.map +1 -0
  198. package/dist/rest/routes.d.ts +37 -0
  199. package/dist/rest/routes.js +744 -0
  200. package/dist/rest/routes.js.map +1 -0
  201. package/dist/seed/fixture-seed.d.ts +35 -0
  202. package/dist/seed/fixture-seed.js +75 -0
  203. package/dist/seed/fixture-seed.js.map +1 -0
  204. package/dist/seed/starship-config.d.ts +3 -0
  205. package/dist/seed/starship-config.js +5 -0
  206. package/dist/seed/starship-config.js.map +1 -0
  207. package/dist/server/headers.d.ts +36 -0
  208. package/dist/server/headers.js +30 -0
  209. package/dist/server/headers.js.map +1 -0
  210. package/dist/server/http-error.d.ts +53 -0
  211. package/dist/server/http-error.js +104 -0
  212. package/dist/server/http-error.js.map +1 -0
  213. package/dist/server/serve.d.ts +56 -0
  214. package/dist/server/serve.js +135 -0
  215. package/dist/server/serve.js.map +1 -0
  216. package/dist/shell/audit.d.ts +32 -0
  217. package/dist/shell/audit.js +28 -0
  218. package/dist/shell/audit.js.map +1 -0
  219. package/dist/shell/guard.d.ts +50 -0
  220. package/dist/shell/guard.js +176 -0
  221. package/dist/shell/guard.js.map +1 -0
  222. package/dist/shell/keys.d.ts +36 -0
  223. package/dist/shell/keys.js +64 -0
  224. package/dist/shell/keys.js.map +1 -0
  225. package/dist/shell/login.d.ts +56 -0
  226. package/dist/shell/login.js +130 -0
  227. package/dist/shell/login.js.map +1 -0
  228. package/dist/shell/oidc.d.ts +62 -0
  229. package/dist/shell/oidc.js +102 -0
  230. package/dist/shell/oidc.js.map +1 -0
  231. package/dist/shell/policy.d.ts +100 -0
  232. package/dist/shell/policy.js +232 -0
  233. package/dist/shell/policy.js.map +1 -0
  234. package/dist/shell/proxy-policy.d.ts +34 -0
  235. package/dist/shell/proxy-policy.js +120 -0
  236. package/dist/shell/proxy-policy.js.map +1 -0
  237. package/dist/shell/proxy.d.ts +47 -0
  238. package/dist/shell/proxy.js +253 -0
  239. package/dist/shell/proxy.js.map +1 -0
  240. package/dist/shell/serve.d.ts +86 -0
  241. package/dist/shell/serve.js +0 -0
  242. package/dist/shell/serve.js.map +1 -0
  243. package/dist/shell/stdio.d.ts +55 -0
  244. package/dist/shell/stdio.js +63 -0
  245. package/dist/shell/stdio.js.map +1 -0
  246. package/dist/storage/registry.d.ts +20 -0
  247. package/dist/storage/registry.js +38 -0
  248. package/dist/storage/registry.js.map +1 -0
  249. package/dist/storage/search-plan.d.ts +93 -0
  250. package/dist/storage/search-plan.js +15 -0
  251. package/dist/storage/search-plan.js.map +1 -0
  252. package/dist/storage/types.d.ts +448 -0
  253. package/dist/storage/types.js +14 -0
  254. package/dist/storage/types.js.map +1 -0
  255. package/dist/storage/versions-since.d.ts +72 -0
  256. package/dist/storage/versions-since.js +92 -0
  257. package/dist/storage/versions-since.js.map +1 -0
  258. package/dist/storage-postgres/adapter.d.ts +17 -0
  259. package/dist/storage-postgres/adapter.js +782 -0
  260. package/dist/storage-postgres/adapter.js.map +1 -0
  261. package/dist/storage-postgres/compile-postgres.d.ts +22 -0
  262. package/dist/storage-postgres/compile-postgres.js +830 -0
  263. package/dist/storage-postgres/compile-postgres.js.map +1 -0
  264. package/dist/storage-postgres/errors.d.ts +34 -0
  265. package/dist/storage-postgres/errors.js +50 -0
  266. package/dist/storage-postgres/errors.js.map +1 -0
  267. package/dist/storage-postgres/migrations/0001_init.sql +113 -0
  268. package/dist/storage-postgres/migrations/0002_content_hash.sql +7 -0
  269. package/dist/storage-postgres/migrations/index.d.ts +22 -0
  270. package/dist/storage-postgres/migrations/index.js +70 -0
  271. package/dist/storage-postgres/migrations/index.js.map +1 -0
  272. package/dist/storage-sqlite/adapter.d.ts +2 -0
  273. package/dist/storage-sqlite/adapter.js +688 -0
  274. package/dist/storage-sqlite/adapter.js.map +1 -0
  275. package/dist/storage-sqlite/compile-filter.d.ts +41 -0
  276. package/dist/storage-sqlite/compile-filter.js +881 -0
  277. package/dist/storage-sqlite/compile-filter.js.map +1 -0
  278. package/dist/storage-sqlite/compile-sqlite.d.ts +19 -0
  279. package/dist/storage-sqlite/compile-sqlite.js +176 -0
  280. package/dist/storage-sqlite/compile-sqlite.js.map +1 -0
  281. package/dist/storage-sqlite/migrations/0001_init.sql +123 -0
  282. package/dist/storage-sqlite/migrations/0002_content_hash.sql +7 -0
  283. package/dist/storage-sqlite/migrations/index.d.ts +6 -0
  284. package/dist/storage-sqlite/migrations/index.js +41 -0
  285. package/dist/storage-sqlite/migrations/index.js.map +1 -0
  286. package/dist/storage-sqlite/vec.d.ts +40 -0
  287. package/dist/storage-sqlite/vec.js +62 -0
  288. package/dist/storage-sqlite/vec.js.map +1 -0
  289. package/dist/sync/cursor.d.ts +36 -0
  290. package/dist/sync/cursor.js +66 -0
  291. package/dist/sync/cursor.js.map +1 -0
  292. package/dist/sync/daemon.d.ts +40 -0
  293. package/dist/sync/daemon.js +202 -0
  294. package/dist/sync/daemon.js.map +1 -0
  295. package/dist/sync/feed.d.ts +38 -0
  296. package/dist/sync/feed.js +125 -0
  297. package/dist/sync/feed.js.map +1 -0
  298. package/dist/sync/fs-store.d.ts +8 -0
  299. package/dist/sync/fs-store.js +76 -0
  300. package/dist/sync/fs-store.js.map +1 -0
  301. package/dist/sync/intrinsics.d.ts +52 -0
  302. package/dist/sync/intrinsics.js +76 -0
  303. package/dist/sync/intrinsics.js.map +1 -0
  304. package/dist/sync/paths.d.ts +38 -0
  305. package/dist/sync/paths.js +56 -0
  306. package/dist/sync/paths.js.map +1 -0
  307. package/dist/sync/push.d.ts +48 -0
  308. package/dist/sync/push.js +328 -0
  309. package/dist/sync/push.js.map +1 -0
  310. package/dist/sync/reconcile.d.ts +54 -0
  311. package/dist/sync/reconcile.js +252 -0
  312. package/dist/sync/reconcile.js.map +1 -0
  313. package/dist/sync/run.d.ts +27 -0
  314. package/dist/sync/run.js +46 -0
  315. package/dist/sync/run.js.map +1 -0
  316. package/dist/version.d.ts +2 -0
  317. package/dist/version.js +5 -0
  318. package/dist/version.js.map +1 -0
  319. package/package.json +80 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Audit log — auth-shell plan §1 (audit), decision 8; noauth-plan decision 7.
3
+ *
4
+ * Append-only JSONL, one line per authenticated call: `{ ts, principal, op,
5
+ * repo, path, outcome }` (+ engine `error` when the forwarded call failed).
6
+ * Written by the guard's audit sink — a single choke point, so no surface can
7
+ * forget to log. The engine's `author` column is *attribution* (who wrote the
8
+ * content); this log is *accountability* (who called the shell). Different
9
+ * facts, stored in different places on purpose.
10
+ */
11
+ import type { AuditSink } from "./guard.js";
12
+ /** One serialized audit record. Field order is stable for greppability. */
13
+ export type AuditRecord = {
14
+ ts: string;
15
+ principal: string;
16
+ op: string;
17
+ repo?: string;
18
+ path?: string;
19
+ outcome: "ok" | "forbidden";
20
+ error?: string;
21
+ };
22
+ /**
23
+ * Build an `AuditSink` bound to a principal that appends JSONL to `path`. The
24
+ * guard is principal-agnostic (it knows only the entitlement), so the principal
25
+ * is closed over here — one sink per authenticated session/request.
26
+ *
27
+ * Appends are synchronous: an audit record must be durable before the call's
28
+ * effect is observable, and the volume (one line per op) doesn't justify an
29
+ * async writer. A write failure throws — losing the audit trail silently is
30
+ * worse than failing the call.
31
+ */
32
+ export declare function fileAuditSink(path: string, principal: string): AuditSink;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Audit log — auth-shell plan §1 (audit), decision 8; noauth-plan decision 7.
3
+ *
4
+ * Append-only JSONL, one line per authenticated call: `{ ts, principal, op,
5
+ * repo, path, outcome }` (+ engine `error` when the forwarded call failed).
6
+ * Written by the guard's audit sink — a single choke point, so no surface can
7
+ * forget to log. The engine's `author` column is *attribution* (who wrote the
8
+ * content); this log is *accountability* (who called the shell). Different
9
+ * facts, stored in different places on purpose.
10
+ */
11
+ import { appendFileSync } from "node:fs";
12
+ /**
13
+ * Build an `AuditSink` bound to a principal that appends JSONL to `path`. The
14
+ * guard is principal-agnostic (it knows only the entitlement), so the principal
15
+ * is closed over here — one sink per authenticated session/request.
16
+ *
17
+ * Appends are synchronous: an audit record must be durable before the call's
18
+ * effect is observable, and the volume (one line per op) doesn't justify an
19
+ * async writer. A write failure throws — losing the audit trail silently is
20
+ * worse than failing the call.
21
+ */
22
+ export function fileAuditSink(path, principal) {
23
+ return (event) => {
24
+ const record = { ts: new Date().toISOString(), principal, ...event };
25
+ appendFileSync(path, `${JSON.stringify(record)}\n`);
26
+ };
27
+ }
28
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/shell/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAczC;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,SAAiB;IAC3D,OAAO,CAAC,KAAiB,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAgB,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,CAAC;QAClF,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * guardKernel — the access-and-identity decorator (auth-shell plan §1, WS2).
3
+ *
4
+ * The shell's core is NOT a proxy: it is an object with the same shape as the
5
+ * `Kernel` interface whose every method
6
+ * • stamps `ctx.author` from the entitlement (never trusts the caller's,
7
+ * unless `impersonate`),
8
+ * • forwards reads with `ctx.scope = entitlement.read` (the engine does the
9
+ * filtering — search ranking, pagination, graph traversal stay kernel-side),
10
+ * • enforces write policy against the TYPED call arguments using
11
+ * `entitlement.write` and the engine's own glob dialect,
12
+ * • gates destructive ops on `entitlement.destructive`,
13
+ * • and forwards to the wrapped kernel.
14
+ *
15
+ * The kernel never learns any of this exists. The shell imports only the
16
+ * kernel's public seam (`Kernel`, `CallContext`, `ScopeClaim`, the glob engine
17
+ * via `normalizeClaims`); nothing here reaches into engine internals, so the
18
+ * whole module could be extracted to its own package without touching engine
19
+ * code — that extractability is the test of the boundary (plan §intro).
20
+ *
21
+ * Write enforcement replays the old design §8.2 rules (plan decision 5):
22
+ * both-endpoints on moves, system-sigil endpoints skipped (the kernel's
23
+ * validatePath owns that namespace), and write does NOT imply read — so writes
24
+ * forward with no read-scope, or the engine's repo-visibility check would
25
+ * block a write to a repo the caller can't read (plan decision, §1 writes).
26
+ */
27
+ import type { Kernel } from "../kernel/kernel.js";
28
+ import type { Entitlement } from "./policy.js";
29
+ /**
30
+ * One audited call. The guard supplies the operation-shaped fields; the sink's
31
+ * owner (embedded serve / stdio launcher) adds `ts` and `principal` — the guard
32
+ * is principal-agnostic, it only knows the compiled entitlement.
33
+ */
34
+ export type AuditEvent = {
35
+ /** Dotted op name, e.g. `docs.put`, `repos.delete`, `query`. */
36
+ op: string;
37
+ repo?: string;
38
+ path?: string;
39
+ outcome: "ok" | "forbidden";
40
+ /** Kernel error code when the forwarded call threw (outcome stays "ok" — the
41
+ * shell allowed it; the engine rejected it for its own reasons). */
42
+ error?: string;
43
+ };
44
+ export type AuditSink = (event: AuditEvent) => void;
45
+ /**
46
+ * Wrap a full-trust kernel in an entitlement. The returned object satisfies the
47
+ * `Kernel` interface exactly, so any surface (embedded HTTP, stdio MCP) mounts
48
+ * it unchanged.
49
+ */
50
+ export declare function guardKernel(kernel: Kernel, entitlement: Entitlement, audit?: AuditSink): Kernel;
@@ -0,0 +1,176 @@
1
+ /**
2
+ * guardKernel — the access-and-identity decorator (auth-shell plan §1, WS2).
3
+ *
4
+ * The shell's core is NOT a proxy: it is an object with the same shape as the
5
+ * `Kernel` interface whose every method
6
+ * • stamps `ctx.author` from the entitlement (never trusts the caller's,
7
+ * unless `impersonate`),
8
+ * • forwards reads with `ctx.scope = entitlement.read` (the engine does the
9
+ * filtering — search ranking, pagination, graph traversal stay kernel-side),
10
+ * • enforces write policy against the TYPED call arguments using
11
+ * `entitlement.write` and the engine's own glob dialect,
12
+ * • gates destructive ops on `entitlement.destructive`,
13
+ * • and forwards to the wrapped kernel.
14
+ *
15
+ * The kernel never learns any of this exists. The shell imports only the
16
+ * kernel's public seam (`Kernel`, `CallContext`, `ScopeClaim`, the glob engine
17
+ * via `normalizeClaims`); nothing here reaches into engine internals, so the
18
+ * whole module could be extracted to its own package without touching engine
19
+ * code — that extractability is the test of the boundary (plan §intro).
20
+ *
21
+ * Write enforcement replays the old design §8.2 rules (plan decision 5):
22
+ * both-endpoints on moves, system-sigil endpoints skipped (the kernel's
23
+ * validatePath owns that namespace), and write does NOT imply read — so writes
24
+ * forward with no read-scope, or the engine's repo-visibility check would
25
+ * block a write to a repo the caller can't read (plan decision, §1 writes).
26
+ */
27
+ import { claimsGrantRead as claimsCoverPath, normalizeClaims } from "../kernel/auth/scope.js";
28
+ import { pathIsInSystemNamespace } from "../kernel/deletion.js";
29
+ import { forbidden } from "../kernel/errors.js";
30
+ import { HARDCODED_DEFAULTS } from "../kernel/path-config.js";
31
+ /**
32
+ * Wrap a full-trust kernel in an entitlement. The returned object satisfies the
33
+ * `Kernel` interface exactly, so any surface (embedded HTTP, stdio MCP) mounts
34
+ * it unchanged.
35
+ */
36
+ export function guardKernel(kernel, entitlement, audit) {
37
+ const writeMatchers = normalizeClaims(entitlement.write);
38
+ const sigils = HARDCODED_DEFAULTS.system_sigils;
39
+ /** Identity stamped on writes — the caller's author only when impersonating. */
40
+ function authorFor(ctx) {
41
+ return entitlement.impersonate && ctx.author !== undefined ? ctx.author : entitlement.author;
42
+ }
43
+ /** Context for a read: the entitlement's read scope, nothing caller-supplied. */
44
+ function readCtx() {
45
+ return { scope: entitlement.read };
46
+ }
47
+ /**
48
+ * Context for a write/destructive op: the derived author and NO scope. Write
49
+ * does not imply read (plan decision 5), so forwarding a read scope here would
50
+ * make the engine's repo-visibility check reject a legitimate write.
51
+ */
52
+ function writeCtx(ctx) {
53
+ return { author: authorFor(ctx) };
54
+ }
55
+ function emit(event) {
56
+ audit?.(event);
57
+ }
58
+ /** Enforce write policy on one endpoint. System-sigil paths are the kernel's
59
+ * to police (validatePath), so the shell skips them. */
60
+ function assertWritable(op, repo, path) {
61
+ if (pathIsInSystemNamespace(path, sigils))
62
+ return;
63
+ if (!claimsCoverPath(writeMatchers, repo, path)) {
64
+ emit({ op, repo, path, outcome: "forbidden" });
65
+ throw forbidden();
66
+ }
67
+ }
68
+ function assertDestructive(op, repo) {
69
+ if (!entitlement.destructive) {
70
+ emit({ op, repo, outcome: "forbidden" });
71
+ throw forbidden();
72
+ }
73
+ }
74
+ /** Forward a call, auditing the outcome (ok, or ok-with-engine-error). */
75
+ async function forward(op, meta, run) {
76
+ try {
77
+ const result = await run();
78
+ emit({ op, ...meta, outcome: "ok" });
79
+ return result;
80
+ }
81
+ catch (err) {
82
+ emit({ op, ...meta, outcome: "ok", error: errorCode(err) });
83
+ throw err;
84
+ }
85
+ }
86
+ return {
87
+ repos: {
88
+ list: (_ctx, opts) => forward("repos.list", {}, () => kernel.repos.list(readCtx(), opts)),
89
+ get: (_ctx, slug) => forward("repos.get", { repo: slug }, () => kernel.repos.get(readCtx(), slug)),
90
+ create: async (ctx, slug) => {
91
+ assertDestructive("repos.create", slug);
92
+ return forward("repos.create", { repo: slug }, () => kernel.repos.create(writeCtx(ctx), slug));
93
+ },
94
+ rename: async (ctx, slug, newSlug) => {
95
+ assertDestructive("repos.rename", slug);
96
+ return forward("repos.rename", { repo: slug }, () => kernel.repos.rename(writeCtx(ctx), slug, newSlug));
97
+ },
98
+ delete: async (ctx, slug) => {
99
+ assertDestructive("repos.delete", slug);
100
+ return forward("repos.delete", { repo: slug }, () => kernel.repos.delete(writeCtx(ctx), slug));
101
+ },
102
+ set_path_config: async (ctx, slug, config) => {
103
+ assertDestructive("repos.set_path_config", slug);
104
+ return forward("repos.set_path_config", { repo: slug }, () => kernel.repos.set_path_config(writeCtx(ctx), slug, config));
105
+ },
106
+ set_link_config: async (ctx, slug, config) => {
107
+ assertDestructive("repos.set_link_config", slug);
108
+ return forward("repos.set_link_config", { repo: slug }, () => kernel.repos.set_link_config(writeCtx(ctx), slug, config));
109
+ },
110
+ },
111
+ docs: {
112
+ get: (_ctx, repo, path) => forward("docs.get", { repo, path }, () => kernel.docs.get(readCtx(), repo, path)),
113
+ get_many: (_ctx, repo, paths) => forward("docs.get_many", { repo }, () => kernel.docs.get_many(readCtx(), repo, paths)),
114
+ get_version: (_ctx, repo, versionId) => forward("docs.get_version", { repo }, () => kernel.docs.get_version(readCtx(), repo, versionId)),
115
+ history: (_ctx, repo, path, opts) => forward("docs.history", { repo, path }, () => kernel.docs.history(readCtx(), repo, path, opts)),
116
+ diff: (_ctx, repo, path, from, to) => forward("docs.diff", { repo, path }, () => kernel.docs.diff(readCtx(), repo, path, from, to)),
117
+ create: async (ctx, repo, path, input) => {
118
+ assertWritable("docs.create", repo, path);
119
+ return forward("docs.create", { repo, path }, () => kernel.docs.create(writeCtx(ctx), repo, path, input));
120
+ },
121
+ put: async (ctx, repo, prevVersionId, path, input) => {
122
+ // A put may move the doc. Enforce write on the destination and — when
123
+ // the source differs — on the source too (both-endpoints, §8.2). The
124
+ // source path is the path of the version being superseded; resolve it
125
+ // with full visibility (the guard is trusted to look up what it must
126
+ // police), so a write-without-read grant still works.
127
+ const source = await kernel.docs.get_version({}, repo, prevVersionId);
128
+ assertWritable("docs.put", repo, source.path);
129
+ assertWritable("docs.put", repo, path);
130
+ return forward("docs.put", { repo, path }, () => kernel.docs.put(writeCtx(ctx), repo, prevVersionId, path, input));
131
+ },
132
+ delete: async (ctx, repo, prevVersionId) => {
133
+ const target = await kernel.docs.get_version({}, repo, prevVersionId);
134
+ assertWritable("docs.delete", repo, target.path);
135
+ return forward("docs.delete", { repo, path: target.path }, () => kernel.docs.delete(writeCtx(ctx), repo, prevVersionId));
136
+ },
137
+ },
138
+ links: {
139
+ backfill: async (ctx, repo) => {
140
+ assertDestructive("links.backfill", repo);
141
+ return forward("links.backfill", { repo }, () => kernel.links.backfill(writeCtx(ctx), repo));
142
+ },
143
+ // Read-only listing; scoped to read visibility like any other read.
144
+ stale: (_ctx, repo) => forward("links.stale", { repo }, () => kernel.links.stale(readCtx(), repo)),
145
+ repair: async (ctx, repo, opts) => {
146
+ const dryRun = opts?.dry_run ?? false;
147
+ // A live repair mutates docs → destructive. A dry run only plans → a
148
+ // read, bounded by read visibility (which docs the caller may see).
149
+ if (!dryRun)
150
+ assertDestructive("links.repair", repo);
151
+ const forwardCtx = dryRun
152
+ ? { scope: entitlement.read }
153
+ : { author: authorFor(ctx), scope: entitlement.read };
154
+ return forward("links.repair", { repo }, () => kernel.links.repair(forwardCtx, repo, opts));
155
+ },
156
+ },
157
+ query: (_ctx, spec) => forward("query", {}, () => kernel.query(readCtx(), spec)),
158
+ // Read-only neighborhood expansion; scoped to read visibility. Traversal
159
+ // stays kernel-side (the engine applies scope∧filter as visibility).
160
+ graph: (_ctx, spec) => forward("graph", { repo: spec.repo }, () => kernel.graph(readCtx(), spec)),
161
+ history: {
162
+ // Read-only change feed; the engine applies read scope to each ref's
163
+ // endpoints (a ref is delivered only if the caller can see either end).
164
+ since: (_ctx, input) => forward("history.since", { repo: input.repo }, () => kernel.history.since(readCtx(), input)),
165
+ index: (_ctx, input) => forward("history.index", { repo: input.repo }, () => kernel.history.index(readCtx(), input)),
166
+ list: (_ctx, input) => forward("history.list", { repo: input.repo }, () => kernel.history.list(readCtx(), input)),
167
+ },
168
+ };
169
+ }
170
+ function errorCode(err) {
171
+ if (err && typeof err === "object" && "code" in err && typeof err.code === "string") {
172
+ return err.code;
173
+ }
174
+ return "error";
175
+ }
176
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/shell/guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * API keys — auth-shell plan §1 (authn front 1), decision 9.
3
+ *
4
+ * High-entropy shell-generated secrets, stored as `sha256:<hex>` hashes in the
5
+ * policy file itself. There is no key database: issuance is a line appended to
6
+ * a diffable file (`key mint`), revocation is deleting the line. A key is a
7
+ * non-human-chosen 256-bit random secret, so a plain sha256 — no KDF, no salt —
8
+ * is the right primitive: deterministic lookup, and there is no low-entropy
9
+ * password to protect against brute force (the old design §8.1 argument,
10
+ * carried over intact).
11
+ *
12
+ * Presented to the shell as `Authorization: Bearer <plaintext-key>`.
13
+ */
14
+ import type { Policy } from "./policy.js";
15
+ /**
16
+ * Mint a fresh plaintext key and its policy-file hash. The plaintext is shown
17
+ * to the operator ONCE (by `key mint`) and never stored; only the hash lives
18
+ * in the policy file. base64url keeps it copy-paste-safe in shell/env/headers.
19
+ */
20
+ export declare function mintKey(): {
21
+ plaintext: string;
22
+ hash: string;
23
+ };
24
+ /** The `sha256:<hex>` hash of a plaintext key — the policy-file storage form. */
25
+ export declare function hashKey(plaintext: string): string;
26
+ /**
27
+ * Resolve a presented plaintext key to its principal id, or null if no
28
+ * principal lists its hash. Comparison is constant-time per candidate hash so
29
+ * a timing side-channel can't distinguish "no such key" from "wrong key".
30
+ */
31
+ export declare function principalForKey(policy: Policy, plaintext: string): string | null;
32
+ /**
33
+ * Extract a bearer token from an `Authorization` header value, or null. Case-
34
+ * insensitive on the scheme per RFC 7235; the token is returned verbatim.
35
+ */
36
+ export declare function bearerToken(authorization: string | undefined): string | null;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * API keys — auth-shell plan §1 (authn front 1), decision 9.
3
+ *
4
+ * High-entropy shell-generated secrets, stored as `sha256:<hex>` hashes in the
5
+ * policy file itself. There is no key database: issuance is a line appended to
6
+ * a diffable file (`key mint`), revocation is deleting the line. A key is a
7
+ * non-human-chosen 256-bit random secret, so a plain sha256 — no KDF, no salt —
8
+ * is the right primitive: deterministic lookup, and there is no low-entropy
9
+ * password to protect against brute force (the old design §8.1 argument,
10
+ * carried over intact).
11
+ *
12
+ * Presented to the shell as `Authorization: Bearer <plaintext-key>`.
13
+ */
14
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
15
+ /** Bytes of entropy in a minted key. 32 = 256 bits. */
16
+ const KEY_BYTES = 32;
17
+ /**
18
+ * Mint a fresh plaintext key and its policy-file hash. The plaintext is shown
19
+ * to the operator ONCE (by `key mint`) and never stored; only the hash lives
20
+ * in the policy file. base64url keeps it copy-paste-safe in shell/env/headers.
21
+ */
22
+ export function mintKey() {
23
+ const plaintext = randomBytes(KEY_BYTES).toString("base64url");
24
+ return { plaintext, hash: hashKey(plaintext) };
25
+ }
26
+ /** The `sha256:<hex>` hash of a plaintext key — the policy-file storage form. */
27
+ export function hashKey(plaintext) {
28
+ const hex = createHash("sha256").update(plaintext, "utf8").digest("hex");
29
+ return `sha256:${hex}`;
30
+ }
31
+ /**
32
+ * Resolve a presented plaintext key to its principal id, or null if no
33
+ * principal lists its hash. Comparison is constant-time per candidate hash so
34
+ * a timing side-channel can't distinguish "no such key" from "wrong key".
35
+ */
36
+ export function principalForKey(policy, plaintext) {
37
+ const presented = Buffer.from(hashKey(plaintext), "utf8");
38
+ let match = null;
39
+ for (const [id, principal] of Object.entries(policy.principals)) {
40
+ for (const stored of principal.keys ?? []) {
41
+ const storedBuf = Buffer.from(stored, "utf8");
42
+ // Length differs only for a malformed stored hash (validation forbids
43
+ // it), but timingSafeEqual throws on unequal lengths, so guard it.
44
+ if (storedBuf.length === presented.length && timingSafeEqual(storedBuf, presented)) {
45
+ // Don't early-return: keep scanning so total work doesn't leak which
46
+ // principal matched. Record the first (and, given unique keys, only) hit.
47
+ if (match === null)
48
+ match = id;
49
+ }
50
+ }
51
+ }
52
+ return match;
53
+ }
54
+ /**
55
+ * Extract a bearer token from an `Authorization` header value, or null. Case-
56
+ * insensitive on the scheme per RFC 7235; the token is returned verbatim.
57
+ */
58
+ export function bearerToken(authorization) {
59
+ if (!authorization)
60
+ return null;
61
+ const m = /^Bearer[ \t]+(.+)$/i.exec(authorization.trim());
62
+ return m ? m[1].trim() : null;
63
+ }
64
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/shell/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGvE,uDAAuD;AACvD,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;;GAIG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;AACjD,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,OAAO,CAAC,SAAiB;IACvC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzE,OAAO,UAAU,GAAG,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,SAAiB;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1D,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,KAAK,MAAM,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAChE,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC9C,sEAAsE;YACtE,mEAAmE;YACnE,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,IAAI,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;gBACnF,qEAAqE;gBACrE,0EAA0E;gBAC1E,IAAI,KAAK,KAAK,IAAI;oBAAE,KAAK,GAAG,EAAE,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,aAAiC;IAC3D,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,CAAC,GAAG,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * OAuth device-authorization login — auth-shell plan §1 (login), WS5.
3
+ *
4
+ * `mrplex login` runs the OAuth 2.0 **device authorization flow** (RFC 8628):
5
+ * request a device+user code, show the user a URL and code to enter, then poll
6
+ * the token endpoint until they approve. The resulting access + refresh tokens
7
+ * are cached under the config dir (mode 600); `mcp-stdio` uses the cached
8
+ * access token when no explicit credential is given, and refreshes it mid-
9
+ * session (recompiling the entitlement on refresh, so long-lived agent sessions
10
+ * neither die at token expiry nor outlive a policy change indefinitely).
11
+ *
12
+ * The IdP is the authorization server; mrplex is only the resource server, so
13
+ * this file speaks the standard endpoints and stores tokens — it verifies
14
+ * nothing (that's oidc.ts, on the serving side).
15
+ */
16
+ export type DeviceFlowConfig = {
17
+ /** OAuth device-authorization endpoint. */
18
+ deviceAuthorizationEndpoint: string;
19
+ /** OAuth token endpoint. */
20
+ tokenEndpoint: string;
21
+ clientId: string;
22
+ /** Space-delimited scopes (e.g. "openid email profile offline_access"). */
23
+ scope?: string;
24
+ /**
25
+ * OAuth `audience` — the API the token is for. Auth0 (and some other IdPs)
26
+ * only issue a *JWT* access token when the device-authorization request names
27
+ * an audience; without it they return an opaque token that fails the shell's
28
+ * JWKS verification. Sent in the device-authorization request when set. This
29
+ * is the shell's `--oidc-audience` value.
30
+ */
31
+ audience?: string;
32
+ };
33
+ export type TokenSet = {
34
+ access_token: string;
35
+ refresh_token?: string;
36
+ /** Absolute expiry (epoch ms), computed from `expires_in` at grant time. */
37
+ expires_at?: number;
38
+ token_type?: string;
39
+ };
40
+ /** Where the token cache lives — `${XDG_CONFIG_HOME}/mrplex/token.json`. */
41
+ export declare function tokenCachePath(): string;
42
+ export declare function loadTokenSet(): TokenSet | null;
43
+ export declare function saveTokenSet(tokens: TokenSet): void;
44
+ /** A token is fresh if it exists and isn't within `skewMs` of expiry. */
45
+ export declare function isFresh(tokens: TokenSet, skewMs?: number): boolean;
46
+ /**
47
+ * Run the device flow to completion. Prompts via `prompt` (defaults to stderr),
48
+ * polls the token endpoint honoring `interval` and `slow_down`, and returns the
49
+ * granted token set. Throws on denial, expiry, or endpoint error.
50
+ */
51
+ export declare function deviceFlowLogin(config: DeviceFlowConfig, prompt?: (msg: string) => void): Promise<TokenSet>;
52
+ /**
53
+ * Exchange a refresh token for a fresh access token. Returns the new token set,
54
+ * carrying the refresh token forward if the IdP didn't rotate it.
55
+ */
56
+ export declare function refreshTokens(config: Pick<DeviceFlowConfig, "tokenEndpoint" | "clientId">, refreshToken: string): Promise<TokenSet>;
@@ -0,0 +1,130 @@
1
+ /**
2
+ * OAuth device-authorization login — auth-shell plan §1 (login), WS5.
3
+ *
4
+ * `mrplex login` runs the OAuth 2.0 **device authorization flow** (RFC 8628):
5
+ * request a device+user code, show the user a URL and code to enter, then poll
6
+ * the token endpoint until they approve. The resulting access + refresh tokens
7
+ * are cached under the config dir (mode 600); `mcp-stdio` uses the cached
8
+ * access token when no explicit credential is given, and refreshes it mid-
9
+ * session (recompiling the entitlement on refresh, so long-lived agent sessions
10
+ * neither die at token expiry nor outlive a policy change indefinitely).
11
+ *
12
+ * The IdP is the authorization server; mrplex is only the resource server, so
13
+ * this file speaks the standard endpoints and stores tokens — it verifies
14
+ * nothing (that's oidc.ts, on the serving side).
15
+ */
16
+ import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
+ import { homedir } from "node:os";
18
+ import { dirname, join } from "node:path";
19
+ /** Where the token cache lives — `${XDG_CONFIG_HOME}/mrplex/token.json`. */
20
+ export function tokenCachePath() {
21
+ const xdg = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
22
+ return join(xdg, "mrplex", "token.json");
23
+ }
24
+ export function loadTokenSet() {
25
+ try {
26
+ return JSON.parse(readFileSync(tokenCachePath(), "utf8"));
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ export function saveTokenSet(tokens) {
33
+ const path = tokenCachePath();
34
+ mkdirSync(dirname(path), { recursive: true });
35
+ writeFileSync(path, `${JSON.stringify(tokens, null, 2)}\n`, { mode: 0o600 });
36
+ try {
37
+ chmodSync(path, 0o600);
38
+ }
39
+ catch {
40
+ // POSIX mode unsupported (Windows) — best-effort.
41
+ }
42
+ }
43
+ /** A token is fresh if it exists and isn't within `skewMs` of expiry. */
44
+ export function isFresh(tokens, skewMs = 30_000) {
45
+ if (tokens.expires_at === undefined)
46
+ return true; // no expiry info → assume usable
47
+ return Date.now() + skewMs < tokens.expires_at;
48
+ }
49
+ function toTokenSet(raw) {
50
+ const set = { access_token: String(raw.access_token) };
51
+ if (typeof raw.refresh_token === "string")
52
+ set.refresh_token = raw.refresh_token;
53
+ if (typeof raw.token_type === "string")
54
+ set.token_type = raw.token_type;
55
+ if (typeof raw.expires_in === "number")
56
+ set.expires_at = Date.now() + raw.expires_in * 1000;
57
+ return set;
58
+ }
59
+ /**
60
+ * Run the device flow to completion. Prompts via `prompt` (defaults to stderr),
61
+ * polls the token endpoint honoring `interval` and `slow_down`, and returns the
62
+ * granted token set. Throws on denial, expiry, or endpoint error.
63
+ */
64
+ export async function deviceFlowLogin(config, prompt = (m) => process.stderr.write(`${m}\n`)) {
65
+ const authResp = await postForm(config.deviceAuthorizationEndpoint, {
66
+ client_id: config.clientId,
67
+ scope: config.scope ?? "openid email profile offline_access",
68
+ // Only include audience when set — some IdPs reject an empty/unknown one.
69
+ ...(config.audience !== undefined ? { audience: config.audience } : {}),
70
+ });
71
+ if (!authResp.ok) {
72
+ throw new Error(`device authorization failed: HTTP ${authResp.status}`);
73
+ }
74
+ const auth = (await authResp.json());
75
+ const uri = auth.verification_uri_complete ?? auth.verification_uri;
76
+ prompt(`To sign in, visit:\n ${uri}\nand enter code: ${auth.user_code}`);
77
+ let intervalMs = (auth.interval ?? 5) * 1000;
78
+ const deadline = Date.now() + auth.expires_in * 1000;
79
+ while (Date.now() < deadline) {
80
+ await sleep(intervalMs);
81
+ const tokenResp = await postForm(config.tokenEndpoint, {
82
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
83
+ device_code: auth.device_code,
84
+ client_id: config.clientId,
85
+ });
86
+ const body = (await tokenResp.json());
87
+ if (tokenResp.ok)
88
+ return toTokenSet(body);
89
+ // Standard device-flow polling errors (RFC 8628 §3.5).
90
+ const error = String(body.error ?? "");
91
+ if (error === "authorization_pending")
92
+ continue;
93
+ if (error === "slow_down") {
94
+ intervalMs += 5_000;
95
+ continue;
96
+ }
97
+ throw new Error(`device token request failed: ${error || `HTTP ${tokenResp.status}`}`);
98
+ }
99
+ throw new Error("device flow timed out before the user approved");
100
+ }
101
+ /**
102
+ * Exchange a refresh token for a fresh access token. Returns the new token set,
103
+ * carrying the refresh token forward if the IdP didn't rotate it.
104
+ */
105
+ export async function refreshTokens(config, refreshToken) {
106
+ const resp = await postForm(config.tokenEndpoint, {
107
+ grant_type: "refresh_token",
108
+ refresh_token: refreshToken,
109
+ client_id: config.clientId,
110
+ });
111
+ const body = (await resp.json());
112
+ if (!resp.ok) {
113
+ throw new Error(`token refresh failed: ${String(body.error ?? `HTTP ${resp.status}`)}`);
114
+ }
115
+ const next = toTokenSet(body);
116
+ if (next.refresh_token === undefined)
117
+ next.refresh_token = refreshToken;
118
+ return next;
119
+ }
120
+ function postForm(url, form) {
121
+ return fetch(url, {
122
+ method: "POST",
123
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
124
+ body: new URLSearchParams(form).toString(),
125
+ });
126
+ }
127
+ function sleep(ms) {
128
+ return new Promise((r) => setTimeout(r, ms));
129
+ }
130
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/shell/login.ts"],"names":[],"mappings":"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"}