@rubytech/create-sitedesk-code 0.1.439 → 0.1.441

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 (118) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +41 -12
  3. package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +15 -5
  4. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/functions/api/calendar/free-busy.ts +152 -0
  5. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/index.html +6 -3
  6. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/schema.sql +11 -0
  7. package/payload/platform/plugins/docs/references/admin-identity-gate.md +32 -17
  8. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  9. package/payload/platform/plugins/docs/references/calendar-booking.md +1 -1
  10. package/payload/platform/plugins/docs/references/graph.md +19 -3
  11. package/payload/platform/plugins/docs/references/internals.md +2 -2
  12. package/payload/platform/plugins/docs/references/outlook-guide.md +9 -4
  13. package/payload/platform/plugins/docs/references/troubleshooting.md +8 -0
  14. package/payload/platform/plugins/graph/.claude-plugin/plugin.json +19 -0
  15. package/payload/platform/plugins/graph/PLUGIN.md +10 -4
  16. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
  17. package/payload/platform/plugins/outlook/PLUGIN.md +7 -3
  18. package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.js +100 -10
  19. package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.js.map +1 -1
  20. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list.test.d.ts +2 -0
  21. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list.test.d.ts.map +1 -0
  22. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list.test.js +55 -0
  23. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mail-list.test.js.map +1 -0
  24. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.d.ts +2 -0
  25. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.d.ts.map +1 -0
  26. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js +64 -0
  27. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-list.test.js.map +1 -0
  28. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.d.ts +2 -0
  29. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.d.ts.map +1 -0
  30. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.js +193 -0
  31. package/payload/platform/plugins/outlook/mcp/dist/__tests__/mailbox-registry.test.js.map +1 -0
  32. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js +58 -1
  33. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js.map +1 -1
  34. package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts +81 -0
  35. package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.d.ts.map +1 -0
  36. package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js +171 -0
  37. package/payload/platform/plugins/outlook/mcp/dist/auth/mailbox-registry.js.map +1 -0
  38. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts +16 -1
  39. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts.map +1 -1
  40. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js +25 -3
  41. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js.map +1 -1
  42. package/payload/platform/plugins/outlook/mcp/dist/index.js +119 -50
  43. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
  44. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +1 -1
  45. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
  46. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +8 -4
  47. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -1
  48. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +22 -3
  49. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -1
  50. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +17 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -1
  52. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +84 -21
  53. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -1
  54. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts +26 -0
  55. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.d.ts.map +1 -0
  56. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js +28 -0
  57. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-list.js.map +1 -0
  58. package/payload/platform/plugins/outlook/references/auth.md +36 -8
  59. package/payload/platform/plugins/outlook/references/graph-surfaces.md +15 -1
  60. package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.d.ts +27 -0
  61. package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.d.ts.map +1 -0
  62. package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js +241 -0
  63. package/payload/platform/plugins/scheduling/mcp/dist/scripts/publish-availability.js.map +1 -0
  64. package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +100 -0
  65. package/payload/platform/scripts/lib/account-schema-owned-dirs.py +207 -0
  66. package/payload/platform/scripts/lib/account-schema-owned-dirs.sh +33 -0
  67. package/payload/platform/scripts/lib/provision-account-dir.sh +7 -0
  68. package/payload/platform/scripts/setup-account.sh +10 -0
  69. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  70. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  71. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  72. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  73. package/payload/platform/services/claude-session-manager/dist/http-server.js +6 -4
  74. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/tool-registration-drift.d.ts +7 -6
  76. package/payload/platform/services/claude-session-manager/dist/tool-registration-drift.d.ts.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/tool-registration-drift.js +56 -7
  78. package/payload/platform/services/claude-session-manager/dist/tool-registration-drift.js.map +1 -1
  79. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  80. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/PLUGIN.md +1 -0
  81. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/dist/lib/gates.d.ts +7 -1
  82. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/dist/lib/gates.d.ts.map +1 -1
  83. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/dist/lib/gates.js +8 -2
  84. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/dist/lib/gates.js.map +1 -1
  85. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/src/lib/__tests__/gates.test.ts +13 -0
  86. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/src/lib/__tests__/render-run.test.ts +11 -0
  87. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/mcp/src/lib/gates.ts +8 -2
  88. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/SKILL.md +4 -2
  89. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/quote-engine.md +8 -0
  90. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/verification.md +12 -0
  91. package/payload/server/{chunk-UGPQCVIW.js → chunk-WC4WJR6X.js} +0 -6
  92. package/payload/server/maxy-edge.js +1 -1
  93. package/payload/server/public/assets/{AdminLoginScreens-DeR71H29.js → AdminLoginScreens-CukwQufW.js} +1 -1
  94. package/payload/server/public/assets/AdminShell-BwEBH6tT.js +2 -0
  95. package/payload/server/public/assets/{admin-C15h-NL0.js → admin-CdFRCUUZ.js} +1 -1
  96. package/payload/server/public/assets/{browser-B7xQLIRK.js → browser-BWR59IkB.js} +1 -1
  97. package/payload/server/public/assets/{calendar-A-vGm6pL.js → calendar-kuTcxX1t.js} +1 -1
  98. package/payload/server/public/assets/chat-ejnq2rck.js +1 -0
  99. package/payload/server/public/assets/data-dZbOyLdT.js +1 -0
  100. package/payload/server/public/assets/{graph-D0orIRAh.js → graph-CboWM2_-.js} +2 -2
  101. package/payload/server/public/assets/{operator-DZzuotDB.js → operator-oSaB1mya.js} +1 -1
  102. package/payload/server/public/assets/{page-Ck_pLhAk.js → page-DEkI-Gl1.js} +1 -1
  103. package/payload/server/public/assets/{page-3g0A19Rv.js → page-DMeJHVfA.js} +5 -5
  104. package/payload/server/public/assets/{public-WFUQw9AD.js → public-C54tl6V4.js} +1 -1
  105. package/payload/server/public/assets/{useCopyFeedback-CSk9KjhY.js → useCopyFeedback-DHoYHiK9.js} +1 -1
  106. package/payload/server/public/assets/{useVoiceRecorder-DCyJQkFK.js → useVoiceRecorder-b7HzTFs0.js} +1 -1
  107. package/payload/server/public/browser.html +2 -2
  108. package/payload/server/public/calendar.html +2 -2
  109. package/payload/server/public/chat.html +5 -5
  110. package/payload/server/public/data.html +3 -3
  111. package/payload/server/public/graph.html +3 -3
  112. package/payload/server/public/index.html +5 -5
  113. package/payload/server/public/operator.html +6 -6
  114. package/payload/server/public/public.html +5 -5
  115. package/payload/server/server.js +255 -112
  116. package/payload/server/public/assets/AdminShell-DlAVQUda.js +0 -2
  117. package/payload/server/public/assets/chat-DAae6Z51.js +0 -1
  118. package/payload/server/public/assets/data-BNWpKx1d.js +0 -1
