@xopcai/xopc 0.0.373 → 0.0.374

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 (210) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear--kDkSTqC.js → agent-avatar-dicebear-BrA20N2m.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-z4_2-Kn2.js → agent-defaults-settings-panel-BZrOdxou.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-plugin-dialog-BYndK83K.js → agent-plugin-dialog-B3ux1AhY.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agents-CVo96cx1.js → agents-CXlXFU6M.js} +3 -3
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-D9oOJKiH.js → app-management-settings-panel-BXahEVPm.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-B0-8Cdyv.js → appearance-settings-CE2qJMkD.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-DasVc6i4.js → apps-page-DGVOnCxZ.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automations-page-BlCNqy2i.js → automations-page-BWL7eT4_.js} +1 -1
  11. package/dist/gateway/static/root/assets/{automations-workspace-C8ipDP05.js → automations-workspace-BxIShhkZ.js} +1 -1
  12. package/dist/gateway/static/root/assets/{block-editor-Cktlez6g.js → block-editor-3n446-mX.js} +1 -1
  13. package/dist/gateway/static/root/assets/{browser-automations-page-KRfDl8ej.js → browser-automations-page-BmTK7Gtn.js} +1 -1
  14. package/dist/gateway/static/root/assets/{browser-settings-page-BraQ4wnh.js → browser-settings-page-DBQ-WETQ.js} +1 -1
  15. package/dist/gateway/static/root/assets/{capabilities-page-B3m8xGzd.js → capabilities-page-D-nQ6Zzi.js} +2 -2
  16. package/dist/gateway/static/root/assets/{capabilities-settings-panel-VQ4fHuBV.js → capabilities-settings-panel-Dx1fpBmH.js} +1 -1
  17. package/dist/gateway/static/root/assets/{capability-header-actions-f5Ido4Eg.js → capability-header-actions-BRMqvQVb.js} +1 -1
  18. package/dist/gateway/static/root/assets/{channels-N4Vc2nEG.js → channels-DXfEP1FR.js} +1 -1
  19. package/dist/gateway/static/root/assets/{chat-terminal-dock-BwvTKwsn.js → chat-terminal-dock-BRdzCjWO.js} +1 -1
  20. package/dist/gateway/static/root/assets/{computer-settings-page-CAwUsKpw.js → computer-settings-page-BhCHMRpD.js} +1 -1
  21. package/dist/gateway/static/root/assets/{connector-service-page-C0HuAMuH.js → connector-service-page-BXE8Z-Ll.js} +1 -1
  22. package/dist/gateway/static/root/assets/{connectors-page-BcBmW8JT.js → connectors-page-D9RZjhw8.js} +1 -1
  23. package/dist/gateway/static/root/assets/{date-picker-DiQxRpe-.js → date-picker-BJ7N92wm.js} +1 -1
  24. package/dist/gateway/static/root/assets/{dependency-picker-Ds0_BJbN.js → dependency-picker-gyxCM-hb.js} +1 -1
  25. package/dist/gateway/static/root/assets/{desktop-pet-ZMEOYwrR.js → desktop-pet-B-WM4l-L.js} +1 -1
  26. package/dist/gateway/static/root/assets/{desktop-pet-settings-DkyTqD07.js → desktop-pet-settings-usJqcew5.js} +1 -1
  27. package/dist/gateway/static/root/assets/{device-pairing-wizard-CvaI5ZJZ.js → device-pairing-wizard-DoSR4DGk.js} +1 -1
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-Bfv93eK1.js → directory-picker-path-field-DqVlV2YH.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-page-JXKGtIdM.js → extension-page-CUule9SU.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-settings-page-lsQ2xvbr.js → extension-settings-page-_OFukkEJ.js} +1 -1
  31. package/dist/gateway/static/root/assets/{fallback-models-7bG0AND1.js → fallback-models-CiSc3h8i.js} +1 -1
  32. package/dist/gateway/static/root/assets/{gateway-settings-BpbcoPx9.js → gateway-settings-qSUrpS1h.js} +1 -1
  33. package/dist/gateway/static/root/assets/{home-page-BxctC0aJ.js → home-page-COjDsuzg.js} +1 -1
  34. package/dist/gateway/static/root/assets/{imports-page-Bq8CazCb.js → imports-page-DdvIj-ZL.js} +1 -1
  35. package/dist/gateway/static/root/assets/{index-B40-KDN8.js → index-DEaVabvo.js} +6 -6
  36. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-kkAevkl2.js → keyboard-shortcuts-settings-DbqFlNsF.js} +1 -1
  37. package/dist/gateway/static/root/assets/{local-app-workbench-page-abLaf1hW.js → local-app-workbench-page-REowUzkp.js} +1 -1
  38. package/dist/gateway/static/root/assets/{local-apps-page-nwsnwYjK.js → local-apps-page-DdCMNn_z.js} +1 -1
  39. package/dist/gateway/static/root/assets/{logs-page-BEgYS-Xg.js → logs-page-B_6fHDoi.js} +1 -1
  40. package/dist/gateway/static/root/assets/management-settings-D4vcSRE3.js +1 -0
  41. package/dist/gateway/static/root/assets/{note-detail-panel-CCnfurBR.js → note-detail-panel-B7U6EbAi.js} +3 -3
  42. package/dist/gateway/static/root/assets/{notes-page-D9u_znxM.js → notes-page-BzHVaH8j.js} +1 -1
  43. package/dist/gateway/static/root/assets/{page-context-capture-button-BO3FoRej.js → page-context-capture-button-D7Y4vFRN.js} +1 -1
  44. package/dist/gateway/static/root/assets/personal-page-E6huhFk4.js +1 -0
  45. package/dist/gateway/static/root/assets/{product-open-page-Dso2_hyl.js → product-open-page-CK_czbBx.js} +1 -1
  46. package/dist/gateway/static/root/assets/{product-preview-content-CkvVb3EA.js → product-preview-content-CU6KlaVP.js} +1 -1
  47. package/dist/gateway/static/root/assets/{project-detail-page-UjrrzE3H.js → project-detail-page-c3ye2bdq.js} +1 -1
  48. package/dist/gateway/static/root/assets/{projects-page-C1h63P2M.js → projects-page-BA1UuuRF.js} +1 -1
  49. package/dist/gateway/static/root/assets/{remote-access-hub-BJifH8AB.js → remote-access-hub-D_FLVZAm.js} +1 -1
  50. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-vG1wqcEb.js → runtime-tools-settings-panel-Cxjmwdyf.js} +1 -1
  51. package/dist/gateway/static/root/assets/{scenes-page-CwoAoYMX.js → scenes-page-Av47PHdM.js} +1 -1
  52. package/dist/gateway/static/root/assets/{schema-form-BIsHdyz7.js → schema-form-IM7QeSm3.js} +1 -1
  53. package/dist/gateway/static/root/assets/{sessions-page-BcCLp3yU.js → sessions-page-Bol3ScEc.js} +1 -1
  54. package/dist/gateway/static/root/assets/settings-advanced-gate-DpCanqrD.js +1 -0
  55. package/dist/gateway/static/root/assets/{settings-page-z9Jlk0BL.js → settings-page-BeVtwwVd.js} +1 -1
  56. package/dist/gateway/static/root/assets/{setup-status-panel-CrpXECqe.js → setup-status-panel-zTmrMwMm.js} +1 -1
  57. package/dist/gateway/static/root/assets/{shares-settings-D9XpTJXP.js → shares-settings-Bkhkt_6M.js} +1 -1
  58. package/dist/gateway/static/root/assets/{skill-api-DtPOf1aW.js → skill-api-Dgwc707w.js} +1 -1
  59. package/dist/gateway/static/root/assets/{skills-page-Bq9-2b9U.js → skills-page-CFIte-vM.js} +1 -1
  60. package/dist/gateway/static/root/assets/{system-settings-panel-P7T729uD.js → system-settings-panel-Ck6zGDHb.js} +1 -1
  61. package/dist/gateway/static/root/assets/{task-detail-page-CsB9AFx6.js → task-detail-page-C3ZPEZqw.js} +1 -1
  62. package/dist/gateway/static/root/assets/{tunnel-api-CuowqIZ7.js → tunnel-api-CjxMpAm2.js} +1 -1
  63. package/dist/gateway/static/root/assets/{usage-page-avX3msoZ.js → usage-page-Dnhp9xQ4.js} +1 -1
  64. package/dist/gateway/static/root/assets/{user-model-page-DGDBWw7P.js → user-model-page-sx1lNWKf.js} +1 -1
  65. package/dist/gateway/static/root/assets/{work-discovery-overlay-BgJNz2tH.js → work-discovery-overlay-CVd_y3K2.js} +1 -1
  66. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-1I2q2J_U.js → workflow-run-setup-panel-Dwg40uGK.js} +1 -1
  67. package/dist/gateway/static/root/assets/{workflows-page-DhJl9pnO.js → workflows-page-BQR4JdXB.js} +1 -1
  68. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-CnPBP1V_.js → xopc-cloud-account-card-CaKc_J7j.js} +1 -1
  69. package/dist/gateway/static/root/index.html +1 -1
  70. package/dist/package.js +1 -1
  71. package/dist/packages/realtime-protocol/src/voice.js +11 -0
  72. package/dist/src/agent/agent-manager.js +4 -4
  73. package/dist/src/agent/background-review/run-background-review.js +1 -1
  74. package/dist/src/agent/embedded/model-runtime.js +1 -1
  75. package/dist/src/agent/embedded/run-for-session.js +2 -2
  76. package/dist/src/agent/embedded/run-turn.js +2 -2
  77. package/dist/src/agent/image/tool-model-config.js +1 -1
  78. package/dist/src/agent/service.js +3 -3
  79. package/dist/src/agent/session/session-inspector.js +1 -1
  80. package/dist/src/agent/tasks/task-judge-service.js +3 -3
  81. package/dist/src/agent-config/schema.d.ts +9 -0
  82. package/dist/src/agent-config/schema.js +1 -0
  83. package/dist/src/ai-assist/text-assist.js +1 -1
  84. package/dist/src/auth/credentials.js +2 -2
  85. package/dist/src/auth/model-credential-store.js +1 -1
  86. package/dist/src/auth/sync-provider-auth.js +1 -1
  87. package/dist/src/chat-commands/builtins/config.js +1 -1
  88. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  89. package/dist/src/cli/commands/doctor/checks/image-providers.js +1 -1
  90. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  91. package/dist/src/cli/commands/gateway/shared.js +2 -1
  92. package/dist/src/cli/commands/models.js +1 -1
  93. package/dist/src/cli/commands/onboard/model.js +3 -3
  94. package/dist/src/computer/runtime.js +1 -1
  95. package/dist/src/config/gateway-bind.js +2 -1
  96. package/dist/src/config/index.js +5 -5
  97. package/dist/src/config/loader.js +1 -1
  98. package/dist/src/config/models-json.d.ts +8 -8
  99. package/dist/src/config/models-json.js +2 -2
  100. package/dist/src/config/schema.d.ts +13 -12
  101. package/dist/src/config/schema.js +7 -3
  102. package/dist/src/daemon/constants.js +14 -9
  103. package/dist/src/daemon/index.js +4 -1
  104. package/dist/src/daemon/install-plan.js +2 -1
  105. package/dist/src/daemon/launchd.js +2 -1
  106. package/dist/src/daemon/schtasks.js +2 -1
  107. package/dist/src/daemon/service-audit.js +2 -1
  108. package/dist/src/daemon/service.js +2 -1
  109. package/dist/src/daemon/systemd.js +2 -1
  110. package/dist/src/extensions/activation-context.js +1 -1
  111. package/dist/src/gateway/client-ip.js +2 -1
  112. package/dist/src/gateway/hono/app.js +2 -1
  113. package/dist/src/gateway/hono/lib/config-payload.js +2 -2
  114. package/dist/src/gateway/hono/middleware/auth.d.ts +3 -5
  115. package/dist/src/gateway/hono/middleware/auth.js +56 -14
  116. package/dist/src/gateway/hono/middleware/logger.js +2 -1
  117. package/dist/src/gateway/hono/middleware/public-device-rate-limit.d.ts +16 -0
  118. package/dist/src/gateway/hono/middleware/public-device-rate-limit.js +43 -0
  119. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +3 -2
  120. package/dist/src/gateway/hono/oauth-async.js +2 -1
  121. package/dist/src/gateway/hono/routes/browser.js +2 -1
  122. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  123. package/dist/src/gateway/hono/routes/config.js +2 -1
  124. package/dist/src/gateway/hono/routes/device-pairing-approval.d.ts +3 -8
  125. package/dist/src/gateway/hono/routes/device-pairing-approval.js +5 -20
  126. package/dist/src/gateway/hono/routes/devices.js +25 -9
  127. package/dist/src/gateway/hono/routes/endpoint-tools.js +1 -0
  128. package/dist/src/gateway/hono/routes/models.js +3 -3
  129. package/dist/src/gateway/hono/routes/observability.js +1 -1
  130. package/dist/src/gateway/hono/routes/personal-agent.js +3 -2
  131. package/dist/src/gateway/hono/routes/public-gateway.js +6 -6
  132. package/dist/src/gateway/hono/routes/shares.js +2 -1
  133. package/dist/src/gateway/hono/routes/voice.js +2 -1
  134. package/dist/src/gateway/host.js +9 -4
  135. package/dist/src/gateway/index.js +8 -4
  136. package/dist/src/gateway/listen.js +2 -1
  137. package/dist/src/gateway/rate-limit/auth-policy.js +7 -11
  138. package/dist/src/gateway/rate-limit/buckets.d.ts +6 -0
  139. package/dist/src/gateway/rate-limit/buckets.js +211 -189
  140. package/dist/src/gateway/rate-limit/env-flags.js +4 -1
  141. package/dist/src/gateway/rate-limit/index.js +13 -4
  142. package/dist/src/gateway/runtime-config.js +5 -3
  143. package/dist/src/gateway/security/audit.js +3 -2
  144. package/dist/src/gateway/security/browser-session.js +2 -1
  145. package/dist/src/gateway/security/device-request-proof.d.ts +28 -0
  146. package/dist/src/gateway/security/device-request-proof.js +122 -0
  147. package/dist/src/gateway/security/loopback.js +7 -6
  148. package/dist/src/gateway/service/config-coordinator.js +1 -1
  149. package/dist/src/gateway/service/session-command-service.js +1 -1
  150. package/dist/src/gateway/service.js +12 -10
  151. package/dist/src/gateway/tailscale-auth.js +2 -1
  152. package/dist/src/gateway/ws-security.js +2 -1
  153. package/dist/src/home-intelligence/generator.js +1 -1
  154. package/dist/src/infra/rate-limit/failure-limiter.js +78 -90
  155. package/dist/src/infra/rate-limit/index.js +11 -3
  156. package/dist/src/infra/rate-limit/keyed-store.js +52 -47
  157. package/dist/src/infra/rate-limit/rate-limiter.js +55 -58
  158. package/dist/src/infra/update-service-refresh.js +2 -1
  159. package/dist/src/notes/service.js +1 -1
  160. package/dist/src/observability/runtime.js +1 -1
  161. package/dist/src/personal-agent/proactivity/service.js +2 -2
  162. package/dist/src/personal-agent/reply-composer.js +2 -2
  163. package/dist/src/personal-agent/repository.d.ts +3 -0
  164. package/dist/src/personal-agent/repository.js +1 -0
  165. package/dist/src/personal-agent/service.d.ts +6 -2
  166. package/dist/src/personal-agent/service.js +4 -3
  167. package/dist/src/platform/client.d.ts +1 -1
  168. package/dist/src/platform/contracts.d.ts +1 -1
  169. package/dist/src/platform/index.js +1 -1
  170. package/dist/src/providers/index.js +4 -4
  171. package/dist/src/providers/model-registry.js +2 -2
  172. package/dist/src/providers/provider-auth-service.js +1 -1
  173. package/dist/src/providers/provider-disconnect-core.js +1 -1
  174. package/dist/src/providers/register-runtime-providers.js +1 -1
  175. package/dist/src/providers/xopc-cloud-catalog-coordinator.js +1 -1
  176. package/dist/src/realtime/runtime.js +6 -0
  177. package/dist/src/realtime/tickets.d.ts +1 -0
  178. package/dist/src/realtime/tickets.js +4 -0
  179. package/dist/src/remote-access/exposure-guards.js +2 -1
  180. package/dist/src/share/share-rate-limit.js +2 -1
  181. package/dist/src/share/share-url.js +2 -1
  182. package/dist/src/share/site-share-router.js +2 -1
  183. package/dist/src/storage/sqlite/device-access-repository.d.ts +7 -0
  184. package/dist/src/storage/sqlite/device-access-repository.js +22 -4
  185. package/dist/src/storage/sqlite/migrations/243_voice_opening_greetings.sql +12 -0
  186. package/dist/src/storage/sqlite/migrations/244_device_request_proofs.sql +8 -0
  187. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  188. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  189. package/dist/src/storage/sqlite/schema.js +1 -1
  190. package/dist/src/tasks/task-main-update-decision-service.js +2 -2
  191. package/dist/src/tui/backends/embedded-backend.js +1 -1
  192. package/dist/src/tui/tui.js +1 -1
  193. package/dist/src/tunnel/broker-client.js +2 -0
  194. package/dist/src/tunnel/tunnel-config.js +2 -2
  195. package/dist/src/tunnel/tunnel-rate-limit.js +2 -1
  196. package/dist/src/utils/logger/redact.js +4 -1
  197. package/dist/src/voice/platform-streams.d.ts +6 -0
  198. package/dist/src/voice/platform-streams.js +43 -4
  199. package/dist/src/voice/realtime/agentEngine.js +138 -83
  200. package/dist/src/voice/realtime/engine.d.ts +6 -0
  201. package/dist/src/voice/realtime/opening-greeting.d.ts +12 -0
  202. package/dist/src/voice/realtime/opening-greeting.js +22 -0
  203. package/dist/src/voice/realtime/runtime.js +90 -1
  204. package/dist/src/voice/realtime/runtime.types.d.ts +4 -0
  205. package/dist/src/work-discovery/service.js +2 -2
  206. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  207. package/package.json +3 -3
  208. package/dist/gateway/static/root/assets/management-settings-D_JQ6_X0.js +0 -1
  209. package/dist/gateway/static/root/assets/personal-page-BJn6UHAF.js +0 -1
  210. package/dist/gateway/static/root/assets/settings-advanced-gate-D114UdRI.js +0 -1
