@moltzap/protocol 2026.401.0 → 2026.425.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 (287) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/rpc-registry.d.ts +446 -0
  6. package/dist/rpc-registry.d.ts.map +1 -0
  7. package/dist/rpc-registry.js +67 -0
  8. package/dist/rpc-registry.js.map +1 -0
  9. package/dist/rpc.d.ts +42 -0
  10. package/dist/rpc.d.ts.map +1 -0
  11. package/dist/rpc.js +29 -0
  12. package/dist/rpc.js.map +1 -0
  13. package/dist/schema/apps.d.ts +86 -0
  14. package/dist/schema/apps.d.ts.map +1 -0
  15. package/dist/schema/apps.js +77 -0
  16. package/dist/schema/apps.js.map +1 -0
  17. package/dist/schema/contacts.d.ts +8 -14
  18. package/dist/schema/contacts.d.ts.map +1 -1
  19. package/dist/schema/contacts.js +9 -15
  20. package/dist/schema/contacts.js.map +1 -1
  21. package/dist/schema/conversations.d.ts +15 -8
  22. package/dist/schema/conversations.d.ts.map +1 -1
  23. package/dist/schema/conversations.js +18 -7
  24. package/dist/schema/conversations.js.map +1 -1
  25. package/dist/schema/delivery.d.ts +1 -4
  26. package/dist/schema/delivery.d.ts.map +1 -1
  27. package/dist/schema/delivery.js +2 -3
  28. package/dist/schema/delivery.js.map +1 -1
  29. package/dist/schema/errors.d.ts +13 -0
  30. package/dist/schema/errors.d.ts.map +1 -1
  31. package/dist/schema/errors.js +14 -0
  32. package/dist/schema/errors.js.map +1 -1
  33. package/dist/schema/events.d.ts +112 -85
  34. package/dist/schema/events.d.ts.map +1 -1
  35. package/dist/schema/events.js +84 -25
  36. package/dist/schema/events.js.map +1 -1
  37. package/dist/schema/identity.d.ts +26 -15
  38. package/dist/schema/identity.d.ts.map +1 -1
  39. package/dist/schema/identity.js +10 -14
  40. package/dist/schema/identity.js.map +1 -1
  41. package/dist/schema/index.d.ts +4 -2
  42. package/dist/schema/index.d.ts.map +1 -1
  43. package/dist/schema/index.js +4 -2
  44. package/dist/schema/index.js.map +1 -1
  45. package/dist/schema/messages.d.ts +3 -7
  46. package/dist/schema/messages.d.ts.map +1 -1
  47. package/dist/schema/messages.js +4 -6
  48. package/dist/schema/messages.js.map +1 -1
  49. package/dist/schema/methods/apps.d.ts +123 -0
  50. package/dist/schema/methods/apps.d.ts.map +1 -0
  51. package/dist/schema/methods/apps.js +93 -0
  52. package/dist/schema/methods/apps.js.map +1 -0
  53. package/dist/schema/methods/auth.d.ts +110 -79
  54. package/dist/schema/methods/auth.d.ts.map +1 -1
  55. package/dist/schema/methods/auth.js +88 -91
  56. package/dist/schema/methods/auth.js.map +1 -1
  57. package/dist/schema/methods/contacts.d.ts +39 -66
  58. package/dist/schema/methods/contacts.d.ts.map +1 -1
  59. package/dist/schema/methods/contacts.js +35 -29
  60. package/dist/schema/methods/contacts.js.map +1 -1
  61. package/dist/schema/methods/conversations.d.ts +48 -52
  62. package/dist/schema/methods/conversations.d.ts.map +1 -1
  63. package/dist/schema/methods/conversations.js +89 -38
  64. package/dist/schema/methods/conversations.js.map +1 -1
  65. package/dist/schema/methods/invites.d.ts +1 -3
  66. package/dist/schema/methods/invites.d.ts.map +1 -1
  67. package/dist/schema/methods/invites.js +8 -1
  68. package/dist/schema/methods/invites.js.map +1 -1
  69. package/dist/schema/methods/messages.d.ts +12 -44
  70. package/dist/schema/methods/messages.d.ts.map +1 -1
  71. package/dist/schema/methods/messages.js +22 -28
  72. package/dist/schema/methods/messages.js.map +1 -1
  73. package/dist/schema/methods/presence.d.ts +7 -22
  74. package/dist/schema/methods/presence.d.ts.map +1 -1
  75. package/dist/schema/methods/presence.js +12 -6
  76. package/dist/schema/methods/presence.js.map +1 -1
  77. package/dist/schema/methods/push.d.ts +8 -6
  78. package/dist/schema/methods/push.d.ts.map +1 -1
  79. package/dist/schema/methods/push.js +20 -7
  80. package/dist/schema/methods/push.js.map +1 -1
  81. package/dist/schema/methods/system.d.ts +4 -0
  82. package/dist/schema/methods/system.d.ts.map +1 -0
  83. package/dist/schema/methods/system.js +11 -0
  84. package/dist/schema/methods/system.js.map +1 -0
  85. package/dist/schema/presence.d.ts +1 -12
  86. package/dist/schema/presence.d.ts.map +1 -1
  87. package/dist/schema/presence.js +2 -7
  88. package/dist/schema/presence.js.map +1 -1
  89. package/dist/schema/surfaces.d.ts +31 -25
  90. package/dist/schema/surfaces.d.ts.map +1 -1
  91. package/dist/schema/surfaces.js +40 -21
  92. package/dist/schema/surfaces.js.map +1 -1
  93. package/dist/testing/agent-registration.d.ts +49 -0
  94. package/dist/testing/agent-registration.d.ts.map +1 -0
  95. package/dist/testing/agent-registration.js +77 -0
  96. package/dist/testing/agent-registration.js.map +1 -0
  97. package/dist/testing/arbitraries/frames.d.ts +24 -0
  98. package/dist/testing/arbitraries/frames.d.ts.map +1 -0
  99. package/dist/testing/arbitraries/frames.js +36 -0
  100. package/dist/testing/arbitraries/frames.js.map +1 -0
  101. package/dist/testing/arbitraries/from-typebox.d.ts +37 -0
  102. package/dist/testing/arbitraries/from-typebox.d.ts.map +1 -0
  103. package/dist/testing/arbitraries/from-typebox.js +131 -0
  104. package/dist/testing/arbitraries/from-typebox.js.map +1 -0
  105. package/dist/testing/arbitraries/index.d.ts +4 -0
  106. package/dist/testing/arbitraries/index.d.ts.map +1 -0
  107. package/dist/testing/arbitraries/index.js +4 -0
  108. package/dist/testing/arbitraries/index.js.map +1 -0
  109. package/dist/testing/arbitraries/rpc.d.ts +66 -0
  110. package/dist/testing/arbitraries/rpc.d.ts.map +1 -0
  111. package/dist/testing/arbitraries/rpc.js +98 -0
  112. package/dist/testing/arbitraries/rpc.js.map +1 -0
  113. package/dist/testing/canonicalize.d.ts +38 -0
  114. package/dist/testing/canonicalize.d.ts.map +1 -0
  115. package/dist/testing/canonicalize.js +55 -0
  116. package/dist/testing/canonicalize.js.map +1 -0
  117. package/dist/testing/captures.d.ts +61 -0
  118. package/dist/testing/captures.d.ts.map +1 -0
  119. package/dist/testing/captures.js +99 -0
  120. package/dist/testing/captures.js.map +1 -0
  121. package/dist/testing/codec.d.ts +44 -0
  122. package/dist/testing/codec.d.ts.map +1 -0
  123. package/dist/testing/codec.js +170 -0
  124. package/dist/testing/codec.js.map +1 -0
  125. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.d.ts +6 -0
  126. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.d.ts.map +1 -0
  127. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.js +33 -0
  128. package/dist/testing/conformance/__divergence_proofs__/executable-proof-helpers.js.map +1 -0
  129. package/dist/testing/conformance/adversity.d.ts +36 -0
  130. package/dist/testing/conformance/adversity.d.ts.map +1 -0
  131. package/dist/testing/conformance/adversity.js +360 -0
  132. package/dist/testing/conformance/adversity.js.map +1 -0
  133. package/dist/testing/conformance/boundary.d.ts +56 -0
  134. package/dist/testing/conformance/boundary.d.ts.map +1 -0
  135. package/dist/testing/conformance/boundary.js +129 -0
  136. package/dist/testing/conformance/boundary.js.map +1 -0
  137. package/dist/testing/conformance/client/_fixtures.d.ts +71 -0
  138. package/dist/testing/conformance/client/_fixtures.d.ts.map +1 -0
  139. package/dist/testing/conformance/client/_fixtures.js +102 -0
  140. package/dist/testing/conformance/client/_fixtures.js.map +1 -0
  141. package/dist/testing/conformance/client/adversity.d.ts +39 -0
  142. package/dist/testing/conformance/client/adversity.d.ts.map +1 -0
  143. package/dist/testing/conformance/client/adversity.js +162 -0
  144. package/dist/testing/conformance/client/adversity.js.map +1 -0
  145. package/dist/testing/conformance/client/boundary.d.ts +12 -0
  146. package/dist/testing/conformance/client/boundary.d.ts.map +1 -0
  147. package/dist/testing/conformance/client/boundary.js +68 -0
  148. package/dist/testing/conformance/client/boundary.js.map +1 -0
  149. package/dist/testing/conformance/client/delivery.d.ts +38 -0
  150. package/dist/testing/conformance/client/delivery.d.ts.map +1 -0
  151. package/dist/testing/conformance/client/delivery.js +202 -0
  152. package/dist/testing/conformance/client/delivery.js.map +1 -0
  153. package/dist/testing/conformance/client/index.d.ts +16 -0
  154. package/dist/testing/conformance/client/index.d.ts.map +1 -0
  155. package/dist/testing/conformance/client/index.js +16 -0
  156. package/dist/testing/conformance/client/index.js.map +1 -0
  157. package/dist/testing/conformance/client/rpc-semantics.d.ts +26 -0
  158. package/dist/testing/conformance/client/rpc-semantics.d.ts.map +1 -0
  159. package/dist/testing/conformance/client/rpc-semantics.js +145 -0
  160. package/dist/testing/conformance/client/rpc-semantics.js.map +1 -0
  161. package/dist/testing/conformance/client/runner.d.ts +258 -0
  162. package/dist/testing/conformance/client/runner.d.ts.map +1 -0
  163. package/dist/testing/conformance/client/runner.js +228 -0
  164. package/dist/testing/conformance/client/runner.js.map +1 -0
  165. package/dist/testing/conformance/client/schema-conformance.d.ts +25 -0
  166. package/dist/testing/conformance/client/schema-conformance.d.ts.map +1 -0
  167. package/dist/testing/conformance/client/schema-conformance.js +123 -0
  168. package/dist/testing/conformance/client/schema-conformance.js.map +1 -0
  169. package/dist/testing/conformance/client/suite.d.ts +90 -0
  170. package/dist/testing/conformance/client/suite.d.ts.map +1 -0
  171. package/dist/testing/conformance/client/suite.js +209 -0
  172. package/dist/testing/conformance/client/suite.js.map +1 -0
  173. package/dist/testing/conformance/coverage-policy.d.ts +8 -0
  174. package/dist/testing/conformance/coverage-policy.d.ts.map +1 -0
  175. package/dist/testing/conformance/coverage-policy.js +10 -0
  176. package/dist/testing/conformance/coverage-policy.js.map +1 -0
  177. package/dist/testing/conformance/delivery.d.ts +40 -0
  178. package/dist/testing/conformance/delivery.d.ts.map +1 -0
  179. package/dist/testing/conformance/delivery.js +231 -0
  180. package/dist/testing/conformance/delivery.js.map +1 -0
  181. package/dist/testing/conformance/env.d.ts +3 -0
  182. package/dist/testing/conformance/env.d.ts.map +1 -0
  183. package/dist/testing/conformance/env.js +14 -0
  184. package/dist/testing/conformance/env.js.map +1 -0
  185. package/dist/testing/conformance/index.d.ts +10 -0
  186. package/dist/testing/conformance/index.d.ts.map +1 -0
  187. package/dist/testing/conformance/index.js +10 -0
  188. package/dist/testing/conformance/index.js.map +1 -0
  189. package/dist/testing/conformance/registry.d.ts +93 -0
  190. package/dist/testing/conformance/registry.d.ts.map +1 -0
  191. package/dist/testing/conformance/registry.js +62 -0
  192. package/dist/testing/conformance/registry.js.map +1 -0
  193. package/dist/testing/conformance/rpc-semantics.d.ts +67 -0
  194. package/dist/testing/conformance/rpc-semantics.d.ts.map +1 -0
  195. package/dist/testing/conformance/rpc-semantics.js +394 -0
  196. package/dist/testing/conformance/rpc-semantics.js.map +1 -0
  197. package/dist/testing/conformance/runner.d.ts +78 -0
  198. package/dist/testing/conformance/runner.d.ts.map +1 -0
  199. package/dist/testing/conformance/runner.js +65 -0
  200. package/dist/testing/conformance/runner.js.map +1 -0
  201. package/dist/testing/conformance/schema-conformance.d.ts +30 -0
  202. package/dist/testing/conformance/schema-conformance.d.ts.map +1 -0
  203. package/dist/testing/conformance/schema-conformance.js +229 -0
  204. package/dist/testing/conformance/schema-conformance.js.map +1 -0
  205. package/dist/testing/conformance/suite.d.ts +92 -0
  206. package/dist/testing/conformance/suite.d.ts.map +1 -0
  207. package/dist/testing/conformance/suite.js +233 -0
  208. package/dist/testing/conformance/suite.js.map +1 -0
  209. package/dist/testing/errors.d.ts +78 -0
  210. package/dist/testing/errors.d.ts.map +1 -0
  211. package/dist/testing/errors.js +34 -0
  212. package/dist/testing/errors.js.map +1 -0
  213. package/dist/testing/index.d.ts +25 -0
  214. package/dist/testing/index.d.ts.map +1 -0
  215. package/dist/testing/index.js +37 -0
  216. package/dist/testing/index.js.map +1 -0
  217. package/dist/testing/models/dispatch.d.ts +61 -0
  218. package/dist/testing/models/dispatch.d.ts.map +1 -0
  219. package/dist/testing/models/dispatch.js +197 -0
  220. package/dist/testing/models/dispatch.js.map +1 -0
  221. package/dist/testing/models/index.d.ts +3 -0
  222. package/dist/testing/models/index.d.ts.map +1 -0
  223. package/dist/testing/models/index.js +3 -0
  224. package/dist/testing/models/index.js.map +1 -0
  225. package/dist/testing/models/state.d.ts +37 -0
  226. package/dist/testing/models/state.d.ts.map +1 -0
  227. package/dist/testing/models/state.js +14 -0
  228. package/dist/testing/models/state.js.map +1 -0
  229. package/dist/testing/test-client.d.ts +70 -0
  230. package/dist/testing/test-client.d.ts.map +1 -0
  231. package/dist/testing/test-client.js +266 -0
  232. package/dist/testing/test-client.js.map +1 -0
  233. package/dist/testing/test-server.d.ts +62 -0
  234. package/dist/testing/test-server.d.ts.map +1 -0
  235. package/dist/testing/test-server.js +134 -0
  236. package/dist/testing/test-server.js.map +1 -0
  237. package/dist/testing/toxics/client.d.ts +52 -0
  238. package/dist/testing/toxics/client.d.ts.map +1 -0
  239. package/dist/testing/toxics/client.js +120 -0
  240. package/dist/testing/toxics/client.js.map +1 -0
  241. package/dist/testing/toxics/defaults.d.ts +43 -0
  242. package/dist/testing/toxics/defaults.d.ts.map +1 -0
  243. package/dist/testing/toxics/defaults.js +9 -0
  244. package/dist/testing/toxics/defaults.js.map +1 -0
  245. package/dist/testing/toxics/index.d.ts +4 -0
  246. package/dist/testing/toxics/index.d.ts.map +1 -0
  247. package/dist/testing/toxics/index.js +4 -0
  248. package/dist/testing/toxics/index.js.map +1 -0
  249. package/dist/testing/toxics/profile.d.ts +69 -0
  250. package/dist/testing/toxics/profile.d.ts.map +1 -0
  251. package/dist/testing/toxics/profile.js +57 -0
  252. package/dist/testing/toxics/profile.js.map +1 -0
  253. package/dist/types.d.ts +7 -11
  254. package/dist/types.d.ts.map +1 -1
  255. package/dist/types.js +3 -0
  256. package/dist/types.js.map +1 -1
  257. package/dist/validators.d.ts +49 -174
  258. package/dist/validators.d.ts.map +1 -1
  259. package/dist/validators.js +77 -47
  260. package/dist/validators.js.map +1 -1
  261. package/dist/version.d.ts +1 -1
  262. package/dist/version.js +1 -1
  263. package/package.json +18 -40
  264. package/dist/optional/contact-events.d.ts +0 -3
  265. package/dist/optional/contact-events.d.ts.map +0 -1
  266. package/dist/optional/contact-events.js +0 -5
  267. package/dist/optional/contact-events.js.map +0 -1
  268. package/dist/optional/contact-methods.d.ts +0 -5
  269. package/dist/optional/contact-methods.d.ts.map +0 -1
  270. package/dist/optional/contact-methods.js +0 -5
  271. package/dist/optional/contact-methods.js.map +0 -1
  272. package/dist/phone-hash.d.ts +0 -10
  273. package/dist/phone-hash.d.ts.map +0 -1
  274. package/dist/phone-hash.js +0 -17
  275. package/dist/phone-hash.js.map +0 -1
  276. package/dist/schema/methods/phone-contacts.d.ts +0 -26
  277. package/dist/schema/methods/phone-contacts.d.ts.map +0 -1
  278. package/dist/schema/methods/phone-contacts.js +0 -10
  279. package/dist/schema/methods/phone-contacts.js.map +0 -1
  280. package/dist/test-client.d.ts +0 -34
  281. package/dist/test-client.d.ts.map +0 -1
  282. package/dist/test-client.js +0 -176
  283. package/dist/test-client.js.map +0 -1
  284. package/dist/test-fixtures/phone-hashes.d.ts +0 -18
  285. package/dist/test-fixtures/phone-hashes.d.ts.map +0 -1
  286. package/dist/test-fixtures/phone-hashes.js +0 -24
  287. package/dist/test-fixtures/phone-hashes.js.map +0 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Per-`RpcMethodName` arbitrary and the `allRpcMethods` walker.