@@ -47,11 +47,12 @@ export declare function indexPluginDirs(pluginRoots: readonly string[]): Map<str
47
47
  *
48
48
  * A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary
49
49
  * rather than a plugin-local `mcp/` dir (e.g. `graph`, served by
50
- * `platform/lib/graph-mcp`) is EXCLUDED from the result the manifest
51
- * generator only emits `mcpServers` for plugins that ship a plugin-local `mcp/`
52
- * (its `hasMcp` predicate), so a shared-lib plugin's generated manifest carries
53
- * no `mcpServers` by architecture, not by a `skip` flag. Judging it by the
54
- * generated-manifest criterion would false-FATAL on every boot. This mirrors
55
- * the generator's `hasMcp` check exactly. */
50
+ * `platform/lib/graph-mcp`) is IN scope (Task 1576). The generator now emits an
51
+ * `mcpServers` block for it via the `shared-lib` disposition, so it is judged by
52
+ * the same generated-manifest criterion: `dist-missing` resolves the shared
53
+ * server arg (the last `args` entry) via `${PLATFORM_ROOT}` from the boot env
54
+ * and checks that file, rather than a plugin-local `mcp/dist/index.js`. A
55
+ * no-local-`mcp/` plugin with no `mcp:` block is skills-only and stays out of
56
+ * scope. */
56
57
  export declare function readToolPluginManifestStates(pluginRoots: readonly string[], toolPluginNames: Iterable<string>): Map<string, ToolPluginManifestState>;
57
58
  //# sourceMappingURL=tool-registration-drift.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-registration-drift.d.ts","sourceRoot":"","sources":["../src/tool-registration-drift.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,2BAA2B,GACnC,eAAe,GACf,wBAAwB,GACxB,cAAc,CAAA;AAElB;;;qDAGqD;AACrD,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,OAAO,CAAA;IACxB,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,2BAA2B,CAAA;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,EAAE,2BAA2B,EAAE,CAAA;IACtC,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;mFACmF;AACnF,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,2BAA2B,GAAG,IAAI,CAKpC;AAED;;;;yBAIyB;AACzB,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,aAAa,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,EACjF,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,GACxD,2BAA2B,CAe7B;AAED;;;8DAG8D;AAC9D,wBAAgB,eAAe,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCnF;AAED;;;;;;;;;;;;;8CAa8C;AAC9C,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,GAChC,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAmCtC"}
