@pellux/goodvibes-sdk 1.0.0 → 1.2.0

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 (241) hide show
  1. package/dist/contracts/artifacts/operator-contract.json +2878 -264
  2. package/dist/events/communication.d.ts +1 -1
  3. package/dist/platform/agents/orchestrator-runner.d.ts +5 -5
  4. package/dist/platform/agents/orchestrator-runner.js +6 -6
  5. package/dist/platform/agents/orchestrator.d.ts +4 -4
  6. package/dist/platform/agents/orchestrator.js +2 -2
  7. package/dist/platform/agents/wrfc-controller.d.ts +1 -1
  8. package/dist/platform/agents/wrfc-controller.js +3 -3
  9. package/dist/platform/calendar/index.d.ts +2 -2
  10. package/dist/platform/calendar/index.js +3 -3
  11. package/dist/platform/calendar/oauth-providers.d.ts +1 -1
  12. package/dist/platform/calendar/oauth-providers.js +1 -1
  13. package/dist/platform/calendar/oauth-types.d.ts +1 -1
  14. package/dist/platform/calendar/oauth-types.js +1 -1
  15. package/dist/platform/companion/companion-chat-branching.d.ts +66 -0
  16. package/dist/platform/companion/companion-chat-branching.d.ts.map +1 -0
  17. package/dist/platform/companion/companion-chat-branching.js +142 -0
  18. package/dist/platform/companion/companion-chat-broker-bridge.d.ts +1 -1
  19. package/dist/platform/companion/companion-chat-broker-bridge.d.ts.map +1 -1
  20. package/dist/platform/companion/companion-chat-broker-sync.d.ts +2 -2
  21. package/dist/platform/companion/companion-chat-broker-sync.d.ts.map +1 -1
  22. package/dist/platform/companion/companion-chat-broker-sync.js +1 -1
  23. package/dist/platform/companion/companion-chat-manager.d.ts +26 -5
  24. package/dist/platform/companion/companion-chat-manager.d.ts.map +1 -1
  25. package/dist/platform/companion/companion-chat-manager.js +67 -81
  26. package/dist/platform/companion/companion-chat-routes.d.ts.map +1 -1
  27. package/dist/platform/companion/companion-chat-routes.js +77 -1
  28. package/dist/platform/companion/companion-chat-turn-execution.d.ts +61 -0
  29. package/dist/platform/companion/companion-chat-turn-execution.d.ts.map +1 -0
  30. package/dist/platform/companion/companion-chat-turn-execution.js +107 -0
  31. package/dist/platform/companion/companion-chat-types.d.ts +67 -0
  32. package/dist/platform/companion/companion-chat-types.d.ts.map +1 -1
  33. package/dist/platform/config/credential-status.d.ts +1 -1
  34. package/dist/platform/config/credential-status.js +1 -1
  35. package/dist/platform/config/index.d.ts +1 -1
  36. package/dist/platform/config/index.js +1 -1
  37. package/dist/platform/config/manager.d.ts +1 -1
  38. package/dist/platform/config/manager.js +1 -1
  39. package/dist/platform/config/migrations.d.ts +2 -2
  40. package/dist/platform/config/migrations.js +2 -2
  41. package/dist/platform/config/schema-domain-runtime.d.ts +8 -0
  42. package/dist/platform/config/schema-domain-runtime.d.ts.map +1 -1
  43. package/dist/platform/config/schema-domain-runtime.js +32 -0
  44. package/dist/platform/config/schema-types.d.ts +10 -2
  45. package/dist/platform/config/schema-types.d.ts.map +1 -1
  46. package/dist/platform/control-plane/gateway-scope-enforcement.js +2 -2
  47. package/dist/platform/control-plane/index.d.ts +2 -0
  48. package/dist/platform/control-plane/index.d.ts.map +1 -1
  49. package/dist/platform/control-plane/index.js +5 -1
  50. package/dist/platform/control-plane/invoke-input-validation.d.ts +1 -1
  51. package/dist/platform/control-plane/invoke-input-validation.js +1 -1
  52. package/dist/platform/control-plane/method-catalog-calendar.d.ts +2 -2
  53. package/dist/platform/control-plane/method-catalog-calendar.js +2 -2
  54. package/dist/platform/control-plane/method-catalog-channels.js +3 -3
  55. package/dist/platform/control-plane/method-catalog-control-automation.js +4 -4
  56. package/dist/platform/control-plane/method-catalog-control-companion.d.ts +1 -1
  57. package/dist/platform/control-plane/method-catalog-control-companion.d.ts.map +1 -1
  58. package/dist/platform/control-plane/method-catalog-control-companion.js +43 -0
  59. package/dist/platform/control-plane/method-catalog-control-core.js +3 -3
  60. package/dist/platform/control-plane/method-catalog-email.d.ts +1 -1
  61. package/dist/platform/control-plane/method-catalog-email.js +1 -1
  62. package/dist/platform/control-plane/method-catalog-fleet.d.ts +1 -1
  63. package/dist/platform/control-plane/method-catalog-push.d.ts +30 -0
  64. package/dist/platform/control-plane/method-catalog-push.d.ts.map +1 -0
  65. package/dist/platform/control-plane/method-catalog-push.js +80 -0
  66. package/dist/platform/control-plane/method-catalog-route-reconcile.d.ts +1 -1
  67. package/dist/platform/control-plane/method-catalog-runtime.d.ts.map +1 -1
  68. package/dist/platform/control-plane/method-catalog-runtime.js +177 -1
  69. package/dist/platform/control-plane/method-catalog.d.ts.map +1 -1
  70. package/dist/platform/control-plane/method-catalog.js +2 -0
  71. package/dist/platform/control-plane/operator-contract-schemas-fleet.js +1 -1
  72. package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts +15 -0
  73. package/dist/platform/control-plane/operator-contract-schemas-runtime.d.ts.map +1 -1
  74. package/dist/platform/control-plane/operator-contract-schemas-runtime.js +81 -0
  75. package/dist/platform/control-plane/routes/checkpoints.d.ts +1 -1
  76. package/dist/platform/control-plane/routes/fleet.d.ts +2 -2
  77. package/dist/platform/control-plane/routes/fleet.js +1 -1
  78. package/dist/platform/control-plane/routes/gateway-verb-error.d.ts +1 -1
  79. package/dist/platform/control-plane/routes/gateway-verb-error.js +1 -1
  80. package/dist/platform/control-plane/routes/index.js +1 -1
  81. package/dist/platform/control-plane/routes/invocation-params.d.ts +1 -1
  82. package/dist/platform/control-plane/routes/push.d.ts +26 -0
  83. package/dist/platform/control-plane/routes/push.d.ts.map +1 -0
  84. package/dist/platform/control-plane/routes/push.js +104 -0
  85. package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts +31 -0
  86. package/dist/platform/control-plane/routes/register-gateway-verb-groups.d.ts.map +1 -0
  87. package/dist/platform/control-plane/routes/register-gateway-verb-groups.js +16 -0
  88. package/dist/platform/control-plane/routes/register-w3-s2.d.ts +2 -2
  89. package/dist/platform/control-plane/routes/session-search.d.ts +4 -4
  90. package/dist/platform/control-plane/session-broker.d.ts +1 -1
  91. package/dist/platform/control-plane/session-broker.js +1 -1
  92. package/dist/platform/control-plane/session-store-importer.d.ts +1 -1
  93. package/dist/platform/control-plane/session-store-importer.js +1 -1
  94. package/dist/platform/control-plane/session-types.d.ts +1 -1
  95. package/dist/platform/core/orchestrator-runtime.d.ts +4 -4
  96. package/dist/platform/core/orchestrator-tool-runtime.d.ts +1 -1
  97. package/dist/platform/core/orchestrator-turn-loop.d.ts +6 -6
  98. package/dist/platform/core/orchestrator-turn-loop.d.ts.map +1 -1
  99. package/dist/platform/core/orchestrator-turn-loop.js +23 -22
  100. package/dist/platform/core/orchestrator.d.ts +10 -10
  101. package/dist/platform/core/orchestrator.d.ts.map +1 -1
  102. package/dist/platform/core/orchestrator.js +8 -8
  103. package/dist/platform/daemon/boot.d.ts +6 -0
  104. package/dist/platform/daemon/boot.d.ts.map +1 -1
  105. package/dist/platform/daemon/boot.js +1 -0
  106. package/dist/platform/daemon/control-plane.js +2 -2
  107. package/dist/platform/daemon/facade.d.ts +4 -7
  108. package/dist/platform/daemon/facade.d.ts.map +1 -1
  109. package/dist/platform/daemon/facade.js +5 -7
  110. package/dist/platform/daemon/http/router-session-broker-adapter.d.ts +1 -1
  111. package/dist/platform/daemon/http/router.d.ts +1 -0
  112. package/dist/platform/daemon/http/router.d.ts.map +1 -1
  113. package/dist/platform/daemon/http/router.js +36 -19
  114. package/dist/platform/daemon/http/runtime-route-types.d.ts +1 -1
  115. package/dist/platform/daemon/http/runtime-route-types.d.ts.map +1 -1
  116. package/dist/platform/daemon/http/webui-serving.d.ts +68 -0
  117. package/dist/platform/daemon/http/webui-serving.d.ts.map +1 -0
  118. package/dist/platform/daemon/http/webui-serving.js +230 -0
  119. package/dist/platform/knowledge/knowledge-api.d.ts +1 -1
  120. package/dist/platform/orchestration/budget.d.ts +2 -2
  121. package/dist/platform/orchestration/cancellation.d.ts +2 -2
  122. package/dist/platform/orchestration/controller-compat.d.ts +2 -3
  123. package/dist/platform/orchestration/controller-compat.d.ts.map +1 -1
  124. package/dist/platform/orchestration/dirty-guard.js +1 -1
  125. package/dist/platform/orchestration/engine.d.ts.map +1 -1
  126. package/dist/platform/orchestration/engine.js +3 -4
  127. package/dist/platform/orchestration/persistence.js +2 -2
  128. package/dist/platform/orchestration/phase-runner.d.ts +4 -4
  129. package/dist/platform/orchestration/scheduler.d.ts +1 -1
  130. package/dist/platform/orchestration/types.d.ts +3 -3
  131. package/dist/platform/presentation/glyphs.d.ts +1 -1
  132. package/dist/platform/presentation/glyphs.js +1 -1
  133. package/dist/platform/presentation/index.d.ts +3 -3
  134. package/dist/platform/presentation/index.js +3 -3
  135. package/dist/platform/presentation/thinking-phrases.d.ts +1 -1
  136. package/dist/platform/presentation/thinking-phrases.js +1 -1
  137. package/dist/platform/presentation/waiting-wording.d.ts +1 -1
  138. package/dist/platform/presentation/waiting-wording.js +1 -1
  139. package/dist/platform/push/delivery.d.ts +48 -0
  140. package/dist/platform/push/delivery.d.ts.map +1 -0
  141. package/dist/platform/push/delivery.js +117 -0
  142. package/dist/platform/push/encryption.d.ts +41 -0
  143. package/dist/platform/push/encryption.d.ts.map +1 -0
  144. package/dist/platform/push/encryption.js +82 -0
  145. package/dist/platform/push/index.d.ts +17 -0
  146. package/dist/platform/push/index.d.ts.map +1 -0
  147. package/dist/platform/push/index.js +10 -0
  148. package/dist/platform/push/service.d.ts +75 -0
  149. package/dist/platform/push/service.d.ts.map +1 -0
  150. package/dist/platform/push/service.js +95 -0
  151. package/dist/platform/push/subscription-store.d.ts +50 -0
  152. package/dist/platform/push/subscription-store.d.ts.map +1 -0
  153. package/dist/platform/push/subscription-store.js +123 -0
  154. package/dist/platform/push/types.d.ts +68 -0
  155. package/dist/platform/push/types.d.ts.map +1 -0
  156. package/dist/platform/push/types.js +13 -0
  157. package/dist/platform/push/vapid.d.ts +54 -0
  158. package/dist/platform/push/vapid.d.ts.map +1 -0
  159. package/dist/platform/push/vapid.js +113 -0
  160. package/dist/platform/runtime/feature-flags/flags.js +3 -3
  161. package/dist/platform/runtime/fleet/adapters/agent.d.ts +2 -2
  162. package/dist/platform/runtime/fleet/adapters/agent.d.ts.map +1 -1
  163. package/dist/platform/runtime/fleet/adapters/agent.js +4 -4
  164. package/dist/platform/runtime/fleet/adapters/automation.d.ts +1 -1
  165. package/dist/platform/runtime/fleet/adapters/automation.js +1 -1
  166. package/dist/platform/runtime/fleet/adapters/code-index.d.ts +1 -1
  167. package/dist/platform/runtime/fleet/adapters/code-index.js +1 -1
  168. package/dist/platform/runtime/fleet/adapters/orchestration.js +1 -1
  169. package/dist/platform/runtime/fleet/adapters/schedule.d.ts +4 -4
  170. package/dist/platform/runtime/fleet/adapters/schedule.js +4 -4
  171. package/dist/platform/runtime/fleet/adapters/trigger.d.ts +3 -4
  172. package/dist/platform/runtime/fleet/adapters/trigger.d.ts.map +1 -1
  173. package/dist/platform/runtime/fleet/adapters/trigger.js +3 -4
  174. package/dist/platform/runtime/fleet/adapters/wrfc.js +1 -1
  175. package/dist/platform/runtime/fleet/registry.d.ts +7 -7
  176. package/dist/platform/runtime/fleet/registry.d.ts.map +1 -1
  177. package/dist/platform/runtime/fleet/registry.js +3 -3
  178. package/dist/platform/runtime/fleet/types.d.ts +9 -9
  179. package/dist/platform/runtime/fleet/types.d.ts.map +1 -1
  180. package/dist/platform/runtime/memory-spine/client.d.ts +240 -0
  181. package/dist/platform/runtime/memory-spine/client.d.ts.map +1 -0
  182. package/dist/platform/runtime/memory-spine/client.js +221 -0
  183. package/dist/platform/runtime/memory-spine/index.d.ts +17 -0
  184. package/dist/platform/runtime/memory-spine/index.d.ts.map +1 -0
  185. package/dist/platform/runtime/memory-spine/index.js +16 -0
  186. package/dist/platform/runtime/memory-spine/recall-snapshot.d.ts +74 -0
  187. package/dist/platform/runtime/memory-spine/recall-snapshot.d.ts.map +1 -0
  188. package/dist/platform/runtime/memory-spine/recall-snapshot.js +74 -0
  189. package/dist/platform/runtime/operator-client.d.ts +1 -1
  190. package/dist/platform/runtime/services.d.ts +6 -6
  191. package/dist/platform/runtime/services.d.ts.map +1 -1
  192. package/dist/platform/runtime/services.js +9 -9
  193. package/dist/platform/runtime/session-spine/union-cache.d.ts +1 -1
  194. package/dist/platform/runtime/session-spine/union-cache.js +1 -1
  195. package/dist/platform/state/canonical-memory.d.ts +7 -7
  196. package/dist/platform/state/canonical-memory.js +8 -8
  197. package/dist/platform/state/code-index-chunking.js +1 -1
  198. package/dist/platform/state/code-index-db.d.ts +1 -1
  199. package/dist/platform/state/code-index-store.js +1 -1
  200. package/dist/platform/state/index.d.ts +2 -2
  201. package/dist/platform/state/index.d.ts.map +1 -1
  202. package/dist/platform/state/index.js +1 -1
  203. package/dist/platform/state/memory-recall-contract.d.ts +59 -4
  204. package/dist/platform/state/memory-recall-contract.d.ts.map +1 -1
  205. package/dist/platform/state/memory-recall-contract.js +79 -3
  206. package/dist/platform/state/memory-registry.d.ts +8 -0
  207. package/dist/platform/state/memory-registry.d.ts.map +1 -1
  208. package/dist/platform/state/memory-registry.js +10 -0
  209. package/dist/platform/state/memory-vector-store.js +1 -1
  210. package/dist/platform/state/sqlite-vec-loader.d.ts +1 -1
  211. package/dist/platform/state/sqlite-vec-loader.js +1 -1
  212. package/dist/platform/state/vibe-projection.d.ts +3 -3
  213. package/dist/platform/state/vibe-projection.js +3 -3
  214. package/dist/platform/tools/agent/manager.d.ts +10 -10
  215. package/dist/platform/tools/agent/manager.js +7 -7
  216. package/dist/platform/tools/exec/runtime.js +5 -5
  217. package/dist/platform/tools/exec/schema.d.ts +1 -1
  218. package/dist/platform/tools/exec/schema.d.ts.map +1 -1
  219. package/dist/platform/tools/fetch/runtime.d.ts +1 -1
  220. package/dist/platform/tools/registry.d.ts +1 -1
  221. package/dist/platform/tools/registry.js +1 -1
  222. package/dist/platform/types/tools.d.ts +1 -1
  223. package/dist/platform/utils/request-body.d.ts.map +1 -1
  224. package/dist/platform/utils/request-body.js +50 -5
  225. package/dist/platform/version.js +1 -1
  226. package/dist/platform/voice/index.d.ts +2 -0
  227. package/dist/platform/voice/index.d.ts.map +1 -1
  228. package/dist/platform/voice/index.js +3 -0
  229. package/dist/platform/voice/spoken-turn/audio-sink.d.ts +111 -0
  230. package/dist/platform/voice/spoken-turn/audio-sink.d.ts.map +1 -0
  231. package/dist/platform/voice/spoken-turn/audio-sink.js +1 -0
  232. package/dist/platform/voice/spoken-turn/controller.d.ts +117 -0
  233. package/dist/platform/voice/spoken-turn/controller.d.ts.map +1 -0
  234. package/dist/platform/voice/spoken-turn/controller.js +448 -0
  235. package/dist/platform/voice/spoken-turn/index.d.ts +16 -0
  236. package/dist/platform/voice/spoken-turn/index.d.ts.map +1 -0
  237. package/dist/platform/voice/spoken-turn/index.js +12 -0
  238. package/dist/platform/voice/spoken-turn/text-chunker.d.ts +33 -0
  239. package/dist/platform/voice/spoken-turn/text-chunker.d.ts.map +1 -0
  240. package/dist/platform/voice/spoken-turn/text-chunker.js +97 -0
  241. package/package.json +13 -9
