@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.
- package/dist/__tests__/google-client-id-env.test.js +68 -0
- package/dist/index.js +26 -18
- package/dist/port-resolution.js +7 -1
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-18-graph-native-ledger.md +807 -0
- package/payload/platform/docs/superpowers/specs/2026-07-18-graph-native-ledger-design.md +241 -0
- package/payload/platform/lib/ledger-core/dist/ageing.d.ts +14 -0
- package/payload/platform/lib/ledger-core/dist/ageing.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/ageing.js +38 -0
- package/payload/platform/lib/ledger-core/dist/ageing.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/balance.d.ts +25 -0
- package/payload/platform/lib/ledger-core/dist/balance.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/balance.js +38 -0
- package/payload/platform/lib/ledger-core/dist/balance.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/index.d.ts +5 -0
- package/payload/platform/lib/ledger-core/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/index.js +5 -0
- package/payload/platform/lib/ledger-core/dist/index.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/money.d.ts +12 -0
- package/payload/platform/lib/ledger-core/dist/money.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/money.js +16 -0
- package/payload/platform/lib/ledger-core/dist/money.js.map +1 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.d.ts +51 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.d.ts.map +1 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.js +77 -0
- package/payload/platform/lib/ledger-core/dist/reconcile.js.map +1 -0
- package/payload/platform/lib/ledger-core/package.json +16 -0
- package/payload/platform/lib/ledger-core/src/__tests__/ageing.test.ts +42 -0
- package/payload/platform/lib/ledger-core/src/__tests__/balance.test.ts +48 -0
- package/payload/platform/lib/ledger-core/src/__tests__/reconcile.test.ts +87 -0
- package/payload/platform/lib/ledger-core/src/ageing.ts +51 -0
- package/payload/platform/lib/ledger-core/src/balance.ts +52 -0
- package/payload/platform/lib/ledger-core/src/index.ts +4 -0
- package/payload/platform/lib/ledger-core/src/money.ts +17 -0
- package/payload/platform/lib/ledger-core/src/reconcile.ts +109 -0
- package/payload/platform/lib/ledger-core/tsconfig.json +6 -0
- package/payload/platform/neo4j/schema.cypher +16 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +98 -2
- package/payload/platform/plugins/cloudflare/bin/__tests__/portal-brand-css.test.sh +139 -0
- package/payload/platform/plugins/cloudflare/bin/portal-brand-css.mjs +128 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +1 -1
- package/payload/platform/plugins/cloudflare/mcp/__tests__/skill-contract.test.ts +25 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +55 -3
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +38 -3
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.css → portal.css} +13 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +1 -1
- package/payload/platform/plugins/docs/references/admin-ui.md +48 -0
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/plugins/docs/references/ledger.md +43 -0
- package/payload/platform/plugins/email/PLUGIN.md +4 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js +196 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/display-truncation.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js +10 -8
- package/payload/platform/plugins/email/mcp/dist/__tests__/source-fetch-efficiency.test.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts +2 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js +110 -0
- package/payload/platform/plugins/email/mcp/dist/__tests__/truncation-tool-output.test.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +22 -0
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js +90 -36
- package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js +6 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-read.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js +6 -2
- package/payload/platform/plugins/email/mcp/dist/tools/email-search.js.map +1 -1
- package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +4 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js +99 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/account-register.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js +48 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/calendar-tools.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js +25 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/google-client.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js +40 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/index-registration.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js +35 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/pending-store.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts +2 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js +85 -0
- package/payload/platform/plugins/google/mcp/dist/__tests__/token-store.test.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts +25 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js +87 -0
- package/payload/platform/plugins/google/mcp/dist/auth/pending-store.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts +46 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.js +138 -0
- package/payload/platform/plugins/google/mcp/dist/auth/token-store.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/index.d.ts +25 -0
- package/payload/platform/plugins/google/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/index.js +300 -0
- package/payload/platform/plugins/google/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts +28 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.js +102 -0
- package/payload/platform/plugins/google/mcp/dist/lib/google-client.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts +3 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.js +16 -0
- package/payload/platform/plugins/google/mcp/dist/lib/log.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts +12 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.js +23 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-info.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts +12 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.js +9 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-list.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts +59 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js +126 -0
- package/payload/platform/plugins/google/mcp/dist/tools/account-register.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts +10 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js +9 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-cancel.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts +20 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js +25 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-create.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts +6 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js +7 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-event.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts +14 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-freebusy.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts +44 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js +36 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-list.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js +29 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-respond.js.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts +16 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.d.ts.map +1 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js +32 -0
- package/payload/platform/plugins/google/mcp/dist/tools/calendar-update.js.map +1 -0
- package/payload/platform/plugins/google/references/auth.md +35 -0
- package/payload/platform/plugins/ledger/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/ledger/PLUGIN.md +82 -0
- package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.js +168 -0
- package/payload/platform/plugins/ledger/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts +4 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js +0 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/ids.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts +5 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js +40 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/neo4j.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts +29 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.js +138 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/read.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts +47 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.js +14 -0
- package/payload/platform/plugins/ledger/mcp/dist/lib/types.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts +18 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js +23 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/balance.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts +26 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js +33 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/cash-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts +27 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js +40 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/invoice-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts +46 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js +68 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/payment-record.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts +20 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js +30 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/reconcile.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts +26 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.d.ts.map +1 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js +35 -0
- package/payload/platform/plugins/ledger/mcp/dist/tools/statement.js.map +1 -0
- package/payload/platform/plugins/ledger/mcp/package.json +21 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js +81 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/ledger-vertical-coverage.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +9 -7
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +10 -8
- package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +22 -0
- package/payload/platform/plugins/memory/references/schema-construction.md +0 -18
- package/payload/platform/plugins/scheduling/PLUGIN.md +20 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js +11 -2
- package/payload/platform/plugins/scheduling/mcp/dist/lib/meeting-write.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +3 -3
- package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts +138 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js +268 -0
- package/payload/platform/services/claude-session-manager/dist/activity-rows.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +8 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +6 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +42 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +10 -1
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +80 -6
- package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-census.js +96 -20
- package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +5 -1
- package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
- package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
- package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
- package/payload/server/{chunk-JRIBGO45.js → chunk-BSTIQX52.js} +44 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/activity.html +19 -0
- package/payload/server/public/assets/{AdminLoginScreens-Bed8SDxY.js → AdminLoginScreens-BfamGqS7.js} +1 -1
- package/payload/server/public/assets/AdminShell-5nHOAzXO.js +2 -0
- package/payload/server/public/assets/{Checkbox-BC_KSbpS.js → Checkbox-CD6aHwac.js} +1 -1
- package/payload/server/public/assets/activity-Dj2nJzPw.js +1 -0
- package/payload/server/public/assets/{admin-DfWgJVI3.js → admin-Cpcw_YE-.js} +1 -1
- package/payload/server/public/assets/{arc-qKfXIt8v.js → arc-BrHWN2Kr.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-CZQzGRSM.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DkVrGn7G.js → architectureDiagram-Q4EWVU46-Clt9NOr0.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DqavswGH.js → blockDiagram-DXYQGD6D-BOe_jmXi.js} +1 -1
- package/payload/server/public/assets/{browser-C0vkv-hH.js → browser-0znOwk1W.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B7fyKiXe.js → c4Diagram-AHTNJAMY-B64FaKMV.js} +1 -1
- package/payload/server/public/assets/calendar-CykigHdg.js +1 -0
- package/payload/server/public/assets/channel-zDUAN9Ks.js +1 -0
- package/payload/server/public/assets/chat-DIOJZ411.js +1 -0
- package/payload/server/public/assets/chevron-left-Cq7UvOI0.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-DsgMtGkv.js → chunk-2KRD3SAO-BGAUfWvM.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-CkdISfNt.js → chunk-336JU56O-PFi6uQZ0.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-iJnqNRug.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-CYpiF2bl.js → chunk-4BX2VUAB-CkxXXCiF.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-CWyc_F7v.js → chunk-4TB4RGXK-B-7tN4IA.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-BbzKMw2Z.js → chunk-55IACEB6-CBkNmqrt.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-u19Nai9e.js → chunk-5FUZZQ4R-wa9ujn7i.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-Ba8by6Uy.js → chunk-5PVQY5BW-DIk-xBaE.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-BwUuxtyb.js → chunk-67CJDMHE-BbMV1lgW.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-BRH9iM9L.js → chunk-7N4EOEYR-C49Mv-nQ.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-BGoztgLL.js → chunk-AA7GKIK3-Dy_pJOp_.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-C5GDAZTl.js → chunk-BSJP7CBP-Ce-OmPqn.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-ChY32VPS.js → chunk-CIAEETIT-tnjq-APC.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-CPSD3p6p.js → chunk-EDXVE4YY-Bvv_deZ2.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-D1oL-iUr.js → chunk-ENJZ2VHE-CmxCPKyU.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-CPvYEr54.js → chunk-FMBD7UC4-Top6y08S.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-9Yyj7Vbz.js → chunk-FOC6F5B3-B9LPNCUS.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-BaYgh8FR.js → chunk-ICPOFSXX-Bi-_c351.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-5ucpeRvm.js → chunk-K5T4RW27-DAnRM04h.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-DW-FHk7T.js → chunk-KGLVRYIC-C0QYcbLe.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-CGGVfAyG.js → chunk-LIHQZDEY-BjvA5ykt.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-Bv8EUa5d.js → chunk-ORNJ4GCN-Cs46Gj7z.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-C1mXJnyw.js → chunk-OYMX7WX6-BBpimab5.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-Qlc2PFAj.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-PwSQz6EP.js → chunk-U2HBQHQK-CQUSBHoK.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP--NPHTBlU.js → chunk-X2U36JSP-Dm8TevG0.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-Bbc7Da32.js → chunk-XPW4576I-B10QuxYb.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-D-9v8e--.js → chunk-YZCP3GAM-vaGsu4Wk.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CMPg670Q.js → chunk-ZZ45TVLE-D1Qi22bL.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CFsKL52p.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BWBUUCiO.js +1 -0
- package/payload/server/public/assets/clone-h5XhkDUL.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-NVSb1Bhy.js → cose-bilkent-S5V4N54A-CRDvLRXs.js} +1 -1
- package/payload/server/public/assets/{dagre-QfLcO-1j.js → dagre-CEmqJTt3.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-V2Ai1DFl.js → dagre-KV5264BT-LXMTo7Fp.js} +1 -1
- package/payload/server/public/assets/data-lHgqlhmu.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-Caw21693.js → diagram-5BDNPKRD-zyis6nPt.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-CgwVkT2q.js → diagram-G4DWMVQ6-BiU0XAAD.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DFUrLZhs.js → diagram-MMDJMWI5-rGFiz1SX.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-CEEiEuZJ.js → diagram-TYMM5635-B0wak1ZJ.js} +1 -1
- package/payload/server/public/assets/{dist-Cvgxm7qv.js → dist-B2N0v8hZ.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-CG10NrT3.js → erDiagram-SMLLAGMA-D8AUxLyX.js} +1 -1
- package/payload/server/public/assets/{flatten-DAO0sfCM.js → flatten-naJ5PJ4f.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BqkV9Okv.js → flowDiagram-DWJPFMVM-BtdUf68b.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-DRiCDQF6.js → ganttDiagram-T4ZO3ILL-C-lkzDmf.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CBZPQJLj.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BZV2voyy.js → gitGraphDiagram-UUTBAWPF-DRUKumq2.js} +1 -1
- package/payload/server/public/assets/{graph-BZiudUGr.js → graph-JV5_xF3V.js} +3 -3
- package/payload/server/public/assets/{graph-labels-BzmmJwCR.js → graph-labels-DPYORjBH.js} +1 -1
- package/payload/server/public/assets/{graphlib-DGPThX8M.js → graphlib-zRsaoFEC.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-1vIoX-kP.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-KHcXRaan.js +2 -0
- package/payload/server/public/assets/{isEmpty-Cb_U81C6.js → isEmpty-Bnpg7b8f.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BKsAxSvp.js → ishikawaDiagram-UXIWVN3A-BguMgoR8.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CmliuOd-.js → journeyDiagram-VCZTEJTY-CXhyK1n-.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DAlElMb-.js → kanban-definition-6JOO6SKY-C0UCWVx-.js} +1 -1
- package/payload/server/public/assets/{line-DKZqLKAC.js → line--uhS9YDE.js} +1 -1
- package/payload/server/public/assets/{linear-CbSGdh1x.js → linear-CAOWPodQ.js} +1 -1
- package/payload/server/public/assets/{maximize-2-Bhdsv0U-.js → maximize-2-8vKr3h21.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DFvbao9C.js → mermaid-parser.core-D6kPx7vc.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-C0vEBxDm.js → mermaid.core-CTd4DS6O.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CShASUKd.js → mindmap-definition-QFDTVHPH-_AyvyG8C.js} +1 -1
- package/payload/server/public/assets/operator-Liul1QEq.js +1 -0
- package/payload/server/public/assets/{ordinal-H0tVmBDP.js → ordinal-Wx4m9zHk.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-CTU0gCGb.js +1 -0
- package/payload/server/public/assets/page-CYRA87CB.js +1 -0
- package/payload/server/public/assets/{page-BoPorLg-.js → page-Cg7B1RQx.js} +4 -4
- package/payload/server/public/assets/{pdf-render-jAQU0nXt.js → pdf-render-CeX6d2v7.js} +1 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-D-EEHxhC.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CBZHpDAJ.js → pieDiagram-DEJITSTG-6TsUDkkQ.js} +1 -1
- package/payload/server/public/assets/{public-DqJk6qgW.js → public-B4HMtpjt.js} +1 -1
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-n3bB3K91.js → quadrantDiagram-34T5L4WZ-CWw9gOI4.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-DHXATZGB.js +1 -0
- package/payload/server/public/assets/{reduce-DAvwat-a.js → reduce-BUmc8RDR.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DiDvQK3c.js → requirementDiagram-MS252O5E-DCOlxNvx.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-D_5cETGt.js → rotate-ccw-sz5IQSnr.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DWDQQZmd.js → sankeyDiagram-XADWPNL6-CW4Xbir3.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-DmAqRlBT.js → sequenceDiagram-FGHM5R23-vhb_pBLG.js} +1 -1
- package/payload/server/public/assets/{src-DV4LKv2E.js → src-DHSQDYx-.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-D4R-n6bZ.js → stateDiagram-FHFEXIEX-Cb1WExEX.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CxOIKvXh.js +1 -0
- package/payload/server/public/assets/tasks-D9oYgEzs.js +1 -0
- package/payload/server/public/assets/{time-entry-format-DAwmmR3i.js → time-entry-format-CSuCexpM.js} +1 -1
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CjiHGP4l.js → timeline-definition-GMOUNBTQ-BAHTf_AF.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CC7ouMFd.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-CaCg27im.js +1 -0
- package/payload/server/public/assets/triangle-alert-ClS81-CU.js +1 -0
- package/payload/server/public/assets/{useCopyFeedback-rOWd_lzl.js → useCopyFeedback-Cn6YgeNx.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-DDmLmPph.js → useSelectionMode-BaD-ZZRk.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-pu0jjLCz.css → useSubAccountSwitcher-CNZL3PKn.css} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CvjWJSGv.js +9 -0
- package/payload/server/public/assets/{useVoiceRecorder-azG8zSUI.js → useVoiceRecorder-BOzHrDAU.js} +2 -2
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CBdDQ7c-.js → vennDiagram-DHZGUBPP-DtEttvW4.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-bMPsqQZ7.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-BlIQPKLb.js → wardleyDiagram-NUSXRM2D-K06y6CVJ.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-CslKgh9B.js → xychartDiagram-5P7HB3ND-D66c40lp.js} +1 -1
- package/payload/server/public/browser.html +6 -6
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +14 -14
- package/payload/server/public/data.html +13 -12
- package/payload/server/public/graph.html +12 -12
- package/payload/server/public/index.html +16 -15
- package/payload/server/public/operator.html +16 -16
- package/payload/server/public/public.html +14 -14
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +558 -260
- package/payload/server/public/assets/AdminShell-BLh9O6dn.js +0 -2
- package/payload/server/public/assets/architecture-YZFGNWBL-FPHT7s-C.js +0 -1
- package/payload/server/public/assets/calendar-_pfHw0Hp.js +0 -1
- package/payload/server/public/assets/channel-j70eMvcL.js +0 -1
- package/payload/server/public/assets/chat-DYT5H81o.js +0 -1
- package/payload/server/public/assets/chevron-left-BnpVBu51.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-D-NcAlTW.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-CAwbQBtf.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-Ct6Rn0vt.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B_2XCIFv.js +0 -1
- package/payload/server/public/assets/clone-DjPWA_NH.js +0 -1
- package/payload/server/public/assets/data-CR-fbPWr.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-B8Hx7f-D.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-BicCJTqU.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-tf-8rOez.js +0 -2
- package/payload/server/public/assets/operator-gm2eP4r6.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Ckn_5hq0.js +0 -1
- package/payload/server/public/assets/page-8AB3jUa_.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-DzlGQW3J.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BHo2YD8b.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BcFRbGRu.js +0 -1
- package/payload/server/public/assets/tasks-EyKLXINi.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BtRr5vXp.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-D8p0sbyo.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CU-lOxTd.js +0 -9
- package/payload/server/public/assets/wardley-RL74JXVD-DgMn-9ZJ.js +0 -1
- /package/payload/platform/plugins/cloudflare/skills/data-portal/{template/schema.sql → schema.sql} +0 -0
- /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/index.html → index.html} +0 -0
- /package/payload/platform/plugins/cloudflare/skills/data-portal/template/{public/portal.js → portal.js} +0 -0
- /package/payload/server/public/assets/{_baseFor-D3BqAOBr.js → _baseFor-k8hYPe-U.js} +0 -0
- /package/payload/server/public/assets/{array-iYP9fzJp.js → array-BFDiaBgf.js} +0 -0
- /package/payload/server/public/assets/{chunk-Ck5AOu5v.js → chunk-TPjIAO9U.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-BQSBzPsB.js → cytoscape.esm-Ch0xptA4.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-BrdA1gDi.js → defaultLocale-ZeknFqNe.js} +0 -0
- /package/payload/server/public/assets/{init-Bx0S6pkp.js → init-0VJVrkRJ.js} +0 -0
- /package/payload/server/public/assets/{katex-BsiH_a6d.js → katex-Br7bH10N.js} +0 -0
- /package/payload/server/public/assets/{path-BLSgTy3w.js → path-INs8XTPH.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-ClBMtM1g.js → preload-helper-D_sPnjeL.js} +0 -0
- /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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|