@rubytech/create-maxy-code 0.1.452 → 0.1.454

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/graph-style/dist/index.d.ts +19 -0
  3. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/graph-style/dist/index.js +111 -0
  5. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  6. package/payload/platform/lib/graph-style/src/__tests__/icons.test.ts +63 -0
  7. package/payload/platform/lib/graph-style/src/index.ts +112 -0
  8. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  9. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +6 -4
  10. package/payload/platform/plugins/cloudflare/references/api.md +1 -1
  11. package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +1 -1
  12. package/payload/platform/plugins/docs/references/admin-ui.md +2 -0
  13. package/payload/platform/plugins/docs/references/outlook-guide.md +3 -3
  14. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
  15. package/payload/platform/plugins/outlook/PLUGIN.md +3 -3
  16. package/payload/platform/plugins/outlook/mcp/dist/__tests__/complete-registration.test.d.ts +2 -0
  17. package/payload/platform/plugins/outlook/mcp/dist/__tests__/complete-registration.test.d.ts.map +1 -0
  18. package/payload/platform/plugins/outlook/mcp/dist/__tests__/complete-registration.test.js +131 -0
  19. package/payload/platform/plugins/outlook/mcp/dist/__tests__/complete-registration.test.js.map +1 -0
  20. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-paged.test.d.ts +2 -0
  21. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-paged.test.d.ts.map +1 -0
  22. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-paged.test.js +55 -0
  23. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-paged.test.js.map +1 -0
  24. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list-paging.test.d.ts +2 -0
  25. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list-paging.test.d.ts.map +1 -0
  26. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list-paging.test.js +120 -0
  27. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list-paging.test.js.map +1 -0
  28. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.d.ts +2 -0
  29. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.d.ts.map +1 -0
  30. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.js +66 -0
  31. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-search-paging.test.js.map +1 -0
  32. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-scan.test.d.ts +2 -0
  33. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-scan.test.d.ts.map +1 -0
  34. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-scan.test.js +48 -0
  35. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-scan.test.js.map +1 -0
  36. package/payload/platform/plugins/outlook/mcp/dist/auth/complete-registration.d.ts +31 -0
  37. package/payload/platform/plugins/outlook/mcp/dist/auth/complete-registration.d.ts.map +1 -0
  38. package/payload/platform/plugins/outlook/mcp/dist/auth/complete-registration.js +47 -0
  39. package/payload/platform/plugins/outlook/mcp/dist/auth/complete-registration.js.map +1 -0
  40. package/payload/platform/plugins/outlook/mcp/dist/auth/pending-scan.d.ts +11 -0
  41. package/payload/platform/plugins/outlook/mcp/dist/auth/pending-scan.d.ts.map +1 -0
  42. package/payload/platform/plugins/outlook/mcp/dist/auth/pending-scan.js +31 -0
  43. package/payload/platform/plugins/outlook/mcp/dist/auth/pending-scan.js.map +1 -0
  44. package/payload/platform/plugins/outlook/mcp/dist/index.js +13 -9
  45. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  46. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +19 -0
  47. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -1
  48. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +14 -0
  49. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
  50. package/payload/platform/plugins/outlook/mcp/dist/scripts/complete-registration.d.ts +2 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/scripts/complete-registration.d.ts.map +1 -0
  52. package/payload/platform/plugins/outlook/mcp/dist/scripts/complete-registration.js +111 -0
  53. package/payload/platform/plugins/outlook/mcp/dist/scripts/complete-registration.js.map +1 -0
  54. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +16 -1
  55. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -1
  56. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +37 -7
  57. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -1
  58. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts +12 -1
  59. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -1
  60. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +16 -12
  61. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -1
  62. package/payload/platform/plugins/outlook/references/auth.md +2 -0
  63. package/payload/platform/plugins/outlook/references/graph-surfaces.md +20 -9
  64. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +7 -7
  65. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  66. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +3 -3
  67. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  68. package/payload/platform/scripts/lib/__tests__/account-settings-askgate.test.sh +144 -0
  69. package/payload/platform/scripts/lib/account-settings-askgate.sh +98 -0
  70. package/payload/platform/scripts/setup-account.sh +14 -0
  71. package/payload/platform/scripts/smoke-boot-services.sh +1 -0
  72. package/payload/platform/scripts/voice-mirror-audit.sh +70 -0
  73. package/payload/platform/services/claude-session-manager/dist/config.d.ts +5 -0
  74. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/config.js +7 -1
  76. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/index.js +72 -6
  78. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  79. package/payload/platform/services/claude-session-manager/dist/interactive-wedge.d.ts +17 -0
  80. package/payload/platform/services/claude-session-manager/dist/interactive-wedge.d.ts.map +1 -1
  81. package/payload/platform/services/claude-session-manager/dist/interactive-wedge.js +14 -0
  82. package/payload/platform/services/claude-session-manager/dist/interactive-wedge.js.map +1 -1
  83. package/payload/platform/services/claude-session-manager/dist/plugin-enum.d.ts +34 -0
  84. package/payload/platform/services/claude-session-manager/dist/plugin-enum.d.ts.map +1 -0
  85. package/payload/platform/services/claude-session-manager/dist/plugin-enum.js +66 -0
  86. package/payload/platform/services/claude-session-manager/dist/plugin-enum.js.map +1 -0
  87. package/payload/server/public/assets/{AdminLoginScreens-Bvf4HKmq.js → AdminLoginScreens-5R0A40Is.js} +1 -1
  88. package/payload/server/public/assets/AdminShell-B2HeKInP.js +2 -0
  89. package/payload/server/public/assets/{Checkbox-2SswiICc.js → Checkbox-yjCERU3B.js} +1 -1
  90. package/payload/server/public/assets/{admin-B7GPCzpr.js → admin-BDio0OER.js} +1 -1
  91. package/payload/server/public/assets/{browser-CodHC_MO.js → browser-bSeWXhod.js} +1 -1
  92. package/payload/server/public/assets/{calendar-DH7cyXKF.js → calendar-MNAmsxL3.js} +1 -1
  93. package/payload/server/public/assets/chat-Bq4Uq3Ht.js +1 -0
  94. package/payload/server/public/assets/chevron-left-D5XwUM2x.js +1 -0
  95. package/payload/server/public/assets/data-DY10qHOy.js +1 -0
  96. package/payload/server/public/assets/{graph-BToB78LG.js → graph-DRWRwsUZ.js} +7 -7
  97. package/payload/server/public/assets/graph-labels-Cy7GyGln.js +1 -0
  98. package/payload/server/public/assets/{maximize-2-CEQRv64B.js → maximize-2-BRHW5pKh.js} +1 -1
  99. package/payload/server/public/assets/{operator-Cx8cq2wf.js → operator-Dv2k2JaW.js} +1 -1
  100. package/payload/server/public/assets/{page-TCsQy4eP.js → page-BZRZZcqM.js} +1 -1
  101. package/payload/server/public/assets/{page-D6kzsk18.js → page-CoBzMOIg.js} +2 -2
  102. package/payload/server/public/assets/{public-B61xcmAr.js → public-CirpatD6.js} +1 -1
  103. package/payload/server/public/assets/{rotate-ccw-7_3ol0Z4.js → rotate-ccw-tv1JxnBS.js} +1 -1
  104. package/payload/server/public/assets/{tasks-BY9ajKXf.js → tasks-B8iXIZ3w.js} +1 -1
  105. package/payload/server/public/assets/{time-entry-format-DmNhIJnM.js → time-entry-format-MGC9wMbZ.js} +1 -1
  106. package/payload/server/public/assets/{useCopyFeedback-C5-GOl5l.js → useCopyFeedback-DdwMdpa-.js} +1 -1
  107. package/payload/server/public/assets/{useSelectionMode-UOUVnP9B.js → useSelectionMode-DyoyGg7d.js} +1 -1
  108. package/payload/server/public/assets/useSubAccountSwitcher-CMi8n_8S.css +1 -0
  109. package/payload/server/public/assets/{useVoiceRecorder-BAP3yGxs.js → useVoiceRecorder-BDtJhfh_.js} +1 -1
  110. package/payload/server/public/browser.html +5 -5
  111. package/payload/server/public/calendar.html +6 -6
  112. package/payload/server/public/chat.html +12 -12
  113. package/payload/server/public/data.html +10 -10
  114. package/payload/server/public/graph.html +11 -11
  115. package/payload/server/public/index.html +13 -13
  116. package/payload/server/public/operator.html +14 -14
  117. package/payload/server/public/public.html +12 -12
  118. package/payload/server/public/tasks.html +5 -5
  119. package/payload/server/server.js +219 -22
  120. package/payload/server/public/assets/AdminShell-CaGc8ODG.js +0 -2
  121. package/payload/server/public/assets/chat-BQyPAEMv.js +0 -1
  122. package/payload/server/public/assets/chevron-left-Cmev0R9v.js +0 -1
  123. package/payload/server/public/assets/data-DWxZzMfL.js +0 -1
  124. package/payload/server/public/assets/graph-labels-JRGrstzM.js +0 -1
  125. package/payload/server/public/assets/useSubAccountSwitcher-DgM1ergs.css +0 -1
  126. /package/payload/server/public/assets/{useSubAccountSwitcher-DF6bohQA.js → useSubAccountSwitcher-B_zj_dY-.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.452",
3
+ "version": "0.1.454",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -37,6 +37,25 @@ export declare const EXTERNAL_LABEL_SHAPES: readonly ["dot", "triangle", "square
37
37
  export type GraphNodeShape = (typeof EXTERNAL_LABEL_SHAPES)[number];
38
38
  export declare const FALLBACK_LABEL_SHAPE: GraphNodeShape;
39
39
  export declare function shapeForLabel(label: string): GraphNodeShape;
40
+ /**
41
+ * Inner SVG markup (Lucide glyph) for a label, or null when the label has no
42
+ * registered icon. A null return is the signal the caller renders the fallback
43
+ * dot and logs op=icon-fallback.
44
+ */
45
+ export declare function iconForLabel(label: string): string | null;
46
+ /**
47
+ * A self-contained node image for vis-network's shape:'image' — a filled disc
48
+ * in the label's colour with the Lucide glyph stroked in white on top, encoded
49
+ * as a data:image/svg+xml URI. Returns null when the label has no icon, so the
50
+ * caller falls back to the plain coloured dot.
51
+ *
52
+ * The disc replicates the legend colour; the glyph group re-declares the
53
+ * stroke/fill attributes Lucide's own <svg> wrapper carries (fill:none,
54
+ * stroke:currentColor, width 2, round caps) with color:#fff so both stroked
55
+ * paths and the few fill='currentColor' marks render white. The glyph is scaled
56
+ * to 0.6 and centred so it sits inside the disc with a margin.
57
+ */
58
+ export declare function nodeImageDataUri(label: string): string | null;
40
59
  export interface ResolvedNodeColour {
41
60
  displayLabel: string | null;
42
61
  colour: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA0HtD,CAAA;AAED,eAAO,MAAM,qBAAqB,YAAY,CAAA;AAE9C,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAE7C,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAOzE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAiBD,eAAO,MAAM,qBAAqB,sFAQxB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnE,eAAO,MAAM,oBAAoB,EAAE,cAAsB,CAAA;AAUzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAE3D;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CAU/E;AASD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D;AAED,iEAAiE;AACjE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAsF1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAuD3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA0HtD,CAAA;AAED,eAAO,MAAM,qBAAqB,YAAY,CAAA;AAE9C,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAE7C,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAOzE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAiBD,eAAO,MAAM,qBAAqB,sFAQxB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnE,eAAO,MAAM,oBAAoB,EAAE,cAAsB,CAAA;AAUzD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAE3D;AA6ED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY7D;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CAU/E;AASD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAKD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI7D;AAED,iEAAiE;AACjE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAsF1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAuD3D"}
@@ -23,6 +23,8 @@ exports.FALLBACK_LABEL_SHAPE = exports.EXTERNAL_LABEL_SHAPES = exports.ALL_GRAPH
23
23
  exports.pickDisplayLabel = pickDisplayLabel;
24
24
  exports.colourForLabel = colourForLabel;
25
25
  exports.shapeForLabel = shapeForLabel;
26
+ exports.iconForLabel = iconForLabel;
27
+ exports.nodeImageDataUri = nodeImageDataUri;
26
28
  exports.resolveNodeColour = resolveNodeColour;
27
29
  exports.formatRunTimestamp = formatRunTimestamp;
28
30
  exports.formatMessageTimestamp = formatMessageTimestamp;
@@ -198,6 +200,115 @@ const SHAPE_BY_LABEL = (() => {
198
200
  function shapeForLabel(label) {
199
201
  return SHAPE_BY_LABEL[label] ?? exports.FALLBACK_LABEL_SHAPE;
200
202
  }
203
+ // ---------------------------------------------------------------------------
204
+ // Icon registry — a third visual channel alongside colour + shape.
205
+ //
206
+ // Each label maps to a Lucide glyph so a node's type is legible on the canvas
207
+ // without consulting the legend. The values are the inner SVG markup of the
208
+ // Lucide icon (stroke-based paths on a 0 0 24 24 viewBox), extracted from
209
+ // lucide-react and embedded as literals so this package stays dependency-free
210
+ // and the browser bundle carries only the ~60 glyphs actually used, not all of
211
+ // Lucide. One intentional glyph per label in GRAPH_LABEL_COLOURS; the coverage
212
+ // test in __tests__/icons.test.ts fails if a colour label is added without one.
213
+ const LABEL_ICONS = {
214
+ LocalBusiness: '<path d="M15 21v-5a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v5"></path><path d="M17.774 10.31a1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.451 0 1.12 1.12 0 0 0-1.548 0 2.5 2.5 0 0 1-3.452 0 1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.77-3.248l2.889-4.184A2 2 0 0 1 7 2h10a2 2 0 0 1 1.653.873l2.895 4.192a2.5 2.5 0 0 1-3.774 3.244"></path><path d="M4 10.95V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8.05"></path>',
215
+ Service: '<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"></path>',
216
+ PriceSpecification: '<path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"></path><circle cx="7.5" cy="7.5" r=".5" fill="currentColor"></circle>',
217
+ OpeningHoursSpecification: '<circle cx="12" cy="12" r="10"></circle><path d="M12 6v6l4 2"></path>',
218
+ Listing: '<rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><path d="M12 11h4"></path><path d="M12 16h4"></path><path d="M8 11h.01"></path><path d="M8 16h.01"></path>',
219
+ Property: '<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"></path><path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>',
220
+ Viewing: '<path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path><path d="m9 16 2 2 4-4"></path>',
221
+ Offer: '<path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"></path><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"></path><path d="m2 16 6 6"></path><circle cx="16" cy="9" r="2.9"></circle><circle cx="6" cy="5" r="3"></circle>',
222
+ Job: '<path d="M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path><rect width="20" height="14" x="2" y="6" rx="2"></rect>',
223
+ Quote: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path>',
224
+ Invoice: '<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"></path><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"></path><path d="M12 17.5v-11"></path>',
225
+ InboundInvoice: '<path d="M4 11V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-1"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M2 15h10"></path><path d="m9 18 3-3-3-3"></path>',
226
+ WhatsAppGroup: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><path d="M16 3.128a4 4 0 0 1 0 7.744"></path><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><circle cx="9" cy="7" r="4"></circle>',
227
+ Customer: '<path d="M16 2v2"></path><path d="M7 22v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2"></path><path d="M8 2v2"></path><circle cx="12" cy="11" r="3"></circle><rect x="3" y="4" width="18" height="18" rx="2"></rect>',
228
+ Site: '<path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"></path><circle cx="12" cy="10" r="3"></circle>',
229
+ Asset: '<path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"></path><path d="M12 22V12"></path><polyline points="3.29 7 12 12 20.71 7"></polyline><path d="m7.5 4.27 9 5.15"></path>',
230
+ Visit: '<path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"></path><path d="M15 18H9"></path><path d="M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"></path><circle cx="17" cy="18" r="2"></circle><circle cx="7" cy="18" r="2"></circle>',
231
+ Part: '<path d="M11 10.27 7 3.34"></path><path d="m11 13.73-4 6.93"></path><path d="M12 22v-2"></path><path d="M12 2v2"></path><path d="M14 12h8"></path><path d="m17 20.66-1-1.73"></path><path d="m17 3.34-1 1.73"></path><path d="M2 12h2"></path><path d="m20.66 17-1.73-1"></path><path d="m20.66 7-1.73 1"></path><path d="m3.34 17 1.73-1"></path><path d="m3.34 7 1.73 1"></path><circle cx="12" cy="12" r="2"></circle><circle cx="12" cy="12" r="8"></circle>',
232
+ PurchaseOrder: '<circle cx="8" cy="21" r="1"></circle><circle cx="19" cy="21" r="1"></circle><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"></path>',
233
+ PpmContract: '<path d="m18.226 5.226-2.52-2.52A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-.351"></path><path d="M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"></path><path d="M8 18h1"></path>',
234
+ Note: '<path d="M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z"></path><path d="M15 3v5a1 1 0 0 0 1 1h5"></path>',
235
+ Organization: '<path d="M12 10h.01"></path><path d="M12 14h.01"></path><path d="M12 6h.01"></path><path d="M16 10h.01"></path><path d="M16 14h.01"></path><path d="M16 6h.01"></path><path d="M8 10h.01"></path><path d="M8 14h.01"></path><path d="M8 6h.01"></path><path d="M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3"></path><rect x="4" y="2" width="16" height="20" rx="2"></rect>',
236
+ Person: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle>',
237
+ UserProfile: '<path d="M16 10h2"></path><path d="M16 14h2"></path><path d="M6.17 15a3 3 0 0 1 5.66 0"></path><circle cx="9" cy="11" r="2"></circle><rect x="2" y="5" width="20" height="14" rx="2"></rect>',
238
+ Preference: '<path d="M10 5H3"></path><path d="M12 19H3"></path><path d="M14 3v4"></path><path d="M16 17v4"></path><path d="M21 12h-9"></path><path d="M21 19h-5"></path><path d="M21 5h-7"></path><path d="M8 10v4"></path><path d="M8 12H3"></path>',
239
+ AdminUser: '<path d="M10 15H6a4 4 0 0 0-4 4v2"></path><path d="m14.305 16.53.923-.382"></path><path d="m15.228 13.852-.923-.383"></path><path d="m16.852 12.228-.383-.923"></path><path d="m16.852 17.772-.383.924"></path><path d="m19.148 12.228.383-.923"></path><path d="m19.53 18.696-.382-.924"></path><path d="m20.772 13.852.924-.383"></path><path d="m20.772 16.148.924.383"></path><circle cx="18" cy="15" r="3"></circle><circle cx="9" cy="7" r="4"></circle>',
240
+ AccessGrant: '<path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle>',
241
+ KnowledgeDocument: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path>',
242
+ ConversationArchive: '<rect width="20" height="5" x="2" y="3" rx="1"></rect><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"></path><path d="M10 12h4"></path>',
243
+ Section: '<rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M21 9H3"></path><path d="M21 15H3"></path>',
244
+ Chunk: '<path d="M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"></path>',
245
+ DigitalDocument: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path>',
246
+ CreativeWork: '<path d="M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z"></path><path d="m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18"></path><path d="m2.3 2.3 7.286 7.286"></path><circle cx="11" cy="11" r="2"></circle>',
247
+ Question: '<circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><path d="M12 17h.01"></path>',
248
+ FAQPage: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><path d="M12 17h.01"></path>',
249
+ DefinedTerm: '<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"></path><path d="m8 13 4-7 4 7"></path><path d="M9.1 11h5.7"></path>',
250
+ Review: '<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"></path>',
251
+ ImageObject: '<rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>',
252
+ Conversation: '<path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"></path>',
253
+ AdminConversation: '<path d="M22 8.5V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v16.286a.71.71 0 0 0 1.212.502l2.202-2.202A2 2 0 0 1 6.828 19H10"></path><path d="M20 15v-2a2 2 0 0 0-4 0v2"></path><rect x="14" y="15" width="8" height="5" rx="1"></rect>',
254
+ PublicConversation: '<path d="M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path><path d="M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"></path>',
255
+ Message: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>',
256
+ UserMessage: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>',
257
+ AssistantMessage: '<path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>',
258
+ ToolCall: '<path d="M12 19h8"></path><path d="m4 17 6-6-6-6"></path>',
259
+ Task: '<rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="m9 12 2 2 4-4"></path>',
260
+ Project: '<path d="M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"></path><path d="M8 10v4"></path><path d="M12 10v2"></path><path d="M16 10v6"></path>',
261
+ Event: '<path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path>',
262
+ Workflow: '<rect width="8" height="8" x="3" y="3" rx="2"></rect><path d="M7 11v4a2 2 0 0 0 2 2h4"></path><rect width="8" height="8" x="13" y="13" rx="2"></rect>',
263
+ WorkflowStep: '<path d="M13 5h8"></path><path d="M13 12h8"></path><path d="M13 19h8"></path><path d="m3 17 2 2 4-4"></path><path d="m3 7 2 2 4-4"></path>',
264
+ WorkflowRun: '<path d="M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z"></path><circle cx="12" cy="12" r="10"></circle>',
265
+ StepResult: '<circle cx="12" cy="12" r="10"></circle><path d="m9 12 2 2 4-4"></path>',
266
+ Email: '<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>',
267
+ EmailAccount: '<circle cx="12" cy="12" r="4"></circle><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"></path>',
268
+ Agent: '<path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>',
269
+ Objective: '<circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="6"></circle><circle cx="12" cy="12" r="2"></circle>',
270
+ KeyResult: '<path d="M16 7h6v6"></path><path d="m22 7-8.5 8.5-5-5L2 17"></path>',
271
+ Decision: '<circle cx="12" cy="18" r="3"></circle><circle cx="6" cy="6" r="3"></circle><circle cx="18" cy="6" r="3"></circle><path d="M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9"></path><path d="M12 12v3"></path>',
272
+ Risk: '<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path>',
273
+ Source: '<path d="M12 7v14"></path><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"></path>',
274
+ Finding: '<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"></path><path d="M9 18h6"></path><path d="M10 22h4"></path>',
275
+ Hypothesis: '<path d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"></path><path d="M6.453 15h11.094"></path><path d="M8.5 2h7"></path>',
276
+ };
277
+ /**
278
+ * Inner SVG markup (Lucide glyph) for a label, or null when the label has no
279
+ * registered icon. A null return is the signal the caller renders the fallback
280
+ * dot and logs op=icon-fallback.
281
+ */
282
+ function iconForLabel(label) {
283
+ return Object.prototype.hasOwnProperty.call(LABEL_ICONS, label)
284
+ ? LABEL_ICONS[label]
285
+ : null;
286
+ }
287
+ /**
288
+ * A self-contained node image for vis-network's shape:'image' — a filled disc
289
+ * in the label's colour with the Lucide glyph stroked in white on top, encoded
290
+ * as a data:image/svg+xml URI. Returns null when the label has no icon, so the
291
+ * caller falls back to the plain coloured dot.
292
+ *
293
+ * The disc replicates the legend colour; the glyph group re-declares the
294
+ * stroke/fill attributes Lucide's own <svg> wrapper carries (fill:none,
295
+ * stroke:currentColor, width 2, round caps) with color:#fff so both stroked
296
+ * paths and the few fill='currentColor' marks render white. The glyph is scaled
297
+ * to 0.6 and centred so it sits inside the disc with a margin.
298
+ */
299
+ function nodeImageDataUri(label) {
300
+ const inner = iconForLabel(label);
301
+ if (inner === null)
302
+ return null;
303
+ const colour = colourForLabel(label);
304
+ const svg = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'>" +
305
+ "<circle cx='12' cy='12' r='12' fill='" + colour + "'/>" +
306
+ "<g transform='translate(4.8 4.8) scale(0.6)' fill='none' stroke='#fff'" +
307
+ " stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' color='#fff'>" +
308
+ inner +
309
+ "</g></svg>";
310
+ return "data:image/svg+xml," + encodeURIComponent(svg);
311
+ }
201
312
  /**
202
313
  * Single-source colour resolver. driftCandidates counts registered
203
314
  * sublabels in labels[1..]; a node with two registered sublabels has
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Coverage + shape gate for the node icon registry (Task 1681). The coverage
3
+ * case is the standing guard the task's Observability section names: it fails
4
+ * the moment a colour label is added without an intentional Lucide glyph, so a
5
+ * new node type can never silently ship as the fallback dot.
6
+ */
7
+
8
+ import { describe, it, expect } from "vitest";
9
+ import {
10
+ ALL_GRAPH_LABELS,
11
+ GRAPH_LABEL_COLOURS,
12
+ iconForLabel,
13
+ nodeImageDataUri,
14
+ } from "../index.js";
15
+
16
+ describe("icon registry coverage", () => {
17
+ it("maps every colour label to an intentional glyph", () => {
18
+ const missing = ALL_GRAPH_LABELS.filter((l) => iconForLabel(l) === null);
19
+ expect(missing).toEqual([]);
20
+ });
21
+
22
+ it("returns null for an unregistered label", () => {
23
+ expect(iconForLabel("NoSuchLabel")).toBeNull();
24
+ });
25
+
26
+ it("every glyph is stroke-based inner SVG markup", () => {
27
+ for (const label of ALL_GRAPH_LABELS) {
28
+ const svg = iconForLabel(label);
29
+ expect(svg, label).toMatch(/<(path|circle|rect|line|polyline)\b/);
30
+ // inner markup only — no wrapping <svg> element
31
+ expect(svg, label).not.toMatch(/<svg/);
32
+ }
33
+ });
34
+ });
35
+
36
+ describe("nodeImageDataUri", () => {
37
+ it("builds a data URI carrying the label colour and its glyph", () => {
38
+ const uri = nodeImageDataUri("Person");
39
+ expect(uri).not.toBeNull();
40
+ expect(uri!.startsWith("data:image/svg+xml,")).toBe(true);
41
+ const decoded = decodeURIComponent(uri!.slice("data:image/svg+xml,".length));
42
+ // the disc carries the registry colour for the label
43
+ expect(decoded).toContain(GRAPH_LABEL_COLOURS.Person);
44
+ // the glyph is stroked white on top
45
+ expect(decoded).toContain("stroke='#fff'");
46
+ // Person's Lucide glyph includes a circle (the head)
47
+ expect(decoded).toContain("<circle");
48
+ // the wrapper is a single well-formed svg with one disc
49
+ expect((decoded.match(/<svg/g) || []).length).toBe(1);
50
+ });
51
+
52
+ it("uses the resolved colour, distinct per label", () => {
53
+ const person = nodeImageDataUri("Person")!;
54
+ const property = nodeImageDataUri("Property")!;
55
+ expect(decodeURIComponent(person)).toContain(GRAPH_LABEL_COLOURS.Person);
56
+ expect(decodeURIComponent(property)).toContain(GRAPH_LABEL_COLOURS.Property);
57
+ expect(person).not.toEqual(property);
58
+ });
59
+
60
+ it("returns null for an unregistered label", () => {
61
+ expect(nodeImageDataUri("NoSuchLabel")).toBeNull();
62
+ });
63
+ });
@@ -213,6 +213,118 @@ export function shapeForLabel(label: string): GraphNodeShape {
213
213
  return SHAPE_BY_LABEL[label] ?? FALLBACK_LABEL_SHAPE
214
214
  }
215
215
 
216
+ // ---------------------------------------------------------------------------
217
+ // Icon registry — a third visual channel alongside colour + shape.
218
+ //
219
+ // Each label maps to a Lucide glyph so a node's type is legible on the canvas
220
+ // without consulting the legend. The values are the inner SVG markup of the
221
+ // Lucide icon (stroke-based paths on a 0 0 24 24 viewBox), extracted from
222
+ // lucide-react and embedded as literals so this package stays dependency-free
223
+ // and the browser bundle carries only the ~60 glyphs actually used, not all of
224
+ // Lucide. One intentional glyph per label in GRAPH_LABEL_COLOURS; the coverage
225
+ // test in __tests__/icons.test.ts fails if a colour label is added without one.
226
+ const LABEL_ICONS: Record<string, string> = {
227
+ LocalBusiness: '<path d="M15 21v-5a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v5"></path><path d="M17.774 10.31a1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.451 0 1.12 1.12 0 0 0-1.548 0 2.5 2.5 0 0 1-3.452 0 1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.77-3.248l2.889-4.184A2 2 0 0 1 7 2h10a2 2 0 0 1 1.653.873l2.895 4.192a2.5 2.5 0 0 1-3.774 3.244"></path><path d="M4 10.95V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8.05"></path>',
228
+ Service: '<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"></path>',
229
+ PriceSpecification: '<path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"></path><circle cx="7.5" cy="7.5" r=".5" fill="currentColor"></circle>',
230
+ OpeningHoursSpecification: '<circle cx="12" cy="12" r="10"></circle><path d="M12 6v6l4 2"></path>',
231
+ Listing: '<rect width="8" height="4" x="8" y="2" rx="1" ry="1"></rect><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><path d="M12 11h4"></path><path d="M12 16h4"></path><path d="M8 11h.01"></path><path d="M8 16h.01"></path>',
232
+ Property: '<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"></path><path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>',
233
+ Viewing: '<path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path><path d="m9 16 2 2 4-4"></path>',
234
+ Offer: '<path d="M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"></path><path d="m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"></path><path d="m2 16 6 6"></path><circle cx="16" cy="9" r="2.9"></circle><circle cx="6" cy="5" r="3"></circle>',
235
+ Job: '<path d="M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"></path><rect width="20" height="14" x="2" y="6" rx="2"></rect>',
236
+ Quote: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path>',
237
+ Invoice: '<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"></path><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"></path><path d="M12 17.5v-11"></path>',
238
+ InboundInvoice: '<path d="M4 11V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-1"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M2 15h10"></path><path d="m9 18 3-3-3-3"></path>',
239
+ WhatsAppGroup: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><path d="M16 3.128a4 4 0 0 1 0 7.744"></path><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><circle cx="9" cy="7" r="4"></circle>',
240
+ Customer: '<path d="M16 2v2"></path><path d="M7 22v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2"></path><path d="M8 2v2"></path><circle cx="12" cy="11" r="3"></circle><rect x="3" y="4" width="18" height="18" rx="2"></rect>',
241
+ Site: '<path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"></path><circle cx="12" cy="10" r="3"></circle>',
242
+ Asset: '<path d="M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z"></path><path d="M12 22V12"></path><polyline points="3.29 7 12 12 20.71 7"></polyline><path d="m7.5 4.27 9 5.15"></path>',
243
+ Visit: '<path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"></path><path d="M15 18H9"></path><path d="M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"></path><circle cx="17" cy="18" r="2"></circle><circle cx="7" cy="18" r="2"></circle>',
244
+ Part: '<path d="M11 10.27 7 3.34"></path><path d="m11 13.73-4 6.93"></path><path d="M12 22v-2"></path><path d="M12 2v2"></path><path d="M14 12h8"></path><path d="m17 20.66-1-1.73"></path><path d="m17 3.34-1 1.73"></path><path d="M2 12h2"></path><path d="m20.66 17-1.73-1"></path><path d="m20.66 7-1.73 1"></path><path d="m3.34 17 1.73-1"></path><path d="m3.34 7 1.73 1"></path><circle cx="12" cy="12" r="2"></circle><circle cx="12" cy="12" r="8"></circle>',
245
+ PurchaseOrder: '<circle cx="8" cy="21" r="1"></circle><circle cx="19" cy="21" r="1"></circle><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"></path>',
246
+ PpmContract: '<path d="m18.226 5.226-2.52-2.52A2.4 2.4 0 0 0 14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-.351"></path><path d="M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"></path><path d="M8 18h1"></path>',
247
+ Note: '<path d="M21 9a2.4 2.4 0 0 0-.706-1.706l-3.588-3.588A2.4 2.4 0 0 0 15 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2z"></path><path d="M15 3v5a1 1 0 0 0 1 1h5"></path>',
248
+ Organization: '<path d="M12 10h.01"></path><path d="M12 14h.01"></path><path d="M12 6h.01"></path><path d="M16 10h.01"></path><path d="M16 14h.01"></path><path d="M16 6h.01"></path><path d="M8 10h.01"></path><path d="M8 14h.01"></path><path d="M8 6h.01"></path><path d="M9 22v-3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3"></path><rect x="4" y="2" width="16" height="20" rx="2"></rect>',
249
+ Person: '<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle>',
250
+ UserProfile: '<path d="M16 10h2"></path><path d="M16 14h2"></path><path d="M6.17 15a3 3 0 0 1 5.66 0"></path><circle cx="9" cy="11" r="2"></circle><rect x="2" y="5" width="20" height="14" rx="2"></rect>',
251
+ Preference: '<path d="M10 5H3"></path><path d="M12 19H3"></path><path d="M14 3v4"></path><path d="M16 17v4"></path><path d="M21 12h-9"></path><path d="M21 19h-5"></path><path d="M21 5h-7"></path><path d="M8 10v4"></path><path d="M8 12H3"></path>',
252
+ AdminUser: '<path d="M10 15H6a4 4 0 0 0-4 4v2"></path><path d="m14.305 16.53.923-.382"></path><path d="m15.228 13.852-.923-.383"></path><path d="m16.852 12.228-.383-.923"></path><path d="m16.852 17.772-.383.924"></path><path d="m19.148 12.228.383-.923"></path><path d="m19.53 18.696-.382-.924"></path><path d="m20.772 13.852.924-.383"></path><path d="m20.772 16.148.924.383"></path><circle cx="18" cy="15" r="3"></circle><circle cx="9" cy="7" r="4"></circle>',
253
+ AccessGrant: '<path d="M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"></path><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"></circle>',
254
+ KnowledgeDocument: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path><path d="M10 9H8"></path><path d="M16 13H8"></path><path d="M16 17H8"></path>',
255
+ ConversationArchive: '<rect width="20" height="5" x="2" y="3" rx="1"></rect><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"></path><path d="M10 12h4"></path>',
256
+ Section: '<rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M21 9H3"></path><path d="M21 15H3"></path>',
257
+ Chunk: '<path d="M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"></path>',
258
+ DigitalDocument: '<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"></path><path d="M14 2v5a1 1 0 0 0 1 1h5"></path>',
259
+ CreativeWork: '<path d="M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z"></path><path d="m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18"></path><path d="m2.3 2.3 7.286 7.286"></path><circle cx="11" cy="11" r="2"></circle>',
260
+ Question: '<circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><path d="M12 17h.01"></path>',
261
+ FAQPage: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><path d="M12 17h.01"></path>',
262
+ DefinedTerm: '<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"></path><path d="m8 13 4-7 4 7"></path><path d="M9.1 11h5.7"></path>',
263
+ Review: '<path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"></path>',
264
+ ImageObject: '<rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><circle cx="9" cy="9" r="2"></circle><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>',
265
+ Conversation: '<path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"></path>',
266
+ AdminConversation: '<path d="M22 8.5V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v16.286a.71.71 0 0 0 1.212.502l2.202-2.202A2 2 0 0 1 6.828 19H10"></path><path d="M20 15v-2a2 2 0 0 0-4 0v2"></path><rect x="14" y="15" width="8" height="5" rx="1"></rect>',
267
+ PublicConversation: '<path d="M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path><path d="M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"></path>',
268
+ Message: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>',
269
+ UserMessage: '<path d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"></path>',
270
+ AssistantMessage: '<path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>',
271
+ ToolCall: '<path d="M12 19h8"></path><path d="m4 17 6-6-6-6"></path>',
272
+ Task: '<rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="m9 12 2 2 4-4"></path>',
273
+ Project: '<path d="M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"></path><path d="M8 10v4"></path><path d="M12 10v2"></path><path d="M16 10v6"></path>',
274
+ Event: '<path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path>',
275
+ Workflow: '<rect width="8" height="8" x="3" y="3" rx="2"></rect><path d="M7 11v4a2 2 0 0 0 2 2h4"></path><rect width="8" height="8" x="13" y="13" rx="2"></rect>',
276
+ WorkflowStep: '<path d="M13 5h8"></path><path d="M13 12h8"></path><path d="M13 19h8"></path><path d="m3 17 2 2 4-4"></path><path d="m3 7 2 2 4-4"></path>',
277
+ WorkflowRun: '<path d="M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z"></path><circle cx="12" cy="12" r="10"></circle>',
278
+ StepResult: '<circle cx="12" cy="12" r="10"></circle><path d="m9 12 2 2 4-4"></path>',
279
+ Email: '<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7"></path><rect x="2" y="4" width="20" height="16" rx="2"></rect>',
280
+ EmailAccount: '<circle cx="12" cy="12" r="4"></circle><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"></path>',
281
+ Agent: '<path d="M12 8V4H8"></path><rect width="16" height="12" x="4" y="8" rx="2"></rect><path d="M2 14h2"></path><path d="M20 14h2"></path><path d="M15 13v2"></path><path d="M9 13v2"></path>',
282
+ Objective: '<circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="6"></circle><circle cx="12" cy="12" r="2"></circle>',
283
+ KeyResult: '<path d="M16 7h6v6"></path><path d="m22 7-8.5 8.5-5-5L2 17"></path>',
284
+ Decision: '<circle cx="12" cy="18" r="3"></circle><circle cx="6" cy="6" r="3"></circle><circle cx="18" cy="6" r="3"></circle><path d="M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9"></path><path d="M12 12v3"></path>',
285
+ Risk: '<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path>',
286
+ Source: '<path d="M12 7v14"></path><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"></path>',
287
+ Finding: '<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"></path><path d="M9 18h6"></path><path d="M10 22h4"></path>',
288
+ Hypothesis: '<path d="M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2"></path><path d="M6.453 15h11.094"></path><path d="M8.5 2h7"></path>',
289
+ }
290
+
291
+ /**
292
+ * Inner SVG markup (Lucide glyph) for a label, or null when the label has no
293
+ * registered icon. A null return is the signal the caller renders the fallback
294
+ * dot and logs op=icon-fallback.
295
+ */
296
+ export function iconForLabel(label: string): string | null {
297
+ return Object.prototype.hasOwnProperty.call(LABEL_ICONS, label)
298
+ ? LABEL_ICONS[label]
299
+ : null
300
+ }
301
+
302
+ /**
303
+ * A self-contained node image for vis-network's shape:'image' — a filled disc
304
+ * in the label's colour with the Lucide glyph stroked in white on top, encoded
305
+ * as a data:image/svg+xml URI. Returns null when the label has no icon, so the
306
+ * caller falls back to the plain coloured dot.
307
+ *
308
+ * The disc replicates the legend colour; the glyph group re-declares the
309
+ * stroke/fill attributes Lucide's own <svg> wrapper carries (fill:none,
310
+ * stroke:currentColor, width 2, round caps) with color:#fff so both stroked
311
+ * paths and the few fill='currentColor' marks render white. The glyph is scaled
312
+ * to 0.6 and centred so it sits inside the disc with a margin.
313
+ */
314
+ export function nodeImageDataUri(label: string): string | null {
315
+ const inner = iconForLabel(label)
316
+ if (inner === null) return null
317
+ const colour = colourForLabel(label)
318
+ const svg =
319
+ "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'>" +
320
+ "<circle cx='12' cy='12' r='12' fill='" + colour + "'/>" +
321
+ "<g transform='translate(4.8 4.8) scale(0.6)' fill='none' stroke='#fff'" +
322
+ " stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round' color='#fff'>" +
323
+ inner +
324
+ "</g></svg>"
325
+ return "data:image/svg+xml," + encodeURIComponent(svg)
326
+ }
327
+
216
328
  export interface ResolvedNodeColour {
217
329
  displayLabel: string | null
218
330
  colour: string
@@ -183,7 +183,7 @@ Tools are available via the `admin` MCP server.
183
183
  - `hooks/quote-render-gate.sh` — **PreToolUse matcher=`mcp__plugin_browser_browser__browser-pdf-save`.** Makes the deterministic quote-render path the only route a client-facing quote PDF can reach a customer. Blocks (exit 2) a `browser-pdf-save` whose output path is a client-quote artefact (`memory/users/<phone>/documents/quote-<jobId>.pdf` or `…-breakdown.pdf`) when no render receipt exists at `quoting/jobs/<jobId>/render-receipt.json` — the receipt `quote-render` writes only after its reconcile / margin-leak / link-liveness gates all pass. A hand-authored quote (the SiteDesk 2026-07-14 bypass: `Write` HTML → `browser-pdf-save`, `quote-render` never called, an internal back-test caveat naming another client folded into the free-text region) has no receipt, so the print is refused rather than delivered. **Block message:** `Blocked: this client quote was not produced by the quote-render tool, so its fixed layout and the reconcile, margin-leak and link-liveness gates never ran. Run quote-render for this job (it files the document and its receipt), then print the client HTML path it returns to PDF.` **Log line** (stderr, on a block): `[quote-render] op=bypass jobId=<jobId> detail=client quote PDF has no render receipt` (or `reason=bad-jobid` when the filename does not resolve to a job). Every non-quote PDF — brochures, invoices, the admin-scope internal view — and the deterministic path itself (receipt present) pass at exit 0. **Fail-open** on an uninspectable call (tty / empty stdin / no `python3`): `browser-pdf-save` is a general-purpose tool and the agent never controls this hook's stdin, so failing open opens no bypass while never bricking unrelated PDFs.
184
184
  - `hooks/webfetch-preflight.mjs` — short-circuits WebFetch on JS-SPA shells with a structured `WEBFETCH_CANNOT_READ_JS_SPA` error so the agent surfaces a loud failure to the owner instead of paying the 60s extraction timeout. Fail-open on any internal error.
185
185
  - `hooks/askuserquestion-investigate-gate.sh` — PreToolUse matcher=`AskUserQuestion`. Blocks the question (exit 2) when no read-only investigation tool has fired since the latest real user turn in the session JSONL. The structural fix for the failure class where the agent fabricates a menu before evidence-gathering (session `c085ec2c-46fb-4b73-8865-68cf85866ea8` 2026-05-22 — "change remote access password" → invented options "Admin PIN / Cloudflare tunnel / WiFi password" with zero prior tool_use; post-correction the agent immediately fired `remote-auth-status` → `ToolSearch` → `remote-auth-set-password`, proving it knew the moves). **Allowlist** (exact, with trailing `__<tool>` suffix-match for namespaced `mcp__plugin_<plugin>_<server>__<tool>` aliases): `ToolSearch`, `Grep`, `Glob`, `Read`, `LS`, `NotebookRead`, `Bash`, `WebFetch`, `WebSearch`, plus the read-only admin / memory MCP tools (`*-status`, `*-list`, `*-read`, `skill-find`, `memory-find-candidates`, `profile-read`, `conversation-list`, `memory-list-attachments`, `memory-read-attachment`). **Block message:** `Blocked: AskUserQuestion requires at least one investigation tool (ToolSearch, Grep, Read, *-list, *-status, *-read, skill-find, ...) earlier in this turn. Search the operator's literal phrase first.` **Log line** (stderr, one per call): `[ask-gate] decision=<allow|block> sessionId=<id8> seen=<csv|-> reason=<allowlist-hit|no-investigation|fail-open-no-transcript|fail-open-parse-error>`. **Fail-open** on missing transcript or parse error — nudges, never bricks the UI.
186
- - `hooks/askuserquestion-channel-carrier-gate.sh` — PreToolUse matcher=`AskUserQuestion`, registered as a **second command on the same matcher** as the investigate-gate (either exit 2 blocks; the two guard different conditions). Blocks the question (exit 2) when the session has a native channel attached, because the Claude Code channel protocol carries only the two permission methods — there is no carrier for the `AskUserQuestion` elicitation, so on an rc-spawn channel (webchat/WhatsApp/Telegram) session the harness would block the turn awaiting a selection that can never arrive and the reader renders only delivered replies, wedging the turn (live SiteDesk incident session `1a085718` 2026-07-11: `/chat` stalled on the delivered "On it…" ack with no card). **Signal:** the rc-spawn writes the channel MCP registration as a config file in `os.tmpdir()` keyed by session id (`maxy-channel-<sid>.json` / `maxy-webchat-channel-<sid>.json` / `maxy-wa-channel-<sid>.json` / `maxy-telegram-channel-<sid>.json`, `sid` sanitized `[^A-Za-z0-9_-]→_` exactly as the writers do); its presence at tool-call time is the authoritative "channel attached to this session" marker. The hook resolves the tmpdir the way Node's `os.tmpdir()` does (`${TMPDIR:-/tmp}`, trailing slash stripped). Correct in both readings of the claude.ai/code scoping question: a Pi channel process sees the tmpfile (block); a claude.ai/code process on another host never sees the Pi tmpfile (fail-open → allow, that surface can answer the card). **Block message:** `Blocked: this is a native-channel session and AskUserQuestion cannot be delivered over a channel (the channel protocol carries no elicitation card, so the turn would wedge). Ask the same question as prose in your channel reply tool and wait for the operator's next message.` **Log line** (stderr, one per decisive call): `[ask-channel] decision=<allow|block> sessionId=<id8> channel=<attached|none> reason=<channel-attached|no-channel|fail-open-no-envelope|fail-open-no-session>`. **Fail-open** on no envelope, blank session id, or absent channel file — nudges, never bricks the UI. The complementary standing check (`interactive-wedge` in the session manager) catches any un-carried interactive tool_use that slips past this hook.
186
+ - `hooks/askuserquestion-channel-carrier-gate.sh` — PreToolUse matcher=`AskUserQuestion`, registered as a **second command on the same matcher** as the investigate-gate (either exit 2 blocks; the two guard different conditions). Blocks the question (exit 2) when the session has a native channel attached, because the Claude Code channel protocol carries only the two permission methods — there is no carrier for the `AskUserQuestion` elicitation, so on an rc-spawn channel (webchat/WhatsApp/Telegram) session the harness would block the turn awaiting a selection that can never arrive and the reader renders only delivered replies, wedging the turn (live SiteDesk incident session `1a085718` 2026-07-11: `/chat` stalled on the delivered "On it…" ack with no card). **Signal:** the rc-spawn writes the channel MCP registration as a config file in `os.tmpdir()` keyed by session id (`maxy-channel-<sid>.json` / `maxy-webchat-channel-<sid>.json` / `maxy-wa-channel-<sid>.json` / `maxy-telegram-channel-<sid>.json`, `sid` sanitized `[^A-Za-z0-9_-]→_` exactly as the writers do); its presence at tool-call time is the authoritative "channel attached to this session" marker. The hook resolves the tmpdir the way Node's `os.tmpdir()` does (`${TMPDIR:-/tmp}`, trailing slash stripped). Correct in both readings of the claude.ai/code scoping question: a Pi channel process sees the tmpfile (block); a claude.ai/code process on another host never sees the Pi tmpfile (fail-open → allow, that surface can answer the card). **Block message:** `Blocked: this is a native-channel session and AskUserQuestion cannot be delivered over a channel (the channel protocol carries no elicitation card, so the turn would wedge). Ask the same question as prose in your channel reply tool and wait for the operator's next message.` **Log line** (stderr, one per decisive call): `[ask-channel] decision=<allow|block> sessionId=<id8> channel=<attached|none> reason=<channel-attached|no-channel|fail-open-no-envelope|fail-open-no-session>`. **Fail-open** on no envelope, blank session id, or absent channel file — nudges, never bricks the UI. The complementary standing check (`interactive-wedge` in the session manager) catches any un-carried interactive tool_use that slips past this hook; it scans every account's project-slug (not just the boot slug), so a client sub-account channel wedge is covered too. **Reach on upgrade:** `provision-account-dir.sh` writes this matcher only at account-provision time, and the upgrade path re-provisions only the house account — so an account provisioned before this gate landed keeps a stale matcher and re-wedges (live SiteDesk recurrence session `d39a22b0`, account `2078cb54`, 2026-07-15). `setup-account.sh` runs `reconcile_all_accounts_askgate` (`platform/scripts/lib/account-settings-askgate.sh`) on every install to retrofit the carrier gate onto every existing account's `settings.json` — idempotent surgical jq patch of the `AskUserQuestion` matcher, one `[backfill-1683] file=<f> status=<absent|no-hooks|already-set|updated|rewrite-failed>` line per account, contents never echoed.
187
187
  - `hooks/mcp-tool-missing.sh` — **PostToolUse hook on `mcp__.*` (directive 3).** Defence-in-depth for the `No such tool available: mcp__…` failure class that the name-binding is built to eliminate. Fires on any MCP tool call; no-op unless the `tool_response` carries `No such tool available` AND the qualified name resolves to a maxy plugin (read from the generated `hooks/lib/maxy-mcp-plugins.txt`). On a maxy match it logs one deterministic `[mcp-tool-missing] server=<server> tool=<tool>` line and exits 2 with a fixed envelope on stderr, so the agent relays a named server-unavailable failure instead of narrating "warming up" or blind-retrying. A missing non-maxy bridge tool (Playwright etc., upstream-owned) passes through (exit 0). The maxy-plugin list is regenerated and gate-diffed by `platform/scripts/check-canonical-tool-names.mjs`.
188
188
  - `hooks/post-tool-use-agent.sh` — **PostToolUse hook on `Agent`.** Drains any subagent hook-decision buffers under `~/.maxy-code/logs/hook-decisions/` modified since this parent's previous PostToolUse-Agent fire (cursor file keyed by parent session id), prints one `[hook-propagate]` line per record to stdout — Claude Code attaches the stdout as a `hook_success` attachment on the parent JSONL, making the records grep-queryable from the parent session alone. Rotates consumed buffers to `consumed/`. Emits one `[hook-propagate-census] parentSession=<…> subagentHooksObserved=<N> attachmentsEmitted=<M>` line per fire to stdout and server.log; `N != M` is the propagation regression signal. The companion emitter library `hooks/lib/hook-emit.sh` is sourced by `post-tool-use-agent.sh` and any other hook that records a block decision (4 KB stderr truncation, `truncated=true` set on the record).
189
189
  - `hooks/admin-authoring-observer.sh` — **PostToolUse hook on Write and Edit.** Observation only — never blocks; exits 0 on every path. Fires when the admin agent (not a specialist subagent — gated by `MAXY_SPECIALIST` env) writes or edits a file under `<accountDir>/output/`. Walks the session transcript from the latest real-user turn forward to detect any prior `Task` `tool_use` whose `subagent_type` starts with `specialists:`. Emits one stderr line `[admin-authoring] inline-write path=<rel> priorSpecialistSpawnInTurn=<true|false|unknown>`. A `false` value on a long-form prose file is the regression signal this hook was designed to make visible — the BioSymm proposal session (admin authored a customer-facing proposal inline despite content-producer being installed) is the failure mode this surfaces mechanically. Mechanical enforcement (refuse the write, force a re-spawn) is deferred per the task spec.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:c170bc722cc54b4882abbe20267c10b8b007ace08d916b4e857ce0868f3769cb
4
+ content-hash: sha256:c15158cff845df71cc5a5367859498af9847ea1040561c21a7b7b01e1596614f
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -2044,7 +2044,7 @@ The `outlook` plugin gives the admin agent access to Microsoft 365 / Outlook.com
2044
2044
 
2045
2045
  1. **No app to register.** The client ID ships with the brand (`brand.json#outlookClientId`), and the installer stamps it onto the session-manager env, so there is zero operator Azure work. On a brand that ships an empty value the plugin stays inert until its vendor app exists — see `platform/plugins/outlook/references/auth.md` for the one-time-per-brand vendor provisioning runbook (a vendor step, not an operator or end-user step), including setting **Allow public client flows** to Yes.
2046
2046
  2. **Per account: register the Outlook account** — in admin chat, ask the agent to "register my Outlook account". The agent runs `outlook-account-register`, which returns a short user code and the URL `microsoft.com/devicelogin` and relays both to you.
2047
- 3. **Consent on any device** — open `microsoft.com/devicelogin` on your phone or laptop, enter the code, sign in to your Microsoft account, and consent to the requested scopes (`offline_access`, `User.Read`, `Mail.ReadWrite`, `Mail.Send`, `Calendars.ReadWrite`, `Contacts.Read`). `Mail.Send` enables sending and `Calendars.ReadWrite` enables calendar control; a mailbox last consented on an older read-only scope set must re-register before send or any calendar write succeeds. The agent finishes by calling `outlook-account-register-poll`.
2047
+ 3. **Consent on any device** — open `microsoft.com/devicelogin` on your phone or laptop, enter the code, sign in to your Microsoft account, and consent to the requested scopes (`offline_access`, `User.Read`, `Mail.ReadWrite`, `Mail.Send`, `Calendars.ReadWrite`, `Contacts.Read`). `Mail.Send` enables sending and `Calendars.ReadWrite` enables calendar control; a mailbox last consented on an older read-only scope set must re-register before send or any calendar write succeeds. Nothing else to do: the server finishes the sign-in automatically once you consent, usually within about half a minute, and the mailbox is then connected.
2048
2048
  4. **Done.** Subsequent tool calls (mail, calendar, contacts) use the persisted refresh token transparently.
2049
2049
  5. **Several mailboxes on one account.** Register again to add a second mailbox; it is stored alongside the first, not in place of it. Every operational tool then takes an optional `mailbox` argument — an email address or graphUserId. With one mailbox, omit it. With two or more, name it; omitting it returns a refusal listing the connected mailboxes. `outlook-mailbox-list` shows every connected mailbox. Only one registration runs at a time per account; starting another while one is live returns an in-progress signal.
2050
2050
 
@@ -2054,8 +2054,8 @@ The `outlook` plugin gives the admin agent access to Microsoft 365 / Outlook.com
2054
2054
  |------|---------|
2055
2055
  | `outlook-account-register` | Start the device-code flow for this account. Returns a user code + `microsoft.com/devicelogin` URL immediately; does not block. |
2056
2056
  | `outlook-account-register-poll` | Finish the device-code flow. One check per call: returns pending, registered, expired, or denied. |
2057
- | `outlook-mail-list` | Recent mail. Default top=25, folder=Inbox. `folder` takes a well-known name or alias (case/space-insensitive): Inbox, Sent Items/sent, Drafts, Deleted Items/trash, Junk Email/junk/spam, Archive, Outbox — or a raw folder id. Custom folder names are not resolved. |
2058
- | `outlook-mail-search` | Microsoft Graph `$search` over the mailbox. Preview-only, like `outlook-mail-list`. |
2057
+ | `outlook-mail-list` | Mail newest-first. Default top=25, folder=Inbox. `folder` takes a well-known name or alias (case/space-insensitive): Inbox, Sent Items/sent, Drafts, Deleted Items/trash, Junk Email/junk/spam, Archive, Outbox — or a raw folder id. Custom folder names are not resolved. `since`/`before` (ISO date-times) narrow by receipt date. The 250-per-page figure is not a ceiling: the reply carries `nextCursor` when older mail remains — pass it back as `cursor` to page further back. Filter by sender/subject via `outlook-mail-search`. |
2058
+ | `outlook-mail-search` | Microsoft Graph `$search` (KQL) over the mailbox. Preview-only, like `outlook-mail-list`, and pages the same way via `nextCursor`/`cursor`. Put sender/subject/recipient/date filters in the query: `from:`, `to:`, `subject:`, `received>=`. Graph forbids `$search`+`$filter`, so a strict date window is on `outlook-mail-list`. |
2059
2059
  | `outlook-mail-fetch-body` | Complete body of one message by id (`GET /me/messages/{id}?$select=body`). HTML decoded to text, no preview cap. The full-read path — list/search return Microsoft's ~255-char preview only. Returns the envelope plus the whole body. |
2060
2060
  | `outlook-mail-reply` | Reply in-thread (`createReply` / `createReplyAll` + send). Threads natively via conversationId. `replyAll`, added cc/bcc, and account-scoped file attachments (up to 25 MB per file; files over Graph's ~3 MB inline limit use a chunked upload session). Body is plain text, prepended above the quote. Needs `Mail.ReadWrite` + `Mail.Send`. |
2061
2061
  | `outlook-mail-delete` | Move messages to Deleted Items (`POST /me/messages/{id}/move`). Recoverable — never hard-deletes. An id already gone is counted not-moved. Needs `Mail.ReadWrite`. |
@@ -2790,6 +2790,8 @@ either is a regression.
2790
2790
 
2791
2791
  **Row title resolution.** Both the sidebar (`/sidebar-sessions`) and the manager's own row payload resolve a row's title in the same order: operator rename → Claude Code `ai-title` → first non-CLI user message → 8-char sessionId prefix. The operator-rename tier is the on-disk `<accountDir>/session-titles.json` (the manager's `UserTitleStore`), keyed by the CC sessionId — the sidebar reads that same file, so a write to the store lights up both surfaces with one write.
2792
2792
 
2793
+ **Session row delete, rename, and select mode.** The sidebar Sessions row supports three operator affordances. **Rename** (kebab → Rename) opens the inline edit input with its existing title pre-selected on focus, so the first keystroke replaces the whole title rather than appending to it — on both the sidebar (`conv-name-edit`) and the `/chat` Conversations flyout (`op-conv-rename-input`). **Delete** (kebab → Delete) arms a confirm that names the session (its label plus the 8-char id prefix) and renders as a popover anchored beside the row it will delete — reusing the same `AnchoredPopover` the kebab menu uses, not the shared bottom-right info dock — so the target is unambiguous; it still states the delete is permanent and, for a live row, that the session is stopped first. **Select mode** (a "Select" control in the Sessions header) turns each row into a checkbox and shows a "Delete N" bar; the row body toggles selection instead of opening, the per-row kebab is hidden, and confirming a count-based `BulkDeleteConfirmModal` (which names N and how many are live) loops the single-id `session-delete` over the selection (no route change — `/api/admin/session-delete` stays single-id). Bulk deletion is instrumented with a `[admin-ui] sidebar-bulk-delete op=start count=<N> live=<M>` / `op=done requested=<N> ok=<X> failed=<Y>` envelope around the per-session `sidebar-session-delete` lines, so a silently-dropped item shows as `ok+failed < requested`. Outside select mode the single-delete and row-open behaviours are unchanged.
2794
+
2793
2795
  **`/chat` empty-state starter chips.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`; degrades to "What's up next?" without one) above three one-tap starter chips (replacing the earlier read-only lists): **Catch me up** (`Inbox`), **My day** (`CalendarClock`), **To-do** (`ListTodo`). `GreetingPanel` no longer fetches `GET /api/webchat/greeting` — the headline reads from the `userName` prop alone. A tap dispatches the chip's verbatim prompt through the existing `send()` with zero typing, via the same arm/fire path as the `?q=` handoff seed: `dispatchChip` logs `[admin-ui] op=chip-tap id=<catch-up|my-day|to-do> chars=<n>`, sets the composer text, and arms a one-shot effect that fires `send()` once the text matches. Chips gate to `variant` admin/operator; the public surface shows the headline alone. The first journaled turn replaces the panel with the transcript. The `/api/webchat/greeting` route (`server/routes/webchat-greeting.ts`) and `specialist-roster.ts` are now unconsumed by this surface — slimming them is a separate follow-up. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
2794
2796
 
2795
2797
  **`/chat` composer transport button.** The button at the end of the input shows a **microphone** while the box is empty — tap it to record a voice note. Type a character, or attach a file, and the same button becomes the **send** arrow; while the agent is replying it becomes a **stop** square. So an empty composer offers voice, a composer with something to send offers send, and a running turn offers stop — one button, three states. The microphone-device chooser (which input to record from) stays in the row of icons below the box. This is the same on the admin `/chat`, the public chat, and the maxy-lite webchat.
@@ -162,7 +162,7 @@ No `expires_on`: the per-scope token is permanent and reused, so decay is the jo
162
162
 
163
163
  **Per-scope token resources.** Each reused per-scope token carries the resource that matches its operation class. The Pages-and-D1 token (`<brand>-pages-d1`) and the Access token (`<brand>-access`) are account-scoped: `"resources": { "com.cloudflare.api.account.${CLOUDFLARE_ACCOUNT_ID}": "*" }`. The DNS token (`<brand>-dns`) is zone-scoped, and since it is a single stable token reused across every zone the install routes, its resource covers the account's zones — but the exact shape depends on the master's prefix (see § Token type — route endpoints by prefix): a `cfut_…` master takes the flat `"resources": { "com.cloudflare.api.account.zone.*": "*" }`, while a `cfat_…` master requires the zone nested under the account, `"resources": { "com.cloudflare.api.account.${CLOUDFLARE_ACCOUNT_ID}": { "com.cloudflare.api.account.zone.*": "*" } }` (the flat shape returns `1001` on an account-owned master). A per-zone DNS token would defeat the one-stable-token-per-scope model (one token, reused, not one per zone); the minted token is still strictly narrower than the master, which already carries Zone DNS Edit over the zones in scope.
164
164
 
165
- **House-code data scopes.** On a multi-tenant install the house credential is a **minter**, not a data token. The storage broker's `cf-exec` and the booking calendar mint their own account-scoped data tokens from it exactly as above — `<brand>-storage` (`D1 Write` + `Workers R2 Storage Write`, key `CF_STORAGE_TOKEN`) and `<brand>-calendar-d1` (`D1 Write`, key `CF_CALENDAR_D1_TOKEN`) — persisted house-side in `cloudflare-house.env` and reused. This is the same mint-or-reuse `cf-token.sh` machinery the hosting scopes use; the only difference is the consumer is trusted house code rather than the agent.
165
+ **House-code data scopes.** The house credential in `cloudflare-house.env` is a **minter**, not a data token, on **every** install, not only multi-tenant ones: the booking calendar and storage broker read it house-only fleet-wide (no per-account fallback), and mint their own account-scoped data tokens from that minter rather than use it directly (a minter returns `10000` on D1/R2). The multi-tenant install adds isolation on top of this same file (§ Multi-tenant installs); the single-tenant install simply reads its calendar/broker credential here. The scopes are — `<brand>-storage` (`D1 Write` + `Workers R2 Storage Write`, key `CF_STORAGE_TOKEN`) and `<brand>-calendar-d1` (`D1 Write`, key `CF_CALENDAR_D1_TOKEN`) — persisted house-side in `cloudflare-house.env` and reused. This is the same mint-or-reuse `cf-token.sh` machinery the hosting scopes use; the only difference is the consumer is trusted house code rather than the agent.
166
166
 
167
167
  **Redaction is binding.** Every example above pipes the token into a variable or an `Authorization` header and never to stdout. The agent surfaces the operation as verb + target — "minting a Pages-deploy token", "creating CNAME `chat.example.com`" — never the secret. A failure surfaces the API error body with any `Authorization` value masked.
168
168
 
@@ -29,7 +29,7 @@ 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 operations are per-brand isolated and unchanged. The admin-run scopes (Pages, DNS, Access) stay admin/house-run: because the per-account secrets file no longer carries the master, `cf-token.sh` resolves and mints those scope tokens against the house credential (`config/cloudflare-house.env`) and persists them there, surfacing `src=house` on its `[cf-token]` lifeline. Hosting a client site to Pages is therefore an admin/house action, never a sub-account one, consistent with the isolation posture. See `references/api.md` and `.docs/cloudflare-storage-isolation.md`.
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 operations are per-brand isolated and unchanged. The admin-run scopes (Pages, DNS, Access) stay admin/house-run: because the per-account secrets file no longer carries the master, `cf-token.sh` resolves and mints those scope tokens against the house credential (`config/cloudflare-house.env`) and persists them there, surfacing `src=house` on its `[cf-token]` lifeline. Hosting a client site to Pages is therefore an admin/house action, never a sub-account one, consistent with the isolation posture. The house credential in `config/cloudflare-house.env` is a **minter**, not a data token, on **every** install, not only multi-tenant ones: the booking calendar and storage broker read it house-only fleet-wide (no per-account fallback), so they mint their own account-scoped data tokens from that minter — `CF_STORAGE_TOKEN` (D1 + R2) and `CF_CALENDAR_D1_TOKEN` (D1) — rather than use the minter directly, which returns `10000` on D1/R2. Multi-tenant installs add per-account isolation on top of this same file; single-tenant installs simply read their calendar/broker credential here. See `references/api.md` and `.docs/cloudflare-storage-isolation.md`.
33
33
 
34
34
  ### Resolve the per-scope token before any `wrangler` / API call (binding)
35
35