@@ -0,0 +1,230 @@
1
+ /**
2
+ * webui-serving.ts
3
+ *
4
+ * Two opt-in capabilities that let a browser-hosted web UI reach the daemon:
5
+ *
6
+ * 1. Same-origin bundle serving (PRIMARY). When `controlPlane.webui.serve` is
7
+ * on, the daemon serves a configured build directory at `/` so the bundle
8
+ * and the API share an origin — the browser's same-origin policy is then a
9
+ * non-issue. This is wire-compatible with `tailscale serve`, which fronts
10
+ * the single daemon origin over HTTPS: bundle + API arrive same-origin.
11
+ * The bundle is public (served without a token); the app itself
12
+ * token-authenticates its API calls, so no wire data leaks from serving
13
+ * static files.
14
+ *
15
+ * 2. Cross-origin request support (SECONDARY). When `controlPlane.cors.enabled`
16
+ * is on, OPTIONS preflight is answered and Access-Control-Allow-* headers
17
+ * are emitted ONLY for origins on the explicit `controlPlane.cors.allowedOrigins`
18
+ * allowlist (the Vite dev server, a deliberately separate origin, etc.).
19
+ * There is no wildcard: the matched origin is echoed back, credentials are
20
+ * allowlist-gated, and `Vary: Origin` is always set so caches stay correct.
21
+ *
22
+ * BOTH default OFF. With both off the daemon behaves exactly as before: no bundle
23
+ * is served and no Access-Control-Allow-Origin is ever emitted. The loopback
24
+ * default posture is unchanged; these capabilities are explicit opt-ins, never
25
+ * auto-enabled by network host mode.
26
+ */
27
+ import { resolve, sep } from 'node:path';
28
+ import { readStringList } from '../helpers.js';
29
+ function readConfig(configManager, key) {
30
+ const getter = configManager.get;
31
+ return typeof getter === 'function' ? getter.call(configManager, key) : undefined;
32
+ }
33
+ /** Read the current serving posture from config. Cheap; called per request. */
34
+ export function resolveWebuiServingPosture(configManager) {
35
+ const serveBundle = readConfig(configManager, 'controlPlane.webui.serve') === true;
36
+ const bundleDirRaw = readConfig(configManager, 'controlPlane.webui.bundleDir');
37
+ const corsEnabled = readConfig(configManager, 'controlPlane.cors.enabled') === true;
38
+ const allowedOrigins = readStringList(readConfig(configManager, 'controlPlane.cors.allowedOrigins')) ?? [];
39
+ const openaiPrefixRaw = readConfig(configManager, 'controlPlane.openaiCompatible.pathPrefix');
40
+ return {
41
+ serveBundle,
42
+ bundleDir: typeof bundleDirRaw === 'string' ? bundleDirRaw.trim() : '',
43
+ cors: { enabled: corsEnabled, allowedOrigins },
44
+ openaiPathPrefix: typeof openaiPrefixRaw === 'string' && openaiPrefixRaw.trim() ? openaiPrefixRaw.trim() : '/v1',
45
+ };
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // CORS (secondary path)
49
+ // ---------------------------------------------------------------------------
50
+ /** Append a token to an existing Vary header without duplicating it. */
51
+ function appendVary(existing, token) {
52
+ if (!existing)
53
+ return token;
54
+ const parts = existing.split(',').map((p) => p.trim()).filter(Boolean);
55
+ if (parts.some((p) => p.toLowerCase() === token.toLowerCase()))
56
+ return existing;
57
+ return [...parts, token].join(', ');
58
+ }
59
+ /** True when the origin is on the explicit allowlist (exact match, no wildcard). */
60
+ function isOriginAllowed(origin, allowlist) {
61
+ return allowlist.includes(origin);
62
+ }
63
+ /**
64
+ * Answer a CORS preflight (OPTIONS). Emits Access-Control-Allow-* only for an
65
+ * allowlisted origin; a non-allowlisted origin is refused honestly (403, no
66
+ * Access-Control-Allow-Origin) so the browser preflight fails cleanly.
67
+ */
68
+ export function handleCorsPreflight(req, posture) {
69
+ const origin = req.headers.get('origin');
70
+ // A preflight with no Origin is not a browser CORS preflight — answer 204 with
71
+ // no allow-origin (nothing to grant); never emit a wildcard.
72
+ if (origin === null) {
73
+ return new Response(null, { status: 204, headers: { Vary: 'Origin' } });
74
+ }
75
+ if (!isOriginAllowed(origin, posture.cors.allowedOrigins)) {
76
+ return Response.json({ error: 'ORIGIN_NOT_ALLOWED', code: 'ORIGIN_NOT_ALLOWED', message: 'Origin is not on controlPlane.cors.allowedOrigins.' }, { status: 403, headers: { Vary: 'Origin' } });
77
+ }
78
+ // Echo the requested headers when present, otherwise a safe default that always
79
+ // includes Authorization so the bearer-token API flow works cross-origin.
80
+ const requestedHeaders = req.headers.get('access-control-request-headers');
81
+ const allowHeaders = requestedHeaders && requestedHeaders.trim()
82
+ ? requestedHeaders
83
+ : 'Authorization, Content-Type';
84
+ return new Response(null, {
85
+ status: 204,
86
+ headers: {
87
+ 'Access-Control-Allow-Origin': origin,
88
+ 'Access-Control-Allow-Credentials': 'true',
89
+ 'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS',
90
+ 'Access-Control-Allow-Headers': allowHeaders,
91
+ 'Access-Control-Max-Age': '600',
92
+ Vary: 'Origin',
93
+ },
94
+ });
95
+ }
96
+ /**
97
+ * Decorate an actual (non-preflight) response with CORS headers when the request
98
+ * carries an allowlisted Origin. `Vary: Origin` is always added while CORS is
99
+ * enabled so caches never serve an allow-origin to the wrong origin. A
100
+ * non-allowlisted origin gets Vary but NO Access-Control-Allow-Origin — the
101
+ * browser then blocks the read honestly.
102
+ */
103
+ export function applyCorsHeaders(req, response, posture) {
104
+ const origin = req.headers.get('origin');
105
+ if (origin === null)
106
+ return response;
107
+ const headers = new Headers(response.headers);
108
+ headers.set('Vary', appendVary(headers.get('Vary'), 'Origin'));
109
+ if (isOriginAllowed(origin, posture.cors.allowedOrigins)) {
110
+ headers.set('Access-Control-Allow-Origin', origin);
111
+ headers.set('Access-Control-Allow-Credentials', 'true');
112
+ }
113
+ return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Static bundle serving (primary path)
117
+ // ---------------------------------------------------------------------------
118
+ /** Extension → content type for the common web-bundle asset kinds. */
119
+ const CONTENT_TYPES = {
120
+ html: 'text/html; charset=utf-8',
121
+ js: 'text/javascript; charset=utf-8',
122
+ mjs: 'text/javascript; charset=utf-8',
123
+ css: 'text/css; charset=utf-8',
124
+ json: 'application/json; charset=utf-8',
125
+ map: 'application/json; charset=utf-8',
126
+ svg: 'image/svg+xml',
127
+ png: 'image/png',
128
+ jpg: 'image/jpeg',
129
+ jpeg: 'image/jpeg',
130
+ gif: 'image/gif',
131
+ webp: 'image/webp',
132
+ avif: 'image/avif',
133
+ ico: 'image/x-icon',
134
+ woff: 'font/woff',
135
+ woff2: 'font/woff2',
136
+ ttf: 'font/ttf',
137
+ wasm: 'application/wasm',
138
+ txt: 'text/plain; charset=utf-8',
139
+ webmanifest: 'application/manifest+json',
140
+ };
141
+ function extensionOf(pathname) {
142
+ const base = pathname.slice(pathname.lastIndexOf('/') + 1);
143
+ const dot = base.lastIndexOf('.');
144
+ return dot > 0 ? base.slice(dot + 1).toLowerCase() : '';
145
+ }
146
+ function contentTypeFor(pathname) {
147
+ return CONTENT_TYPES[extensionOf(pathname)] ?? 'application/octet-stream';
148
+ }
149
+ /** True when a path belongs to the daemon API/route surface and must never be
150
+ * served as a static file (API routes keep precedence). Boundary-aware so a SPA
151
+ * route like `/tasks` is not mistaken for the daemon's `/task` route. */
152
+ function isReservedApiPath(pathname, openaiPrefix) {
153
+ const reserved = ['/api', '/login', '/webhook', '/task', openaiPrefix];
154
+ return reserved.some((base) => pathname === base || pathname.startsWith(`${base}/`));
155
+ }
156
+ /** True when the request looks like an SPA navigation (HTML document) rather than
157
+ * a fetch for a concrete asset — used to decide whether the index.html fallback
158
+ * applies. A missing concrete asset must 404, not return the HTML shell. */
159
+ function isNavigationRequest(req, pathname) {
160
+ if (extensionOf(pathname) === '')
161
+ return true;
162
+ return (req.headers.get('accept') ?? '').includes('text/html');
163
+ }
164
+ function cacheControlFor(pathname, isShell) {
165
+ if (isShell || extensionOf(pathname) === 'html')
166
+ return 'no-cache';
167
+ if (pathname.includes('/assets/'))
168
+ return 'public, max-age=31536000, immutable';
169
+ return 'public, max-age=3600';
170
+ }
171
+ async function fileResponse(req, file, pathname, isShell) {
172
+ const headers = {
173
+ 'Content-Type': contentTypeFor(pathname),
174
+ 'Cache-Control': cacheControlFor(pathname, isShell),
175
+ };
176
+ if (req.method === 'HEAD') {
177
+ const size = await file.size;
178
+ return new Response(null, { status: 200, headers: { ...headers, 'Content-Length': String(size) } });
179
+ }
180
+ return new Response(file, { status: 200, headers });
181
+ }
182
+ /**
183
+ * Serve a file from the configured bundle directory, with SPA fallback to
184
+ * index.html for navigation routes. Returns null when serving is disabled, the
185
+ * request is not a GET/HEAD, or the path is a reserved API route — in every
186
+ * "null" case the caller continues with normal daemon routing, so behavior is
187
+ * unchanged when the capability is off. Path traversal outside the bundle
188
+ * directory is refused with 403.
189
+ */
190
+ export async function serveWebuiBundle(req, posture) {
191
+ if (!posture.serveBundle || !posture.bundleDir)
192
+ return null;
193
+ if (req.method !== 'GET' && req.method !== 'HEAD')
194
+ return null;
195
+ const url = new URL(req.url);
196
+ let pathname;
197
+ try {
198
+ pathname = decodeURIComponent(url.pathname);
199
+ }
200
+ catch {
201
+ return new Response('Bad Request', { status: 400 });
202
+ }
203
+ if (pathname.includes('\0'))
204
+ return new Response('Bad Request', { status: 400 });
205
+ if (isReservedApiPath(pathname, posture.openaiPathPrefix))
206
+ return null;
207
+ const root = resolve(posture.bundleDir);
208
+ const relative = pathname === '/' ? 'index.html' : pathname.replace(/^\/+/, '');
209
+ const resolved = resolve(root, relative);
210
+ // Reject anything that escapes the bundle root (path traversal).
211
+ if (resolved !== root && !resolved.startsWith(root + sep)) {
212
+ return new Response('Forbidden', { status: 403 });
213
+ }
214
+ const file = Bun.file(resolved);
215
+ if (await file.exists()) {
216
+ const isShell = resolved === resolve(root, 'index.html');
217
+ // Derive the content type from the resolved file path, not the request path —
218
+ // a `GET /` serves index.html and must answer text/html, not octet-stream.
219
+ return fileResponse(req, file, resolved, isShell);
220
+ }
221
+ // SPA fallback: an unknown navigation route serves the app shell; a missing
222
+ // concrete asset is an honest 404 (never the HTML shell in a JS/CSS request).
223
+ if (isNavigationRequest(req, pathname)) {
224
+ const indexFile = Bun.file(resolve(root, 'index.html'));
225
+ if (await indexFile.exists()) {
226
+ return fileResponse(req, indexFile, '/index.html', true);
227
+ }
228
+ }
229
+ return new Response('Not Found', { status: 404 });
230
+ }
@@ -75,7 +75,7 @@ export interface MemoryApi {
75
75
  export type MemoryApiRegistry = Pick<MemoryRegistry, 'add' | 'doctor' | 'delete' | 'exportBundle' | 'get' | 'getAll' | 'importBundle' | 'link' | 'linksFor' | 'rebuildVectors' | 'rebuildVectorsAsync' | 'review' | 'reviewQueue' | 'search' | 'searchSemantic' | 'update' | 'vectorStats'>;
76
76
  /**
77
77
  * memory-api-parallel query surface for the repo source-tree code index
78
- * (Wave-5 wo802, W5.3 Stage A). Deliberately NOT folded into MemoryApi:
78
+ * (Stage A, see CHANGELOG 0.38.0). Deliberately NOT folded into MemoryApi:
79
79
  * CodeContextResult/CodeIndexStats are a different record shape than
80
80
  * MemoryRecord, and code-index retrieval carries no cls/reviewState/trustTier
81
81
  * provenance semantics — see createCodeIndexApi / createMemoryApi below.
@@ -1,10 +1,10 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Budget enforcement (Wave 4, wo701). Enforcement point is BEFORE the
3
+ * Budget enforcement (see CHANGELOG 0.38.0). Enforcement point is BEFORE the
4
4
  * scheduler claims an item into a new phase (i.e. before a new agent spawn)
5
5
  * — never mid-item. An in-flight item's phase always runs to completion even
6
6
  * if a later check here would refuse a NEW claim: honest semantics, never a
7
- * mid-run kill on budget (see design doc (e)).
7
+ * mid-run kill on budget.
8
8
  *
9
9
  * Usage is summed directly from WorkItem.usage, which phase-runner.ts
10
10
  * populates from the SAME `priceUsage` function threaded through
@@ -1,7 +1,7 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Per-work-item cancellation registry (Wave 4, wo701) — the deferred W0.1
4
- * cooperative-cancellation piece.
3
+ * Per-work-item cancellation registry (see CHANGELOG 0.38.0) — closing a
4
+ * previously deferred cooperative-cancellation gap.
5
5
  *
6
6
  * One AbortController per in-flight WorkItem. `engine.kill(itemId)` aborts
7
7
  * the controller here AND calls `agentManager.cancel(agentId, 'kill')` — the
@@ -1,8 +1,7 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Controller-compat (Wave 4, wo701) — stage 1 of the 3-stage WrfcController
4
- * migration (see design doc (g) and the work-order report's design-
5
- * divergences section).
3
+ * Controller-compat (see CHANGELOG 0.38.0) — stage 1 of the 3-stage WrfcController
4
+ * migration.
6
5
  *
7
6
  * `fromChainSpec()` produces the canned two-phase engineer->review
8
7
  * WORKSTREAM SPEC that a `WrfcController.createChain(ownerRecord)` call
@@ -1 +1 @@
1
- {"version":3,"file":"controller-compat.d.ts","sourceRoot":"","sources":["../../../src/platform/orchestration/controller-compat.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,eAAe,EAAE,QAAQ,SAAI,GAAG,SAAS,EAAE,CAK5F;AAED,wBAAgB,aAAa,CAC3B,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,CAAC,EAC7C,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,aAAa,CAAC,GACxD,qBAAqB,CAOvB"}
1
+ {"version":3,"file":"controller-compat.d.ts","sourceRoot":"","sources":["../../../src/platform/orchestration/controller-compat.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,eAAe,EAAE,QAAQ,SAAI,GAAG,SAAS,EAAE,CAK5F;AAED,wBAAgB,aAAa,CAC3B,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,MAAM,CAAC,EAC7C,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,aAAa,CAAC,GACxD,qBAAqB,CAOvB"}
@@ -1,6 +1,6 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Dirty-residue guard (Wave 6, wo-F item 4) — prevents an orchestration
3
+ * Dirty-residue guard (see CHANGELOG 0.38.0) — prevents an orchestration
4
4
  * engine run's scoped commit from sweeping in uncommitted changes that were
5
5
  * ALREADY sitting in the working tree before this engine launched (typically
6
6
  * residue left behind by a previously killed run sharing the same
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/platform/orchestration/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/platform/orchestration/engine.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,8 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * OrchestrationEngine (Wave 4, wo701) — owns Workstream state and drives the
3
+ * OrchestrationEngine (see CHANGELOG 0.38.0) — owns Workstream state and drives the
4
4
  * pipeline. WRAPS a canned/authored workstream; does not rewrite or touch
5
- * WrfcController (stage 1 of the 3-stage migration — see controller-compat.ts
6
- * and the work-order report).
5
+ * WrfcController (stage 1 of the 3-stage migration — see controller-compat.ts).
7
6
  *
8
7
  * The tick loop is reactive, not timer-driven: `start()` runs one tick;
9
8
  * every phase-run completion re-runs tick() for its workstream. Because JS
@@ -49,7 +48,7 @@ export function createOrchestrationEngine(deps) {
49
48
  listeners.add(listener);
50
49
  return () => listeners.delete(listener);
51
50
  }
52
- // Dirty-residue guard (Wave 6, wo-F item 4): snapshot the working tree's
51
+ // Dirty-residue guard (see CHANGELOG 0.38.0): snapshot the working tree's
53
52
  // dirty paths + content hashes ONCE, right at engine launch (synchronous —
54
53
  // see dirty-guard.ts's doc comment for why this must not be a promise
55
54
  // backed by real subprocess I/O), before any phase of this run has had a
@@ -1,6 +1,6 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Persistence (Wave 4, wo701) — mirrors the WrfcController chain seams
3
+ * Persistence (see CHANGELOG 0.38.0) — mirrors the WrfcController chain seams
4
4
  * exactly: serializeChain:323 / deserializeChain:345 (including the
5
5
  * future-schemaVersion-reject guard at :364) / importChain:402. Writes to
6
6
  * `.goodvibes/orchestration/<workstreamId>.json` — SEPARATE from the TUI's
@@ -164,7 +164,7 @@ export function attachDebouncedWriter(projectRoot, getWorkstream, getCompletedRe
164
164
  timers.set(workstreamId, timer);
165
165
  }
166
166
  const unsubscribe = subscribe((event) => {
167
- // 'dirty-tree-at-launch' (Wave 6, wo-F item 4) is engine-wide, not
167
+ // 'dirty-tree-at-launch' (see CHANGELOG 0.38.0) is engine-wide, not
168
168
  // workstream-scoped — it has no workstreamId to schedule a write for.
169
169
  if (event.type === 'dirty-tree-at-launch')
170
170
  return;
@@ -1,6 +1,6 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Phase-runner (Wave 4, wo701) — runs one WorkItem through one Phase: spawn
3
+ * Phase-runner (see CHANGELOG 0.38.0) — runs one WorkItem through one Phase: spawn
4
4
  * agent, await completion, verify claims, run gates, commit, cleanup.
5
5
  *
6
6
  * REUSES the hardened WRFC primitives verbatim (same functions WrfcController
@@ -26,7 +26,7 @@
26
26
  * itself has either. This module therefore mirrors WrfcController's ACTUAL
27
27
  * (shared-directory) behavior rather than the brief's aspirational
28
28
  * per-item-isolated-worktree fan-out; true fan-out isolation is a valuable,
29
- * separately-scoped follow-up (see the work-order report).
29
+ * separately-scoped follow-up.
30
30
  *
31
31
  * SECOND REALITY-WINS DIVERGENCE: AgentManager.spawn()'s root-spawn
32
32
  * normalization (tools/agent/wrfc-batch-policy.ts isRootReviewRoleTask) force
@@ -84,8 +84,8 @@ export interface PhaseRunnerDeps {
84
84
  readonly priceUsage?: ((model: string | undefined, usage: WorkItemUsage) => number | null) | undefined;
85
85
  readonly skipClaimVerification?: boolean | undefined;
86
86
  /**
87
- * The dirty-tree snapshot taken synchronously at engine launch (Wave 6,
88
- * wo-F item 4 — see dirty-guard.ts). Absent (undefined) degrades to
87
+ * The dirty-tree snapshot taken synchronously at engine launch (see
88
+ * CHANGELOG 0.38.0 and dirty-guard.ts). Absent (undefined) degrades to
89
89
  * today's behavior: no exclusion, every candidate path is committed.
90
90
  */
91
91
  readonly launchDirtySnapshot?: DirtyLaunchSnapshot | undefined;
@@ -1,6 +1,6 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Scheduler (Wave 4, wo701) — pure capacity-matching helpers, no side
3
+ * Scheduler (see CHANGELOG 0.38.0) — pure capacity-matching helpers, no side
4
4
  * effects. The hard departure from WrfcController's pairwise
5
5
  * engineer<->reviewer binding (startReview:883/startFix:1042): each tick,
6
6
  * for every phase in ordinal order, free capacity slots (capacity minus
@@ -1,6 +1,6 @@
1
1
  /** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */
2
2
  /**
3
- * Orchestration engine — the model (W4.1, wo701).
3
+ * Orchestration engine — the model (see CHANGELOG 0.38.0).
4
4
  *
5
5
  * A phase/work-item pipeline layered OVER (not replacing) WrfcController. The
6
6
  * hard departure from WrfcController is pipeline semantics: an item advances
@@ -297,7 +297,7 @@ export interface GateOutcome {
297
297
  readonly unsatisfiedConstraintIds?: readonly string[] | undefined;
298
298
  }
299
299
  /**
300
- * Recorded on a PhaseResult when a scoped commit (Wave 6, wo-F item 4)
300
+ * Recorded on a PhaseResult when a scoped commit (see CHANGELOG 0.38.0)
301
301
  * excluded one or more candidate paths because they were already dirty
302
302
  * before this engine run launched and this phase never actually touched
303
303
  * them (see dirty-guard.ts's excludeUntouchedLaunchResidue). `skipped: true`
@@ -521,7 +521,7 @@ export type OrchestrationEvent = {
521
521
  readonly disposition: 'adopted' | 'reported';
522
522
  }
523
523
  /**
524
- * Emitted once per engine instance (Wave 6, wo-F item 4), right after the
524
+ * Emitted once per engine instance (see CHANGELOG 0.38.0), right after the
525
525
  * launch-time dirty-tree snapshot resolves, ONLY when it is non-empty.
526
526
  * Engine-wide, not workstream-scoped — `workstreamId` is absent (unlike
527
527
  * every other variant above) because it fires before any workstream is
@@ -4,7 +4,7 @@
4
4
  * and src/renderer/status-glyphs.ts (STATE_GLYPHS).
5
5
  *
6
6
  * This is one of the four genuinely-duplicated presentation tables named by the
7
- * W4-R1 renderer/input parity audit (both the TUI and the agent shipped a near-twin
7
+ * renderer/input parity audit (see CHANGELOG 1.0.0; both the TUI and the agent shipped a near-twin
8
8
  * copy). The TUI is the reference: it is the more-complete, more-recently-fixed
9
9
  * copy, and per the presentation-contract decision record its `status` group is
10
10
  * the one both renderers converge on.
@@ -4,7 +4,7 @@
4
4
  * and src/renderer/status-glyphs.ts (STATE_GLYPHS).
5
5
  *
6
6
  * This is one of the four genuinely-duplicated presentation tables named by the
7
- * W4-R1 renderer/input parity audit (both the TUI and the agent shipped a near-twin
7
+ * renderer/input parity audit (see CHANGELOG 1.0.0; both the TUI and the agent shipped a near-twin
8
8
  * copy). The TUI is the reference: it is the more-complete, more-recently-fixed
9
9
  * copy, and per the presentation-contract decision record its `status` group is
10
10
  * the one both renderers converge on.
@@ -2,7 +2,7 @@
2
2
  * @pellux/goodvibes-sdk/platform/presentation
3
3
  *
4
4
  * The presentation contract — the four genuinely-duplicated presentation
5
- * tables named by the W4-R1 renderer/input parity audit (goodvibes-tui vs
5
+ * tables named by the renderer/input parity audit (see CHANGELOG 1.0.0; goodvibes-tui vs
6
6
  * goodvibes-agent), hoisted into one pure, dependency-free module per Mike's
7
7
  * SDK-boundary rule (machinery needed by 2+ surfaces => SDK):
8
8
  *
@@ -15,8 +15,8 @@
15
15
  * The TUI is the reference for every value here; dark stays byte-identical to
16
16
  * today's TUI. See docs/decisions/2026-07-05-presentation-contract-sdk-extraction.md
17
17
  * for the full decision record, including the GLYPHS status-group reconciliation
18
- * ruling and the consumption plan (agent this wave via R4; TUI swap deferred to
19
- * a Wave-6 coherence pass).
18
+ * ruling and the consumption plan (the agent picks this up via R4; the TUI swap is
19
+ * deferred to a future coherence pass).
20
20
  *
21
21
  * PURE — no fs, no terminal I/O, no process globals. Painting stays
22
22
  * renderer-owned; this module owns only tokens and pure wording functions.
@@ -2,7 +2,7 @@
2
2
  * @pellux/goodvibes-sdk/platform/presentation
3
3
  *
4
4
  * The presentation contract — the four genuinely-duplicated presentation
5
- * tables named by the W4-R1 renderer/input parity audit (goodvibes-tui vs
5
+ * tables named by the renderer/input parity audit (see CHANGELOG 1.0.0; goodvibes-tui vs
6
6
  * goodvibes-agent), hoisted into one pure, dependency-free module per Mike's
7
7
  * SDK-boundary rule (machinery needed by 2+ surfaces => SDK):
8
8
  *
@@ -15,8 +15,8 @@
15
15
  * The TUI is the reference for every value here; dark stays byte-identical to
16
16
  * today's TUI. See docs/decisions/2026-07-05-presentation-contract-sdk-extraction.md
17
17
  * for the full decision record, including the GLYPHS status-group reconciliation
18
- * ruling and the consumption plan (agent this wave via R4; TUI swap deferred to
19
- * a Wave-6 coherence pass).
18
+ * ruling and the consumption plan (the agent picks this up via R4; the TUI swap is
19
+ * deferred to a future coherence pass).
20
20
  *
21
21
  * PURE — no fs, no terminal I/O, no process globals. Painting stays
22
22
  * renderer-owned; this module owns only tokens and pure wording functions.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * thinking-phrases.ts — the rotating "thinking" phrase pool, hoisted from
3
3
  * `goodvibes-tui` src/renderer/ui-factory.ts (THINKING_PHRASES). Verbatim
4
- * identical to the agent's copy today (per the W4-R1 parity audit) — a pure
4
+ * identical to the agent's copy today (per the renderer/input parity audit) — a pure
5
5
  * move, no reconciliation needed.
6
6
  *
7
7
  * Vaporwave / good-vibes themed; shown by waitingPhrase()'s 'thinking' case
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * thinking-phrases.ts — the rotating "thinking" phrase pool, hoisted from
3
3
  * `goodvibes-tui` src/renderer/ui-factory.ts (THINKING_PHRASES). Verbatim
4
- * identical to the agent's copy today (per the W4-R1 parity audit) — a pure
4
+ * identical to the agent's copy today (per the renderer/input parity audit) — a pure
5
5
  * move, no reconciliation needed.
6
6
  *
7
7
  * Vaporwave / good-vibes themed; shown by waitingPhrase()'s 'thinking' case
@@ -11,7 +11,7 @@
11
11
  * TUI's precedence order — approval beats reconnect beats pre-first-token
12
12
  * beats stalled beats thinking) and calls waitingPhrase(state, ctx) for the
13
13
  * exact wording. Neither renderer should carry its own copy of these five
14
- * strings/rotation — that duplication is exactly what the W4-R1 audit found
14
+ * strings/rotation — that duplication is exactly what the renderer/input parity audit found
15
15
  * (the agent's ui-factory.ts:308-313 was rotating-only, with no honest
16
16
  * stall/reconnect/approval split at all).
17
17
  *
@@ -11,7 +11,7 @@
11
11
  * TUI's precedence order — approval beats reconnect beats pre-first-token
12
12
  * beats stalled beats thinking) and calls waitingPhrase(state, ctx) for the
13
13
  * exact wording. Neither renderer should carry its own copy of these five
14
- * strings/rotation — that duplication is exactly what the W4-R1 audit found
14
+ * strings/rotation — that duplication is exactly what the renderer/input parity audit found
15
15
  * (the agent's ui-factory.ts:308-313 was rotating-only, with no honest
16
16
  * stall/reconnect/approval split at all).
17
17
  *
@@ -0,0 +1,48 @@
1
+ /**
2
+ * push/delivery.ts
3
+ *
4
+ * The single place a push message is actually encrypted and sent. Every send —
5
+ * a `push.subscriptions.verify` test, or an approval/completion fan-out — flows
6
+ * through `deliverToSubscription`, so the honesty rules live in one spot:
7
+ *
8
+ * - A push service that answers 404/410 means the browser subscription is gone;
9
+ * the record is pruned and the receipt says `pruned`, never a fake success.
10
+ * - Any other non-2xx (or a transport error) is reported as `failed` with the
11
+ * status/reason, never swallowed into a success.
12
+ * - The request carries the RFC 8188 `Content-Encoding: aes128gcm` body plus
13
+ * the `TTL`, `Urgency`, and VAPID `Authorization` headers a push service
14
+ * requires.
15
+ *
16
+ * The endpoint is whatever the browser registered. In tests that is a local
17
+ * HTTP sink; in production it is the browser vendor's push service. This module
18
+ * never contacts a hard-coded external service of its own.
19
+ */
20
+ import type { VapidManager } from './vapid.js';
21
+ import type { PushSubscriptionStore } from './subscription-store.js';
22
+ import type { PushDeliveryReceipt, PushMessage, StoredPushSubscription } from './types.js';
23
+ /** The `fetch` slice used to POST an encrypted payload. Injectable for tests. */
24
+ export type PushTransport = (url: string, init: {
25
+ method: string;
26
+ headers: Record<string, string>;
27
+ body: Buffer;
28
+ }) => Promise<{
29
+ status: number;
30
+ }>;
31
+ export interface DeliveryDeps {
32
+ readonly vapid: VapidManager;
33
+ readonly store: PushSubscriptionStore;
34
+ readonly transport?: PushTransport | undefined;
35
+ }
36
+ /**
37
+ * Encrypt and send one message to one subscription, prune-on-gone, and return
38
+ * an honest receipt. The subscription's `lastOutcome` is stamped either way.
39
+ */
40
+ export declare function deliverToSubscription(subscription: StoredPushSubscription, message: PushMessage, deps: DeliveryDeps): Promise<PushDeliveryReceipt>;
41
+ /**
42
+ * Fan one message out to every stored subscription, delivering (and pruning) in
43
+ * sequence. Returns one receipt per subscription — an empty array when there
44
+ * are no subscriptions at all (the honest "nobody to notify" result, not a
45
+ * silent success).
46
+ */
47
+ export declare function deliverToAll(message: PushMessage, deps: DeliveryDeps): Promise<PushDeliveryReceipt[]>;
48
+ //# sourceMappingURL=delivery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../../src/platform/push/delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,iFAAiF;AACjF,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KACpE,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAgCjC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAChD;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,sBAAsB,EACpC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,mBAAmB,CAAC,CAyD9B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAOhC"}