@rubytech/create-maxy-code 0.1.443 → 0.1.445
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/package.json +1 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts +4 -0
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +37 -1
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +39 -0
- package/payload/platform/lib/graph-style/src/index.ts +41 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js +46 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/authorize.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/authorize.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/authorize.test.js +27 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/authorize.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +51 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/house-credential.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/house-credential.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/house-credential.test.js +39 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/house-credential.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/registry.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/registry.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/registry.test.js +59 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/registry.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate-run.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate-run.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate-run.test.js +77 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate-run.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate.test.d.ts +2 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate.test.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate.test.js +23 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/remediate.test.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/audit.d.ts +19 -0
- package/payload/platform/lib/storage-broker/dist/audit.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/audit.js +41 -0
- package/payload/platform/lib/storage-broker/dist/audit.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/authorize.d.ts +11 -0
- package/payload/platform/lib/storage-broker/dist/authorize.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/authorize.js +17 -0
- package/payload/platform/lib/storage-broker/dist/authorize.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/bin/remediate-run.d.ts +25 -0
- package/payload/platform/lib/storage-broker/dist/bin/remediate-run.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/bin/remediate-run.js +131 -0
- package/payload/platform/lib/storage-broker/dist/bin/remediate-run.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +20 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +53 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/house-credential.d.ts +6 -0
- package/payload/platform/lib/storage-broker/dist/house-credential.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/house-credential.js +33 -0
- package/payload/platform/lib/storage-broker/dist/house-credential.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/index.d.ts +7 -0
- package/payload/platform/lib/storage-broker/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/index.js +30 -0
- package/payload/platform/lib/storage-broker/dist/index.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/registry.d.ts +18 -0
- package/payload/platform/lib/storage-broker/dist/registry.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/registry.js +45 -0
- package/payload/platform/lib/storage-broker/dist/registry.js.map +1 -0
- package/payload/platform/lib/storage-broker/dist/remediate.d.ts +7 -0
- package/payload/platform/lib/storage-broker/dist/remediate.d.ts.map +1 -0
- package/payload/platform/lib/storage-broker/dist/remediate.js +25 -0
- package/payload/platform/lib/storage-broker/dist/remediate.js.map +1 -0
- package/payload/platform/lib/storage-broker/src/__tests__/audit.test.ts +49 -0
- package/payload/platform/lib/storage-broker/src/__tests__/authorize.test.ts +28 -0
- package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +52 -0
- package/payload/platform/lib/storage-broker/src/__tests__/house-credential.test.ts +35 -0
- package/payload/platform/lib/storage-broker/src/__tests__/registry.test.ts +64 -0
- package/payload/platform/lib/storage-broker/src/__tests__/remediate-run.test.ts +79 -0
- package/payload/platform/lib/storage-broker/src/__tests__/remediate.test.ts +21 -0
- package/payload/platform/lib/storage-broker/src/audit.ts +55 -0
- package/payload/platform/lib/storage-broker/src/authorize.ts +22 -0
- package/payload/platform/lib/storage-broker/src/bin/remediate-run.ts +156 -0
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +73 -0
- package/payload/platform/lib/storage-broker/src/house-credential.ts +32 -0
- package/payload/platform/lib/storage-broker/src/index.ts +14 -0
- package/payload/platform/lib/storage-broker/src/registry.ts +85 -0
- package/payload/platform/lib/storage-broker/src/remediate.ts +31 -0
- package/payload/platform/lib/storage-broker/tsconfig.json +8 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js +40 -24
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +7 -7
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +7 -7
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +8 -4
- package/payload/platform/plugins/cloudflare/PLUGIN.md +4 -1
- package/payload/platform/plugins/cloudflare/bin/__tests__/cf-schema-check.test.sh +128 -0
- package/payload/platform/plugins/cloudflare/bin/__tests__/cf-store-name.test.sh +77 -0
- package/payload/platform/plugins/cloudflare/bin/cf-schema-check.sh +60 -0
- package/payload/platform/plugins/cloudflare/bin/cf-store-name.sh +37 -0
- package/payload/platform/plugins/cloudflare/bin/remediate-storage-isolation.sh +36 -0
- package/payload/platform/plugins/cloudflare/references/api.md +4 -0
- package/payload/platform/plugins/cloudflare/references/d1-data-capture.md +58 -0
- package/payload/platform/plugins/cloudflare/references/r2-object-storage.md +39 -0
- package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +2 -0
- package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +2 -0
- package/payload/platform/plugins/docs/references/admin-session.md +2 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +4 -0
- package/payload/platform/plugins/docs/references/cross-account-authority.md +3 -3
- package/payload/platform/plugins/outlook/references/auth.md +8 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +3 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js +11 -4
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +15 -10
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/storage-broker/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/storage-broker/PLUGIN.md +48 -0
- package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/caller-scope-headers.test.d.ts +2 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/caller-scope-headers.test.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/caller-scope-headers.test.js +16 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/__tests__/caller-scope-headers.test.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/call-api.d.ts +8 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/call-api.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/call-api.js +39 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/call-api.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/caller-scope-headers.d.ts +7 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/caller-scope-headers.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/caller-scope-headers.js +16 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/caller-scope-headers.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.d.ts +8 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js +98 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/storage-broker/mcp/package.json +10 -0
- package/payload/platform/plugins/storage-broker/mcp/vitest.config.ts +4 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.d.ts +2 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.js +44 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.js.map +1 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts +7 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/format.js +27 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.js.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +6 -19
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +10 -7
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -1
- 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 +6 -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 +1 -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 +99 -8
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +0 -13
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +11 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.d.ts +20 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.js +66 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.d.ts +19 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.js +50 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +14 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/server/chunk-4W6IEUFE.js +175 -0
- package/payload/server/public/assets/{AdminLoginScreens-BJVwtpLH.js → AdminLoginScreens-D9L-CuWi.js} +1 -1
- package/payload/server/public/assets/{AdminShell-CMu8_Xwn.js → AdminShell-DSQrvZXq.js} +1 -1
- package/payload/server/public/assets/{Checkbox-CzD0ORqA.js → Checkbox-CFdt8ljo.js} +1 -1
- package/payload/server/public/assets/{admin-D0yk2LMq.js → admin-Ch4n-G0j.js} +1 -1
- package/payload/server/public/assets/{browser-CvfbgznO.js → browser-B2AIxiuk.js} +1 -1
- package/payload/server/public/assets/{calendar-fw4WethJ.js → calendar-BvItH3B0.js} +1 -1
- package/payload/server/public/assets/chat-eQFMaX9y.js +1 -0
- package/payload/server/public/assets/chevron-left-D2AnCEyE.js +1 -0
- package/payload/server/public/assets/data-BzOmbHoe.js +1 -0
- package/payload/server/public/assets/{file-download-Px4s0Bhp.js → file-download-CK9j_Jx2.js} +1 -1
- package/payload/server/public/assets/graph-DrE7KupQ.js +51 -0
- package/payload/server/public/assets/graph-labels-CwEtvIRV.js +1 -0
- package/payload/server/public/assets/{maximize-2-BwphzI9S.js → maximize-2-CuzEom3K.js} +1 -1
- package/payload/server/public/assets/{operator-zcIfeB14.js → operator-DlboYPPu.js} +1 -1
- package/payload/server/public/assets/page-BuWH5gNK.js +1 -0
- package/payload/server/public/assets/page-Co9E8U5x.js +32 -0
- package/payload/server/public/assets/{public-C0ehZCdE.js → public-DtFpPMTG.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-C7BqkMec.js → rotate-ccw-Cqp4oqHV.js} +1 -1
- package/payload/server/public/assets/{tasks-DlgiCafL.js → tasks-bQKOhMga.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-CyNYVDkq.js → time-entry-format-BIL4ZaDK.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-rB8QuqyH.js +1 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-1izQvPiD.css → useSubAccountSwitcher-CVHKTSst.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-XgpWvXpk.js → useVoiceRecorder-Ctny8qWx.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +13 -13
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +1082 -841
- package/payload/server/src-BQ2NYMOT.js +24 -0
- package/payload/server/public/assets/chat-DhD-NES_.js +0 -1
- package/payload/server/public/assets/chevron-left-B3xSeEDR.js +0 -1
- package/payload/server/public/assets/data-CUnDzDox.js +0 -1
- package/payload/server/public/assets/graph-DbT8nA6R.js +0 -51
- package/payload/server/public/assets/graph-labels-C1YIyLiA.js +0 -1
- package/payload/server/public/assets/page-6fCnIb45.js +0 -32
- package/payload/server/public/assets/page-CfQFAJia.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-ByGUMN94.js +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-s6WlRn52.js → useSubAccountSwitcher-CHEt_m6q.js} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# R2 object storage — establishment discipline
|
|
2
|
+
|
|
3
|
+
R2 buckets follow the **same establishment discipline as D1 databases** (`d1-data-capture.md` § Establishing a store): a canonical name derived from the account, one bucket per purpose, and a provision breadcrumb. This reference states those rules for R2; it does not add a new capture mechanism.
|
|
4
|
+
|
|
5
|
+
Pair this with `api.md` for the token discipline that authenticates every `wrangler` call.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Naming — `<accountId>-<purpose>`
|
|
10
|
+
|
|
11
|
+
Every bucket is named `<accountId>-<purpose>`, computed with the helper, never hand-built:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
BUCKET="$(bash bin/cf-store-name.sh "<accountId>" "<purpose>")" # e.g. acc9f2-uploads
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The helper lowercases each segment, which also satisfies R2's lowercase-only bucket-name rule. The name identifies the bucket's owner and purpose at a glance — the same property that keeps one client's bucket from colliding with another's on a multi-tenant install.
|
|
18
|
+
|
|
19
|
+
## One bucket per purpose
|
|
20
|
+
|
|
21
|
+
A purpose gets exactly **one** bucket. Before creating one, list what already exists (`wrangler r2 bucket list`); if a bucket already serves the purpose, **reuse it** rather than creating a second. A new object *kind* within a purpose is a key prefix inside the one bucket, not a second bucket.
|
|
22
|
+
|
|
23
|
+
## Create (or reuse) the bucket
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
BUCKET="$(bash bin/cf-store-name.sh "<accountId>" "<purpose>")"
|
|
27
|
+
wrangler r2 bucket list | grep -qx "$BUCKET" \
|
|
28
|
+
|| wrangler r2 bucket create "$BUCKET"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The token must carry an R2-scoped permission; resolve it the same reuse-a-stable-per-scope-token way `api.md` prescribes. The token is never written into a project tree or echoed into chat.
|
|
32
|
+
|
|
33
|
+
## Store-provision breadcrumb
|
|
34
|
+
|
|
35
|
+
When a bucket is created or reused, log the establishment decision so a reuse is visible and a create is attributable to a purpose that genuinely had none:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
op=storage-provision resource=r2 purpose=<purpose> account=<accountId> name=<canonical-name> action=create|reuse
|
|
39
|
+
```
|
|
@@ -29,6 +29,8 @@ This is the entry point for every Cloudflare task on the install. Pick the opera
|
|
|
29
29
|
|
|
30
30
|
Neither the master token nor any per-scope token is ever written into a project tree, committed, or echoed into chat — the per-scope tokens persist only in the account-scoped secrets file, never in a deployable project tree.
|
|
31
31
|
|
|
32
|
+
On a multi-client install where client sub-accounts share one Cloudflare account, the master lives house-only at `config/cloudflare-house.env` and sub-account D1/R2 data work goes through the storage broker, not raw `wrangler`. This skill's tunnel, DNS, and Pages operations stay admin-run and unchanged. See `references/api.md` and `.docs/cloudflare-storage-isolation.md`.
|
|
33
|
+
|
|
32
34
|
### Resolve the per-scope token before any `wrangler` / API call (binding)
|
|
33
35
|
|
|
34
36
|
This binding governs **every** Pages, D1, DNS, or Access operation, not only calls you think of as "token operations." Before the first `wrangler pages …`, `wrangler d1 …`, or Cloudflare-API `curl` of a task, resolve the per-scope token with the deterministic helper and pass **that** token to the command:
|
|
@@ -59,6 +59,8 @@ Creating that DNS record is a **DNS-scope** operation, not a Pages-scope one: th
|
|
|
59
59
|
|
|
60
60
|
When the canonical tree carries a contact or waitlist form, the deploy is not complete until that form records to D1. Follow `references/d1-data-capture.md`: create the database, add the `[[d1_databases]]` binding to `wrangler.toml`, create the table, and ship `functions/api/contact.ts`. The token from the auth step already carries D1 Edit, so the form does not silently 500 at the insert. A site with no form skips this section.
|
|
61
61
|
|
|
62
|
+
Name the database with the canonical `<accountId>-<purpose>` scheme from `bin/cf-store-name.sh`, and keep one store per capture purpose: a new capture kind is a discriminator column, not a second database. A document-acceptance form (works agreement, quote signing) uses the canonical `acceptances` shape declared in `references/d1-data-capture.md`, not a per-build table, so the watcher reads one known store.
|
|
63
|
+
|
|
62
64
|
## Open Graph correctness
|
|
63
65
|
|
|
64
66
|
The live page must carry brand-correct Open Graph metadata: `<meta property="og:title">`, `og:description`, `og:image`, and `og:url` reflecting this site and this brand, not a leftover from whatever the tree was cloned from. Stale OG (a live card still naming a previous brand) is a recorded failure mode of hand deployment. Confirm the `og:*` tags in the deployed HTML are correct before claiming done; if they are stale, fix them in the source tree, redeploy, and re-check.
|
|
@@ -99,6 +99,8 @@ The metadata pane surfaces two distinct identifier values. The three-id model wa
|
|
|
99
99
|
|
|
100
100
|
**The footer reads model/effort/turn-count from one shared JSONL resolver.** The `/chat` footer's model / effort / turn-count are the manager `GET /:sessionId/meta` enrichment, read from the session's JSONL tail. That read resolves the JSONL by the **same all-slug scan** the transcript uses — `findExistingJsonlForSessionId`, covering top-level and `archive/` under every project slug — not the single house-cwd slug. Previously the enrichment gated on the `spawnCwd` slug, so a sub-account session rc-spawned in a different cwd (its JSONL under a different slug) reported `model:null turns:0` while its transcript rendered; the transcript already scanned all slugs. `findSessionProjectDir` (the transcript resolver) delegates to the same function, so the two are one resolver — a session findable on disk is never reported `model:null`. The standing line is `[session-meta] op=enrich session=<id8> resolver=scan jsonl=<found|absent> model=… effort=… turns=…`.
|
|
101
101
|
|
|
102
|
+
The same all-slug scan runs on the **row-absent branch** too. The manager's fs-watcher is armed to only the boot/house account's project dir, so a sub-account session (its JSONL under a different slug) has no watcher row and `resolveRow` returns nothing. Rather than 404 — which gives the footer no payload at all, blanking model/effort/thinking — `/meta` scans for the JSONL first and, when found, returns an enriched 200 built rowless (`pid:null`, `role:null`, `status:ended`, `activity:idle`; model/turns/tokens from the tail, effort from settings). Only a session id with no JSONL anywhere still 404s. The row-absent line carries a `row=absent` token to distinguish it: `resolver=scan row=absent jsonl=found …` for the enriched 200, `resolver=none row=absent jsonl=absent …` for the genuine 404. So a session the transcript can render can never blank its footer on account of a missing watcher row.
|
|
103
|
+
|
|
102
104
|
| Operator label | What it is | Manager wire field | Log key |
|
|
103
105
|
|---|---|---|---|
|
|
104
106
|
| `sessionId` | Claude's session. Two phases: bridge suffix (`session_xxx`, the URL segment in `claude.ai/code/<session_xxx>`, set when claude prints the `/remote-control` URL) and JSONL basename UUID (claude's intrinsic id on disk, bound when the first turn flushes the JSONL). Both phases coexist on a live row after URL capture; the manager wire emits the bridge form when set, falling back to the JSONL basename in the pre-URL-capture window. The resolver routes either phase to the same row, so callers never need to choose. | `sessionId` (collapsed from the earlier three-field surface `sessionId` + `claudeSessionId` + `bridgeSessionId`) | `sessionId=` |
|
|
@@ -73,8 +73,12 @@ either is a regression.
|
|
|
73
73
|
|
|
74
74
|
**`/chat` header always shows the account name.** The admin/operator `HeaderMenu` centre always renders the active account's name alongside the brand logo, on every chat surface, regardless of the active conversation — `headerTitle = businessName || brand.productName`. There is no per-conversation header title: the active conversation's label stays in the sidebar and the Conversations flyout (each resolves its own per-session title independently), never in the header. The account name is `LocalBusiness.name`, resolved by `fetchAccountName(accountId)` in `neo4j-store.ts` with **no theme gate** — unlike `fetchBranding` (which returns null unless a colour/logo property is also set, and stays the source for actual theming). The house account is seeded with `LocalBusiness.name = <brand productName>` (`seed-neo4j.sh`, coalesced ON MATCH so a re-seed backfills a name-less node and never clobbers a name the business-profile recorder set later), so the sub-account picker's house row shows the product name (e.g. "SiteDesk"), not the raw accountId UUID. When a name is absent the resolver emits `[branding] account-name-fallback accountId=<id8>… reason=no-name`, and the picker falls back to the accountId; the seed + backfill is the name source. The lite variant header is unchanged.
|
|
75
75
|
|
|
76
|
+
**`/chat` sub-account switch starts a fresh conversation.** Switching sub-accounts from the header picker while on the chat page presents an empty greeting with no active session — no footer id, no highlighted conversation. The next message starts a **new** conversation for the switched-to account rather than reopening that account's previous one, and the previous conversation is left untouched and still resumable from the Conversations list. A normal visit to the chat page that did not switch accounts still reopens the account's most recent conversation as before. The full mechanism (the `clearSignal` first send and the `op=post-switch-pointer`/`op=send-target-resolve` diagnostics) lives in `.docs/admin-webchat-native-channel.md`.
|
|
77
|
+
|
|
76
78
|
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp/operator reader (`/whatsapp`, `OperatorConversations`) omits the prop and keeps the default `renderTimeline`, so its bubble/DM chrome is unchanged — except that since the attachment-render extraction the default renderer draws inbound `operator-inbound` uploads and `agent-file` deliveries inline (image thumbnail / pdf.js preview / voice-note player / download chip) via the attachment renderer shared with `/chat`, extracted to `app/chat/attachment-render.tsx` to break the cycle with `transcript-render.tsx`; `renderChatTimeline` is untouched. Both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`, `app/chat/__tests__/pdf-preview.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
|
|
77
79
|
|
|
80
|
+
**One delivered bubble per turn when the agent replied.** On the admin `/chat`, a turn that used the reply tool shows exactly one delivered bubble — the reply. A trailing sign-off or recap the agent writes after the reply is treated as narration and is not shown as a second bubble (it collapses like any mid-turn prose). Only a turn that ends **without** using the reply tool has its final text promoted to a delivered bubble, so a genuine no-reply answer is never lost. The tradeoff, accepted by the operator: a turn that acknowledges on the reply tool and then writes the real answer as trailing text will not show that trailing answer — the agent is steered to put the answer on the reply tool so this stays rare.
|
|
81
|
+
|
|
78
82
|
**WhatsApp reader is read/write (WhatsApp-Web surface).** A WhatsApp store conversation in the operator Conversations reader (`OperatorConversations`) and the admin root channel viewer (`app/page.tsx`) no longer opens the plain read-only DM chrome — it opens `app/whatsapp/WhatsappWebConversation.tsx`, a WhatsApp-Web-styled surface: a conversation header, the delivered-only store transcript reskinned green/white under a `.wa-web` root class, and a reply composer (`app/whatsapp/ReplyComposer.tsx`). The operator can type text, insert emoji (a codepoint-data picker — no OS input, so the `check-no-emoji-in-jsx` gate stays green), record a voice note (MediaRecorder → the existing audio send path), attach a file **from device storage** (a modal browsing the DATA_ROOT tree via `GET /api/admin/files`, sent by reference — the OS file dialog is no longer the reader's picker), reply to a specific message (a per-bubble affordance that quotes the original in the composer and threads natively on WhatsApp), and search the loaded transcript (a header control that filters to matching turns and highlights the match). The header carries only that Search control — the former Video / Phone / menu icons are gone, because no call or presence data exists behind them. Sent files honour the webchat allowlist (`SUPPORTED_MIME_SET` / 50 MB / 5 files); a device-file reference is authorised server-side (`authorizeReplyFileRef`) against the send's own account (the conversation owner) **or** the session's pinned account (`getAccountIdForSession` — the exact scope the DeviceFilePicker used to offer it), so a house/managing-admin session can attach a managed-client file the picker listed. Because a reply sends bytes OUT to an external WhatsApp recipient, any other account, a `public` partition, and any install-wide / non-account path are refused fail-closed; the cross-account admission's authority is the session's pinned account, never the caller-supplied body `accountId` (the own-account admission matches the body `accountId`, which the route already trusts via `isValidAccountId` and the existing-conversation guard). A scope refusal returns a distinct HTTP 403 reason (`file-ref-cross-account` / `file-ref-public` / `file-ref-foreign`) and copy, never "device file not found" (reserved for a genuine resolve/stat miss). Per-ref `[wa-manual-send] op=reply-file-ref … via=own|session|deny reason=<…> ok=<bool>` logs the decision before any send; `via=deny ok=true` is the exfiltration signature that must never appear. **Send is reply-only and DM-only:** `POST /api/whatsapp-reader/reply` (`requireAdminSession`) refuses any target with no existing stored conversation (`reason=no-existing-conversation`, HTTP 403) — a cold first-contact send bans the account, so the composer is never a cold-contact path, enforced server-side — and refuses `@g.us` groups (`reason=group-send-blocked`), matching the agent's observe-only group invariant; a group thread shows a read-only note in place of the composer. The endpoint is the sole store writer for a manual send: right after each send resolves it appends the record itself, stamped `origin:'operator-manual'` (attributed "You", distinct from an assistant reply), because the Baileys echo that normally persists the store is gated on message text (`manager.ts:906`) and would leave an uncaptioned media send delivered-but-invisible. The record's `messageId` matches the echo's derivation so the async text echo's own persist dedups to a no-op; the send is confirmed by re-read (`op=recorded present=<bool>`). A sent send does not spawn an assistant turn (echo dispatch stays suppressed). Attachments deliver as WhatsApp media/documents and render **inline** in the store reader (image thumbnail / pdf preview / audio player / download chip), because the manual-send path records the message with the servable `attachmentId`. The `.wa-web` skin is scoped to WhatsApp store threads only, so `/chat`, the admin agent session view, and the public visitor webchat are unchanged; the visitor webchat gains no send capability. The in-bubble delivered-tick is cosmetic (no read-receipt data is stored); inbound bubbles keep their sender name so group threads stay attributable, and both directions carry a WhatsApp callout tail (`.wa-web`-scoped only). Non-WhatsApp reader rows (Telegram/webchat session JSONLs) keep the plain read-only `Transcript`. Observability rides `[wa-manual-send]` lines correlated by a per-request `sendId`. **Composer sizing matches the webchat composer:** the reply textarea auto-grows to fit multi-line content (measured from `scrollHeight`, clamped to a one-row minimum and a `viewport/3` maximum, scrollable past the cap with the scrollbar hidden), and a top-border grab handle drags (pointer) or nudges (ArrowUp/ArrowDown, keyboard-focusable) to an explicit height in the same clamp; a manual drag pins the height and overrides auto-grow until the field is cleared, which releases it back to auto-grow. A completed manual resize logs `[operator-ui] op=wa-composer-resize mode=drag|key h=<px>`; a bare click on the handle (no drag) logs nothing.
|
|
79
83
|
|
|
80
84
|
**`/chat` live activity line.** While a turn is in flight the transcript tail shows one ephemeral `ChatActivity` line (mounted only while `busy`, admin/operator only). It tracks real activity, not a timer: while a `Task` subagent runs it shows that subagent's headline (`agentType · description`, prefixed `N agents ·` when ≥2 are concurrent), sourced from `agent-<hex>.meta.json` via named `activity` SSE events the admin reader pushes from the session's `subagents/` dir; with no subagent active it shows a neutral word that advances only on a real turn arrival. The line carries a turn-elapsed clock and flips to a `stalled` state once nothing has been written for 5 minutes (`now − lastEmitAt`), so the operator can tell a wedge from progress without SSH. It is never added to the persisted timeline. Detail and the `[webchat-activity]` observability live in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
|
|
@@ -6,13 +6,13 @@ By default the admin assistant is scoped the same way — it acts on the house a
|
|
|
6
6
|
|
|
7
7
|
The operator wants this for two surfaces: the account graph and the account filesystem. Each is a separate adoption; a coverage ledger tracks them and a background check confirms neither silently regresses.
|
|
8
8
|
|
|
9
|
-
## Creating a sub-account
|
|
9
|
+
## Creating a sub-account can name a managing admin
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
A client sub-account may have a responsible house admin, but one is optional. `account_create` takes the `userId` of a current house admin as the managing admin — the admin agent asks the operator which house admin manages the client (the choices come from `admin-list`) — and records it as `managingAdminUserId` on the sub-account; a supplied `userId` that is not a live house admin is refused. Omit it for a client run by its owner rather than a house team member. A WhatsApp requirement that comes in for that sub-account is filed as a task assigned to its managing admin; when the sub-account has no managing admin (or its recorded one is no longer a live house admin), the task is assigned to the install's primary admin (the first house admin) instead, so it always lands with a named owner rather than unassigned.
|
|
12
12
|
|
|
13
13
|
## Reassigning and removing a managing admin
|
|
14
14
|
|
|
15
|
-
To hand a client to a different team member — or to
|
|
15
|
+
To hand a client to a different team member — or to record a managing admin on an unmanaged account, or repair one whose admin was removed — use `account_reassign_admin` with the client's `accountId` and the new admin's `userId`. It refuses a target that is not a client sub-account or a `userId` that is not a current house admin. Removing a house admin is guarded so it cannot silently orphan anyone: `admin-remove` refuses to remove an admin who is still the managing admin of one or more client sub-accounts and names those accounts. Reassign each with `account_reassign_admin`, then remove the admin.
|
|
16
16
|
|
|
17
17
|
## Memory (graph)
|
|
18
18
|
|
|
@@ -81,6 +81,14 @@ operator plugin
|
|
|
81
81
|
|
|
82
82
|
`poll` maps Microsoft's polling errors: `authorization_pending` → `pending` (wait `intervalSec`, poll again), `slow_down` → `pending` with a bumped interval, `expired_token` → `expired`, `access_denied` → `denied`.
|
|
83
83
|
|
|
84
|
+
### Re-registering an account that already consented
|
|
85
|
+
|
|
86
|
+
First-time registration completes cleanly. Re-registering a mailbox whose Microsoft account has **already granted this app access** on a prior registration does not: after the operator enters the user code, Microsoft's consent step redirects the browser to `http://localhost/?error=invalid_request&error_description=...response_type...`, a "site can't be reached" dead-end, and consent never finishes. Observed for personal accounts (outlook.com, hotmail.com, live.com), whose completion runs through the consumer stack (`login.live.com` `msaidpvalidate` → `post.srf`).
|
|
87
|
+
|
|
88
|
+
This is Microsoft's re-consent behaviour, not a plugin fault. Confirmed 2026-07-14: our `/devicecode` request is byte-identical to a run that succeeded days earlier (only the account's consent state differed); the `response_type` the error names is absent because the device-code grant has no such parameter; and the malformed redirect is built by Microsoft's `post.srf`, not by anything the plugin sends. Removing the app's `http://localhost` reply URL does not help (the redirect uses a request-supplied `redirect_uri`, not a registered one), and the Implicit-grant/ID-token toggle does not apply (device-code is a public-client flow, not Web/SPA).
|
|
89
|
+
|
|
90
|
+
The block is the **stale Microsoft-side grant**, which lives in the end user's own Microsoft account, so there is no server-side tool to clear it. The operator revokes the app at **https://account.microsoft.com/privacy/app-access** (remove the brand's app entry), then re-runs `outlook-account-register`; the next sign-in is treated as first-time and completes. The already-connected mailbox keeps working the whole time — only the re-registration is blocked. See `.tasks/backlog/1634-outlook-account-deregister-and-reconsent-guidance.md` for the follow-up on a server-side deregister tool and a register-time hint.
|
|
91
|
+
|
|
84
92
|
## Token store layout
|
|
85
93
|
|
|
86
94
|
One account can hold several mailboxes. Each mailbox owns its own `tokens.enc`
|
|
@@ -37,6 +37,8 @@ Subsequent tool calls use the persisted refresh token to mint access tokens tran
|
|
|
37
37
|
|
|
38
38
|
If the brand ships no vendor app yet, `outlook-account-register` reports that the client ID is not configured. There is no per-install workaround; the brand's vendor app has to exist first.
|
|
39
39
|
|
|
40
|
+
**Re-connecting a mailbox that already granted access.** First-time registration works cleanly. But if the target Microsoft account has *already* consented to this brand's app on a prior registration, starting a fresh `outlook-account-register` for it dead-ends: after the operator enters the code, Microsoft's consent step redirects the browser to a `http://localhost` "this site can't be reached" page instead of completing. This is Microsoft's re-consent behaviour for a personal account (outlook.com, hotmail.com, live.com), not a fault in this plugin; our device-code request is unchanged, and the connected mailbox keeps working throughout. The block is the stale Microsoft-side grant, and there is no server-side tool to clear it because that grant lives in the end user's own Microsoft account. To re-connect, the operator first revokes this app at **https://account.microsoft.com/privacy/app-access** (find the brand's app, remove it), then re-runs `outlook-account-register`; the next sign-in is treated as new and completes. Relay this to the operator whenever a re-registration stalls at a localhost page.
|
|
41
|
+
|
|
40
42
|
**Microsoft mail does not use IMAP or app passwords.** Microsoft retired Basic auth for Exchange Online and app passwords stopped working. Never route a Microsoft mailbox through the `email` plugin's IMAP path, and never suggest an app password. The device-code flow above is the only supported connection.
|
|
41
43
|
|
|
42
44
|
## Reading mail
|
|
@@ -85,6 +87,7 @@ All calendar writes need the `Calendars.ReadWrite` consent (see setup above). Ti
|
|
|
85
87
|
| `Microsoft Graph does not support on-premises Exchange` | Mailbox is on hybrid Exchange | Use the `email` plugin (IMAP) |
|
|
86
88
|
| `Outlook send scope not granted (missing Mail.Send)` | Mailbox registered under the old read-only consent | Re-run `outlook-account-register` and consent to the send scopes |
|
|
87
89
|
| `Outlook rate-limited without Retry-After hint` | Graph 429 with no backoff guidance | Retry later; if persistent, file a bug |
|
|
90
|
+
| Registration dead-ends at a `http://localhost` "site can't be reached" page | The account already granted this app access on a prior registration; Microsoft's re-consent path for a personal account breaks | Revoke this app at https://account.microsoft.com/privacy/app-access, then re-run `outlook-account-register` |
|
|
88
91
|
|
|
89
92
|
## Reference files
|
|
90
93
|
|
|
@@ -141,10 +141,17 @@ async function main() {
|
|
|
141
141
|
console.error(`[calendar-availability] op=publish accountId=${accountId} result=skipped reason=no-booking-db`);
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
// Task 1631 — house code uses the house-only Cloudflare credential, never a
|
|
145
|
+
// per-account token. The booking DB is still targeted by its per-account name.
|
|
146
|
+
const platformRoot = process.env.PLATFORM_ROOT;
|
|
147
|
+
if (!platformRoot) {
|
|
148
|
+
console.error(`[calendar-availability] op=publish accountId=${accountId} result=skipped reason=no-platform-root`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const houseCred = readEnvFile(join(platformRoot, "config", "cloudflare-house.env"));
|
|
152
|
+
const token = houseCred.CLOUDFLARE_API_TOKEN;
|
|
146
153
|
if (!token) {
|
|
147
|
-
console.error(`[calendar-availability] op=publish accountId=${accountId} result=skipped reason=no-
|
|
154
|
+
console.error(`[calendar-availability] op=publish accountId=${accountId} result=skipped reason=no-house-cloudflare-credential`);
|
|
148
155
|
return;
|
|
149
156
|
}
|
|
150
157
|
const port = process.env.MAXY_UI_INTERNAL_PORT;
|
|
@@ -209,7 +216,7 @@ ON CONFLICT(id) DO UPDATE SET payload=excluded.payload, updatedAt=excluded.updat
|
|
|
209
216
|
writeFileSync(sqlFile, sql);
|
|
210
217
|
const wranglerEnv = {
|
|
211
218
|
CLOUDFLARE_API_TOKEN: token,
|
|
212
|
-
...(
|
|
219
|
+
...(houseCred.CLOUDFLARE_ACCOUNT_ID ? { CLOUDFLARE_ACCOUNT_ID: houseCred.CLOUDFLARE_ACCOUNT_ID } : {}),
|
|
213
220
|
};
|
|
214
221
|
const proc = spawnSync("npx", ["wrangler", "d1", "execute", dbName, "--remote", "--file", sqlFile], {
|
|
215
222
|
env: { ...process.env, ...wranglerEnv },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-availability.js","sourceRoot":"","sources":["../../src/scripts/publish-availability.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"publish-availability.js","sourceRoot":"","sources":["../../src/scripts/publish-availability.ts"],"names":[],"mappings":"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"}
|
|
@@ -146,7 +146,7 @@ async function resolveEmailNotify(accountId) {
|
|
|
146
146
|
return {};
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
-
async function reconcileAccount(driver, accountId, accountDir) {
|
|
149
|
+
async function reconcileAccount(driver, accountId, accountDir, houseToken, houseAccountId) {
|
|
150
150
|
const availPath = join(accountDir, "calendar-availability.json");
|
|
151
151
|
if (!existsSync(availPath))
|
|
152
152
|
return; // no booking site for this account
|
|
@@ -163,15 +163,12 @@ async function reconcileAccount(driver, accountId, accountDir) {
|
|
|
163
163
|
console.error(`[calendar-reconcile] account=${accountId} skip reason=no-booking-db`);
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
console.error(`[calendar-reconcile] account=${accountId} skip reason=no-pages-d1-token`);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
166
|
+
// Task 1631 — house code uses the house-only Cloudflare credential, never a
|
|
167
|
+
// per-account token. The account-wide token no longer lives in a sub-account
|
|
168
|
+
// secrets file; the booking DB is still targeted by its per-account name.
|
|
172
169
|
const wranglerEnv = {
|
|
173
|
-
CLOUDFLARE_API_TOKEN:
|
|
174
|
-
...(
|
|
170
|
+
CLOUDFLARE_API_TOKEN: houseToken,
|
|
171
|
+
...(houseAccountId ? { CLOUDFLARE_ACCOUNT_ID: houseAccountId } : {}),
|
|
175
172
|
};
|
|
176
173
|
let pending;
|
|
177
174
|
try {
|
|
@@ -258,10 +255,18 @@ async function main() {
|
|
|
258
255
|
const accountIds = readdirSync(accountsDir).filter((d) => existsSync(join(accountsDir, d, "account.json")));
|
|
259
256
|
if (accountIds.length === 0)
|
|
260
257
|
return;
|
|
258
|
+
// Task 1631 — the account-wide Cloudflare credential lives house-only.
|
|
259
|
+
const houseCred = readEnvFile(join(platformRoot, "config", "cloudflare-house.env"));
|
|
260
|
+
const houseToken = houseCred.CLOUDFLARE_API_TOKEN;
|
|
261
|
+
if (!houseToken) {
|
|
262
|
+
console.error("[calendar-reconcile] skip reason=no-house-cloudflare-credential");
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const houseAccountId = houseCred.CLOUDFLARE_ACCOUNT_ID;
|
|
261
266
|
driver = connectNeo4j();
|
|
262
267
|
for (const accountId of accountIds) {
|
|
263
268
|
try {
|
|
264
|
-
await reconcileAccount(driver, accountId, join(accountsDir, accountId));
|
|
269
|
+
await reconcileAccount(driver, accountId, join(accountsDir, accountId), houseToken, houseAccountId);
|
|
265
270
|
}
|
|
266
271
|
catch (err) {
|
|
267
272
|
console.error(`[calendar-reconcile] account=${accountId} run-failed err="${err.message}"`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-bookings.js","sourceRoot":"","sources":["../../src/scripts/reconcile-bookings.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"reconcile-bookings.js","sourceRoot":"","sources":["../../src/scripts/reconcile-bookings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "storage-broker",
|
|
3
|
+
"description": "Per-account Cloudflare D1/R2 storage broker. The only agent-reachable path to storage; the account-wide credential stays house-only and every operation is scoped to the caller's account.",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Rubytech LLC"
|
|
7
|
+
},
|
|
8
|
+
"mcpServers": {
|
|
9
|
+
"storage-broker": {
|
|
10
|
+
"type": "stdio",
|
|
11
|
+
"command": "node",
|
|
12
|
+
"args": [
|
|
13
|
+
"${CLAUDE_PLUGIN_ROOT}/lib/mcp-spawn-tee/index.js",
|
|
14
|
+
"${CLAUDE_PLUGIN_ROOT}/mcp/dist/index.js"
|
|
15
|
+
],
|
|
16
|
+
"env": {
|
|
17
|
+
"MCP_SPAWN_TEE_NAME": "storage-broker"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: storage-broker
|
|
3
|
+
description: Per-account Cloudflare D1/R2 storage broker. The only agent-reachable path to storage; the account-wide credential stays house-only and every operation is scoped to the caller's account.
|
|
4
|
+
tools:
|
|
5
|
+
- name: storage-d1-list
|
|
6
|
+
publicAllowlist: false
|
|
7
|
+
adminAllowlist: true
|
|
8
|
+
- name: storage-d1-create
|
|
9
|
+
publicAllowlist: false
|
|
10
|
+
adminAllowlist: true
|
|
11
|
+
- name: storage-d1-query
|
|
12
|
+
publicAllowlist: false
|
|
13
|
+
adminAllowlist: true
|
|
14
|
+
- name: storage-r2-bucket-list
|
|
15
|
+
publicAllowlist: false
|
|
16
|
+
adminAllowlist: true
|
|
17
|
+
- name: storage-r2-bucket-create
|
|
18
|
+
publicAllowlist: false
|
|
19
|
+
adminAllowlist: true
|
|
20
|
+
metadata: {"platform":{"embed":["admin"]}}
|
|
21
|
+
mcp:
|
|
22
|
+
command: node
|
|
23
|
+
args:
|
|
24
|
+
- ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
|
|
25
|
+
- ${PLATFORM_ROOT}/plugins/storage-broker/mcp/dist/index.js
|
|
26
|
+
env:
|
|
27
|
+
MCP_SPAWN_TEE_NAME: storage-broker
|
|
28
|
+
LOG_DIR: ${LOG_DIR}
|
|
29
|
+
PLATFORM_ROOT: ${PLATFORM_ROOT}
|
|
30
|
+
ACCOUNT_ID: ${ACCOUNT_ID}
|
|
31
|
+
SESSION_ID: ${SESSION_ID}
|
|
32
|
+
PLATFORM_PORT: ${PLATFORM_PORT}
|
|
33
|
+
mcp-manifest: auto
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
# storage-broker
|
|
37
|
+
|
|
38
|
+
The isolation boundary for per-account Cloudflare D1 and R2 on a multi-tenant install. A sub-account agent holds no Cloudflare credential and cannot reach `wrangler` or `curl` against storage directly. Every D1 and R2 operation goes through these tools, which forward the caller's account as the platform-stamped `x-maxy-caller-account` header (never a tool argument) to the house-level broker service. The service holds the sole account-wide credential in `config/cloudflare-house.env`, resolves each resource's recorded owner, and denies any cross-account access before it ever calls Cloudflare.
|
|
39
|
+
|
|
40
|
+
## Tools
|
|
41
|
+
|
|
42
|
+
- `storage-d1-list` — the caller account's D1 databases.
|
|
43
|
+
- `storage-d1-create` — create a D1 database, registered to the caller.
|
|
44
|
+
- `storage-d1-query` — run SQL against a database the caller owns.
|
|
45
|
+
- `storage-r2-bucket-list` — the caller account's R2 buckets.
|
|
46
|
+
- `storage-r2-bucket-create` — create an R2 bucket, registered to the caller.
|
|
47
|
+
|
|
48
|
+
A request against a database or bucket the caller does not own returns an authorization error, not another account's data.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* MCP spawn-tee — in-process stderr capture + lifecycle observability.
|
|
5
|
+
*
|
|
6
|
+
* Claude Code spawns each MCP server itself; the platform never holds a
|
|
7
|
+
* ChildProcess handle. This shim sits between Claude Code and the real MCP
|
|
8
|
+
* server: Claude Code runs `node <this> <real-entry>`, and the shim runs the
|
|
9
|
+
* real entry IN ITS OWN PROCESS via dynamic import() — one node runtime, not
|
|
10
|
+
* two. Before importing, it replaces process.stderr.write with a tee so every
|
|
11
|
+
* stderr byte the server writes is mirrored to the log sinks; stdin and stdout
|
|
12
|
+
* (the JSON-RPC channel) are never touched.
|
|
13
|
+
*
|
|
14
|
+
* Claude Code CLI → shim (this file) = node running <real-entry> in-process
|
|
15
|
+
* stdin/stdout : untouched (JSON-RPC channel)
|
|
16
|
+
* stderr : process.stderr.write teed → per-date + per-session + passthrough
|
|
17
|
+
*
|
|
18
|
+
* Destinations (Task 706) — unchanged:
|
|
19
|
+
* - `${LOG_DIR}/mcp-<name>-stderr-<date>.log` — per-date raw (back-compat;
|
|
20
|
+
* the in-process mcp-stderr-tee and the [mcp-init-error] probe read it).
|
|
21
|
+
* - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — per-session raw + lifecycle
|
|
22
|
+
* lines. Authoritative sink. Absent when SESSION_ID is unset (enumeration
|
|
23
|
+
* spawn) — then the per-date file is the fallback.
|
|
24
|
+
* - `server.log` via the loopback log-ingest route — best-effort mirror of
|
|
25
|
+
* the [mcp-helper] lifecycle lines.
|
|
26
|
+
*
|
|
27
|
+
* Lifecycle lines, correlation key `session=<id8> server=<name>` — unchanged:
|
|
28
|
+
* [mcp-helper] op=spawn ... pid= entry=
|
|
29
|
+
* [mcp-helper] op=boot ... head=<first stderr bytes>
|
|
30
|
+
* [mcp-helper] op=exit ... code= signal= lifetimeMs= stderr-tail=
|
|
31
|
+
*
|
|
32
|
+
* Process model (Task 989): the shim IS the server's process. op=exit fires
|
|
33
|
+
* from process.on("exit"), so it covers a normal exit, a non-zero exit, an
|
|
34
|
+
* uncaught throw (code 1), and a catchable-signal exit (SIGTERM/SIGINT/SIGHUP,
|
|
35
|
+
* whose handlers record the signal name). An external SIGKILL is uncatchable
|
|
36
|
+
* and leaves no op=exit line — the per-session stderr tail already on disk and
|
|
37
|
+
* Claude Code's own transport-drop are the evidence for that death mode.
|
|
38
|
+
*
|
|
39
|
+
* The shim never writes to fd 1 (stdout) — that is the JSON-RPC channel.
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
const node_fs_1 = require("node:fs");
|
|
43
|
+
const node_path_1 = require("node:path");
|
|
44
|
+
const node_url_1 = require("node:url");
|
|
45
|
+
const SERVER_NAME = process.env.MCP_SPAWN_TEE_NAME ?? "unknown";
|
|
46
|
+
const LOG_DIR = process.env.LOG_DIR;
|
|
47
|
+
const SESSION_ID = process.env.SESSION_ID;
|
|
48
|
+
const PLATFORM_PORT = process.env.PLATFORM_PORT;
|
|
49
|
+
const ENTRY = process.argv[2];
|
|
50
|
+
const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
|
|
51
|
+
const spawnStamp = Date.now();
|
|
52
|
+
// Per-session raw + lifecycle log (Task 706). Empty SESSION_ID (enumeration
|
|
53
|
+
// spawn) → undefined, and the per-date file is the fallback.
|
|
54
|
+
const perSessionPath = LOG_DIR && SESSION_ID
|
|
55
|
+
? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-${SESSION_ID}.log`)
|
|
56
|
+
: undefined;
|
|
57
|
+
const perDatePath = LOG_DIR
|
|
58
|
+
? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-stderr-${new Date(spawnStamp).toISOString().slice(0, 10)}.log`)
|
|
59
|
+
: undefined;
|
|
60
|
+
// Rolling tail of entry stderr for op=exit. Capped so a chatty server cannot
|
|
61
|
+
// grow the buffer without bound.
|
|
62
|
+
const TAIL_CAP = 2048;
|
|
63
|
+
let stderrTail = "";
|
|
64
|
+
let bootEmitted = false;
|
|
65
|
+
let exitEmitted = false;
|
|
66
|
+
let exitSignal;
|
|
67
|
+
// The real stderr writer, captured before the tee replaces it. Lifecycle lines
|
|
68
|
+
// and stderr passthrough both go through this so they are never re-teed into
|
|
69
|
+
// the per-date sink nor recursed back into the patched writer.
|
|
70
|
+
const rawStderrWrite = process.stderr.write.bind(process.stderr);
|
|
71
|
+
// LOG_DIR is created once, lazily, on the first successful append — not per
|
|
72
|
+
// chunk. teeWrite runs on the server's own stderr hot path now, so a per-call
|
|
73
|
+
// mkdirSync would be two syscalls per log line for nothing.
|
|
74
|
+
let logDirReady = false;
|
|
75
|
+
function appendSafe(path, data) {
|
|
76
|
+
if (!path || !LOG_DIR)
|
|
77
|
+
return;
|
|
78
|
+
try {
|
|
79
|
+
if (!logDirReady) {
|
|
80
|
+
(0, node_fs_1.mkdirSync)(LOG_DIR, { recursive: true });
|
|
81
|
+
logDirReady = true;
|
|
82
|
+
}
|
|
83
|
+
(0, node_fs_1.appendFileSync)(path, data);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
/* unwritable destination — never mask primary output */
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Best-effort mirror of a lifecycle line to server.log via the loopback
|
|
90
|
+
// log-ingest route. Fire-and-forget: the per-session file is authoritative, so
|
|
91
|
+
// a dropped POST loses nothing. On the "exit" event the loop is stopping, so
|
|
92
|
+
// the op=exit mirror may not flush — the per-session line, written sync, holds.
|
|
93
|
+
function postToServerLog(suffix, level) {
|
|
94
|
+
if (!PLATFORM_PORT)
|
|
95
|
+
return;
|
|
96
|
+
try {
|
|
97
|
+
const ctrl = new AbortController();
|
|
98
|
+
const t = setTimeout(() => ctrl.abort(), 500);
|
|
99
|
+
t.unref?.(); // never let the abort timer keep the shim's event loop alive
|
|
100
|
+
void fetch(`http://127.0.0.1:${PLATFORM_PORT}/api/admin/log-ingest`, {
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers: { "content-type": "application/json" },
|
|
103
|
+
body: JSON.stringify({ tag: "mcp-helper", level, line: suffix }),
|
|
104
|
+
signal: ctrl.signal,
|
|
105
|
+
}).then(() => clearTimeout(t)).catch(() => clearTimeout(t));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* fetch threw synchronously — best-effort only */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Emit one [mcp-helper] lifecycle line: authoritative per-session file (sync,
|
|
112
|
+
// survives process.exit), the shim's own stderr via the RAW writer (journald /
|
|
113
|
+
// Claude Code visibility, never re-teed), and a best-effort server.log mirror.
|
|
114
|
+
// `suffix` is the line body after the tag and carries no newline (the
|
|
115
|
+
// log-ingest route rejects newlines).
|
|
116
|
+
function emitLifecycle(suffix, level) {
|
|
117
|
+
const line = `[mcp-helper] ${suffix}\n`;
|
|
118
|
+
appendSafe(perSessionPath, line);
|
|
119
|
+
try {
|
|
120
|
+
rawStderrWrite(line);
|
|
121
|
+
}
|
|
122
|
+
catch { /* stderr closed */ }
|
|
123
|
+
postToServerLog(suffix, level);
|
|
124
|
+
}
|
|
125
|
+
if (!ENTRY) {
|
|
126
|
+
emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason="no entry given (argv[2] missing)"`, "error");
|
|
127
|
+
process.exit(2);
|
|
128
|
+
}
|
|
129
|
+
// Replace process.stderr.write with a tee: mirror every server stderr byte to
|
|
130
|
+
// the per-date and per-session sinks, keep a rolling tail for op=exit, emit
|
|
131
|
+
// op=boot on the first bytes, then pass the write through to the real stderr.
|
|
132
|
+
const teeWrite = ((...args) => {
|
|
133
|
+
const chunk = args[0];
|
|
134
|
+
appendSafe(perDatePath, chunk); // per-date raw (back-compat)
|
|
135
|
+
appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
|
|
136
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
137
|
+
stderrTail = (stderrTail + text).slice(-TAIL_CAP);
|
|
138
|
+
if (!bootEmitted) {
|
|
139
|
+
bootEmitted = true;
|
|
140
|
+
const head = text.split("\n")[0].slice(0, 200);
|
|
141
|
+
emitLifecycle(`op=boot session=${SESSION_ID8} server=${SERVER_NAME} head=${JSON.stringify(head)}`, "info");
|
|
142
|
+
}
|
|
143
|
+
return rawStderrWrite(...args); // passthrough
|
|
144
|
+
});
|
|
145
|
+
process.stderr.write = teeWrite;
|
|
146
|
+
// Catchable-signal handling. The shim drives the exit ONLY when it is the sole
|
|
147
|
+
// listener for the signal — i.e. the imported entry installed no handler of its
|
|
148
|
+
// own. In that case it records the signal (so op=exit carries signal=<sig>) and
|
|
149
|
+
// exits with 128+signum, mirroring the prior wrapper's exit-status convention.
|
|
150
|
+
//
|
|
151
|
+
// When the entry DID install a handler, the shim defers entirely and records
|
|
152
|
+
// nothing: the entry's handler decides the exit code, and op=exit reflects that
|
|
153
|
+
// exit verbatim. This matches the prior two-process model, where a child that
|
|
154
|
+
// caught the signal and exited cleanly was observed as code=0 signal=— (a clean
|
|
155
|
+
// self-exit), not as a signal death. Setting exitSignal here unconditionally
|
|
156
|
+
// would mislabel every graceful signal-driven shutdown as a signal kill.
|
|
157
|
+
function onSignal(sig, code) {
|
|
158
|
+
return () => {
|
|
159
|
+
if (process.listenerCount(sig) === 1) {
|
|
160
|
+
exitSignal = sig;
|
|
161
|
+
process.exit(code);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
process.on("SIGTERM", onSignal("SIGTERM", 143));
|
|
166
|
+
process.on("SIGINT", onSignal("SIGINT", 130));
|
|
167
|
+
process.on("SIGHUP", onSignal("SIGHUP", 129));
|
|
168
|
+
// op=exit, emitted once from the process "exit" event. Sync-only — the loop is
|
|
169
|
+
// stopping. When a catchable signal caused the exit, report code=— signal=<sig>
|
|
170
|
+
// to match the prior wrapper's format; otherwise code=<exit code> signal=—.
|
|
171
|
+
process.on("exit", (code) => {
|
|
172
|
+
if (exitEmitted)
|
|
173
|
+
return;
|
|
174
|
+
exitEmitted = true;
|
|
175
|
+
const lifetimeMs = Date.now() - spawnStamp;
|
|
176
|
+
const tail = stderrTail.slice(-200);
|
|
177
|
+
const codeField = exitSignal ? "—" : String(code);
|
|
178
|
+
const level = exitSignal || code !== 0 ? "error" : "info";
|
|
179
|
+
emitLifecycle(`op=exit session=${SESSION_ID8} server=${SERVER_NAME} pid=${process.pid} ` +
|
|
180
|
+
`code=${codeField} signal=${exitSignal ?? "—"} lifetimeMs=${lifetimeMs} stderr-tail=${JSON.stringify(tail)}`, level);
|
|
181
|
+
});
|
|
182
|
+
emitLifecycle(`op=spawn session=${SESSION_ID8} server=${SERVER_NAME} pid=${process.pid} entry=${ENTRY}`, "info");
|
|
183
|
+
// Run the real MCP server in THIS process. Dynamic import() (not top-level
|
|
184
|
+
// await — this file compiles to CommonJS) loads the ESM entry; a load-time
|
|
185
|
+
// failure mirrors the old child spawn-error path (op=error, exit 127). The
|
|
186
|
+
// op=exit handler is suppressed on this path so op=error stays the sole record.
|
|
187
|
+
import((0, node_url_1.pathToFileURL)(ENTRY).href).catch((err) => {
|
|
188
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
189
|
+
exitEmitted = true;
|
|
190
|
+
emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason=${JSON.stringify(`import error: ${msg}`)}`, "error");
|
|
191
|
+
process.exit(127);
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller-scope-headers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/caller-scope-headers.test.ts"],"names":[],"mappings":""}
|