@@ -1,63 +1,60 @@
1
- import { KeyedStore } from "./keyed-store.js";
1
+ import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
+ import { KeyedStore, init_keyed_store } from "./keyed-store.js";
2
3
  //#region src/infra/rate-limit/rate-limiter.ts
3
- /**
4
- * Per-key fixed-window request-rate limiter. Every `consume()` counts toward
5
- * the limit; once the window's count hits `maxRequests`, subsequent consumes
6
- * return `allowed: false` until the window rolls over.
7
- *
8
- * Use this for *throughput* limiting (e.g. "15 req/min on /admin"). For
9
- * *failure-rate* limiting with lockout (e.g. brute-force protection), use
10
- * {@link FailureLimiter} instead.
11
- */
12
- var RateLimiter = class {
13
- store;
14
- clock;
15
- maxRequests;
16
- windowMs;
17
- constructor(cfg) {
18
- this.maxRequests = Math.max(1, Math.floor(cfg.maxRequests));
19
- this.windowMs = Math.max(1, Math.floor(cfg.windowMs));
20
- this.clock = cfg.clock ?? Date.now;
21
- this.store = new KeyedStore({
22
- staleAfterMs: cfg.staleAfterMs ?? this.windowMs * 4,
23
- clock: this.clock
24
- });
25
- }
26
- consume(key) {
27
- const now = this.clock();
28
- let state = this.store.get(key);
29
- if (!state) {
30
- state = {
31
- windowStart: now,
32
- count: 0,
33
- lastTouchedMs: now
4
+ var RateLimiter;
5
+ var init_rate_limiter = __esmMin((() => {
6
+ init_keyed_store();
7
+ RateLimiter = class {
8
+ store;
9
+ clock;
10
+ maxRequests;
11
+ windowMs;
12
+ constructor(cfg) {
13
+ this.maxRequests = Math.max(1, Math.floor(cfg.maxRequests));
14
+ this.windowMs = Math.max(1, Math.floor(cfg.windowMs));
15
+ this.clock = cfg.clock ?? Date.now;
16
+ this.store = new KeyedStore({
17
+ staleAfterMs: cfg.staleAfterMs ?? this.windowMs * 4,
18
+ clock: this.clock
19
+ });
20
+ }
21
+ consume(key) {
22
+ const now = this.clock();
23
+ let state = this.store.get(key);
24
+ if (!state) {
25
+ state = {
26
+ windowStart: now,
27
+ count: 0,
28
+ lastTouchedMs: now
29
+ };
30
+ this.store.set(key, state);
31
+ }
32
+ if (now - state.windowStart >= this.windowMs) {
33
+ state.windowStart = now;
34
+ state.count = 0;
35
+ }
36
+ state.lastTouchedMs = now;
37
+ if (state.count >= this.maxRequests) return {
38
+ allowed: false,
39
+ remaining: 0,
40
+ retryAfterMs: Math.max(0, state.windowStart + this.windowMs - now)
41
+ };
42
+ state.count += 1;
43
+ return {
44
+ allowed: true,
45
+ remaining: this.maxRequests - state.count,
46
+ retryAfterMs: 0
34
47
  };
35
- this.store.set(key, state);
36
48
  }
37
- if (now - state.windowStart >= this.windowMs) {
38
- state.windowStart = now;
39
- state.count = 0;
49
+ /** @internal Test hook. */
50
+ resetForTests() {
51
+ this.store.clear();
52
+ }
53
+ destroy() {
54
+ this.store.destroy();
40
55
  }
41
- state.lastTouchedMs = now;
42
- if (state.count >= this.maxRequests) return {
43
- allowed: false,
44
- remaining: 0,
45
- retryAfterMs: Math.max(0, state.windowStart + this.windowMs - now)
46
- };
47
- state.count += 1;
48
- return {
49
- allowed: true,
50
- remaining: this.maxRequests - state.count,
51
- retryAfterMs: 0
52
- };
53
- }
54
- /** @internal Test hook. */
55
- resetForTests() {
56
- this.store.clear();
57
- }
58
- destroy() {
59
- this.store.destroy();
60
- }
61
- };
56
+ };
57
+ }));
62
58
  //#endregion
63
- export { RateLimiter };
59
+ init_rate_limiter();
60
+ export { RateLimiter, init_rate_limiter };
@@ -1,9 +1,10 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { SERVICE_VERSION_ENV_KEY, formatGatewayServiceDescription } from "../daemon/constants.js";
3
+ import { SERVICE_VERSION_ENV_KEY, formatGatewayServiceDescription, init_constants } from "../daemon/constants.js";
4
4
  import path from "node:path";
5
5
  import fs from "node:fs/promises";
6
6
  //#region src/infra/update-service-refresh.ts
7
+ init_constants();
7
8
  init_logger();
8
9
  const log = createLogger("UpdateServiceRefresh");
9
10
  function resolveBinPath(bin) {
@@ -7,8 +7,8 @@ import { init_note_markdown, parseNoteMarkdown } from "./note-markdown.js";
7
7
  import { init_notes_repository, listNoteProjectSummaries } from "../storage/sqlite/notes-repository.js";
8
8
  import { changedFieldsFromPatch, emitActivity, previewText, systemActivityActor, systemActivitySource } from "../activity/emitter.js";
9
9
  import { getDefaultModelSync, init_providers, resolveModel } from "../providers/index.js";
10
- import { completeWithResolvedCredentials } from "../providers/model-call.js";
11
10
  import { DomainOutboxDispatcher } from "../infra/domain-outbox-dispatcher.js";
11
+ import { completeWithResolvedCredentials } from "../providers/model-call.js";
12
12
  import { partitionAttachmentsByReference } from "./note-attachment-sync.js";
13
13
  import { buildNoteAgentContextArtifact, getCachedNoteAgentContextArtifact } from "./agent-context.js";
14
14
  import { revokeNoteShareRecords } from "../share/note-share-revocation.js";
@@ -1,8 +1,8 @@
1
1
  import { init_context, runWithLogContext } from "../utils/logger/context.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { TracingConfigSchema, defaultTracingConfig, init_config } from "./config.js";
5
4
  import { CredentialResolver, init_credentials } from "../auth/credentials.js";
5
+ import { TracingConfigSchema, defaultTracingConfig, init_config } from "./config.js";
6
6
  import { LangfuseTarget } from "./langfuse.js";
7
7
  import { boundedJson, redactString } from "./sanitize.js";
8
8
  import { LocalTraceStore } from "./store.js";
@@ -6,13 +6,13 @@ import { init_src } from "../../../packages/gateway-contract/src/index.js";
6
6
  import { init_session_instance_repository, readCurrentTranscriptId } from "../../storage/sqlite/session-instance-repository.js";
7
7
  import { appendTranscriptEntry, init_transcript_repository } from "../../storage/sqlite/transcript-repository.js";
8
8
  import { AgentCatalogRepository, init_repository } from "../../agent-catalog/repository.js";
9
- import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../../providers/model-response.js";
10
9
  import { init_providers, resolveModel } from "../../providers/index.js";
11
- import { completeWithResolvedCredentials } from "../../providers/model-call.js";
12
10
  import { resolveUserContextSessionAccess } from "../../user-context/access-policy.js";
13
11
  import { getPersonalAgent } from "../repository.js";
14
12
  import { DurableState } from "../../storage/sqlite/durable-state.js";
15
13
  import { enqueueDue, enqueueWakeup, getAttention, getAttentionSources, getProactivitySettings, isQuiet, listAttention, localDay, preparationStrategy, recordFeedback, reserveModelCall, saveAttention, sourceFingerprint, userText } from "./repository.js";
14
+ import { completeWithResolvedCredentials } from "../../providers/model-call.js";
15
+ import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../../providers/model-response.js";
16
16
  import { emitSessionTranscriptUpdate } from "../../session/transcript-events.js";
17
17
  import { PERSONAL_PERSONA_GUIDANCE } from "../persona.js";
18
18
  import { personalConversationState } from "../conversation-state.js";
@@ -9,12 +9,12 @@ import { appendTranscriptEntry, init_transcript_repository, loadLlmMessagesForSe
9
9
  import { getSessionConfig, init_config_repository } from "../storage/sqlite/config-repository.js";
10
10
  import { AgentCatalogRepository, init_repository } from "../agent-catalog/repository.js";
11
11
  import { init_agent_scope, resolveAgentProfileDir } from "../agent/agent-scope.js";
12
- import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../providers/model-response.js";
13
12
  import { init_providers, resolveModel } from "../providers/index.js";
14
- import { completeWithResolvedCredentials } from "../providers/model-call.js";
15
13
  import { getPersonalAgentByConversation } from "./repository.js";
16
14
  import { TaskConversationRepository } from "../tasks/task-conversation-repository.js";
17
15
  import { loadProfileBootstrapFiles } from "../agent/bootstrap/load-bootstrap-files.js";
16
+ import { completeWithResolvedCredentials } from "../providers/model-call.js";
17
+ import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../providers/model-response.js";
18
18
  import { emitSessionTranscriptUpdate } from "../session/transcript-events.js";
19
19
  import { PERSONAL_PERSONA_GUIDANCE } from "./persona.js";
20
20
  import { PERSONAL_REPLY_EXAMPLES, PERSONAL_REPLY_STYLE_RULES } from "./reply-style.js";
@@ -13,6 +13,9 @@ export interface PersonalAgentRecord {
13
13
  model: string;
14
14
  voice: string;
15
15
  } | null;
16
+ voiceCallPreferences: {
17
+ openingGreetingEnabled: boolean;
18
+ };
16
19
  preferences: Record<string, unknown>;
17
20
  revision: number;
18
21
  errorMessage: string | null;
@@ -48,6 +48,7 @@ function toRecord(ownerId, agent, session) {
48
48
  userCallName: getUserProfileSnapshot().callName ?? null,
49
49
  appearance: appearanceFrom(agent),
50
50
  voicePreference: agent.profile?.voicePreference ?? null,
51
+ voiceCallPreferences: agent.profile?.voiceCallPreferences ?? { openingGreetingEnabled: true },
51
52
  preferences: agent.profile?.responsePreferences ?? DEFAULT_PERSONAL_PREFERENCES,
52
53
  revision: agent.revision,
53
54
  errorMessage: agent.provisioningError ?? null
@@ -63,9 +63,13 @@ export declare function patchPersonalProfile(service: PersonalAgentHost, ownerId
63
63
  provider: string;
64
64
  model: string;
65
65
  voice: string;
66
- } | null): Promise<PersonalAgentRecord | null>;
66
+ } | null, voiceCallPreferences?: {
67
+ openingGreetingEnabled: boolean;
68
+ }): Promise<PersonalAgentRecord | null>;
67
69
  export declare function updatePersonalProfileRecord(ownerId: string, revision: number, displayName: string, preferences: PersonalPreferences, appearance: PersonalAppearance, voicePreference?: {
68
70
  provider: string;
69
71
  model: string;
70
72
  voice: string;
71
- } | null): Promise<PersonalAgentRecord | null>;
73
+ } | null, voiceCallPreferences?: {
74
+ openingGreetingEnabled: boolean;
75
+ }): Promise<PersonalAgentRecord | null>;
@@ -159,14 +159,14 @@ async function provisionPersonalAgent(service, ownerId, requestedModel, availabl
159
159
  completePersonalOnboarding(ownerId);
160
160
  return getPersonalAgent(ownerId) ?? record;
161
161
  }
162
- async function patchPersonalProfile(service, ownerId, revision, displayName, preferences, appearance, voicePreference) {
163
- const updated = await updatePersonalProfileRecord(ownerId, revision, displayName, preferences, appearance, voicePreference);
162
+ async function patchPersonalProfile(service, ownerId, revision, displayName, preferences, appearance, voicePreference, voiceCallPreferences) {
163
+ const updated = await updatePersonalProfileRecord(ownerId, revision, displayName, preferences, appearance, voicePreference, voiceCallPreferences);
164
164
  if (!updated) return null;
165
165
  service.refreshAgentCatalog();
166
166
  service.agentService.evictSessionAgent(updated.conversationId);
167
167
  return updated;
168
168
  }
169
- async function updatePersonalProfileRecord(ownerId, revision, displayName, preferences, appearance, voicePreference) {
169
+ async function updatePersonalProfileRecord(ownerId, revision, displayName, preferences, appearance, voicePreference, voiceCallPreferences) {
170
170
  const current = new AgentCatalogRepository().get(personalAgentId(ownerId));
171
171
  if (!current || current.provisioningState !== "ready" || current.revision !== revision || getPersonalAgent(ownerId)?.state !== "ready") return null;
172
172
  const profile = {
@@ -175,6 +175,7 @@ async function updatePersonalProfileRecord(ownerId, revision, displayName, prefe
175
175
  emoji: appearanceEmoji(appearance),
176
176
  avatar: appearanceAvatar(appearance),
177
177
  ...voicePreference !== void 0 ? { voicePreference: voicePreference ?? void 0 } : {},
178
+ ...voiceCallPreferences ? { voiceCallPreferences } : {},
178
179
  responsePreferences: preferences,
179
180
  instructions: personalInstructions(preferences)
180
181
  };
@@ -67,9 +67,9 @@ export declare const RuntimeCommandSchema: z.ZodObject<{
67
67
  write: "write";
68
68
  execute: "execute";
69
69
  purchase: "purchase";
70
- admin: "admin";
71
70
  send: "send";
72
71
  publish: "publish";
72
+ admin: "admin";
73
73
  }>>;
74
74
  }, z.core.$strict>;
75
75
  data: z.ZodObject<{
@@ -153,9 +153,9 @@ export declare const AgentManifestSchema: z.ZodObject<{
153
153
  write: "write";
154
154
  execute: "execute";
155
155
  purchase: "purchase";
156
- admin: "admin";
157
156
  send: "send";
158
157
  publish: "publish";
158
+ admin: "admin";
159
159
  }>>;
160
160
  }, z.core.$strict>;
161
161
  data: z.ZodObject<{
@@ -1,5 +1,5 @@
1
- import { AgentManifestSchema, PlatformCapabilitySchema, PlatformConfigSchema, PlatformDiscoverySchema, PlatformEventSchema, init_contracts } from "./contracts.js";
2
1
  import { init_resolution, resolveConnectedPlatformDiscovery, resolveConnectedPlatformEndpoint, setActivePlatformDiscovery } from "./resolution.js";
2
+ import { AgentManifestSchema, PlatformCapabilitySchema, PlatformConfigSchema, PlatformDiscoverySchema, PlatformEventSchema, init_contracts } from "./contracts.js";
3
3
  import { PLATFORM_RUNTIME_PROFILE, PLATFORM_RUNTIME_PROVIDER, PlatformRuntimeClient, RuntimeCommandSchema, discoverPlatform } from "./client.js";
4
4
  import { processRuntimeCommand } from "./worker.js";
5
5
  //#region src/platform/index.ts
@@ -1,12 +1,12 @@
1
1
  import { __esmMin, __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
- import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
3
- import { assertCurrentModelProvider, init_provider_policy, isRetiredModelProvider } from "./provider-policy.js";
4
2
  import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
5
- import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
6
- import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
7
3
  import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
4
+ import { assertCurrentModelProvider, init_provider_policy, isRetiredModelProvider } from "./provider-policy.js";
8
5
  import { CredentialResolver, hasCredentials, init_credentials } from "../auth/credentials.js";
6
+ import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
9
7
  import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
8
+ import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
9
+ import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
10
10
  import { EXTENSION_PROVIDER_BASE_URL, init_constants } from "./constants.js";
11
11
  import { applyOfficialModelMetadataCorrections, getSupplementalModels, init_model_supplements } from "./model-supplements.js";
12
12
  import { getProviderRegistry, init_plugin_registry } from "./plugin-registry.js";
@@ -1,11 +1,11 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { createLogger } from "../utils/logger/index.js";
3
3
  import { init_logger } from "../utils/logger.js";
4
- import { init_resolve_config_value, resolveConfigValue, resolveHeaders } from "../config/resolve-config-value.js";
4
+ import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
5
5
  import { resolveModelsJsonPath } from "../config/paths.js";
6
6
  import { init_provider_policy, isRetiredModelProvider } from "./provider-policy.js";
7
+ import { init_resolve_config_value, resolveConfigValue, resolveHeaders } from "../config/resolve-config-value.js";
7
8
  import { getDefaultModelValues, init_models_json, validateModelsConfig } from "../config/models-json.js";
8
- import { getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
9
9
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
10
10
  import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
11
11
  import { existsSync, readFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { init_paths, resolveModelsJsonPath } from "../config/paths.js";
3
- import { assertCurrentModelProvider, init_provider_policy } from "./provider-policy.js";
4
3
  import { init_register_bundled_oauth_flows, registerBundledOAuthFlows } from "./register-bundled-oauth-flows.js";
4
+ import { assertCurrentModelProvider, init_provider_policy } from "./provider-policy.js";
5
5
  import { CredentialResolver, init_credentials } from "../auth/credentials.js";
6
6
  import { XopcModelCredentialStore, init_model_credential_store } from "../auth/model-credential-store.js";
7
7
  import { init_register_runtime_providers, registerRuntimeProviders } from "./register-runtime-providers.js";
@@ -1,8 +1,8 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { getModelRegistry, init_model_registry } from "./model-registry.js";
4
3
  import { init_oauth_provider_lock, withOAuthProviderLock } from "../auth/oauth-provider-lock.js";
5
4
  import { CredentialResolver, init_credentials } from "../auth/credentials.js";
5
+ import { getModelRegistry, init_model_registry } from "./model-registry.js";
6
6
  import { getProviderAuthService, init_provider_auth_service } from "./provider-auth-service.js";
7
7
  import { evictAllEmbeddedSessionRunners } from "../agent/embedded/session-runner.js";
8
8
  //#region src/providers/provider-disconnect-core.ts
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
+ import { getOAuthProviderDefinition, init_registry } from "../auth/oauth/registry.js";
2
3
  import { init_provider_policy, isRetiredModelProvider } from "./provider-policy.js";
3
4
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
4
- import { getOAuthProviderDefinition, init_registry } from "../auth/oauth/registry.js";
5
5
  import { XOPC_CLOUD_PROVIDER_ID, init_xopc_cloud_config, resolveXopcModelRouterUrl } from "./xopc-cloud-config.js";
6
6
  //#region src/providers/register-runtime-providers.ts
7
7
  function registerRuntimeProvider(modelRuntime, source) {
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { init_oauth_provider_lock, withOAuthProviderLock } from "../auth/oauth-provider-lock.js";
3
4
  import { ModelCatalogPersistence, init_model_catalog_persistence } from "./model-catalog-persistence.js";
4
5
  import { getModelCatalogStore, init_model_catalog_store } from "./model-catalog-store.js";
5
6
  import { getModelRegistry, init_model_registry } from "./model-registry.js";
6
- import { init_oauth_provider_lock, withOAuthProviderLock } from "../auth/oauth-provider-lock.js";
7
7
  import { reloadImageGenerationProviders } from "../agent/image/generation/provider-registry.js";
8
8
  import { disconnectProviderCore } from "./provider-disconnect-core.js";
9
9
  import { XopcCloudModelSource } from "./xopc-cloud-model-source.js";
@@ -3,6 +3,7 @@ import { init_logger } from "../utils/logger.js";
3
3
  import { hasGatewayScope, init_gateway_scopes } from "../gateway/security/gateway-scopes.js";
4
4
  import { EndpointToolPolicyError } from "../endpoint-tools/policy.js";
5
5
  import { REALTIME_CAPABILITIES, REALTIME_HEARTBEAT_INTERVAL_MS, REALTIME_HEARTBEAT_TIMEOUT_MS, REALTIME_HELLO_TIMEOUT_MS, REALTIME_MAX_CLIENT_FRAME_BYTES, parseClientRealtimeJsonFrame, parseClientRealtimeMessage } from "../../packages/realtime-protocol/src/index.js";
6
+ import { verifyDeviceConnectionProof } from "../gateway/security/device-request-proof.js";
6
7
  import { compactRunEvent } from "./compact-run-event.js";
7
8
  import { createPreauthConnectionBudget } from "../gateway/security/preauth-connection-budget.js";
8
9
  import { RealtimeBroker } from "./broker.js";
@@ -221,6 +222,11 @@ var RealtimeRuntime = class {
221
222
  socket.close(4401, "First realtime message must be hello");
222
223
  return;
223
224
  }
225
+ const pendingClaim = this.tickets.peek(message.payload.ticket);
226
+ if (!pendingClaim || pendingClaim.deviceId && !verifyDeviceConnectionProof(pendingClaim.deviceId, message.payload.ticket, new URL(request.url, "http://localhost").pathname + new URL(request.url, "http://localhost").search, typeof request.headers["x-xopc-proof"] === "string" ? request.headers["x-xopc-proof"] : void 0)) {
227
+ socket.close(4401, "Realtime authentication failed");
228
+ return;
229
+ }
224
230
  const claim = this.tickets.consume(message.payload.ticket, message.payload.clientId, message.payload.clientKind);
225
231
  if (!claim || !this.isPrincipalActive(claim.principalId)) {
226
232
  socket.close(4401, "Realtime authentication failed");
@@ -15,6 +15,7 @@ export interface IssuedRealtimeTicket extends RealtimeTicketClaim {
15
15
  export declare class RealtimeTicketStore {
16
16
  private readonly claims;
17
17
  issue(clientId: string, clientKind: RealtimeClientKind, principal: Omit<RealtimeTicketClaim, 'clientId' | 'clientKind' | 'expiresAt'>, now?: number): IssuedRealtimeTicket;
18
+ peek(ticket: string, now?: number): RealtimeTicketClaim | undefined;
18
19
  consume(ticket: string, clientId: string, clientKind: RealtimeClientKind, now?: number): RealtimeTicketClaim | undefined;
19
20
  revokePrincipal(principalId: string): void;
20
21
  private prune;
@@ -23,6 +23,10 @@ var RealtimeTicketStore = class {
23
23
  ...claim
24
24
  };
25
25
  }
26
+ peek(ticket, now = Date.now()) {
27
+ const claim = this.claims.get(ticketKey(ticket));
28
+ return claim && claim.expiresAt >= now ? claim : void 0;
29
+ }
26
30
  consume(ticket, clientId, clientKind, now = Date.now()) {
27
31
  const key = ticketKey(ticket);
28
32
  const claim = this.claims.get(key);
@@ -1,7 +1,8 @@
1
- import { isLoopbackHost } from "../gateway/host.js";
1
+ import { init_host, isLoopbackHost } from "../gateway/host.js";
2
2
  import { resolveGatewayBindMode } from "../config/gateway-bind.js";
3
3
  import { resolveGatewayListenPlan } from "../gateway/listen.js";
4
4
  //#region src/remote-access/exposure-guards.ts
5
+ init_host();
5
6
  function collectExposureConflicts(cfg) {
6
7
  const conflicts = [];
7
8
  const tailscaleMode = cfg.gateway?.tailscale?.mode ?? "off";
@@ -1,8 +1,9 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { buckets } from "../gateway/rate-limit/buckets.js";
4
- import "../gateway/rate-limit/index.js";
4
+ import { init_rate_limit } from "../gateway/rate-limit/index.js";
5
5
  //#region src/share/share-rate-limit.ts
6
+ init_rate_limit();
6
7
  init_logger();
7
8
  const log = createLogger("ShareRateLimit");
8
9
  /**
@@ -1,6 +1,7 @@
1
- import { enumerateLanGatewayCandidates } from "../gateway/host.js";
1
+ import { enumerateLanGatewayCandidates, init_host } from "../gateway/host.js";
2
2
  import { getTunnelService } from "../tunnel/tunnel-service.js";
3
3
  //#region src/share/share-url.ts
4
+ init_host();
4
5
  function resolveShareUrl(token, ctx) {
5
6
  const tunnelPublicUrl = activeTunnelPublicUrl();
6
7
  const { gatewayHost, gatewayPort, reverseProxyPublicUrl } = ctx;
@@ -1,13 +1,14 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { getClientIpFromHeaders, init_loopback } from "../gateway/security/loopback.js";
3
4
  import { resolveSiteShareConfig } from "./site-share-config.js";
4
5
  import "./share-store.js";
5
6
  import { getSiteShareStore } from "./site-share-store.js";
6
- import { getClientIpFromHeaders } from "../gateway/security/loopback.js";
7
7
  import { serveStaticSiteRequest } from "./site-static-serve.js";
8
8
  import { forwardHttpRequest, handleProxyWebSocketUpgrade } from "./site-proxy.js";
9
9
  import { renderShareExpiredPage } from "./share-landing.js";
10
10
  //#region src/share/site-share-router.ts
11
+ init_loopback();
11
12
  init_logger();
12
13
  const log = createLogger("SiteShareRouter");
13
14
  const SITE_SUBPATH_PREFIX = "/site/";
@@ -8,6 +8,7 @@ export type DeviceRecord = {
8
8
  platform: DevicePlatform;
9
9
  extensionId?: string;
10
10
  publicKeyJwk: DevicePublicKeyJwk;
11
+ requestProofVersion: number;
11
12
  scopes: GatewayScope[];
12
13
  createdAt: number;
13
14
  lastSeenAt?: number;
@@ -45,7 +46,12 @@ export declare function buildRefreshProofMessage(input: {
45
46
  nonce: string;
46
47
  requestId: string;
47
48
  nextRefreshToken: string;
49
+ requestProofVersion?: number;
48
50
  }): string;
51
+ export declare class DeviceRefreshRateLimitError extends Error {
52
+ readonly retryAfterMs: number;
53
+ constructor(retryAfterMs: number);
54
+ }
49
55
  export declare function rotateDeviceRefreshToken(input: {
50
56
  refreshToken: string;
51
57
  timestamp: number;
@@ -53,6 +59,7 @@ export declare function rotateDeviceRefreshToken(input: {
53
59
  requestId: string;
54
60
  nextRefreshToken: string;
55
61
  signature: string;
62
+ requestProofVersion?: number;
56
63
  now?: number;
57
64
  }): DeviceTokenPair;
58
65
  export declare function revokeDevice(deviceId: string, now?: number): boolean;
@@ -2,6 +2,8 @@ import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
2
  import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "./transaction.js";
3
3
  import { initialDeviceRefreshTokenSchema } from "../../../packages/gateway-contract/src/device-pairing.js";
4
4
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
5
+ import { buckets } from "../../gateway/rate-limit/buckets.js";
6
+ import { init_rate_limit } from "../../gateway/rate-limit/index.js";
5
7
  import { init_gateway_scopes, parseGatewayScopes } from "../../gateway/security/gateway-scopes.js";
6
8
  import crypto from "node:crypto";
7
9
  //#region src/storage/sqlite/device-access-repository.ts
@@ -23,6 +25,7 @@ function deviceFromRow(row) {
23
25
  displayName: row.display_name,
24
26
  platform: row.platform,
25
27
  publicKeyJwk: JSON.parse(row.public_key_jwk),
28
+ requestProofVersion: row.request_proof_version,
26
29
  ...row.extension_id ? { extensionId: row.extension_id } : {},
27
30
  scopes: parseGatewayScopes(row.scopes_json),
28
31
  createdAt: row.created_at,
@@ -109,7 +112,7 @@ function authenticateDeviceAccessToken(token, now = Date.now()) {
109
112
  };
110
113
  }
111
114
  function buildRefreshProofMessage(input) {
112
- return `xopc-device-refresh-v2\n${input.credentialId}\n${input.timestamp}\n${input.nonce}\n${input.requestId}\n${input.nextRefreshToken}`;
115
+ return `xopc-device-refresh-v2\n${input.credentialId}\n${input.timestamp}\n${input.nonce}\n${input.requestId}\n${input.nextRefreshToken}${input.requestProofVersion ? `\nrequest-proof:${input.requestProofVersion}` : ""}`;
113
116
  }
114
117
  function verifyRefreshProof(publicKeyJwk, message, signature) {
115
118
  try {
@@ -146,9 +149,17 @@ function rotateDeviceRefreshToken(input) {
146
149
  timestamp: input.timestamp,
147
150
  nonce: input.nonce,
148
151
  requestId: input.requestId,
149
- nextRefreshToken: input.nextRefreshToken
152
+ nextRefreshToken: input.nextRefreshToken,
153
+ requestProofVersion: input.requestProofVersion
150
154
  });
151
155
  if (!verifyRefreshProof(JSON.parse(deviceRow.public_key_jwk), message, input.signature)) throw new Error("Invalid refresh proof");
156
+ const refreshBudget = buckets.deviceRefresh().consume(credential.device_id);
157
+ if (!refreshBudget.allowed) throw new DeviceRefreshRateLimitError(refreshBudget.retryAfterMs);
158
+ if (deviceRow.request_proof_version > (input.requestProofVersion ?? 0)) throw new Error("Request proof downgrade denied");
159
+ if (input.requestProofVersion === 1 && deviceRow.request_proof_version === 0) {
160
+ db.prepare("UPDATE devices SET request_proof_version = 1 WHERE device_id = ?").run(credential.device_id);
161
+ db.prepare("UPDATE device_access_sessions SET revoked_at = ? WHERE device_id = ? AND revoked_at IS NULL").run(now, credential.device_id);
162
+ }
152
163
  if (credential.replaced_by === nextParsed.id && credential.rotation_request_id === input.requestId) {
153
164
  const nextCredential = db.prepare(`
154
165
  SELECT credential_id, device_id, token_hash, expires_at, replaced_by,
@@ -198,9 +209,10 @@ function revokeDevice(deviceId, now = Date.now()) {
198
209
  return changed;
199
210
  });
200
211
  }
201
- var ACCESS_TOKEN_TTL_MS, REFRESH_TOKEN_TTL_MS, REFRESH_PROOF_MAX_AGE_MS, ACCESS_TOKEN_PREFIX, REFRESH_TOKEN_PREFIX;
212
+ var ACCESS_TOKEN_TTL_MS, REFRESH_TOKEN_TTL_MS, REFRESH_PROOF_MAX_AGE_MS, ACCESS_TOKEN_PREFIX, REFRESH_TOKEN_PREFIX, DeviceRefreshRateLimitError;
202
213
  var init_device_access_repository = __esmMin((() => {
203
214
  init_src();
215
+ init_rate_limit();
204
216
  init_gateway_scopes();
205
217
  init_transaction();
206
218
  ACCESS_TOKEN_TTL_MS = 900 * 1e3;
@@ -208,7 +220,13 @@ var init_device_access_repository = __esmMin((() => {
208
220
  REFRESH_PROOF_MAX_AGE_MS = 300 * 1e3;
209
221
  ACCESS_TOKEN_PREFIX = "xopc_at_";
210
222
  REFRESH_TOKEN_PREFIX = "xopc_rt_";
223
+ DeviceRefreshRateLimitError = class extends Error {
224
+ constructor(retryAfterMs) {
225
+ super("Too many device refresh requests");
226
+ this.retryAfterMs = retryAfterMs;
227
+ }
228
+ };
211
229
  }));
212
230
  //#endregion
213
231
  init_device_access_repository();
214
- export { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, init_device_access_repository, issueDeviceTokenPair, listDevices, registerInitialDeviceRefreshToken, revokeDevice, rotateDeviceRefreshToken };
232
+ export { DeviceRefreshRateLimitError, authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, init_device_access_repository, issueDeviceTokenPair, listDevices, registerInitialDeviceRefreshToken, revokeDevice, rotateDeviceRefreshToken };
@@ -0,0 +1,12 @@
1
+ CREATE TABLE voice_opening_greetings (
2
+ principal_id TEXT NOT NULL,
3
+ conversation_id TEXT NOT NULL,
4
+ logical_call_id TEXT NOT NULL,
5
+ response_id TEXT NOT NULL,
6
+ state TEXT NOT NULL CHECK(state IN ('claimed', 'completed', 'skipped', 'interrupted', 'failed', 'expired')),
7
+ reason TEXT,
8
+ created_at INTEGER NOT NULL,
9
+ updated_at INTEGER NOT NULL,
10
+ PRIMARY KEY (principal_id, conversation_id, logical_call_id)
11
+ );
12
+ CREATE INDEX idx_voice_opening_greetings_created ON voice_opening_greetings(created_at);
@@ -0,0 +1,8 @@
1
+ ALTER TABLE devices ADD COLUMN request_proof_version INTEGER NOT NULL DEFAULT 0;
2
+ CREATE TABLE device_request_nonces (
3
+ device_id TEXT NOT NULL REFERENCES devices(device_id) ON DELETE CASCADE,
4
+ nonce TEXT NOT NULL,
5
+ expires_at INTEGER NOT NULL,
6
+ PRIMARY KEY (device_id, nonce)
7
+ ) WITHOUT ROWID;
8
+ CREATE INDEX device_request_nonces_expiry ON device_request_nonces(expires_at);
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 165;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 242;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 244;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration, discardOldScenes = false) {
57
57
  */
58
58
  function applyPendingMigrations(db, options = {}) {
59
59
  db.function("xopc_operation_id", () => currentOperationId() ?? null);
60
- const targetVersion = options.targetVersion ?? 242;
60
+ const targetVersion = options.targetVersion ?? 244;
61
61
  let currentVersion = readSchemaVersion(db);
62
62
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
63
63
  if (!options.migrationsDir && currentVersion < 165) throw new DatabaseSchemaTooOldError(currentVersion, 165);
@@ -95,7 +95,7 @@ function applyPendingMigrations(db, options = {}) {
95
95
  }
96
96
  /** Inspect schema version without mutating the database. */
97
97
  function inspectSchemaMigrationStatus(db, options = {}) {
98
- const appVersion = options.targetVersion ?? 242;
98
+ const appVersion = options.targetVersion ?? 244;
99
99
  const dbVersion = readSchemaVersion(db);
100
100
  if (dbVersion > appVersion) return {
101
101
  dbVersion,
@@ -137,7 +137,7 @@ var init_runner = __esmMin((() => {
137
137
  init_errors();
138
138
  log = createLogger("Sqlite:Migrations");
139
139
  XOPC_DB_BASELINE_SCHEMA_VERSION = 165;
140
- XOPC_DB_SCHEMA_VERSION = 242;
140
+ XOPC_DB_SCHEMA_VERSION = 244;
141
141
  }));
142
142
  //#endregion
143
143
  init_runner();
@@ -28,7 +28,7 @@ function ensureXopcDatabaseSchema(db, options = {}) {
28
28
  currentVersion = 165;
29
29
  }
30
30
  applyPendingMigrations(db, {
31
- targetVersion: 242,
31
+ targetVersion: 244,
32
32
  databasePath: fresh ? void 0 : options.databasePath
33
33
  });
34
34
  }