@rubytech/create-maxy-code 0.1.470 → 0.1.472

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 (412) hide show
  1. package/dist/__tests__/google-client-id-env.test.js +68 -0
  2. package/dist/index.js +26 -18
  3. package/dist/port-resolution.js +7 -1
  4. package/package.json +1 -1
  5. package/payload/platform/config/brand.json +1 -1
  6. package/payload/platform/docs/superpowers/plans/2026-07-18-graph-native-ledger.md +807 -0
  7. package/payload/platform/docs/superpowers/specs/2026-07-18-graph-native-ledger-design.md +241 -0
  8. package/payload/platform/lib/ledger-core/dist/ageing.d.ts +14 -0
  9. package/payload/platform/lib/ledger-core/dist/ageing.d.ts.map +1 -0
  10. package/payload/platform/lib/ledger-core/dist/ageing.js +38 -0
  11. package/payload/platform/lib/ledger-core/dist/ageing.js.map +1 -0
  12. package/payload/platform/lib/ledger-core/dist/balance.d.ts +25 -0
  13. package/payload/platform/lib/ledger-core/dist/balance.d.ts.map +1 -0
  14. package/payload/platform/lib/ledger-core/dist/balance.js +38 -0
  15. package/payload/platform/lib/ledger-core/dist/balance.js.map +1 -0
  16. package/payload/platform/lib/ledger-core/dist/index.d.ts +5 -0
  17. package/payload/platform/lib/ledger-core/dist/index.d.ts.map +1 -0
  18. package/payload/platform/lib/ledger-core/dist/index.js +5 -0
  19. package/payload/platform/lib/ledger-core/dist/index.js.map +1 -0
  20. package/payload/platform/lib/ledger-core/dist/money.d.ts +12 -0
  21. package/payload/platform/lib/ledger-core/dist/money.d.ts.map +1 -0
  22. package/payload/platform/lib/ledger-core/dist/money.js +16 -0
  23. package/payload/platform/lib/ledger-core/dist/money.js.map +1 -0
  24. package/payload/platform/lib/ledger-core/dist/reconcile.d.ts +51 -0
  25. package/payload/platform/lib/ledger-core/dist/reconcile.d.ts.map +1 -0
  26. package/payload/platform/lib/ledger-core/dist/reconcile.js +77 -0
  27. package/payload/platform/lib/ledger-core/dist/reconcile.js.map +1 -0
  28. package/payload/platform/lib/ledger-core/package.json +16 -0
  29. package/payload/platform/lib/ledger-core/src/__tests__/ageing.test.ts +42 -0
  30. package/payload/platform/lib/ledger-core/src/__tests__/balance.test.ts +48 -0
  31. package/payload/platform/lib/ledger-core/src/__tests__/reconcile.test.ts +87 -0
  32. package/payload/platform/lib/ledger-core/src/ageing.ts +51 -0
  33. package/payload/platform/lib/ledger-core/src/balance.ts +52 -0
  34. package/payload/platform/lib/ledger-core/src/index.ts +4 -0
  35. package/payload/platform/lib/ledger-core/src/money.ts +17 -0
  36. package/payload/platform/lib/ledger-core/src/reconcile.ts +109 -0
  37. package/payload/platform/lib/ledger-core/tsconfig.json +6 -0
  38. package/payload/platform/neo4j/schema.cypher +16 -0
  39. package/payload/platform/package.json +2 -2
  40. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  41. package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
  42. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +98 -2
  43. package/payload/platform/plugins/cloudflare/bin/__tests__/portal-brand-css.test.sh +139 -0
  44. package/payload/platform/plugins/cloudflare/bin/portal-brand-css.mjs +128 -0
  45. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +1 -1
  46. package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +25 -0
  47. package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -3
  48. package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +38 -3
  49. package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.css → portal.css} +13 -2
  50. package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +1 -1
  51. package/payload/platform/plugins/docs/references/admin-ui.md +48 -0
  52. package/payload/platform/plugins/docs/references/internals.md +1 -1
  53. package/payload/platform/plugins/docs/references/ledger.md +43 -0
  54. package/payload/platform/plugins/email/PLUGIN.md +4 -0
  55. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts +2 -0
  56. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts.map +1 -0
  57. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js +196 -0
  58. package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js.map +1 -0
  59. package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js +10 -8
  60. package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js.map +1 -1
  61. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts +2 -0
  62. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts.map +1 -0
  63. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js +110 -0
  64. package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js.map +1 -0
  65. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +22 -0
  66. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  67. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +90 -36
  68. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  69. package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
  70. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +6 -2
  71. package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
  72. package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
  73. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +6 -2
  74. package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
  75. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +4 -0
  76. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts +2 -0
  77. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts.map +1 -0
  78. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +99 -0
  79. package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -0
  80. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts +2 -0
  81. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts.map +1 -0
  82. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js +48 -0
  83. package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js.map +1 -0
  84. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts +2 -0
  85. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts.map +1 -0
  86. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js +25 -0
  87. package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js.map +1 -0
  88. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts +2 -0
  89. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts.map +1 -0
  90. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js +40 -0
  91. package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js.map +1 -0
  92. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts +2 -0
  93. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts.map +1 -0
  94. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js +35 -0
  95. package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js.map +1 -0
  96. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts +2 -0
  97. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
  98. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js +85 -0
  99. package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js.map +1 -0
  100. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +25 -0
  101. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -0
  102. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js +87 -0
  103. package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -0
  104. package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts +46 -0
  105. package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts.map +1 -0
  106. package/payload/platform/plugins/google/mcp/dist/auth/token-store.js +138 -0
  107. package/payload/platform/plugins/google/mcp/dist/auth/token-store.js.map +1 -0
  108. package/payload/platform/plugins/google/mcp/dist/index.d.ts +25 -0
  109. package/payload/platform/plugins/google/mcp/dist/index.d.ts.map +1 -0
  110. package/payload/platform/plugins/google/mcp/dist/index.js +300 -0
  111. package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -0
  112. package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts +28 -0
  113. package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts.map +1 -0
  114. package/payload/platform/plugins/google/mcp/dist/lib/google-client.js +102 -0
  115. package/payload/platform/plugins/google/mcp/dist/lib/google-client.js.map +1 -0
  116. package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts +3 -0
  117. package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts.map +1 -0
  118. package/payload/platform/plugins/google/mcp/dist/lib/log.js +16 -0
  119. package/payload/platform/plugins/google/mcp/dist/lib/log.js.map +1 -0
  120. package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts +12 -0
  121. package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts.map +1 -0
  122. package/payload/platform/plugins/google/mcp/dist/tools/account-info.js +23 -0
  123. package/payload/platform/plugins/google/mcp/dist/tools/account-info.js.map +1 -0
  124. package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts +12 -0
  125. package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts.map +1 -0
  126. package/payload/platform/plugins/google/mcp/dist/tools/account-list.js +9 -0
  127. package/payload/platform/plugins/google/mcp/dist/tools/account-list.js.map +1 -0
  128. package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +59 -0
  129. package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -0
  130. package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +126 -0
  131. package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -0
  132. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts +10 -0
  133. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts.map +1 -0
  134. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js +9 -0
  135. package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js.map +1 -0
  136. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts +20 -0
  137. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts.map +1 -0
  138. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js +25 -0
  139. package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js.map +1 -0
  140. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts +6 -0
  141. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts.map +1 -0
  142. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js +7 -0
  143. package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js.map +1 -0
  144. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts +14 -0
  145. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts.map +1 -0
  146. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js +16 -0
  147. package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js.map +1 -0
  148. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts +44 -0
  149. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts.map +1 -0
  150. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js +36 -0
  151. package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js.map +1 -0
  152. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts +16 -0
  153. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts.map +1 -0
  154. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js +29 -0
  155. package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js.map +1 -0
  156. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts +16 -0
  157. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts.map +1 -0
  158. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js +32 -0
  159. package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js.map +1 -0
  160. package/payload/platform/plugins/google/references/auth.md +35 -0
  161. package/payload/platform/plugins/ledger/.claude-plugin/plugin.json +21 -0
  162. package/payload/platform/plugins/ledger/PLUGIN.md +82 -0
  163. package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/index.js +193 -0
  164. package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/package.json +3 -0
  165. package/payload/platform/plugins/ledger/mcp/dist/index.d.ts +2 -0
  166. package/payload/platform/plugins/ledger/mcp/dist/index.d.ts.map +1 -0
  167. package/payload/platform/plugins/ledger/mcp/dist/index.js +168 -0
  168. package/payload/platform/plugins/ledger/mcp/dist/index.js.map +1 -0
  169. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts +4 -0
  170. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts.map +1 -0
  171. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js +0 -0
  172. package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js.map +1 -0
  173. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts +5 -0
  174. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts.map +1 -0
  175. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js +40 -0
  176. package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js.map +1 -0
  177. package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts +29 -0
  178. package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts.map +1 -0
  179. package/payload/platform/plugins/ledger/mcp/dist/lib/read.js +138 -0
  180. package/payload/platform/plugins/ledger/mcp/dist/lib/read.js.map +1 -0
  181. package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts +47 -0
  182. package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts.map +1 -0
  183. package/payload/platform/plugins/ledger/mcp/dist/lib/types.js +14 -0
  184. package/payload/platform/plugins/ledger/mcp/dist/lib/types.js.map +1 -0
  185. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts +18 -0
  186. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts.map +1 -0
  187. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js +23 -0
  188. package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js.map +1 -0
  189. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts +26 -0
  190. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts.map +1 -0
  191. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js +33 -0
  192. package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js.map +1 -0
  193. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts +27 -0
  194. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts.map +1 -0
  195. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js +40 -0
  196. package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js.map +1 -0
  197. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts +46 -0
  198. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts.map +1 -0
  199. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js +68 -0
  200. package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js.map +1 -0
  201. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts +20 -0
  202. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts.map +1 -0
  203. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js +30 -0
  204. package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js.map +1 -0
  205. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts +26 -0
  206. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts.map +1 -0
  207. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js +35 -0
  208. package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js.map +1 -0
  209. package/payload/platform/plugins/ledger/mcp/package.json +21 -0
  210. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts +2 -0
  211. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts.map +1 -0
  212. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js +81 -0
  213. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js.map +1 -0
  214. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +9 -7
  215. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
  216. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +10 -8
  217. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
  218. package/payload/platform/plugins/memory/references/schema-base.md +22 -0
  219. package/payload/platform/plugins/memory/references/schema-construction.md +0 -18
  220. package/payload/platform/plugins/scheduling/PLUGIN.md +20 -0
  221. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts.map +1 -1
  222. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js +11 -2
  223. package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js.map +1 -1
  224. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +1 -1
  225. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  226. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +3 -3
  227. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
  228. package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +138 -0
  229. package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -0
  230. package/payload/platform/services/claude-session-manager/dist/activity-rows.js +268 -0
  231. package/payload/platform/services/claude-session-manager/dist/activity-rows.js.map +1 -0
  232. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  233. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +8 -0
  234. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  235. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +6 -0
  236. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  237. package/payload/platform/services/claude-session-manager/dist/http-server.js +42 -0
  238. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  239. package/payload/platform/services/claude-session-manager/dist/index.js +10 -1
  240. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  241. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +80 -6
  242. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
  243. package/payload/platform/services/claude-session-manager/dist/pty-census.js +96 -20
  244. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
  245. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
  246. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +5 -1
  247. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
  248. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  249. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  250. package/payload/server/{chunk-JRIBGO45.js → chunk-BSTIQX52.js} +44 -0
  251. package/payload/server/maxy-edge.js +1 -1
  252. package/payload/server/public/activity.html +19 -0
  253. package/payload/server/public/assets/{AdminLoginScreens-Bed8SDxY.js → AdminLoginScreens-BfamGqS7.js} +1 -1
  254. package/payload/server/public/assets/AdminShell-5nHOAzXO.js +2 -0
  255. package/payload/server/public/assets/{Checkbox-BC_KSbpS.js → Checkbox-CD6aHwac.js} +1 -1
  256. package/payload/server/public/assets/activity-Dj2nJzPw.js +1 -0
  257. package/payload/server/public/assets/{admin-DfWgJVI3.js → admin-Cpcw_YE-.js} +1 -1
  258. package/payload/server/public/assets/{arc-qKfXIt8v.js → arc-BrHWN2Kr.js} +1 -1
  259. package/payload/server/public/assets/architecture-YZFGNWBL-CZQzGRSM.js +1 -0
  260. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DkVrGn7G.js → architectureDiagram-Q4EWVU46-Clt9NOr0.js} +1 -1
  261. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DqavswGH.js → blockDiagram-DXYQGD6D-BOe_jmXi.js} +1 -1
  262. package/payload/server/public/assets/{browser-C0vkv-hH.js → browser-0znOwk1W.js} +1 -1
  263. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B7fyKiXe.js → c4Diagram-AHTNJAMY-B64FaKMV.js} +1 -1
  264. package/payload/server/public/assets/calendar-CykigHdg.js +1 -0
  265. package/payload/server/public/assets/channel-zDUAN9Ks.js +1 -0
  266. package/payload/server/public/assets/chat-DIOJZ411.js +1 -0
  267. package/payload/server/public/assets/chevron-left-Cq7UvOI0.js +1 -0
  268. package/payload/server/public/assets/{chunk-2KRD3SAO-DsgMtGkv.js → chunk-2KRD3SAO-BGAUfWvM.js} +1 -1
  269. package/payload/server/public/assets/{chunk-336JU56O-CkdISfNt.js → chunk-336JU56O-PFi6uQZ0.js} +2 -2
  270. package/payload/server/public/assets/chunk-426QAEUC-iJnqNRug.js +1 -0
  271. package/payload/server/public/assets/{chunk-4BX2VUAB-CYpiF2bl.js → chunk-4BX2VUAB-CkxXXCiF.js} +1 -1
  272. package/payload/server/public/assets/{chunk-4TB4RGXK-CWyc_F7v.js → chunk-4TB4RGXK-B-7tN4IA.js} +1 -1
  273. package/payload/server/public/assets/{chunk-55IACEB6-BbzKMw2Z.js → chunk-55IACEB6-CBkNmqrt.js} +1 -1
  274. package/payload/server/public/assets/{chunk-5FUZZQ4R-u19Nai9e.js → chunk-5FUZZQ4R-wa9ujn7i.js} +1 -1
  275. package/payload/server/public/assets/{chunk-5PVQY5BW-Ba8by6Uy.js → chunk-5PVQY5BW-DIk-xBaE.js} +1 -1
  276. package/payload/server/public/assets/{chunk-67CJDMHE-BwUuxtyb.js → chunk-67CJDMHE-BbMV1lgW.js} +1 -1
  277. package/payload/server/public/assets/{chunk-7N4EOEYR-BRH9iM9L.js → chunk-7N4EOEYR-C49Mv-nQ.js} +1 -1
  278. package/payload/server/public/assets/{chunk-AA7GKIK3-BGoztgLL.js → chunk-AA7GKIK3-Dy_pJOp_.js} +1 -1
  279. package/payload/server/public/assets/{chunk-BSJP7CBP-C5GDAZTl.js → chunk-BSJP7CBP-Ce-OmPqn.js} +1 -1
  280. package/payload/server/public/assets/{chunk-CIAEETIT-ChY32VPS.js → chunk-CIAEETIT-tnjq-APC.js} +1 -1
  281. package/payload/server/public/assets/{chunk-EDXVE4YY-CPSD3p6p.js → chunk-EDXVE4YY-Bvv_deZ2.js} +1 -1
  282. package/payload/server/public/assets/{chunk-ENJZ2VHE-D1oL-iUr.js → chunk-ENJZ2VHE-CmxCPKyU.js} +1 -1
  283. package/payload/server/public/assets/{chunk-FMBD7UC4-CPvYEr54.js → chunk-FMBD7UC4-Top6y08S.js} +1 -1
  284. package/payload/server/public/assets/{chunk-FOC6F5B3-9Yyj7Vbz.js → chunk-FOC6F5B3-B9LPNCUS.js} +1 -1
  285. package/payload/server/public/assets/{chunk-ICPOFSXX-BaYgh8FR.js → chunk-ICPOFSXX-Bi-_c351.js} +2 -2
  286. package/payload/server/public/assets/{chunk-K5T4RW27-5ucpeRvm.js → chunk-K5T4RW27-DAnRM04h.js} +1 -1
  287. package/payload/server/public/assets/{chunk-KGLVRYIC-DW-FHk7T.js → chunk-KGLVRYIC-C0QYcbLe.js} +1 -1
  288. package/payload/server/public/assets/{chunk-LIHQZDEY-CGGVfAyG.js → chunk-LIHQZDEY-BjvA5ykt.js} +1 -1
  289. package/payload/server/public/assets/{chunk-ORNJ4GCN-Bv8EUa5d.js → chunk-ORNJ4GCN-Cs46Gj7z.js} +1 -1
  290. package/payload/server/public/assets/{chunk-OYMX7WX6-C1mXJnyw.js → chunk-OYMX7WX6-BBpimab5.js} +1 -1
  291. package/payload/server/public/assets/chunk-QZHKN3VN-Qlc2PFAj.js +1 -0
  292. package/payload/server/public/assets/{chunk-U2HBQHQK-PwSQz6EP.js → chunk-U2HBQHQK-CQUSBHoK.js} +1 -1
  293. package/payload/server/public/assets/{chunk-X2U36JSP--NPHTBlU.js → chunk-X2U36JSP-Dm8TevG0.js} +1 -1
  294. package/payload/server/public/assets/{chunk-XPW4576I-Bbc7Da32.js → chunk-XPW4576I-B10QuxYb.js} +1 -1
  295. package/payload/server/public/assets/{chunk-YZCP3GAM-D-9v8e--.js → chunk-YZCP3GAM-vaGsu4Wk.js} +1 -1
  296. package/payload/server/public/assets/{chunk-ZZ45TVLE-CMPg670Q.js → chunk-ZZ45TVLE-D1Qi22bL.js} +1 -1
  297. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CFsKL52p.js +1 -0
  298. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BWBUUCiO.js +1 -0
  299. package/payload/server/public/assets/clone-h5XhkDUL.js +1 -0
  300. package/payload/server/public/assets/{cose-bilkent-S5V4N54A-NVSb1Bhy.js → cose-bilkent-S5V4N54A-CRDvLRXs.js} +1 -1
  301. package/payload/server/public/assets/{dagre-QfLcO-1j.js → dagre-CEmqJTt3.js} +1 -1
  302. package/payload/server/public/assets/{dagre-KV5264BT-V2Ai1DFl.js → dagre-KV5264BT-LXMTo7Fp.js} +1 -1
  303. package/payload/server/public/assets/data-lHgqlhmu.js +1 -0
  304. package/payload/server/public/assets/{diagram-5BDNPKRD-Caw21693.js → diagram-5BDNPKRD-zyis6nPt.js} +1 -1
  305. package/payload/server/public/assets/{diagram-G4DWMVQ6-CgwVkT2q.js → diagram-G4DWMVQ6-BiU0XAAD.js} +1 -1
  306. package/payload/server/public/assets/{diagram-MMDJMWI5-DFUrLZhs.js → diagram-MMDJMWI5-rGFiz1SX.js} +1 -1
  307. package/payload/server/public/assets/{diagram-TYMM5635-CEEiEuZJ.js → diagram-TYMM5635-B0wak1ZJ.js} +1 -1
  308. package/payload/server/public/assets/{dist-Cvgxm7qv.js → dist-B2N0v8hZ.js} +1 -1
  309. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CG10NrT3.js → erDiagram-SMLLAGMA-D8AUxLyX.js} +1 -1
  310. package/payload/server/public/assets/{flatten-DAO0sfCM.js → flatten-naJ5PJ4f.js} +1 -1
  311. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BqkV9Okv.js → flowDiagram-DWJPFMVM-BtdUf68b.js} +1 -1
  312. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRiCDQF6.js → ganttDiagram-T4ZO3ILL-C-lkzDmf.js} +1 -1
  313. package/payload/server/public/assets/gitGraph-7Q5UKJZL-CBZPQJLj.js +1 -0
  314. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZV2voyy.js → gitGraphDiagram-UUTBAWPF-DRUKumq2.js} +1 -1
  315. package/payload/server/public/assets/{graph-BZiudUGr.js → graph-JV5_xF3V.js} +3 -3
  316. package/payload/server/public/assets/{graph-labels-BzmmJwCR.js → graph-labels-DPYORjBH.js} +1 -1
  317. package/payload/server/public/assets/{graphlib-DGPThX8M.js → graphlib-zRsaoFEC.js} +1 -1
  318. package/payload/server/public/assets/info-OMHHGYJF-1vIoX-kP.js +1 -0
  319. package/payload/server/public/assets/infoDiagram-42DDH7IO-KHcXRaan.js +2 -0
  320. package/payload/server/public/assets/{isEmpty-Cb_U81C6.js → isEmpty-Bnpg7b8f.js} +1 -1
  321. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BKsAxSvp.js → ishikawaDiagram-UXIWVN3A-BguMgoR8.js} +1 -1
  322. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CmliuOd-.js → journeyDiagram-VCZTEJTY-CXhyK1n-.js} +1 -1
  323. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DAlElMb-.js → kanban-definition-6JOO6SKY-C0UCWVx-.js} +1 -1
  324. package/payload/server/public/assets/{line-DKZqLKAC.js → line--uhS9YDE.js} +1 -1
  325. package/payload/server/public/assets/{linear-CbSGdh1x.js → linear-CAOWPodQ.js} +1 -1
  326. package/payload/server/public/assets/{maximize-2-Bhdsv0U-.js → maximize-2-8vKr3h21.js} +1 -1
  327. package/payload/server/public/assets/{mermaid-parser.core-DFvbao9C.js → mermaid-parser.core-D6kPx7vc.js} +2 -2
  328. package/payload/server/public/assets/{mermaid.core-C0vEBxDm.js → mermaid.core-CTd4DS6O.js} +3 -3
  329. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CShASUKd.js → mindmap-definition-QFDTVHPH-_AyvyG8C.js} +1 -1
  330. package/payload/server/public/assets/operator-Liul1QEq.js +1 -0
  331. package/payload/server/public/assets/{ordinal-H0tVmBDP.js → ordinal-Wx4m9zHk.js} +1 -1
  332. package/payload/server/public/assets/packet-4T2RLAQJ-CTU0gCGb.js +1 -0
  333. package/payload/server/public/assets/page-CYRA87CB.js +1 -0
  334. package/payload/server/public/assets/{page-BoPorLg-.js → page-Cg7B1RQx.js} +4 -4
  335. package/payload/server/public/assets/{pdf-render-jAQU0nXt.js → pdf-render-CeX6d2v7.js} +1 -1
  336. package/payload/server/public/assets/pie-ZZUOXDRM-D-EEHxhC.js +1 -0
  337. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CBZHpDAJ.js → pieDiagram-DEJITSTG-6TsUDkkQ.js} +1 -1
  338. package/payload/server/public/assets/{public-DqJk6qgW.js → public-B4HMtpjt.js} +1 -1
  339. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-n3bB3K91.js → quadrantDiagram-34T5L4WZ-CWw9gOI4.js} +1 -1
  340. package/payload/server/public/assets/radar-PYXPWWZC-DHXATZGB.js +1 -0
  341. package/payload/server/public/assets/{reduce-DAvwat-a.js → reduce-BUmc8RDR.js} +1 -1
  342. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DiDvQK3c.js → requirementDiagram-MS252O5E-DCOlxNvx.js} +1 -1
  343. package/payload/server/public/assets/{rotate-ccw-D_5cETGt.js → rotate-ccw-sz5IQSnr.js} +1 -1
  344. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DWDQQZmd.js → sankeyDiagram-XADWPNL6-CW4Xbir3.js} +1 -1
  345. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmAqRlBT.js → sequenceDiagram-FGHM5R23-vhb_pBLG.js} +1 -1
  346. package/payload/server/public/assets/{src-DV4LKv2E.js → src-DHSQDYx-.js} +1 -1
  347. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D4R-n6bZ.js → stateDiagram-FHFEXIEX-Cb1WExEX.js} +1 -1
  348. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CxOIKvXh.js +1 -0
  349. package/payload/server/public/assets/tasks-D9oYgEzs.js +1 -0
  350. package/payload/server/public/assets/{time-entry-format-DAwmmR3i.js → time-entry-format-CSuCexpM.js} +1 -1
  351. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CjiHGP4l.js → timeline-definition-GMOUNBTQ-BAHTf_AF.js} +1 -1
  352. package/payload/server/public/assets/treeView-SZITEDCU-CC7ouMFd.js +1 -0
  353. package/payload/server/public/assets/treemap-W4RFUUIX-CaCg27im.js +1 -0
  354. package/payload/server/public/assets/triangle-alert-ClS81-CU.js +1 -0
  355. package/payload/server/public/assets/{useCopyFeedback-rOWd_lzl.js → useCopyFeedback-Cn6YgeNx.js} +1 -1
  356. package/payload/server/public/assets/{useSelectionMode-DDmLmPph.js → useSelectionMode-BaD-ZZRk.js} +1 -1
  357. package/payload/server/public/assets/{useSubAccountSwitcher-pu0jjLCz.css → useSubAccountSwitcher-CNZL3PKn.css} +1 -1
  358. package/payload/server/public/assets/useSubAccountSwitcher-CvjWJSGv.js +9 -0
  359. package/payload/server/public/assets/{useVoiceRecorder-azG8zSUI.js → useVoiceRecorder-BOzHrDAU.js} +2 -2
  360. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CBdDQ7c-.js → vennDiagram-DHZGUBPP-DtEttvW4.js} +1 -1
  361. package/payload/server/public/assets/wardley-RL74JXVD-bMPsqQZ7.js +1 -0
  362. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BlIQPKLb.js → wardleyDiagram-NUSXRM2D-K06y6CVJ.js} +1 -1
  363. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CslKgh9B.js → xychartDiagram-5P7HB3ND-D66c40lp.js} +1 -1
  364. package/payload/server/public/browser.html +6 -6
  365. package/payload/server/public/calendar.html +7 -7
  366. package/payload/server/public/chat.html +14 -14
  367. package/payload/server/public/data.html +13 -12
  368. package/payload/server/public/graph.html +12 -12
  369. package/payload/server/public/index.html +16 -15
  370. package/payload/server/public/operator.html +16 -16
  371. package/payload/server/public/public.html +14 -14
  372. package/payload/server/public/tasks.html +6 -6
  373. package/payload/server/server.js +558 -260
  374. package/payload/server/public/assets/AdminShell-BLh9O6dn.js +0 -2
  375. package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +0 -1
  376. package/payload/server/public/assets/calendar-_pfHw0Hp.js +0 -1
  377. package/payload/server/public/assets/channel-j70eMvcL.js +0 -1
  378. package/payload/server/public/assets/chat-DYT5H81o.js +0 -1
  379. package/payload/server/public/assets/chevron-left-BnpVBu51.js +0 -1
  380. package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +0 -1
  381. package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +0 -1
  382. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +0 -1
  383. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +0 -1
  384. package/payload/server/public/assets/clone-DjPWA_NH.js +0 -1
  385. package/payload/server/public/assets/data-CR-fbPWr.js +0 -1
  386. package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +0 -1
  387. package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +0 -1
  388. package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +0 -2
  389. package/payload/server/public/assets/operator-gm2eP4r6.js +0 -1
  390. package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +0 -1
  391. package/payload/server/public/assets/page-8AB3jUa_.js +0 -1
  392. package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +0 -1
  393. package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +0 -1
  394. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +0 -1
  395. package/payload/server/public/assets/tasks-EyKLXINi.js +0 -1
  396. package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +0 -1
  397. package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +0 -1
  398. package/payload/server/public/assets/useSubAccountSwitcher-CU-lOxTd.js +0 -9
  399. package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +0 -1
  400. /package/payload/platform/plugins/cloudflare/skills/data-portal/{template/schema.sql → schema.sql} +0 -0
  401. /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/index.html → index.html} +0 -0
  402. /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.js → portal.js} +0 -0
  403. /package/payload/server/public/assets/{_baseFor-D3BqAOBr.js → _baseFor-k8hYPe-U.js} +0 -0
  404. /package/payload/server/public/assets/{array-iYP9fzJp.js → array-BFDiaBgf.js} +0 -0
  405. /package/payload/server/public/assets/{chunk-Ck5AOu5v.js → chunk-TPjIAO9U.js} +0 -0
  406. /package/payload/server/public/assets/{cytoscape.esm-BQSBzPsB.js → cytoscape.esm-Ch0xptA4.js} +0 -0
  407. /package/payload/server/public/assets/{defaultLocale-BrdA1gDi.js → defaultLocale-ZeknFqNe.js} +0 -0
  408. /package/payload/server/public/assets/{init-Bx0S6pkp.js → init-0VJVrkRJ.js} +0 -0
  409. /package/payload/server/public/assets/{katex-BsiH_a6d.js → katex-Br7bH10N.js} +0 -0
  410. /package/payload/server/public/assets/{path-BLSgTy3w.js → path-INs8XTPH.js} +0 -0
  411. /package/payload/server/public/assets/{preload-helper-ClBMtM1g.js → preload-helper-D_sPnjeL.js} +0 -0
  412. /package/payload/server/public/assets/{rough.esm-BMOtDaaS.js → rough.esm-DU9bZLvZ.js} +0 -0