1
+ {"version":3,"file":"tool-registration-drift.d.ts","sourceRoot":"","sources":["../src/tool-registration-drift.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,2BAA2B,GACnC,eAAe,GACf,wBAAwB,GACxB,cAAc,CAAA;AAElB;;;qDAGqD;AACrD,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,OAAO,CAAA;IACxB,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,2BAA2B,CAAA;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,EAAE,2BAA2B,EAAE,CAAA;IACtC,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;mFACmF;AACnF,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,uBAAuB,GAC7B,2BAA2B,GAAG,IAAI,CAKpC;AAED;;;;yBAIyB;AACzB,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,aAAa,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,EACjF,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,uBAAuB,CAAC,GACxD,2BAA2B,CAe7B;AAED;;;8DAG8D;AAC9D,wBAAgB,eAAe,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCnF;AAED;;;;;;;;;;;;;;aAca;AACb,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,GAChC,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAqFtC"}
@@ -101,12 +101,13 @@ export function indexPluginDirs(pluginRoots) {
101
101
  *
102
102
  * A tool-plugin whose `mcp:` server is a shared `platform/lib/<name>` binary
103
103
  * rather than a plugin-local `mcp/` dir (e.g. `graph`, served by
104
- * `platform/lib/graph-mcp`) is EXCLUDED from the result the manifest
105
- * generator only emits `mcpServers` for plugins that ship a plugin-local `mcp/`
106
- * (its `hasMcp` predicate), so a shared-lib plugin's generated manifest carries
107
- * no `mcpServers` by architecture, not by a `skip` flag. Judging it by the
108
- * generated-manifest criterion would false-FATAL on every boot. This mirrors
109
- * the generator's `hasMcp` check exactly. */
104
+ * `platform/lib/graph-mcp`) is IN scope (Task 1576). The generator now emits an
105
+ * `mcpServers` block for it via the `shared-lib` disposition, so it is judged by
106
+ * the same generated-manifest criterion: `dist-missing` resolves the shared
107
+ * server arg (the last `args` entry) via `${PLATFORM_ROOT}` from the boot env
108
+ * and checks that file, rather than a plugin-local `mcp/dist/index.js`. A
109
+ * no-local-`mcp/` plugin with no `mcp:` block is skills-only and stays out of
110
+ * scope. */
110
111
  export function readToolPluginManifestStates(pluginRoots, toolPluginNames) {
111
112
  const dirs = indexPluginDirs(pluginRoots);
112
113
  const out = new Map();
@@ -121,8 +122,56 @@ export function readToolPluginManifestStates(pluginRoots, toolPluginNames) {
121
122
  // different mount architecture, out of this gate's remit.
122
123
  const hasLocalMcp = existsSync(join(dir, 'mcp', 'dist', 'index.js')) ||
123
124
  existsSync(join(dir, 'mcp', 'package.json'));
124
- if (!hasLocalMcp)
125
+ if (!hasLocalMcp) {
126
+ // Shared-lib tool-plugin (Task 1576): PLUGIN.md declares an mcp: block but
127
+ // the server is a shared platform/lib binary, so the generator emits
128
+ // mcpServers via the shared-lib disposition. A dir with no mcp: block is
129
+ // skills-only and out of this gate's remit. distPresent resolves the
130
+ // shared server arg (the last args entry) via ${PLATFORM_ROOT}.
131
+ let hasMcpBlock = false;
132
+ try {
133
+ hasMcpBlock = /(^|\n)mcp:[ \t]*(\r?\n|$)/.test(readFileSync(join(dir, 'PLUGIN.md'), 'utf-8'));
134
+ }
135
+ catch {
136
+ /* no readable PLUGIN.md → not a tool-plugin */
137
+ }
138
+ if (!hasMcpBlock)
139
+ continue;
140
+ const manifestPath = join(dir, '.claude-plugin', 'plugin.json');
141
+ const manifestPresent = existsSync(manifestPath);
142
+ let hasMcpServers = false;
143
+ let serverArg = null;
144
+ if (manifestPresent) {
145
+ try {
146
+ const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));
147
+ const servers = parsed.mcpServers;
148
+ if (servers &&
149
+ typeof servers === 'object' &&
150
+ !Array.isArray(servers) &&
151
+ Object.keys(servers).length > 0) {
152
+ hasMcpServers = true;
153
+ const entry = servers[name] ?? Object.values(servers)[0];
154
+ const args = Array.isArray(entry?.args) ? entry.args : [];
155
+ const last = args.length ? args[args.length - 1] : null;
156
+ serverArg = typeof last === 'string' ? last : null;
157
+ }
158
+ }
159
+ catch {
160
+ /* corrupt manifest → hasMcpServers stays false → no-mcpServers-manifest */
161
+ }
162
+ }
163
+ let distPresent = false;
164
+ if (serverArg) {
165
+ // Resolve exactly as the manager boot does (index.ts): PLATFORM_ROOT with
166
+ // MAXY_PLATFORM_ROOT as the supported alias. Re-reading only PLATFORM_ROOT
167
+ // would spuriously report dist-missing on a box booted with only the alias.
168
+ const platformRoot = process.env.PLATFORM_ROOT ?? process.env.MAXY_PLATFORM_ROOT;
169
+ const resolved = platformRoot ? serverArg.split('${PLATFORM_ROOT}').join(platformRoot) : serverArg;
170
+ distPresent = !resolved.includes('${') && existsSync(resolved);
171
+ }
172
+ out.set(name, { manifestPresent, hasMcpServers, distPresent });
125
173
  continue;
174
+ }
126
175
  const manifestPath = join(dir, '.claude-plugin', 'plugin.json');
127
176
  const manifestPresent = existsSync(manifestPath);
128
177
  let hasMcpServers = false;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-registration-drift.js","sourceRoot":"","sources":["../src/tool-registration-drift.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-registration-drift.js","sourceRoot":"","sources":["../src/tool-registration-drift.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ name: personal-assistant
3
3
  description: "Scheduling, platform settings, messaging channels (Telegram, WhatsApp, email, Outlook), and browser automation. Delegate when the work is on your calendar, configuring the platform, sending or reading messages, or driving a browser."
4
4
  summary: "Handles the operational tasks you'd give a personal assistant: scheduling meetings, managing your platform settings, connecting messaging channels, and completing browser-based tasks on your behalf."
5
5
  model: claude-sonnet-5
6
- tools: Skill, mcp__plugin_admin_admin__system-status, mcp__plugin_admin_admin__brand-settings, mcp__plugin_admin_admin__account-manage, mcp__plugin_admin_admin__account-update, mcp__plugin_admin_admin__logs-read, mcp__plugin_admin_admin__plugin-read, mcp__plugin_admin_admin__wifi, mcp__plugin_contacts_contacts__contact-create, mcp__plugin_contacts_contacts__contact-lookup, mcp__plugin_contacts_contacts__contact-update, mcp__plugin_contacts_contacts__contact-delete, mcp__plugin_contacts_contacts__contact-list, mcp__plugin_contacts_contacts__contact-export, mcp__plugin_contacts_contacts__contact-erase, mcp__plugin_contacts_contacts__group-create, mcp__plugin_contacts_contacts__group-manage, mcp__plugin_telegram_telegram__message, mcp__plugin_telegram_telegram__message-history, mcp__plugin_telegram_telegram__telegram-webhook-register, mcp__plugin_whatsapp_whatsapp__whatsapp-login-start, mcp__plugin_whatsapp_whatsapp__whatsapp-login-wait, mcp__plugin_whatsapp_whatsapp__whatsapp-status, mcp__plugin_whatsapp_whatsapp__whatsapp-disconnect, mcp__plugin_whatsapp_whatsapp__whatsapp-config, mcp__plugin_whatsapp_whatsapp__whatsapp-activity, mcp__plugin_whatsapp_whatsapp__whatsapp-conversations, mcp__plugin_whatsapp_whatsapp__whatsapp-messages, mcp__plugin_whatsapp_whatsapp__whatsapp-conversation-graph-state, mcp__plugin_whatsapp_whatsapp__whatsapp-group-info, mcp__plugin_whatsapp_whatsapp__whatsapp-send-admin, mcp__plugin_email_email__email-provider-info, mcp__plugin_email_email__email-setup, mcp__plugin_email_email__email-read, mcp__plugin_email_email__email-fetch-body, mcp__plugin_email_email__email-send, mcp__plugin_email_email__email-draft, mcp__plugin_email_email__email-draft-edit, mcp__plugin_email_email__email-draft-send, mcp__plugin_email_email__email-reply, mcp__plugin_email_email__email-search, mcp__plugin_email_email__email-delete, mcp__plugin_email_email__email-graph-query, mcp__plugin_email_email__email-otp-extract, mcp__plugin_email_email__email-status, mcp__plugin_email_email__email-fetch, mcp__plugin_email_email__email-ingest, mcp__plugin_outlook_outlook__outlook-account-register, mcp__plugin_outlook_outlook__outlook-account-register-poll, mcp__plugin_outlook_outlook__outlook-mail-list, mcp__plugin_outlook_outlook__outlook-mail-search, mcp__plugin_outlook_outlook__outlook-mail-send, mcp__plugin_outlook_outlook__outlook-draft, mcp__plugin_outlook_outlook__outlook-draft-send, mcp__plugin_outlook_outlook__outlook-calendar-list, mcp__plugin_outlook_outlook__outlook-calendar-event, mcp__plugin_outlook_outlook__outlook-calendar-create, mcp__plugin_outlook_outlook__outlook-calendar-update, mcp__plugin_outlook_outlook__outlook-calendar-cancel, mcp__plugin_outlook_outlook__outlook-calendar-respond, mcp__plugin_outlook_outlook__outlook-calendar-freebusy, mcp__plugin_outlook_outlook__outlook-contacts-list, mcp__plugin_outlook_outlook__outlook-mailbox-info, mcp__plugin_scheduling_scheduling__schedule-event, mcp__plugin_scheduling_scheduling__schedule-list, mcp__plugin_scheduling_scheduling__schedule-get, mcp__plugin_scheduling_scheduling__schedule-update, mcp__plugin_scheduling_scheduling__schedule-cancel, mcp__plugin_scheduling_scheduling__schedule-export-ics, mcp__plugin_scheduling_scheduling__schedule-import-ics, mcp__plugin_scheduling_scheduling__time-resolve, mcp__plugin_memory_memory__memory-search, mcp__plugin_memory_memory__profile-update, mcp__plugin_url-get_url-get__url-get, mcp__plugin_browser_browser__browser-render, mcp__plugin_browser_browser__browser-navigate, mcp__plugin_browser_browser__browser-snapshot, mcp__plugin_browser_browser__browser-click, mcp__plugin_browser_browser__browser-fill, mcp__plugin_browser_browser__browser-fill-form, mcp__plugin_browser_browser__browser-type, mcp__plugin_browser_browser__browser-press-key, mcp__plugin_browser_browser__browser-hover, mcp__plugin_browser_browser__browser-select-option, mcp__plugin_browser_browser__browser-wait-for, mcp__plugin_browser_browser__browser-handle-dialog, mcp__plugin_browser_browser__browser-evaluate, mcp__plugin_browser_browser__browser-console-messages, mcp__plugin_browser_browser__browser-tabs, mcp__plugin_browser_browser__browser-pdf-save, mcp__plugin_browser_browser__browser-screenshot, mcp__plugin_browser_browser__browser-resize
6
+ tools: Skill, mcp__plugin_admin_admin__system-status, mcp__plugin_admin_admin__brand-settings, mcp__plugin_admin_admin__account-manage, mcp__plugin_admin_admin__account-update, mcp__plugin_admin_admin__logs-read, mcp__plugin_admin_admin__plugin-read, mcp__plugin_admin_admin__wifi, mcp__plugin_contacts_contacts__contact-create, mcp__plugin_contacts_contacts__contact-lookup, mcp__plugin_contacts_contacts__contact-update, mcp__plugin_contacts_contacts__contact-delete, mcp__plugin_contacts_contacts__contact-list, mcp__plugin_contacts_contacts__contact-export, mcp__plugin_contacts_contacts__contact-erase, mcp__plugin_contacts_contacts__group-create, mcp__plugin_contacts_contacts__group-manage, mcp__plugin_telegram_telegram__message, mcp__plugin_telegram_telegram__message-history, mcp__plugin_telegram_telegram__telegram-webhook-register, mcp__plugin_whatsapp_whatsapp__whatsapp-login-start, mcp__plugin_whatsapp_whatsapp__whatsapp-login-wait, mcp__plugin_whatsapp_whatsapp__whatsapp-status, mcp__plugin_whatsapp_whatsapp__whatsapp-disconnect, mcp__plugin_whatsapp_whatsapp__whatsapp-config, mcp__plugin_whatsapp_whatsapp__whatsapp-activity, mcp__plugin_whatsapp_whatsapp__whatsapp-conversations, mcp__plugin_whatsapp_whatsapp__whatsapp-messages, mcp__plugin_whatsapp_whatsapp__whatsapp-conversation-graph-state, mcp__plugin_whatsapp_whatsapp__whatsapp-group-info, mcp__plugin_whatsapp_whatsapp__whatsapp-send-admin, mcp__plugin_email_email__email-provider-info, mcp__plugin_email_email__email-setup, mcp__plugin_email_email__email-read, mcp__plugin_email_email__email-fetch-body, mcp__plugin_email_email__email-send, mcp__plugin_email_email__email-draft, mcp__plugin_email_email__email-draft-edit, mcp__plugin_email_email__email-draft-send, mcp__plugin_email_email__email-reply, mcp__plugin_email_email__email-search, mcp__plugin_email_email__email-delete, mcp__plugin_email_email__email-graph-query, mcp__plugin_email_email__email-otp-extract, mcp__plugin_email_email__email-status, mcp__plugin_email_email__email-fetch, mcp__plugin_email_email__email-ingest, mcp__plugin_outlook_outlook__outlook-account-register, mcp__plugin_outlook_outlook__outlook-account-register-poll, mcp__plugin_outlook_outlook__outlook-mail-list, mcp__plugin_outlook_outlook__outlook-mail-search, mcp__plugin_outlook_outlook__outlook-mail-send, mcp__plugin_outlook_outlook__outlook-draft, mcp__plugin_outlook_outlook__outlook-draft-send, mcp__plugin_outlook_outlook__outlook-calendar-list, mcp__plugin_outlook_outlook__outlook-calendar-event, mcp__plugin_outlook_outlook__outlook-calendar-create, mcp__plugin_outlook_outlook__outlook-calendar-update, mcp__plugin_outlook_outlook__outlook-calendar-cancel, mcp__plugin_outlook_outlook__outlook-calendar-respond, mcp__plugin_outlook_outlook__outlook-calendar-freebusy, mcp__plugin_outlook_outlook__outlook-contacts-list, mcp__plugin_outlook_outlook__outlook-mailbox-info, mcp__plugin_outlook_outlook__outlook-mailbox-list, mcp__plugin_scheduling_scheduling__schedule-event, mcp__plugin_scheduling_scheduling__schedule-list, mcp__plugin_scheduling_scheduling__schedule-get, mcp__plugin_scheduling_scheduling__schedule-update, mcp__plugin_scheduling_scheduling__schedule-cancel, mcp__plugin_scheduling_scheduling__schedule-export-ics, mcp__plugin_scheduling_scheduling__schedule-import-ics, mcp__plugin_scheduling_scheduling__time-resolve, mcp__plugin_memory_memory__memory-search, mcp__plugin_memory_memory__profile-update, mcp__plugin_url-get_url-get__url-get, mcp__plugin_browser_browser__browser-render, mcp__plugin_browser_browser__browser-navigate, mcp__plugin_browser_browser__browser-snapshot, mcp__plugin_browser_browser__browser-click, mcp__plugin_browser_browser__browser-fill, mcp__plugin_browser_browser__browser-fill-form, mcp__plugin_browser_browser__browser-type, mcp__plugin_browser_browser__browser-press-key, mcp__plugin_browser_browser__browser-hover, mcp__plugin_browser_browser__browser-select-option, mcp__plugin_browser_browser__browser-wait-for, mcp__plugin_browser_browser__browser-handle-dialog, mcp__plugin_browser_browser__browser-evaluate, mcp__plugin_browser_browser__browser-console-messages, mcp__plugin_browser_browser__browser-tabs, mcp__plugin_browser_browser__browser-pdf-save, mcp__plugin_browser_browser__browser-screenshot, mcp__plugin_browser_browser__browser-resize
7
7
  ---
8
8
 
9
9
  # Personal Assistant
@@ -24,6 +24,7 @@ tools:
24
24
  publicAllowlist: false
25
25
  adminAllowlist: true
26
26
  metadata: {"platform":{"optional":true,"embed":["admin"]}}
27
+ account-owned-dirs: [{"dir": "quoting", "description": "The operator's persisted pricing and quotation engine (engine.mjs), method (method.json), render script (render.mjs) and per-job figures under quoting/jobs/. Authored by the quotation skill and executed by the sitedesk-job quote tools. Its internal structure is tool-owned and recreated on the next write."}]
27
28
  keywords: ["pricing", "quotation", "valuation", "quoting", "estimating", "pricing-method", "quote-generation", "construction", "interim-valuation", "progress-claim", "variations", "job", "timesheet", "invoice", "check-in", "CIS", "takeoff", "quantities", "measure", "drawing", "dimensions", "scale"]
28
29
  ---
29
30
 
@@ -11,7 +11,13 @@ export interface SignLinkVerdict {
11
11
  reason?: "no-anchor" | "empty" | "fragment" | "non-https" | "relative";
12
12
  }
13
13
  /** The document's displayed grand total (data-quote-total) must equal the
14
- * engine total. No marker fail closed (an unverifiable total is not shipped). */
14
+ * engine total at penny precision money is penny-precise, so a sub-penny
15
+ * engine total (e.g. 3395.235) reconciles against the penny total the client
16
+ * document shows (3395.24). A genuine >=1p discrepancy still fails. Both sides
17
+ * are rounded to pennies with toFixed(2) — the same rounding an operator's
18
+ * render performs — so an engine total sitting exactly on a half-penny (2.045)
19
+ * reconciles rather than diverging, which a *100 multiply-then-round would.
20
+ * No marker → fail closed (an unverifiable total is not shipped). */
15
21
  export declare function gateReconcile(html: string, engineTotal: number): ReconcileVerdict;
16
22
  /** A client document carrying a cost/margin marker (data-internal-only) is a
17
23
  * leak — the boundary is structural, not a matter of remembering to omit. */
@@ -1 +1 @@
1
- {"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../src/lib/gates.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAAG,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AACnE,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,OAAO,CAAA;CAAE;AAC9C,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAA;CAAE;AAEzI;oFACoF;AACpF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAMjF;AAED;8EAC8E;AAC9E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAExD;AAED;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAS1D"}
1
+ {"version":3,"file":"gates.d.ts","sourceRoot":"","sources":["../../src/lib/gates.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAAG,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AACnE,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,OAAO,CAAA;CAAE;AAC9C,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAA;CAAE;AAEzI;;;;;;;sEAOsE;AACtE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAMjF;AAED;8EAC8E;AAC9E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAExD;AAED;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAS1D"}
@@ -5,7 +5,13 @@
5
5
  // data-internal-only cost/margin-bearing figures (must be absent from client docs)
6
6
  // data-esign-accept the client quote's Sign-Online anchor (absolute https only)
7
7
  /** The document's displayed grand total (data-quote-total) must equal the
8
- * engine total. No marker fail closed (an unverifiable total is not shipped). */
8
+ * engine total at penny precision money is penny-precise, so a sub-penny
9
+ * engine total (e.g. 3395.235) reconciles against the penny total the client
10
+ * document shows (3395.24). A genuine >=1p discrepancy still fails. Both sides
11
+ * are rounded to pennies with toFixed(2) — the same rounding an operator's
12
+ * render performs — so an engine total sitting exactly on a half-penny (2.045)
13
+ * reconciles rather than diverging, which a *100 multiply-then-round would.
14
+ * No marker → fail closed (an unverifiable total is not shipped). */
9
15
  export function gateReconcile(html, engineTotal) {
10
16
  const m = html.match(/data-quote-total="([^"]*)"/i);
11
17
  if (!m || m[1].trim() === "")
@@ -13,7 +19,7 @@ export function gateReconcile(html, engineTotal) {
13
19
  const shown = Number(m[1]);
14
20
  if (!Number.isFinite(shown))
15
21
  return { pass: false };
16
- return { pass: shown === engineTotal, shown };
22
+ return { pass: Number(shown.toFixed(2)) === Number(engineTotal.toFixed(2)), shown };
17
23
  }
18
24
  /** A client document carrying a cost/margin marker (data-internal-only) is a
19
25
  * leak — the boundary is structural, not a matter of remembering to omit. */
@@ -1 +1 @@
1
- {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../src/lib/gates.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,6DAA6D;AAC7D,gFAAgF;AAChF,qFAAqF;AACrF,mFAAmF;AAMnF;oFACoF;AACpF,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAmB;IAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACpD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,KAAK,KAAK,WAAW,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC;AAED;8EAC8E;AAC9E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,EAAE,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACzD,CAAC;AAED;+EAC+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC3E,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACzF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC"}
1
+ {"version":3,"file":"gates.js","sourceRoot":"","sources":["../../src/lib/gates.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,6DAA6D;AAC7D,gFAAgF;AAChF,qFAAqF;AACrF,mFAAmF;AAMnF;;;;;;;sEAOsE;AACtE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,WAAmB;IAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACpD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;AACtF,CAAC;AAED;8EAC8E;AAC9E,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,EAAE,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACzD,CAAC;AAED;+EAC+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3D,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC3E,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACzF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC"}
@@ -14,6 +14,19 @@ describe("gateReconcile — displayed total must equal the engine total", () =>
14
14
  it("fails closed on an empty data-quote-total marker, even when the engine total is zero", () => {
15
15
  expect(gateReconcile('<p data-quote-total="">x</p>', 0)).toEqual({ pass: false });
16
16
  });
17
+ it("passes when the displayed penny total equals a sub-penny engine total rounded to pennies", () => {
18
+ expect(gateReconcile('<p data-quote-total="3395.24">x</p>', 3395.235)).toEqual({ pass: true, shown: 3395.24 });
19
+ });
20
+ it("passes at an exact half-penny engine total (2.045 renders 2.04, both round the same way)", () => {
21
+ // guards the *100-multiply divergence: Math.round(2.045*100)=205 but toFixed(2)=2.04
22
+ expect(gateReconcile('<p data-quote-total="2.04">x</p>', 2.045)).toEqual({ pass: true, shown: 2.04 });
23
+ });
24
+ it("fails a genuine 1-penny discrepancy (tightest boundary)", () => {
25
+ expect(gateReconcile('<p data-quote-total="3395.24">x</p>', 3395.25)).toEqual({ pass: false, shown: 3395.24 });
26
+ });
27
+ it("fails a genuine multi-pound discrepancy", () => {
28
+ expect(gateReconcile('<p data-quote-total="3395.24">x</p>', 3396.0)).toEqual({ pass: false, shown: 3395.24 });
29
+ });
17
30
  });
18
31
 
19
32
  describe("gateMarginLeak — client docs must not carry cost/margin markers", () => {
@@ -37,6 +37,9 @@ process.stdin.on("end", () => {
37
37
  }));
38
38
  });
39
39
  `;
40
+ // operator's render penny-rounds the display (toFixed(2)) while the engine total
41
+ // is sub-penny → the doc shows the penny total, the engine total is sub-penny
42
+ const SUBPENNY = GOOD.replace("const t = figures.total;", "const t = figures.total.toFixed(2);");
40
43
  const THROW = `process.stdin.resume(); process.exit(1);`;
41
44
 
42
45
  let dir: string;
@@ -51,6 +54,7 @@ beforeAll(() => {
51
54
  writeFileSync(join(dir, "quoting", "render-leak.mjs"), LEAK);
52
55
  writeFileSync(join(dir, "quoting", "render-deadlink.mjs"), DEADLINK);
53
56
  writeFileSync(join(dir, "quoting", "render-wrongtotal.mjs"), WRONGTOTAL);
57
+ writeFileSync(join(dir, "quoting", "render-subpenny.mjs"), SUBPENNY);
54
58
  writeFileSync(join(dir, "quoting", "render-throw.mjs"), THROW);
55
59
  });
56
60
  afterAll(() => rmSync(dir, { recursive: true, force: true }));
@@ -85,6 +89,13 @@ describe("runRender — a failing gate is fail-closed and atomic (no doc filed)"
85
89
  const r = await runRender({ accountDir: dir, renderScriptPath: rs("render-wrongtotal.mjs"), figures, signUrl, jobId: "job-wt" });
86
90
  expect(r).toMatchObject({ ok: false, reason: "reconcile-fail" });
87
91
  });
92
+ it("reconciles when the engine total is sub-penny and the docs show the penny-rounded total", async () => {
93
+ const subFigures = { total: 3395.235, header: { phone: "44700900000" }, lines: [] };
94
+ const r = await runRender({ accountDir: dir, renderScriptPath: rs("render-subpenny.mjs"), figures: subFigures, signUrl, jobId: "job-sub" });
95
+ expect(r.ok).toBe(true);
96
+ if (!r.ok) return;
97
+ expect(r.reconcile).toEqual({ internal: true, breakdown: true, quote: true });
98
+ });
88
99
  it("render-error when the figures header phone contains a path traversal", async () => {
89
100
  const evil = { total: 1250, header: { phone: "../../etc" }, lines: [] };
90
101
  const r = await runRender({ accountDir: dir, renderScriptPath: rs("render.mjs"), figures: evil, signUrl, jobId: "job-evil" });
@@ -10,13 +10,19 @@ export interface LeakVerdict { pass: boolean }
10
10
  export interface SignLinkVerdict { pass: boolean; href?: string; reason?: "no-anchor" | "empty" | "fragment" | "non-https" | "relative" }
11
11
 
12
12
  /** The document's displayed grand total (data-quote-total) must equal the
13
- * engine total. No marker fail closed (an unverifiable total is not shipped). */
13
+ * engine total at penny precision money is penny-precise, so a sub-penny
14
+ * engine total (e.g. 3395.235) reconciles against the penny total the client
15
+ * document shows (3395.24). A genuine >=1p discrepancy still fails. Both sides
16
+ * are rounded to pennies with toFixed(2) — the same rounding an operator's
17
+ * render performs — so an engine total sitting exactly on a half-penny (2.045)
18
+ * reconciles rather than diverging, which a *100 multiply-then-round would.
19
+ * No marker → fail closed (an unverifiable total is not shipped). */
14
20
  export function gateReconcile(html: string, engineTotal: number): ReconcileVerdict {
15
21
  const m = html.match(/data-quote-total="([^"]*)"/i);
16
22
  if (!m || m[1].trim() === "") return { pass: false };
17
23
  const shown = Number(m[1]);
18
24
  if (!Number.isFinite(shown)) return { pass: false };
19
- return { pass: shown === engineTotal, shown };
25
+ return { pass: Number(shown.toFixed(2)) === Number(engineTotal.toFixed(2)), shown };
20
26
  }
21
27
 
22
28
  /** A client document carrying a cost/margin marker (data-internal-only) is a
@@ -44,7 +44,7 @@ Everything this skill does lives under `references/`. Reach for one by what you
44
44
  - `references/manual-definition.md` — build or edit the method by hand for an operator with no usable history, or to make an adjustment.
45
45
 
46
46
  **Keep it correct**
47
- - `references/verification.md` — accept the method only when it reproduces the operator's own past quotes to their own precision; the report is a per-level delta, never a boolean.
47
+ - `references/verification.md` — accept the method only when it reproduces the operator's own past quotes to their own precision; the report is a per-level delta, never a boolean, and the reproduction that accepts the method runs through the `quote-engine-run` tool in `mode: "verify"`, never a hand-run.
48
48
  - `references/maintenance.md` — re-learn or edit while preserving prior manual adjustments, then re-verify green.
49
49
 
50
50
  **Apply it to produce a quote**
@@ -69,7 +69,9 @@ Two things are always visible:
69
69
  ambiguous, or guessed — is logged as such, so gaps are seen at onboarding, not later in a wrong quote.
70
70
  - **A reconciliation report.** The standing check is reproduction against the operator's own history:
71
71
  per past job, the **delta** between the reproduced figures and the operator's own, at line, group,
72
- and final level — a delta, never a boolean. `references/verification.md` owns why and how.
72
+ and final level — a delta, never a boolean. That reproduction runs through `quote-engine-run` in
73
+ `mode: "verify"`, so an accepted method leaves an observable `[quote-engine] op=verify` line rather
74
+ than passing silently through a hand-run. `references/verification.md` owns why and how.
73
75
 
74
76
  ## Scope
75
77
 
@@ -135,6 +135,14 @@ history, supplied with their method; there are no built-in figures to test again
135
135
  history, not parsing cleanly, is the signal that the engine prices the way they do. Verify on every
136
136
  generate and every method change; a reproduction failure blocks issuing a computed quote.
137
137
 
138
+ The reproduction that **signs off** a method is produced by the `sitedesk-job:quote-engine-run` tool
139
+ in `mode: "verify"` — the same deterministic apply-path tool that runs the persisted engine — never a
140
+ hand-run of the engine or a side script. A reproduction produced any other way is not acceptance. This
141
+ closes the gap where an engine the tool cannot run (a non-node or non-conformant script), or one the
142
+ owner's live path bypasses, is declared verified through a parallel run the shipped tools never touch.
143
+ Every tool verify leaves a `[quote-engine] op=verify jobId=… worst=…` line; that line is the evidence
144
+ the sign-off actually ran, and its absence for a method claimed verified is the bypass to catch.
145
+
138
146
  ## Boundaries
139
147
 
140
148
  - **Capturing and maintaining** the content of the method (items, rules, dials, roll-up, past-job
@@ -37,3 +37,15 @@ The compute that turns the captured method plus a job into reproduced figures
37
37
  runs that compute against the operator's past jobs. This reference owns the acceptance discipline:
38
38
  which jobs to reproduce, that the comparison is a per-level delta, and that reproduction to the
39
39
  operator's precision is the bar.
40
+
41
+ ## The reproduction runs through the tool
42
+
43
+ The delta report that accepts a method is the output of `quote-engine-run` in `mode: "verify"` against
44
+ the operator's past jobs — not a hand-run of the engine and not a side script. A method declared
45
+ verified with no corresponding `mode: "verify"` tool run is **not** accepted, however exactly a
46
+ hand-run reproduces the figures: the sign-off is the tool run, because that is the path a live quote
47
+ takes. Verifying by any parallel route — a script in another language, an engine the tool cannot
48
+ execute, a direct invocation that bypasses the persisted `quoting/engine.mjs` — proves nothing about
49
+ the quote the operator will actually issue. The tool records each verify as `[quote-engine] op=verify
50
+ jobId=… worst=…`; absence of that line for a method claimed verified is the bypass this discipline
51
+ exists to catch.
@@ -4031,11 +4031,6 @@ function setWantsPriorConversation(cacheKey2) {
4031
4031
  function unregisterSession(cacheKey2) {
4032
4032
  return sessionStore.delete(cacheKey2);
4033
4033
  }
4034
- function retagAccountForUser(userId, accountId) {
4035
- for (const session of sessionStore.values()) {
4036
- if (session.userId === userId) session.accountId = accountId;
4037
- }
4038
- }
4039
4034
  function getSessionKeyBySessionId(_sessionId) {
4040
4035
  return void 0;
4041
4036
  }
@@ -5961,7 +5956,6 @@ export {
5961
5956
  setSessionIdForSession,
5962
5957
  setWantsPriorConversation,
5963
5958
  unregisterSession,
5964
- retagAccountForUser,
5965
5959
  getSessionKeyBySessionId,
5966
5960
  findMissingPlugins,
5967
5961
  walkPremiumBundles,
@@ -16,7 +16,7 @@ import {
16
16
  sanitizeClientCorrId,
17
17
  vncLog,
18
18
  websockifyLog
19
- } from "./chunk-UGPQCVIW.js";
19
+ } from "./chunk-WC4WJR6X.js";
20
20
  import "./chunk-PFF6I7KP.js";
21
21
 
22
22
  // server/edge.ts
@@ -1 +1 @@
1
- import{o as e}from"./chunk-Ck5AOu5v.js";import{E as t,S as n,_ as r,x as i,y as a}from"./useSubAccountSwitcher-DLJFISqf.js";import{E as o}from"./useVoiceRecorder-DCyJQkFK.js";import{b as s,y as c}from"./AdminShell-DlAVQUda.js";import{t as l}from"./Checkbox-B629mOPp.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(t(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=c.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){n(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,c]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,setPin:a,operatorName:c,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=i();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:t,setPin:n,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:i}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!t||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:t,setPin:n,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:t,setAuthPolling:n,authLoading:i,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),n(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),t&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(c,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};
1
+ import{o as e}from"./chunk-Ck5AOu5v.js";import{E as t,S as n,_ as r,x as i,y as a}from"./useSubAccountSwitcher-DLJFISqf.js";import{E as o}from"./useVoiceRecorder-b7HzTFs0.js";import{b as s,y as c}from"./AdminShell-BwEBH6tT.js";import{t as l}from"./Checkbox-B629mOPp.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(t(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1),[G,K]=(0,p.useState)(!0);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let q=(0,p.useRef)(null),J=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let Y=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=c.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){n(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,c]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(0,p.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,setPin:a,operatorName:c,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=i();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:t,setPin:n,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:i}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!t||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:t,setPin:n,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:t,setAuthPolling:n,authLoading:i,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1),v(e.transport||``);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),n(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,h.jsx)(`button`,{onClick:E,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})}),t&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(c,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(c,{variant:`primary`,onClick:T,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:w,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};