@pellux/goodvibes-sdk 1.0.0 → 1.1.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 (223) hide show
  1. package/dist/contracts/artifacts/operator-contract.json +1320 -10
  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 +83 -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 +8 -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 +43 -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 +127 -0
  181. package/dist/platform/runtime/memory-spine/client.d.ts.map +1 -0
  182. package/dist/platform/runtime/memory-spine/client.js +113 -0
  183. package/dist/platform/runtime/memory-spine/index.d.ts +11 -0
  184. package/dist/platform/runtime/memory-spine/index.d.ts.map +1 -0
  185. package/dist/platform/runtime/memory-spine/index.js +10 -0
  186. package/dist/platform/runtime/operator-client.d.ts +1 -1
  187. package/dist/platform/runtime/services.d.ts +6 -6
  188. package/dist/platform/runtime/services.d.ts.map +1 -1
  189. package/dist/platform/runtime/services.js +9 -9
  190. package/dist/platform/runtime/session-spine/union-cache.d.ts +1 -1
  191. package/dist/platform/runtime/session-spine/union-cache.js +1 -1
  192. package/dist/platform/state/canonical-memory.d.ts +7 -7
  193. package/dist/platform/state/canonical-memory.js +8 -8
  194. package/dist/platform/state/code-index-chunking.js +1 -1
  195. package/dist/platform/state/code-index-db.d.ts +1 -1
  196. package/dist/platform/state/code-index-store.js +1 -1
  197. package/dist/platform/state/index.d.ts +2 -2
  198. package/dist/platform/state/index.d.ts.map +1 -1
  199. package/dist/platform/state/index.js +1 -1
  200. package/dist/platform/state/memory-recall-contract.d.ts +59 -4
  201. package/dist/platform/state/memory-recall-contract.d.ts.map +1 -1
  202. package/dist/platform/state/memory-recall-contract.js +79 -3
  203. package/dist/platform/state/memory-registry.d.ts +8 -0
  204. package/dist/platform/state/memory-registry.d.ts.map +1 -1
  205. package/dist/platform/state/memory-registry.js +10 -0
  206. package/dist/platform/state/memory-vector-store.js +1 -1
  207. package/dist/platform/state/sqlite-vec-loader.d.ts +1 -1
  208. package/dist/platform/state/sqlite-vec-loader.js +1 -1
  209. package/dist/platform/state/vibe-projection.d.ts +3 -3
  210. package/dist/platform/state/vibe-projection.js +3 -3
  211. package/dist/platform/tools/agent/manager.d.ts +10 -10
  212. package/dist/platform/tools/agent/manager.js +7 -7
  213. package/dist/platform/tools/exec/runtime.js +5 -5
  214. package/dist/platform/tools/exec/schema.d.ts +1 -1
  215. package/dist/platform/tools/exec/schema.d.ts.map +1 -1
  216. package/dist/platform/tools/fetch/runtime.d.ts +1 -1
  217. package/dist/platform/tools/registry.d.ts +1 -1
  218. package/dist/platform/tools/registry.js +1 -1
  219. package/dist/platform/types/tools.d.ts +1 -1
  220. package/dist/platform/utils/request-body.d.ts.map +1 -1
  221. package/dist/platform/utils/request-body.js +50 -5
  222. package/dist/platform/version.js +1 -1
  223. package/package.json +13 -9