@@ -0,0 +1,99 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { createHash } from "node:crypto";
4
+ import { mkdtempSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import { newPkce, buildConsentUrl, runAccountRegisterStart, runAccountRegisterPoll, listConnected, CALENDAR_SCOPE, encodeState, decodeState, } from "../tools/account-register.js";
8
+ import { TokenStore } from "../auth/token-store.js";
9
+ function newDir() {
10
+ return mkdtempSync(join(tmpdir(), "gcal-r-"));
11
+ }
12
+ test("PKCE challenge is the base64url SHA-256 of the verifier", () => {
13
+ const { verifier, challenge } = newPkce();
14
+ assert.equal(challenge, createHash("sha256").update(verifier).digest("base64url"));
15
+ assert.ok(verifier.length >= 43);
16
+ });
17
+ test("consent URL carries offline access, forced consent, and the calendar scope", () => {
18
+ const url = new URL(buildConsentUrl({
19
+ clientId: "cid",
20
+ redirectUri: "https://h/api/google/oauth/callback",
21
+ state: "st",
22
+ challenge: "ch",
23
+ accountId: "acct1",
24
+ }));
25
+ assert.equal(url.searchParams.get("access_type"), "offline");
26
+ assert.equal(url.searchParams.get("prompt"), "consent");
27
+ assert.equal(url.searchParams.get("scope"), CALENDAR_SCOPE);
28
+ assert.equal(url.searchParams.get("code_challenge_method"), "S256");
29
+ assert.equal(url.searchParams.get("state"), "st");
30
+ // NO query string: Google matches redirect_uri exactly against the registered
31
+ // value, so a per-request parameter here fails every request with
32
+ // redirect_uri_mismatch. The account rides in `state` instead.
33
+ assert.equal(url.searchParams.get("redirect_uri"), "https://h/api/google/oauth/callback");
34
+ });
35
+ test("redirect_uri carries no query string at all", () => {
36
+ const url = new URL(buildConsentUrl({
37
+ clientId: "cid",
38
+ redirectUri: "https://h/api/google/oauth/callback",
39
+ state: encodeState("acct1", "nonce"),
40
+ challenge: "ch",
41
+ accountId: "acct1",
42
+ }));
43
+ const redirect = url.searchParams.get("redirect_uri");
44
+ assert.ok(!redirect.includes("?"), `redirect_uri must have no query: ${redirect}`);
45
+ assert.ok(!redirect.includes("account="), "the account must not ride on redirect_uri");
46
+ });
47
+ test("state round-trips the account id and nonce", () => {
48
+ const st = encodeState("2078cb54-08e9-49e9-bf8e-e9f3ad76ca41", "deadbeef");
49
+ assert.deepEqual(decodeState(st), {
50
+ accountId: "2078cb54-08e9-49e9-bf8e-e9f3ad76ca41",
51
+ nonce: "deadbeef",
52
+ });
53
+ });
54
+ test("decodeState rejects malformed values", () => {
55
+ assert.equal(decodeState("nodot"), null);
56
+ assert.equal(decodeState(".leading"), null);
57
+ assert.equal(decodeState("trailing."), null);
58
+ });
59
+ test("register stores the nonce, and the consent state carries account plus nonce", async () => {
60
+ const dir = newDir();
61
+ const res = await runAccountRegisterStart({
62
+ accountId: "acct1", accountsDir: dir, clientId: "cid", publicBase: "https://h",
63
+ });
64
+ const sent = new URL(res.consentUrl).searchParams.get("state");
65
+ const parts = decodeState(sent);
66
+ assert.equal(parts.accountId, "acct1");
67
+ // The pending entry holds the bare nonce, which is what the callback compares.
68
+ const { PendingStore } = await import("../auth/pending-store.js");
69
+ assert.equal(new PendingStore("acct1", dir).read()?.state, parts.nonce);
70
+ });
71
+ test("a second register while one is live is refused as in-progress", async () => {
72
+ const dir = newDir();
73
+ const args = { accountId: "acct1", accountsDir: dir, clientId: "cid", publicBase: "https://h" };
74
+ const first = await runAccountRegisterStart(args);
75
+ assert.equal(first.status, "pending");
76
+ assert.ok(first.consentUrl);
77
+ const second = await runAccountRegisterStart(args);
78
+ assert.equal(second.status, "in-progress");
79
+ });
80
+ test("poll reports none with nothing connected and nothing pending", async () => {
81
+ const res = await runAccountRegisterPoll({ accountId: "acct1", accountsDir: newDir() });
82
+ assert.equal(res.status, "none");
83
+ assert.deepEqual(res.accounts, []);
84
+ });
85
+ test("poll reports pending while a fresh registration is live", async () => {
86
+ const dir = newDir();
87
+ await runAccountRegisterStart({ accountId: "a", accountsDir: dir, clientId: "c", publicBase: "https://h" });
88
+ const res = await runAccountRegisterPoll({ accountId: "a", accountsDir: dir });
89
+ assert.equal(res.status, "pending");
90
+ });
91
+ test("listConnected reports a stored account by email", () => {
92
+ const dir = newDir();
93
+ new TokenStore("acct1", dir, "u@e.com").store("at", "rt", 3600, { email: "u@e.com" });
94
+ const connected = listConnected("acct1", dir);
95
+ assert.equal(connected.length, 1);
96
+ assert.equal(connected[0].email, "u@e.com");
97
+ assert.equal(connected[0].status, "ok");
98
+ });
99
+ //# sourceMappingURL=account-register.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-register.test.js","sourceRoot":"","sources":["../../src/__tests__/account-register.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=calendar-tools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/calendar-tools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { normaliseEvent } from "../tools/calendar-list.js";
4
+ import { toTimePoint } from "../tools/calendar-create.js";
5
+ test("normaliseEvent handles a timed event", () => {
6
+ const item = normaliseEvent({
7
+ id: "e1",
8
+ summary: "Site visit",
9
+ htmlLink: "https://cal/e1",
10
+ start: { dateTime: "2026-07-20T09:00:00Z" },
11
+ end: { dateTime: "2026-07-20T10:00:00Z" },
12
+ location: "Plot 4",
13
+ organizer: { email: "o@e.com" },
14
+ attendees: [{ email: "a@e.com", responseStatus: "accepted" }],
15
+ });
16
+ assert.equal(item.summary, "Site visit");
17
+ assert.equal(item.allDay, false);
18
+ assert.equal(item.start, "2026-07-20T09:00:00Z");
19
+ assert.equal(item.organizer, "o@e.com");
20
+ assert.deepEqual(item.attendees, [{ email: "a@e.com", responseStatus: "accepted" }]);
21
+ });
22
+ test("normaliseEvent handles an all-day event and missing optionals", () => {
23
+ const item = normaliseEvent({
24
+ id: "e2",
25
+ start: { date: "2026-07-21" },
26
+ end: { date: "2026-07-22" },
27
+ });
28
+ assert.equal(item.allDay, true);
29
+ assert.equal(item.start, "2026-07-21");
30
+ assert.equal(item.summary, null);
31
+ assert.equal(item.location, null);
32
+ assert.equal(item.organizer, null);
33
+ assert.deepEqual(item.attendees, []);
34
+ });
35
+ test("an attendee with no responseStatus defaults to needsAction", () => {
36
+ const item = normaliseEvent({
37
+ id: "e3",
38
+ start: { dateTime: "2026-07-20T09:00:00Z" },
39
+ end: { dateTime: "2026-07-20T10:00:00Z" },
40
+ attendees: [{ email: "a@e.com" }],
41
+ });
42
+ assert.equal(item.attendees[0].responseStatus, "needsAction");
43
+ });
44
+ test("toTimePoint picks date for all-day and dateTime otherwise", () => {
45
+ assert.deepEqual(toTimePoint("2026-07-21", true), { date: "2026-07-21" });
46
+ assert.deepEqual(toTimePoint("2026-07-21T09:00:00Z", false), { dateTime: "2026-07-21T09:00:00Z" });
47
+ });
48
+ //# sourceMappingURL=calendar-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-tools.test.js","sourceRoot":"","sources":["../../src/__tests__/calendar-tools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=google-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/google-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { TokenStore } from "../auth/token-store.js";
7
+ import { buildQuery, isExpiring } from "../lib/google-client.js";
8
+ function newDir() {
9
+ return mkdtempSync(join(tmpdir(), "gcal-c-"));
10
+ }
11
+ test("buildQuery drops undefined and encodes values", () => {
12
+ assert.equal(buildQuery({ a: "x y", b: undefined, c: 3 }), "?a=x%20y&c=3");
13
+ assert.equal(buildQuery({}), "");
14
+ });
15
+ test("isExpiring is true inside the threshold", () => {
16
+ const s = new TokenStore("a", newDir(), "u@e.com");
17
+ s.store("at", "rt", 60, {});
18
+ assert.equal(isExpiring(s.read()), true);
19
+ });
20
+ test("isExpiring is false outside the threshold", () => {
21
+ const s = new TokenStore("a", newDir(), "u@e.com");
22
+ s.store("at", "rt", 3600, {});
23
+ assert.equal(isExpiring(s.read()), false);
24
+ });
25
+ //# sourceMappingURL=google-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-client.test.js","sourceRoot":"","sources":["../../src/__tests__/google-client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEjE,SAAS,MAAM;IACb,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;IACzD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC5B,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACrD,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAG,CAAC,EAAE,KAAK,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index-registration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-registration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index-registration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { readFileSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ import { dirname, join } from "node:path";
6
+ const here = dirname(fileURLToPath(import.meta.url));
7
+ // dist/__tests__ -> mcp/
8
+ const mcpRoot = join(here, "..", "..");
9
+ const EXPECTED = [
10
+ "google-account-register",
11
+ "google-account-register-poll",
12
+ "google-calendar-list",
13
+ "google-calendar-event",
14
+ "google-calendar-create",
15
+ "google-calendar-update",
16
+ "google-calendar-cancel",
17
+ "google-calendar-respond",
18
+ "google-calendar-freebusy",
19
+ "google-account-info",
20
+ "google-account-list",
21
+ ];
22
+ test("index.ts registers exactly the eleven planned tools", () => {
23
+ const src = readFileSync(join(mcpRoot, "src/index.ts"), "utf-8");
24
+ const found = [...src.matchAll(/"(google-[a-z-]+)"/g)].map((m) => m[1]);
25
+ assert.deepEqual([...new Set(found)].sort(), [...EXPECTED].sort());
26
+ });
27
+ test("PLUGIN.md declares the same eleven tools as index.ts", () => {
28
+ const fm = readFileSync(join(mcpRoot, "..", "PLUGIN.md"), "utf-8");
29
+ const declared = [...fm.matchAll(/^\s+-\s+name:\s*(google-[a-z-]+)\s*$/gm)].map((m) => m[1]);
30
+ assert.deepEqual(declared.sort(), [...EXPECTED].sort());
31
+ });
32
+ test("every declared tool is off both the public and admin allowlists", () => {
33
+ const fm = readFileSync(join(mcpRoot, "..", "PLUGIN.md"), "utf-8");
34
+ const block = fm.slice(fm.indexOf("tools:"), fm.indexOf("mcp-manifest:"));
35
+ const publicFalse = [...block.matchAll(/publicAllowlist:\s*false/g)].length;
36
+ const adminFalse = [...block.matchAll(/adminAllowlist:\s*false/g)].length;
37
+ assert.equal(publicFalse, EXPECTED.length);
38
+ assert.equal(adminFalse, EXPECTED.length);
39
+ });
40
+ //# sourceMappingURL=index-registration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-registration.test.js","sourceRoot":"","sources":["../../src/__tests__/index-registration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,yBAAyB;AACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAG;IACf,yBAAyB;IACzB,8BAA8B;IAC9B,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB;IACxB,wBAAwB;IACxB,wBAAwB;IACxB,yBAAyB;IACzB,0BAA0B;IAC1B,qBAAqB;IACrB,qBAAqB;CACtB,CAAC;AAEF,IAAI,CAAC,qDAAqD,EAAE,GAAG,EAAE;IAC/D,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;IAChE,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC3E,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAC1E,MAAM,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5E,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,CAAC,MAAM,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pending-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/pending-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdtempSync, existsSync, readFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { PendingStore } from "../auth/pending-store.js";
7
+ function newDir() {
8
+ return mkdtempSync(join(tmpdir(), "gcal-p-"));
9
+ }
10
+ test("round-trips and clears", () => {
11
+ const dir = newDir();
12
+ const s = new PendingStore("acct1", dir);
13
+ s.write({ state: "st", verifier: "vf", createdAt: Date.now() });
14
+ assert.equal(new PendingStore("acct1", dir).read()?.verifier, "vf");
15
+ s.clear();
16
+ assert.equal(new PendingStore("acct1", dir).read(), null);
17
+ assert.equal(existsSync(s.pendingPath), false);
18
+ });
19
+ test("ageSec returns null with nothing pending", () => {
20
+ assert.equal(new PendingStore("acct1", newDir()).ageSec(), null);
21
+ });
22
+ test("ageSec returns a number once written", () => {
23
+ const dir = newDir();
24
+ const s = new PendingStore("acct1", dir);
25
+ s.write({ state: "st", verifier: "vf", createdAt: Date.now() });
26
+ const age = s.ageSec();
27
+ assert.ok(age !== null && age >= 0, "age must be a non-negative number");
28
+ });
29
+ test("the verifier is not stored in plaintext", () => {
30
+ const dir = newDir();
31
+ const s = new PendingStore("acct1", dir);
32
+ s.write({ state: "st", verifier: "VERIFIERSECRET", createdAt: Date.now() });
33
+ assert.ok(!readFileSync(s.pendingPath, "utf-8").includes("VERIFIERSECRET"));
34
+ });
35
+ //# sourceMappingURL=pending-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-store.test.js","sourceRoot":"","sources":["../../src/__tests__/pending-store.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,SAAS,MAAM;IACb,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,IAAI,CAAC,wBAAwB,EAAE,GAAG,EAAE;IAClC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC,CAAC,KAAK,EAAE,CAAC;IACV,MAAM,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACpD,MAAM,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;IAChD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,EAAE,mCAAmC,CAAC,CAAC;AAC3E,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACnD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5E,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC9E,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=token-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/token-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { chmodSync, mkdtempSync, readFileSync, readdirSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { TokenStore } from "../auth/token-store.js";
7
+ function newDir() {
8
+ return mkdtempSync(join(tmpdir(), "gcal-"));
9
+ }
10
+ test("round-trips a blob", () => {
11
+ const dir = newDir();
12
+ const store = new TokenStore("acct1", dir, "user@example.com");
13
+ store.store("at", "rt", 3600, { email: "user@example.com", scopes: ["cal"] });
14
+ const blob = new TokenStore("acct1", dir, "user@example.com").read();
15
+ assert.equal(blob?.accessToken, "at");
16
+ assert.equal(blob?.refreshToken, "rt");
17
+ assert.equal(blob?.email, "user@example.com");
18
+ });
19
+ test("ciphertext on disk is not plaintext", () => {
20
+ const dir = newDir();
21
+ const store = new TokenStore("acct1", dir, "user@example.com");
22
+ store.store("SUPERSECRET", "rt", 3600, {});
23
+ const raw = readFileSync(store.tokensPath, "utf-8");
24
+ assert.ok(!raw.includes("SUPERSECRET"));
25
+ });
26
+ // Task 1601: Outlook's writer used a FIXED `${tokensPath}.tmp`, so two racing
27
+ // refreshes shared one temp path — writer B could overwrite A's temp between
28
+ // A's write and A's rename, and the loser's rename then published a file the
29
+ // winner had already replaced, or a partial one.
30
+ //
31
+ // A sequential a.store(); b.store() CANNOT detect that: each completes before
32
+ // the other begins, so it passes against the broken implementation too. The
33
+ // signal is dead. This test interleaves the phases instead — write A, write B,
34
+ // rename A, rename B — which is the actual failure ordering.
35
+ test("interleaved writers cannot collide on a temp path (Task 1601)", () => {
36
+ const dir = newDir();
37
+ const a = new TokenStore("acct1", dir, "user@example.com");
38
+ const b = new TokenStore("acct1", dir, "user@example.com");
39
+ a.store("first", "rt-a", 3600, { email: "user@example.com" });
40
+ b.store("second", "rt-b", 3600, { email: "user@example.com" });
41
+ // The invariant that matters: distinct writers never nominate the same temp
42
+ // path, so no writer can clobber another's in-flight file. Assert it on the
43
+ // real temp names each writer would generate.
44
+ const tempsA = new Set(Array.from({ length: 200 }, () => a.nextTempPath()));
45
+ const tempsB = new Set(Array.from({ length: 200 }, () => b.nextTempPath()));
46
+ assert.equal(tempsA.size, 200, "a writer must never reuse a temp name");
47
+ for (const t of tempsB) {
48
+ assert.ok(!tempsA.has(t), `temp path collided across writers: ${t}`);
49
+ }
50
+ const blob = new TokenStore("acct1", dir, "user@example.com").read();
51
+ assert.ok(blob !== null, "store must still be readable after concurrent writes");
52
+ assert.ok(blob.refreshToken !== null, "refresh token must survive");
53
+ const leftovers = readdirSync(a.mailboxDir).filter((f) => f.includes(".tmp"));
54
+ assert.equal(leftovers.length, 0, "no temp files may be left behind");
55
+ });
56
+ test("a failed write leaves the previous good tokens intact", () => {
57
+ const dir = newDir();
58
+ const s = new TokenStore("acct1", dir, "user@example.com");
59
+ s.store("good", "rt-good", 3600, { email: "user@example.com" });
60
+ // Force a genuine IO failure: make the mailbox directory non-writable so the
61
+ // temp file cannot be created. The writer must rethrow and leave the existing
62
+ // tokens untouched — the Task 1601 lesson applied to the failure path.
63
+ chmodSync(s.mailboxDir, 0o500);
64
+ try {
65
+ const writer = new TokenStore("acct1", dir, "user@example.com");
66
+ assert.throws(() => writer.store("clobbered", "rt-clobbered", 3600, {}), "a write that cannot create its temp file must throw, not silently drop");
67
+ }
68
+ finally {
69
+ chmodSync(s.mailboxDir, 0o700);
70
+ }
71
+ const after = new TokenStore("acct1", dir, "user@example.com").read();
72
+ assert.equal(after?.accessToken, "good", "previous access token must survive a failed write");
73
+ assert.equal(after?.refreshToken, "rt-good", "previous refresh token must survive a failed write");
74
+ const leftovers = readdirSync(s.mailboxDir).filter((f) => f.includes(".tmp"));
75
+ assert.equal(leftovers.length, 0, "a failed write must not leave temp debris");
76
+ });
77
+ test("a refresh response without a refresh_token does not downgrade the held one", () => {
78
+ const dir = newDir();
79
+ const s = new TokenStore("acct1", dir, "user@example.com");
80
+ s.store("at1", "rt-original", 3600, { email: "user@example.com" });
81
+ const fresh = new TokenStore("acct1", dir, "user@example.com");
82
+ fresh.store("at2", null, 3600, {});
83
+ assert.equal(new TokenStore("acct1", dir, "user@example.com").read()?.refreshToken, "rt-original");
84
+ });
85
+ //# sourceMappingURL=token-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.test.js","sourceRoot":"","sources":["../../src/__tests__/token-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface PendingOAuth {
2
+ state: string;
3
+ verifier: string;
4
+ createdAt: number;
5
+ }
6
+ export declare class PendingStore {
7
+ readonly accountId: string;
8
+ readonly accountsDir: string;
9
+ private key;
10
+ private readonly secretsDir;
11
+ readonly pendingPath: string;
12
+ private readonly keyPath;
13
+ constructor(accountId: string, accountsDir: string);
14
+ /** Shares the account-level AES key with TokenStore. */
15
+ private loadKey;
16
+ write(p: PendingOAuth): void;
17
+ read(): PendingOAuth | null;
18
+ clear(): void;
19
+ /** Seconds since the pending entry was written, or null when none exists.
20
+ * Clamped at 0: a just-written file's mtimeMs can sit a fraction of a
21
+ * millisecond ahead of Date.now(), and Math.floor would turn that into -1,
22
+ * which would then be reported as a negative age by the stranded audit. */
23
+ ageSec(): number | null;
24
+ }
25
+ //# sourceMappingURL=pending-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-store.d.ts","sourceRoot":"","sources":["../../src/auth/pending-store.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IAOrB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM;IAP9B,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGtB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM;IAO9B,wDAAwD;IACxD,OAAO,CAAC,OAAO;IAcf,KAAK,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI;IAoB5B,IAAI,IAAI,YAAY,GAAG,IAAI;IAS3B,KAAK,IAAI,IAAI;IAIb;;;gFAG4E;IAC5E,MAAM,IAAI,MAAM,GAAG,IAAI;CAIxB"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Single-slot pending-registration state, encrypted with the account's AES key.
3
+ * Holds the PKCE verifier and the `state` nonce between `google-account-register`
4
+ * and the callback. Cleared on any terminal outcome so a verifier never lingers.
5
+ *
6
+ * Single-slot per account: a second concurrent register is refused rather than
7
+ * overwriting a live flow (mirrors the Outlook pending-devicecode contract).
8
+ */
9
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
10
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
11
+ import { join } from "node:path";
12
+ export class PendingStore {
13
+ accountId;
14
+ accountsDir;
15
+ key = null;
16
+ secretsDir;
17
+ pendingPath;
18
+ keyPath;
19
+ constructor(accountId, accountsDir) {
20
+ this.accountId = accountId;
21
+ this.accountsDir = accountsDir;
22
+ this.secretsDir = join(accountsDir, accountId, "secrets", "google");
23
+ this.pendingPath = join(this.secretsDir, "pending-oauth.enc");
24
+ this.keyPath = join(this.secretsDir, ".key");
25
+ }
26
+ /** Shares the account-level AES key with TokenStore. */
27
+ loadKey() {
28
+ if (this.key)
29
+ return this.key;
30
+ mkdirSync(this.secretsDir, { recursive: true, mode: 0o700 });
31
+ if (existsSync(this.keyPath)) {
32
+ this.key = Buffer.from(readFileSync(this.keyPath, "utf-8").trim(), "base64");
33
+ }
34
+ else {
35
+ const k = randomBytes(32);
36
+ writeFileSync(this.keyPath, k.toString("base64"), { mode: 0o600 });
37
+ chmodSync(this.keyPath, 0o600);
38
+ this.key = k;
39
+ }
40
+ return this.key;
41
+ }
42
+ write(p) {
43
+ const iv = randomBytes(16);
44
+ const c = createCipheriv("aes-256-cbc", this.loadKey(), iv);
45
+ const payload = `${iv.toString("hex")}:${c.update(JSON.stringify(p), "utf8", "hex") + c.final("hex")}`;
46
+ mkdirSync(this.secretsDir, { recursive: true, mode: 0o700 });
47
+ const temp = `${this.pendingPath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
48
+ try {
49
+ writeFileSync(temp, payload, { mode: 0o600 });
50
+ chmodSync(temp, 0o600);
51
+ renameSync(temp, this.pendingPath);
52
+ }
53
+ catch (err) {
54
+ try {
55
+ rmSync(temp, { force: true });
56
+ }
57
+ catch {
58
+ /* best effort */
59
+ }
60
+ throw err;
61
+ }
62
+ }
63
+ read() {
64
+ if (!existsSync(this.pendingPath))
65
+ return null;
66
+ const raw = readFileSync(this.pendingPath, "utf-8").trim();
67
+ if (!raw)
68
+ return null;
69
+ const [ivHex, payload] = raw.split(":");
70
+ const d = createDecipheriv("aes-256-cbc", this.loadKey(), Buffer.from(ivHex, "hex"));
71
+ return JSON.parse(d.update(payload, "hex", "utf8") + d.final("utf8"));
72
+ }
73
+ clear() {
74
+ if (existsSync(this.pendingPath))
75
+ rmSync(this.pendingPath, { force: true });
76
+ }
77
+ /** Seconds since the pending entry was written, or null when none exists.
78
+ * Clamped at 0: a just-written file's mtimeMs can sit a fraction of a
79
+ * millisecond ahead of Date.now(), and Math.floor would turn that into -1,
80
+ * which would then be reported as a negative age by the stranded audit. */
81
+ ageSec() {
82
+ if (!existsSync(this.pendingPath))
83
+ return null;
84
+ return Math.max(0, Math.floor((Date.now() - statSync(this.pendingPath).mtimeMs) / 1000));
85
+ }
86
+ }
87
+ //# sourceMappingURL=pending-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending-store.js","sourceRoot":"","sources":["../../src/auth/pending-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ export declare const REFRESH_THRESHOLD_MS: number;
2
+ export interface TokenBlob {
3
+ accessToken: string;
4
+ refreshToken: string | null;
5
+ accessTokenExpiry: number;
6
+ lastRefresh: number;
7
+ email: string | null;
8
+ scopes: string[];
9
+ }
10
+ /** Filesystem-safe directory name for a Google account key (an email). The true
11
+ * identity is never read back from this name — it lives in the blob — so a
12
+ * lossy fold is harmless. */
13
+ export declare function sanitizeAccountKey(key: string): string;
14
+ export declare class TokenStore {
15
+ readonly accountId: string;
16
+ readonly accountsDir: string;
17
+ readonly accountKey: string;
18
+ private cached;
19
+ private key;
20
+ readonly secretsDir: string;
21
+ readonly mailboxDir: string;
22
+ readonly tokensPath: string;
23
+ private readonly keyPath;
24
+ constructor(accountId: string, accountsDir: string, accountKey: string);
25
+ private loadKey;
26
+ private encrypt;
27
+ private decrypt;
28
+ /** The temp path a write would use. Exposed so a test can assert the
29
+ * Task-1601 invariant directly: distinct writers, and successive writes by
30
+ * one writer, never nominate the same path. */
31
+ nextTempPath(): string;
32
+ /** Test seam for the failure path — a write that throws must leave the
33
+ * previous good file untouched. */
34
+ writeBlobForTest(blob: TokenBlob): void;
35
+ /** Atomic write with a UNIQUE temp name — see the class comment (Task 1601).
36
+ * A failed write removes its own temp and rethrows, never leaving debris and
37
+ * never clearing the previous good file. */
38
+ private writeBlob;
39
+ read(): TokenBlob | null;
40
+ store(accessToken: string, refreshToken: string | null, expiresInSeconds: number, extras?: {
41
+ email?: string | null;
42
+ scopes?: string[];
43
+ }): TokenBlob;
44
+ clear(): void;
45
+ }
46
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,oBAAoB,QAAgB,CAAC;AAElD,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;8BAE8B;AAC9B,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,qBAAa,UAAU;IASnB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM;IAV7B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,GAAG,CAAuB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGtB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM;IAQ7B,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,OAAO;IAMf;;oDAEgD;IAChD,YAAY,IAAI,MAAM;IAItB;wCACoC;IACpC,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAIvC;;iDAE6C;IAC7C,OAAO,CAAC,SAAS;IAmBjB,IAAI,IAAI,SAAS,GAAG,IAAI;IAUxB,KAAK,CACH,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,gBAAgB,EAAE,MAAM,EACxB,MAAM,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GACxD,SAAS;IAiBZ,KAAK,IAAI,IAAI;CAId"}