3
+ *
4
+ * Tier A's A5 (RpcMap coverage) and Tier B's B1 (model equivalence) both
5
+ * iterate every method name. Centralizing the iterator here keeps the
6
+ * property bodies compiler-checked against `RpcMap`.
7
+ */
8
+ import * as fc from "fast-check";
9
+ import { type RpcMap, type RpcMethodName } from "../../rpc-registry.js";
10
+ /**
11
+ * A single drawn RPC invocation: the method name carries through to the
12
+ * reference model so it can pick the matching reducer.
13
+ */
14
+ export interface ArbitraryRpcCall<M extends RpcMethodName = RpcMethodName> {
15
+ readonly method: M;
16
+ readonly params: RpcMap[M]["params"];
17
+ }
18
+ /**
19
+ * Ordered list of every `RpcMethodName`. Exposed so properties can assert
20
+ * "every method exercised at least once" without going through `RpcMap`
21
+ * directly.
22
+ */
23
+ export declare const allRpcMethods: ReadonlyArray<RpcMethodName>;
24
+ /** Arbitrary of a valid params tree for a single, fixed RPC. */
25
+ export declare function arbitraryCallFor<M extends RpcMethodName>(method: M): fc.Arbitrary<ArbitraryRpcCall<M>>;
26
+ /**
27
+ * Arbitrary that draws any method name + matching params. Used by Tier A
28
+ * A5 and by Tier E E2's cross-RPC fuzz.
29
+ */
30
+ export declare function arbitraryAnyCall(): fc.Arbitrary<ArbitraryRpcCall>;
31
+ /**
32
+ * The set of `RpcMethodName`s the reference model predicts `_tag: "ok"`
33
+ * for on `initialReferenceState` — derived mechanically at module load
34
+ * by probing `applyCall` with a single drawn params value per method.
35
+ *
36
+ * Per architect #197 §2.2: this is NOT a hand-curated list. Methods
37
+ * move in/out of the confident set automatically when `applyCall`'s
38
+ * `allowNoEvents` / `uncertainError` split moves, so the sampling
39
+ * distribution tracks the model.
40
+ *
41
+ * **Param-invariance contract:** every kept method is treated as
42
+ * oracle-confident for every params value. If a future `applyCall`
43
+ * amendment branches on `call.params`, the safety-net guard in
44
+ * `registerModelEquivalence` (rpc-semantics.ts) fires loudly on the
45
+ * first non-confident draw and the derivation must widen from the
46
+ * single-probe form to an `fc.sample`-based invariant check.
47
+ */
48
+ export declare const confidentOracleMethods: ReadonlyArray<RpcMethodName>;
49
+ /**
50
+ * Draw a call from the model's confident-oracle set. Per architect
51
+ * #197 §2.2 literal shape: `fc.constantFrom(...kept).chain(
52
+ * arbitraryCallFor)`. Probe at module load uses the same
53
+ * `arbitraryCallFor(m)` generator as execution — so confidence is
54
+ * checked on the same distribution the property exercises.
55
+ *
56
+ * If a kept method turns out to be param-sensitive under a later
57
+ * draw (model predicts ok for the one probe sample but rejects a
58
+ * subsequent arbitrary-drawn params), the safety-net guard in
59
+ * `registerModelEquivalence` raises `PropertyInvariantViolation`
60
+ * pointing at this file — the fix is to widen the derivation (probe
61
+ * K > 1 samples and keep only methods where every probe predicts ok)
62
+ * per the architect's contract. Single-probe is sufficient when
63
+ * `applyCall` is method-only (today).
64
+ */
65
+ export declare function arbitraryConfidentCall(): fc.Arbitrary<ArbitraryRpcCall>;
66
+ //# sourceMappingURL=rpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../../../src/testing/arbitraries/rpc.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,aAAa,EACnB,MAAM,uBAAuB,CAAC;AAK/B;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa;IACvE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,aAAa,CAEtD,CAAC;AAKF,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,aAAa,EACtD,MAAM,EAAE,CAAC,GACR,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAYnC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAKjE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAAa,CAAC,aAAa,CAY5D,CAAC;AAEL;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,IAAI,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,CASvE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Per-`RpcMethodName` arbitrary and the `allRpcMethods` walker.
3
+ *
4
+ * Tier A's A5 (RpcMap coverage) and Tier B's B1 (model equivalence) both
5
+ * iterate every method name. Centralizing the iterator here keeps the
6
+ * property bodies compiler-checked against `RpcMap`.
7
+ */
8
+ import * as fc from "fast-check";
9
+ import { rpcMethods, } from "../../rpc-registry.js";
10
+ import { applyCall } from "../models/dispatch.js";
11
+ import { initialReferenceState } from "../models/state.js";
12
+ import { arbitraryForParams } from "./from-typebox.js";
13
+ /**
14
+ * Ordered list of every `RpcMethodName`. Exposed so properties can assert
15
+ * "every method exercised at least once" without going through `RpcMap`
16
+ * directly.
17
+ */
18
+ export const allRpcMethods = rpcMethods.map((m) => m.name);
19
+ // Precomputed lookup from wire name → manifest, so `arbitraryCallFor` is O(1).
20
+ const methodByName = new Map(rpcMethods.map((m) => [m.name, m]));
21
+ /** Arbitrary of a valid params tree for a single, fixed RPC. */
22
+ export function arbitraryCallFor(method) {
23
+ const def = methodByName.get(method);
24
+ if (def === undefined) {
25
+ throw new Error(`arbitraryCallFor: unknown method ${String(method)}`);
26
+ }
27
+ return arbitraryForParams(def.paramsSchema).map((params) => ({
28
+ method,
29
+ params: params,
30
+ }));
31
+ }
32
+ /**
33
+ * Arbitrary that draws any method name + matching params. Used by Tier A
34
+ * A5 and by Tier E E2's cross-RPC fuzz.
35
+ */
36
+ export function arbitraryAnyCall() {
37
+ if (allRpcMethods.length === 0) {
38
+ throw new Error("arbitraryAnyCall: rpcMethods empty");
39
+ }
40
+ return fc.constantFrom(...allRpcMethods).chain((m) => arbitraryCallFor(m));
41
+ }
42
+ /**
43
+ * The set of `RpcMethodName`s the reference model predicts `_tag: "ok"`
44
+ * for on `initialReferenceState` — derived mechanically at module load
45
+ * by probing `applyCall` with a single drawn params value per method.
46
+ *
47
+ * Per architect #197 §2.2: this is NOT a hand-curated list. Methods
48
+ * move in/out of the confident set automatically when `applyCall`'s
49
+ * `allowNoEvents` / `uncertainError` split moves, so the sampling
50
+ * distribution tracks the model.
51
+ *
52
+ * **Param-invariance contract:** every kept method is treated as
53
+ * oracle-confident for every params value. If a future `applyCall`
54
+ * amendment branches on `call.params`, the safety-net guard in
55
+ * `registerModelEquivalence` (rpc-semantics.ts) fires loudly on the
56
+ * first non-confident draw and the derivation must widen from the
57
+ * single-probe form to an `fc.sample`-based invariant check.
58
+ */
59
+ export const confidentOracleMethods = (() => {
60
+ // `models/dispatch.ts` imports `ArbitraryRpcCall` as a type-only
61
+ // reference, so the values imported above (`applyCall`,
62
+ // `initialReferenceState`) are safe to call at module load.
63
+ const kept = [];
64
+ for (const method of allRpcMethods) {
65
+ const [sample] = fc.sample(arbitraryCallFor(method), 1);
66
+ if (sample === undefined)
67
+ continue;
68
+ const outcome = applyCall(initialReferenceState, sample).outcome;
69
+ if (outcome._tag === "ok")
70
+ kept.push(method);
71
+ }
72
+ return kept;
73
+ })();
74
+ /**
75
+ * Draw a call from the model's confident-oracle set. Per architect
76
+ * #197 §2.2 literal shape: `fc.constantFrom(...kept).chain(
77
+ * arbitraryCallFor)`. Probe at module load uses the same
78
+ * `arbitraryCallFor(m)` generator as execution — so confidence is
79
+ * checked on the same distribution the property exercises.
80
+ *
81
+ * If a kept method turns out to be param-sensitive under a later
82
+ * draw (model predicts ok for the one probe sample but rejects a
83
+ * subsequent arbitrary-drawn params), the safety-net guard in
84
+ * `registerModelEquivalence` raises `PropertyInvariantViolation`
85
+ * pointing at this file — the fix is to widen the derivation (probe
86
+ * K > 1 samples and keep only methods where every probe predicts ok)
87
+ * per the architect's contract. Single-probe is sufficient when
88
+ * `applyCall` is method-only (today).
89
+ */
90
+ export function arbitraryConfidentCall() {
91
+ if (confidentOracleMethods.length === 0) {
92
+ throw new Error("arbitraryConfidentCall: model has zero confident-oracle methods; flag needs-structural-rework");
93
+ }
94
+ return fc
95
+ .constantFrom(...confidentOracleMethods)
96
+ .chain((method) => arbitraryCallFor(method));
97
+ }
98
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../../src/testing/arbitraries/rpc.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EACL,UAAU,GAGX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAWvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiC,UAAU,CAAC,GAAG,CACvE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CACd,CAAC;AAEF,+EAA+E;AAC/E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAEjE,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAC9B,MAAS;IAET,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,CAC7C,CAAC,MAAM,EAAE,EAAE,CACT,CAAC;QACC,MAAM;QACN,MAAM,EAAE,MAA6B;KACtC,CAAU,CACd,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,CAAC,YAAY,CAAC,GAAG,aAAa,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAiC,CAAC,GAAG,EAAE;IACxE,iEAAiE;IACjE,wDAAwD;IACxD,4DAA4D;IAC5D,MAAM,IAAI,GAAoB,EAAE,CAAC;IACjC,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS;QACnC,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC;QACjE,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC,EAAE,CAAC;AAEL;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,sBAAsB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,+FAA+F,CAChG,CAAC;IACJ,CAAC;IACD,OAAO,EAAE;SACN,YAAY,CAAC,GAAG,sBAAsB,CAAC;SACvC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Canonicalization primitives — narrow, composable building blocks for
3
+ * body-compare property assertions.
4
+ *
5
+ * Per architect #197 §3: properties that compare response bodies route
6
+ * through a named canonical-projection function that normalizes order
7
+ * **only where the protocol spec marks it unordered**. These primitives
8
+ * let the property author that projection without reaching for a
9
+ * blanket deep-sort that would hide real re-ordering regressions inside
10
+ * nested arrays.
11
+ *
12
+ * Callers cite the spec clause for each array they sort, in JSDoc on
13
+ * the projection. Reviewer spot-checks during stamina pass.
14
+ *
15
+ * No blanket `canonicalizeUnordered` helper: picking which arrays to
16
+ * sort is a spec decision, not an ergonomic default.
17
+ */
18
+ /**
19
+ * Sort a JSON-array by the canonical stringification of each element.
20
+ * Shallow: does NOT recurse into elements. Caller composes with
21
+ * `sortObjectKeysDeep` per element if element-wise key-order stability
22
+ * matters. Preserves input immutability (returns a fresh array).
23
+ */
24
+ export declare function sortJsonArray(arr: ReadonlyArray<unknown>): ReadonlyArray<unknown>;
25
+ /**
26
+ * Deep key-sort on objects; array order preserved at every depth.
27
+ * Use before final `JSON.stringify` so key-order noise does not break
28
+ * byte-compare. Safe to apply over any payload.
29
+ */
30
+ export declare function sortObjectKeysDeep(value: unknown): unknown;
31
+ /**
32
+ * Final stable serialization: `sortObjectKeysDeep → JSON.stringify`.
33
+ * Intended as the last step after the property has applied whatever
34
+ * array-scoped sorts its spec citation allows. Array order is
35
+ * preserved; object key order is normalized.
36
+ */
37
+ export declare function canonicalJson(value: unknown): string;
38
+ //# sourceMappingURL=canonicalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../src/testing/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,CAAC,OAAO,CAAC,GAC1B,aAAa,CAAC,OAAO,CAAC,CAIxB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Canonicalization primitives — narrow, composable building blocks for
3
+ * body-compare property assertions.
4
+ *
5
+ * Per architect #197 §3: properties that compare response bodies route
6
+ * through a named canonical-projection function that normalizes order
7
+ * **only where the protocol spec marks it unordered**. These primitives
8
+ * let the property author that projection without reaching for a
9
+ * blanket deep-sort that would hide real re-ordering regressions inside
10
+ * nested arrays.
11
+ *
12
+ * Callers cite the spec clause for each array they sort, in JSDoc on
13
+ * the projection. Reviewer spot-checks during stamina pass.
14
+ *
15
+ * No blanket `canonicalizeUnordered` helper: picking which arrays to
16
+ * sort is a spec decision, not an ergonomic default.
17
+ */
18
+ /**
19
+ * Sort a JSON-array by the canonical stringification of each element.
20
+ * Shallow: does NOT recurse into elements. Caller composes with
21
+ * `sortObjectKeysDeep` per element if element-wise key-order stability
22
+ * matters. Preserves input immutability (returns a fresh array).
23
+ */
24
+ export function sortJsonArray(arr) {
25
+ const keyed = arr.map((el) => ({ el, key: canonicalJson(el) }));
26
+ keyed.sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
27
+ return keyed.map((k) => k.el);
28
+ }
29
+ /**
30
+ * Deep key-sort on objects; array order preserved at every depth.
31
+ * Use before final `JSON.stringify` so key-order noise does not break
32
+ * byte-compare. Safe to apply over any payload.
33
+ */
34
+ export function sortObjectKeysDeep(value) {
35
+ if (Array.isArray(value))
36
+ return value.map(sortObjectKeysDeep);
37
+ if (value === null || typeof value !== "object")
38
+ return value;
39
+ const out = {};
40
+ for (const key of Object.keys(value).sort()) {
41
+ const v = value[key];
42
+ out[key] = sortObjectKeysDeep(v);
43
+ }
44
+ return out;
45
+ }
46
+ /**
47
+ * Final stable serialization: `sortObjectKeysDeep → JSON.stringify`.
48
+ * Intended as the last step after the property has applied whatever
49
+ * array-scoped sorts its spec citation allows. Array order is
50
+ * preserved; object key order is normalized.
51
+ */
52
+ export function canonicalJson(value) {
53
+ return JSON.stringify(sortObjectKeysDeep(value));
54
+ }
55
+ //# sourceMappingURL=canonicalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../src/testing/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,GAA2B;IAE3B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC/D,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAa,KAA2C,CAAC,GAAG,CAAC,CAAC;QACrE,GAAG,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Bounded, ordered capture buffers. TestClient captures every frame the
3
+ * real server replied with; TestServer captures every frame a real client
4
+ * pushed in. Both are append-only ring buffers exposed as `Effect` Streams
5
+ * so property code can `Stream.take` or `Stream.filter` without racing the
6
+ * underlying fiber.
7
+ *
8
+ * Exhaustiveness: `CaptureKind` discriminates inbound vs outbound so the
9
+ * same buffer can record both sides when a primitive is proxied through
10
+ * Toxiproxy (Tier D).
11
+ */
12
+ import { Effect, Stream } from "effect";
13
+ import type { AnyFrame, MalformedFrameKind } from "./codec.js";
14
+ export type CaptureKind = "inbound" | "outbound";
15
+ /**
16
+ * One recorded event. `frame` is `null` when the capture is a raw-bytes
17
+ * record that failed to decode — Tier A's A4 property asserts on both the
18
+ * raw bytes and the typed `FrameSchemaError` that fired.
19
+ */
20
+ export interface CapturedFrame {
21
+ readonly at: number;
22
+ readonly kind: CaptureKind;
23
+ readonly raw: string;
24
+ readonly frame: AnyFrame | null;
25
+ readonly malformed: MalformedFrameKind | null;
26
+ }
27
+ /** Opaque handle to a running buffer; held by TestClient / TestServer. */
28
+ export interface CaptureBuffer {
29
+ readonly snapshot: Effect.Effect<ReadonlyArray<CapturedFrame>>;
30
+ readonly stream: Stream.Stream<CapturedFrame>;
31
+ readonly clear: Effect.Effect<void>;
32
+ /** @internal — used by primitives to append. Not exported from barrel. */
33
+ readonly _publish: (entry: CapturedFrame) => Effect.Effect<void>;
34
+ /** @internal — soft capacity so `mergeCaptures` can fan messages out safely. */
35
+ readonly _capacity: number;
36
+ }
37
+ /**
38
+ * Ring-buffer + PubSub implementation. The Ref holds the bounded
39
+ * array; PubSub fans each append out to every subscriber so `stream`
40
+ * behaves as a live tail.
41
+ */
42
+ export declare function makeCaptureBuffer(opts: {
43
+ readonly capacity: number;
44
+ }): Effect.Effect<CaptureBuffer>;
45
+ /**
46
+ * Multiplex captures across many connections — used by Tier C properties
47
+ * where N real clients emit concurrently and the property asserts on the
48
+ * merged ordered stream.
49
+ *
50
+ * Semantics:
51
+ * - `snapshot` returns every buffer's current contents concatenated and
52
+ * sorted by `at` (stable for equal timestamps by buffer index).
53
+ * - `stream` is `Stream.mergeAll(stream...)` — live events in arrival order.
54
+ * - `clear` clears every upstream buffer.
55
+ */
56
+ export declare function mergeCaptures(buffers: ReadonlyArray<CaptureBuffer>): Effect.Effect<CaptureBuffer>;
57
+ /** Internal hook used by primitives to push a decode failure as-bytes. */
58
+ export declare function recordMalformed(buffer: CaptureBuffer, raw: string, kind: MalformedFrameKind): Effect.Effect<void>;
59
+ /** Internal hook: push a successfully-decoded frame. */
60
+ export declare function recordFrame(buffer: CaptureBuffer, kind: CaptureKind, raw: string, frame: AnyFrame): Effect.Effect<void>;
61
+ //# sourceMappingURL=captures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captures.d.ts","sourceRoot":"","sources":["../../src/testing/captures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAO,MAAM,EAAU,MAAM,QAAQ,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAEjD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAC/C;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAC/D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjE,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAwB/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC,GACpC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAkC9B;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,kBAAkB,GACvB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAQrB;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CACzB,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,QAAQ,GACd,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAQrB"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Bounded, ordered capture buffers. TestClient captures every frame the
3
+ * real server replied with; TestServer captures every frame a real client
4
+ * pushed in. Both are append-only ring buffers exposed as `Effect` Streams
5
+ * so property code can `Stream.take` or `Stream.filter` without racing the
6
+ * underlying fiber.
7
+ *
8
+ * Exhaustiveness: `CaptureKind` discriminates inbound vs outbound so the
9
+ * same buffer can record both sides when a primitive is proxied through
10
+ * Toxiproxy (Tier D).
11
+ */
12
+ import { Effect, Ref, Stream, PubSub } from "effect";
13
+ const startTime = Date.now();
14
+ /**
15
+ * Ring-buffer + PubSub implementation. The Ref holds the bounded
16
+ * array; PubSub fans each append out to every subscriber so `stream`
17
+ * behaves as a live tail.
18
+ */
19
+ export function makeCaptureBuffer(opts) {
20
+ return Effect.gen(function* () {
21
+ const cap = Math.max(1, opts.capacity);
22
+ const ref = yield* Ref.make([]);
23
+ const pubsub = yield* PubSub.sliding(cap);
24
+ const publish = (entry) => Effect.gen(function* () {
25
+ yield* Ref.update(ref, (cur) => {
26
+ const next = cur.length >= cap ? cur.slice(1) : cur.slice();
27
+ return [...next, entry];
28
+ });
29
+ yield* PubSub.publish(pubsub, entry);
30
+ });
31
+ const buf = {
32
+ snapshot: Ref.get(ref),
33
+ stream: Stream.fromPubSub(pubsub),
34
+ clear: Ref.set(ref, []),
35
+ _publish: publish,
36
+ _capacity: cap,
37
+ };
38
+ return buf;
39
+ });
40
+ }
41
+ /**
42
+ * Multiplex captures across many connections — used by Tier C properties
43
+ * where N real clients emit concurrently and the property asserts on the
44
+ * merged ordered stream.
45
+ *
46
+ * Semantics:
47
+ * - `snapshot` returns every buffer's current contents concatenated and
48
+ * sorted by `at` (stable for equal timestamps by buffer index).
49
+ * - `stream` is `Stream.mergeAll(stream...)` — live events in arrival order.
50
+ * - `clear` clears every upstream buffer.
51
+ */
52
+ export function mergeCaptures(buffers) {
53
+ return Effect.gen(function* () {
54
+ const merged = yield* makeCaptureBuffer({
55
+ capacity: buffers.reduce((sum, b) => sum + b._capacity, 0) || 1,
56
+ });
57
+ // Return a view that aggregates snapshots on demand rather than a live
58
+ // merged copy: the source buffers are authoritative.
59
+ const snapshot = Effect.gen(function* () {
60
+ const snaps = yield* Effect.forEach(buffers, (b) => b.snapshot, {
61
+ concurrency: "unbounded",
62
+ });
63
+ const flat = snaps.flat();
64
+ return [...flat].sort((a, b) => a.at - b.at);
65
+ });
66
+ const stream = Stream.mergeAll(buffers.map((b) => b.stream), { concurrency: "unbounded" });
67
+ const clear = Effect.forEach(buffers, (b) => b.clear, {
68
+ concurrency: "unbounded",
69
+ }).pipe(Effect.asVoid);
70
+ return {
71
+ snapshot,
72
+ stream,
73
+ clear,
74
+ _publish: merged._publish,
75
+ _capacity: merged._capacity,
76
+ };
77
+ });
78
+ }
79
+ /** Internal hook used by primitives to push a decode failure as-bytes. */
80
+ export function recordMalformed(buffer, raw, kind) {
81
+ return buffer._publish({
82
+ at: Date.now() - startTime,
83
+ kind: "inbound",
84
+ raw,
85
+ frame: null,
86
+ malformed: kind,
87
+ });
88
+ }
89
+ /** Internal hook: push a successfully-decoded frame. */
90
+ export function recordFrame(buffer, kind, raw, frame) {
91
+ return buffer._publish({
92
+ at: Date.now() - startTime,
93
+ kind,
94
+ raw,
95
+ frame,
96
+ malformed: null,
97
+ });
98
+ }
99
+ //# sourceMappingURL=captures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captures.js","sourceRoot":"","sources":["../../src/testing/captures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Frame codec for the testing primitives.
3
+ *
4
+ * Satisfies §5.A1/A2/A3/A4 and Invariant I3: every frame crossing a
5
+ * primitive is `Value.Check`-validated before it is surfaced to property
6
+ * code. Malformed-frame arbitraries are generated *here* so Tier A can
7
+ * inject bit-flips, truncations, and oversized frames without leaking the
8
+ * malformation strategy into the primitives.
9
+ */
10
+ import { Effect } from "effect";
11
+ import { type RequestFrame, type ResponseFrame, type EventFrame } from "../schema/frames.js";
12
+ import { FrameSchemaError } from "./errors.js";
13
+ /**
14
+ * Valid-frame kinds exposed on the wire. The string literal discriminator
15
+ * matches the `type` field in `RequestFrameSchema` / `ResponseFrameSchema`
16
+ * and the outer `type: "event"` sentinel for `EventFrameSchema`.
17
+ */
18
+ export type AnyFrame = ({
19
+ readonly type: "request";
20
+ } & RequestFrame) | ({
21
+ readonly type: "response";
22
+ } & ResponseFrame) | ({
23
+ readonly type: "event";
24
+ } & EventFrame);
25
+ /**
26
+ * Kinds of malformation Tier A / Tier D-slicer can inject. Each maps to a
27
+ * deterministic mutation driven by fast-check so shrinks reproduce.
28
+ */
29
+ export type MalformedFrameKind = "bit-flip" | "truncated" | "oversized" | "invalid-utf8" | "missing-required-field" | "extra-property";
30
+ /** Serialize a typed frame to the wire bytes. */
31
+ export declare function encodeFrame(frame: AnyFrame): string;
32
+ /**
33
+ * Parse + `Value.Check` an inbound frame. `FrameSchemaError` captures
34
+ * the failing branch so Tier A can assert "drop or typed error, never
35
+ * crash."
36
+ */
37
+ export declare function decodeFrame(raw: string, direction: "outbound" | "inbound"): Effect.Effect<AnyFrame, FrameSchemaError>;
38
+ /**
39
+ * Produce a malformed wire payload from a valid frame. The mutation is
40
+ * deterministic given the `kind` + `seed`; replaying with the same seed
41
+ * reproduces the exact bytes. Used by Tier A (A4) and Tier D (D3).
42
+ */
43
+ export declare function malformFrame(base: AnyFrame, kind: MalformedFrameKind, seed: number): string;
44
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/testing/codec.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAChB,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,aAAa,CAAC,GAC/C,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,UAAU,CAAC,CAAC;AAE9C;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAC1B,UAAU,GACV,WAAW,GACX,WAAW,GACX,cAAc,GACd,wBAAwB,GACxB,gBAAgB,CAAC;AAErB,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAEnD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,UAAU,GAAG,SAAS,GAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAiF3C;AAaD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,kBAAkB,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAoDR"}