@@ -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"}
@@ -0,0 +1,117 @@
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 { encryptPushPayload } from './encryption.js';
21
+ const DEFAULT_TTL_SECONDS = 24 * 60 * 60;
22
+ const GONE_STATUSES = new Set([404, 410]);
23
+ function defaultTransport() {
24
+ return async (url, init) => {
25
+ // Re-wrap over a plain ArrayBuffer so the body matches fetch's BodyInit.
26
+ const res = await fetch(url, {
27
+ method: init.method,
28
+ headers: init.headers,
29
+ body: new Uint8Array(init.body),
30
+ });
31
+ return { status: res.status };
32
+ };
33
+ }
34
+ function endpointOrigin(endpoint) {
35
+ try {
36
+ return new URL(endpoint).origin;
37
+ }
38
+ catch {
39
+ return 'invalid';
40
+ }
41
+ }
42
+ function messagePlaintext(message) {
43
+ return Buffer.from(JSON.stringify({ title: message.title, body: message.body, data: message.data ?? {} }), 'utf8');
44
+ }
45
+ /**
46
+ * Encrypt and send one message to one subscription, prune-on-gone, and return
47
+ * an honest receipt. The subscription's `lastOutcome` is stamped either way.
48
+ */
49
+ export async function deliverToSubscription(subscription, message, deps) {
50
+ const origin = endpointOrigin(subscription.endpoint);
51
+ const transport = deps.transport ?? defaultTransport();
52
+ let httpStatus;
53
+ try {
54
+ const encrypted = encryptPushPayload(subscription.keys, messagePlaintext(message));
55
+ const authorization = await deps.vapid.buildAuthorizationHeader(subscription.endpoint);
56
+ const headers = {
57
+ 'content-encoding': encrypted.contentEncoding,
58
+ 'content-type': 'application/octet-stream',
59
+ ttl: String(message.ttlSeconds ?? DEFAULT_TTL_SECONDS),
60
+ urgency: message.urgency ?? 'normal',
61
+ authorization,
62
+ };
63
+ const result = await transport(subscription.endpoint, {
64
+ method: 'POST',
65
+ headers,
66
+ body: encrypted.body,
67
+ });
68
+ httpStatus = result.status;
69
+ }
70
+ catch (error) {
71
+ await deps.store.recordOutcome(subscription.id, 'failed');
72
+ return {
73
+ subscriptionId: subscription.id,
74
+ endpointOrigin: origin,
75
+ outcome: 'failed',
76
+ detail: `delivery request failed: ${error instanceof Error ? error.message : String(error)}`,
77
+ };
78
+ }
79
+ if (httpStatus >= 200 && httpStatus < 300) {
80
+ await deps.store.recordOutcome(subscription.id, 'delivered');
81
+ return { subscriptionId: subscription.id, endpointOrigin: origin, outcome: 'delivered', httpStatus };
82
+ }
83
+ if (GONE_STATUSES.has(httpStatus)) {
84
+ // The subscription is gone at the push service — prune it (delete means
85
+ // delete) and report the prune with the status that proved it dead.
86
+ await deps.store.remove(subscription.id);
87
+ return {
88
+ subscriptionId: subscription.id,
89
+ endpointOrigin: origin,
90
+ outcome: 'pruned',
91
+ httpStatus,
92
+ detail: `push endpoint reported ${httpStatus} gone; subscription removed`,
93
+ };
94
+ }
95
+ await deps.store.recordOutcome(subscription.id, 'failed');
96
+ return {
97
+ subscriptionId: subscription.id,
98
+ endpointOrigin: origin,
99
+ outcome: 'failed',
100
+ httpStatus,
101
+ detail: `push service returned ${httpStatus}`,
102
+ };
103
+ }
104
+ /**
105
+ * Fan one message out to every stored subscription, delivering (and pruning) in
106
+ * sequence. Returns one receipt per subscription — an empty array when there
107
+ * are no subscriptions at all (the honest "nobody to notify" result, not a
108
+ * silent success).
109
+ */
110
+ export async function deliverToAll(message, deps) {
111
+ const subscriptions = await deps.store.all();
112
+ const receipts = [];
113
+ for (const subscription of subscriptions) {
114
+ receipts.push(await deliverToSubscription(subscription, message, deps));
115
+ }
116
+ return receipts;
117
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * push/encryption.ts
3
+ *
4
+ * Browser-push payload encryption, implemented with Node's built-in crypto
5
+ * (node:crypto) — no third-party web-push dependency. This is the daemon-side
6
+ * (Node/Bun) delivery path only; nothing here is imported by the runtime-neutral
7
+ * or browser bundles (see scripts/browser-compat-check.ts).
8
+ *
9
+ * Two standards are combined here, exactly as a browser Push service expects:
10
+ *
11
+ * - RFC 8291 (Message Encryption for Web Push): derive a shared secret from an
12
+ * ephemeral P-256 keypair and the subscription's public key + auth secret.
13
+ * - RFC 8188 (aes128gcm content encoding): expand that secret into a
14
+ * content-encryption key + nonce and encrypt one record, then frame it with
15
+ * the salt / record-size / sender-public-key header the receiver reads back.
16
+ *
17
+ * The output Buffer is the raw request body sent to the subscription endpoint
18
+ * with `Content-Encoding: aes128gcm`.
19
+ */
20
+ /** The subscription's own key material, base64url-encoded (browser PushSubscription shape). */
21
+ export interface SubscriptionKeyMaterial {
22
+ /** The receiver's public key — 65-byte uncompressed P-256 point, base64url. */
23
+ readonly p256dh: string;
24
+ /** The receiver's 16-byte authentication secret, base64url. */
25
+ readonly auth: string;
26
+ }
27
+ export interface EncryptedPushPayload {
28
+ /** The aes128gcm request body: header || ciphertext || GCM tag. */
29
+ readonly body: Buffer;
30
+ /** Always `aes128gcm` — the value for the Content-Encoding request header. */
31
+ readonly contentEncoding: 'aes128gcm';
32
+ }
33
+ /**
34
+ * Encrypt `plaintext` for a subscription's key material.
35
+ *
36
+ * A fresh ephemeral sender keypair and salt are generated per call (RFC 8291
37
+ * requires this — the same salt/key pair must never encrypt two messages), so
38
+ * the result is non-deterministic by design.
39
+ */
40
+ export declare function encryptPushPayload(keys: SubscriptionKeyMaterial, plaintext: Buffer): EncryptedPushPayload;
41
+ //# sourceMappingURL=encryption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../src/platform/push/encryption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,+FAA+F;AAC/F,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC;CACvC;AAyBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,uBAAuB,EAC7B,SAAS,EAAE,MAAM,GAChB,oBAAoB,CA2CtB"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * push/encryption.ts
3
+ *
4
+ * Browser-push payload encryption, implemented with Node's built-in crypto
5
+ * (node:crypto) — no third-party web-push dependency. This is the daemon-side
6
+ * (Node/Bun) delivery path only; nothing here is imported by the runtime-neutral
7
+ * or browser bundles (see scripts/browser-compat-check.ts).
8
+ *
9
+ * Two standards are combined here, exactly as a browser Push service expects:
10
+ *
11
+ * - RFC 8291 (Message Encryption for Web Push): derive a shared secret from an
12
+ * ephemeral P-256 keypair and the subscription's public key + auth secret.
13
+ * - RFC 8188 (aes128gcm content encoding): expand that secret into a
14
+ * content-encryption key + nonce and encrypt one record, then frame it with
15
+ * the salt / record-size / sender-public-key header the receiver reads back.
16
+ *
17
+ * The output Buffer is the raw request body sent to the subscription endpoint
18
+ * with `Content-Encoding: aes128gcm`.
19
+ */
20
+ import { createCipheriv, createECDH, createHmac, randomBytes } from 'node:crypto';
21
+ /**
22
+ * Single fixed record size. Push payloads here (an approval summary, a
23
+ * completion note) are far below this, so one aes128gcm record always
24
+ * suffices; a payload that would not fit is rejected honestly rather than
25
+ * silently truncated or split.
26
+ */
27
+ const RECORD_SIZE = 4096;
28
+ const KEY_INFO_PREFIX = Buffer.from('WebPush: info\0', 'utf8');
29
+ const CEK_INFO = Buffer.from('Content-Encoding: aes128gcm\0', 'utf8');
30
+ const NONCE_INFO = Buffer.from('Content-Encoding: nonce\0', 'utf8');
31
+ /** HKDF (RFC 5869) specialized to a single output block (length <= 32). */
32
+ function hkdf(salt, ikm, info, length) {
33
+ const prk = createHmac('sha256', salt).update(ikm).digest();
34
+ const okm = createHmac('sha256', prk).update(Buffer.concat([info, Buffer.from([0x01])])).digest();
35
+ return okm.subarray(0, length);
36
+ }
37
+ function base64UrlToBuffer(value) {
38
+ return Buffer.from(value, 'base64url');
39
+ }
40
+ /**
41
+ * Encrypt `plaintext` for a subscription's key material.
42
+ *
43
+ * A fresh ephemeral sender keypair and salt are generated per call (RFC 8291
44
+ * requires this — the same salt/key pair must never encrypt two messages), so
45
+ * the result is non-deterministic by design.
46
+ */
47
+ export function encryptPushPayload(keys, plaintext) {
48
+ const receiverPublic = base64UrlToBuffer(keys.p256dh);
49
+ const authSecret = base64UrlToBuffer(keys.auth);
50
+ if (receiverPublic.length !== 65) {
51
+ throw new Error('Push subscription p256dh key is not a 65-byte uncompressed P-256 point');
52
+ }
53
+ if (authSecret.length !== 16) {
54
+ throw new Error('Push subscription auth secret is not 16 bytes');
55
+ }
56
+ // Ephemeral sender (application-server) keypair for this one message.
57
+ const sender = createECDH('prime256v1');
58
+ sender.generateKeys();
59
+ const senderPublic = sender.getPublicKey();
60
+ const sharedSecret = sender.computeSecret(receiverPublic);
61
+ const salt = randomBytes(16);
62
+ // RFC 8291: mix the shared secret with the auth secret and both public keys.
63
+ const keyInfo = Buffer.concat([KEY_INFO_PREFIX, receiverPublic, senderPublic]);
64
+ const ikm = hkdf(authSecret, sharedSecret, keyInfo, 32);
65
+ // RFC 8188: expand into the content-encryption key and nonce.
66
+ const contentEncryptionKey = hkdf(salt, ikm, CEK_INFO, 16);
67
+ const nonce = hkdf(salt, ikm, NONCE_INFO, 12);
68
+ // One record: plaintext followed by the 0x02 last-record delimiter.
69
+ const record = Buffer.concat([plaintext, Buffer.from([0x02])]);
70
+ if (record.length + 16 > RECORD_SIZE) {
71
+ throw new Error(`Push payload too large for a single aes128gcm record (max ${RECORD_SIZE - 17} bytes)`);
72
+ }
73
+ const cipher = createCipheriv('aes-128-gcm', contentEncryptionKey, nonce);
74
+ const ciphertext = Buffer.concat([cipher.update(record), cipher.final(), cipher.getAuthTag()]);
75
+ // aes128gcm header: salt(16) | record-size(4, big-endian) | keyid-len(1) | keyid(=senderPublic).
76
+ const header = Buffer.alloc(16 + 4 + 1 + senderPublic.length);
77
+ salt.copy(header, 0);
78
+ header.writeUInt32BE(RECORD_SIZE, 16);
79
+ header.writeUInt8(senderPublic.length, 20);
80
+ senderPublic.copy(header, 21);
81
+ return { body: Buffer.concat([header, ciphertext]), contentEncoding: 'aes128gcm' };
82
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * push/index.ts — the browser-push module barrel (VAPID custody, subscription
3
+ * store, RFC 8291 encryption, and the delivery path). Daemon-side only; not
4
+ * part of the runtime-neutral or browser bundles.
5
+ */
6
+ export { encryptPushPayload } from './encryption.js';
7
+ export type { SubscriptionKeyMaterial, EncryptedPushPayload } from './encryption.js';
8
+ export { VapidManager, VAPID_SECRET_KEY } from './vapid.js';
9
+ export type { VapidSecretStore, VapidManagerOptions } from './vapid.js';
10
+ export { PushSubscriptionStore, toPublicSubscription } from './subscription-store.js';
11
+ export type { RegisterSubscriptionInput } from './subscription-store.js';
12
+ export { deliverToSubscription, deliverToAll } from './delivery.js';
13
+ export type { PushTransport, DeliveryDeps } from './delivery.js';
14
+ export { PushService } from './service.js';
15
+ export type { PushServiceDeps, SubscribeInput, ApprovalSource, ApprovalNotice } from './service.js';
16
+ export type { StoredPushSubscription, PublicPushSubscription, PushDeliveryOutcome, PushDeliveryReceipt, PushUrgency, PushMessage, } from './types.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/platform/push/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACtF,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACpG,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * push/index.ts — the browser-push module barrel (VAPID custody, subscription
3
+ * store, RFC 8291 encryption, and the delivery path). Daemon-side only; not
4
+ * part of the runtime-neutral or browser bundles.
5
+ */
6
+ export { encryptPushPayload } from './encryption.js';
7
+ export { VapidManager, VAPID_SECRET_KEY } from './vapid.js';
8
+ export { PushSubscriptionStore, toPublicSubscription } from './subscription-store.js';
9
+ export { deliverToSubscription, deliverToAll } from './delivery.js';
10
+ export { PushService } from './service.js';