@moltzap/protocol 2026.408.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 (288) 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 -18
  18. package/dist/schema/contacts.d.ts.map +1 -1
  19. package/dist/schema/contacts.js +9 -13
  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 -93
  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 +19 -17
  38. package/dist/schema/identity.d.ts.map +1 -1
  39. package/dist/schema/identity.js +7 -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 +102 -90
  54. package/dist/schema/methods/auth.d.ts.map +1 -1
  55. package/dist/schema/methods/auth.js +86 -74
  56. package/dist/schema/methods/auth.js.map +1 -1
  57. package/dist/schema/methods/contacts.d.ts +39 -74
  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 -177
  258. package/dist/validators.d.ts.map +1 -1
  259. package/dist/validators.js +77 -48
  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/LICENSE +0 -21
  265. package/dist/optional/contact-events.d.ts +0 -3
  266. package/dist/optional/contact-events.d.ts.map +0 -1
  267. package/dist/optional/contact-events.js +0 -5
  268. package/dist/optional/contact-events.js.map +0 -1
  269. package/dist/optional/contact-methods.d.ts +0 -5
  270. package/dist/optional/contact-methods.d.ts.map +0 -1
  271. package/dist/optional/contact-methods.js +0 -5
  272. package/dist/optional/contact-methods.js.map +0 -1
  273. package/dist/phone-hash.d.ts +0 -10
  274. package/dist/phone-hash.d.ts.map +0 -1
  275. package/dist/phone-hash.js +0 -17
  276. package/dist/phone-hash.js.map +0 -1
  277. package/dist/schema/methods/phone-contacts.d.ts +0 -30
  278. package/dist/schema/methods/phone-contacts.d.ts.map +0 -1
  279. package/dist/schema/methods/phone-contacts.js +0 -10
  280. package/dist/schema/methods/phone-contacts.js.map +0 -1
  281. package/dist/test-client.d.ts +0 -34
  282. package/dist/test-client.d.ts.map +0 -1
  283. package/dist/test-client.js +0 -176
  284. package/dist/test-client.js.map +0 -1
  285. package/dist/test-fixtures/phone-hashes.d.ts +0 -18
  286. package/dist/test-fixtures/phone-hashes.d.ts.map +0 -1
  287. package/dist/test-fixtures/phone-hashes.js +0 -24
  288. package/dist/test-fixtures/phone-hashes.js.map +0 -1
@@ -0,0 +1,394 @@
1
+ /**
2
+ * RPC semantics — properties that compare the real server's observable
3
+ * outcome against the reference-model reducer, and exercise authority
4
+ * + request-id + idempotence invariants end-to-end.
5
+ *
6
+ * Historical grouping note: spec #181 §5 calls this "Tier B". Code uses
7
+ * semantic names only.
8
+ *
9
+ * Principle 3: every property body is `Effect<void, PropertyFailure>`.
10
+ */
11
+ import * as fc from "fast-check";
12
+ import { Effect } from "effect";
13
+ import { arbitraryAnyCall, arbitraryConfidentCall, confidentOracleMethods, } from "../arbitraries/rpc.js";
14
+ import { applyCall, authorizationOutcome, isIdempotent, } from "../models/dispatch.js";
15
+ import { initialReferenceState } from "../models/state.js";
16
+ import { ErrorCodes } from "../../schema/errors.js";
17
+ import { canonicalJson, sortJsonArray } from "../canonicalize.js";
18
+ import { makeTestClient } from "../test-client.js";
19
+ import { registerTestAgent } from "../agent-registration.js";
20
+ import { allRpcMethods } from "../arbitraries/rpc.js";
21
+ import { assertProperty, PropertyInvariantViolation, PropertyUnavailable, registerProperty, } from "./registry.js";
22
+ const CATEGORY = "rpc-semantics";
23
+ const DEFAULT_TIMEOUT_MS = 3000;
24
+ const DEFAULT_CAPTURE_CAPACITY = 64;
25
+ /**
26
+ * Model-equivalence — conditional oracle over the model-derived
27
+ * confident set (architect #195 §4.1 + #197 §2).
28
+ *
29
+ * Spec §5 B1: the server must produce what the model predicts when
30
+ * the model is confident. `arbitraryConfidentCall()` draws calls via
31
+ * the architect-literal shape `fc.constantFrom(...kept).chain(
32
+ * arbitraryCallFor)` — probe and execution share the same generator
33
+ * so confidence is checked on the same distribution the property
34
+ * exercises (round-8 finding: a `.map(m => ({method: m, params: {}}))`
35
+ * shortcut narrowed execution below the probe and hid real
36
+ * param-dependent divergences).
37
+ *
38
+ * Param-invariance safety net (#197 §2.2 + §6.1): if a drawn call
39
+ * comes back `_tag: "error"` from the model, the single-probe
40
+ * derivation has diverged from runtime truth (applyCall became
41
+ * param-sensitive for that method under a later draw). The property
42
+ * raises `PropertyInvariantViolation` instead of silently short-
43
+ * circuiting; the fix is to widen the derivation (probe with K > 1
44
+ * samples), not extend this property.
45
+ *
46
+ * Current K = 1 (agents/list only). Architect #197 §2.3 notes that
47
+ * "when K ≤ 2, the property is operating as a small number of hand-
48
+ * picked examples; document it in JSDoc, don't pretend it's a fuzz
49
+ * property." Widening K requires either teaching `applyCall` per-
50
+ * method param filters (e.g. `conversations/list` confident only
51
+ * when cursor is undefined/valid) or fixing server-side parsers that
52
+ * error on pathological schema-valid params (e.g. `cursor: " "` →
53
+ * SqlError on pglite cursor parsing). Tracked under #186.
54
+ *
55
+ * numRuns floor: `max(10, 2K)` = 10 today.
56
+ */
57
+ export function registerModelEquivalence(ctx) {
58
+ const K = confidentOracleMethods.length;
59
+ const numRunsFloor = Math.max(10, 2 * K);
60
+ registerProperty(ctx, CATEGORY, "model-equivalence", `when model predicts ok, server MUST return ok (K=${K} confident methods)`, assertProperty(CATEGORY, "model-equivalence", () => fc.assert(
61
+ // #ignore-sloppy-code-next-line[async-keyword]: fast-check asyncProperty contract requires Promise-returning callback
62
+ fc.asyncProperty(arbitraryConfidentCall(), async (call) => {
63
+ const modelTag = applyCall(initialReferenceState, call).outcome._tag;
64
+ if (modelTag === "error") {
65
+ // Safety-net guard: `arbitraryConfidentCall` derived this
66
+ // method as confident at module load. If the model now
67
+ // disagrees, applyCall became param-sensitive for the
68
+ // kept method and the derivation must widen. Surface
69
+ // loudly instead of silent short-circuit.
70
+ throw new Error(`arbitraryConfidentCall drew ${call.method} with params ${JSON.stringify(call.params)} → model _tag: "error" — param-invariance contract broken; widen derivation to fc.sample-based check per architect #197 §2.2`);
71
+ }
72
+ const serverTag = await Effect.runPromise(Effect.scoped(Effect.gen(function* () {
73
+ const agent = yield* registerTestAgent({
74
+ baseUrl: ctx.realServer.baseUrl,
75
+ name: "me",
76
+ });
77
+ const client = yield* makeTestClient({
78
+ serverUrl: ctx.realServer.wsUrl,
79
+ agentKey: agent.apiKey,
80
+ agentId: agent.agentId,
81
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
82
+ captureCapacity: DEFAULT_CAPTURE_CAPACITY,
83
+ });
84
+ const outcome = yield* client
85
+ .sendRpc(call.method, call.params)
86
+ .pipe(Effect.either);
87
+ return outcome._tag === "Right" ? "ok" : "error";
88
+ })));
89
+ // Model is confident it's `ok`. Server MUST agree.
90
+ return serverTag === "ok";
91
+ }), { seed: ctx.seed, numRuns: ctx.opts.numRuns ?? numRunsFloor })));
92
+ // Keep `arbitraryAnyCall` import alive — used by sibling properties.
93
+ void arbitraryAnyCall;
94
+ }
95
+ /**
96
+ * Authorized caller → typed success on at least one known-safe RPC.
97
+ * Registers a fresh agent, completes the handshake, calls
98
+ * `conversations/list` (empty-collection result is defined for every
99
+ * newly-registered agent), asserts a Right outcome.
100
+ */
101
+ export function registerAuthorityPositive(ctx) {
102
+ registerProperty(ctx, CATEGORY, "authority-positive", "authorized agent → typed success on conversations/list", Effect.scoped(Effect.gen(function* () {
103
+ const agent = yield* registerTestAgent({
104
+ baseUrl: ctx.realServer.baseUrl,
105
+ name: "ap",
106
+ }).pipe(Effect.mapError((e) => new PropertyInvariantViolation({
107
+ category: CATEGORY,
108
+ name: "authority-positive",
109
+ reason: `agent registration failed: ${e.body}`,
110
+ })));
111
+ const client = yield* makeTestClient({
112
+ serverUrl: ctx.realServer.wsUrl,
113
+ agentKey: agent.apiKey,
114
+ agentId: agent.agentId,
115
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
116
+ captureCapacity: DEFAULT_CAPTURE_CAPACITY,
117
+ }).pipe(Effect.mapError((e) => new PropertyInvariantViolation({
118
+ category: CATEGORY,
119
+ name: "authority-positive",
120
+ reason: `client acquire failed: ${String(e)}`,
121
+ })));
122
+ const outcome = yield* client
123
+ .sendRpc("conversations/list", {})
124
+ .pipe(Effect.either);
125
+ if (outcome._tag === "Left") {
126
+ return yield* Effect.fail(new PropertyInvariantViolation({
127
+ category: CATEGORY,
128
+ name: "authority-positive",
129
+ reason: `authorized conversations/list failed: ${outcome.left._tag}`,
130
+ }));
131
+ }
132
+ })));
133
+ }
134
+ /**
135
+ * Unauthenticated caller → typed denial on an auth-gated RPC. Opens a
136
+ * TestClient with `autoConnect: false` and calls `conversations/list`
137
+ * without first completing `auth/connect`; asserts the server replies
138
+ * with a typed error (not a success, not a crash).
139
+ */
140
+ export function registerAuthorityNegative(ctx) {
141
+ registerProperty(ctx, CATEGORY, "authority-negative", "unauthenticated agent → typed denial on conversations/list", Effect.scoped(Effect.gen(function* () {
142
+ // We still need an agentKey to open the socket, but we skip
143
+ // `auth/connect` so the server sees an un-authed session.
144
+ const agent = yield* registerTestAgent({
145
+ baseUrl: ctx.realServer.baseUrl,
146
+ name: "an",
147
+ }).pipe(Effect.mapError((e) => new PropertyInvariantViolation({
148
+ category: CATEGORY,
149
+ name: "authority-negative",
150
+ reason: `agent registration failed: ${e.body}`,
151
+ })));
152
+ const client = yield* makeTestClient({
153
+ serverUrl: ctx.realServer.wsUrl,
154
+ agentKey: agent.apiKey,
155
+ agentId: agent.agentId,
156
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
157
+ captureCapacity: DEFAULT_CAPTURE_CAPACITY,
158
+ autoConnect: false,
159
+ }).pipe(Effect.mapError((e) => new PropertyInvariantViolation({
160
+ category: CATEGORY,
161
+ name: "authority-negative",
162
+ reason: `client acquire failed: ${String(e)}`,
163
+ })));
164
+ const outcome = yield* client
165
+ .sendRpc("conversations/list", {})
166
+ .pipe(Effect.either);
167
+ if (outcome._tag === "Right") {
168
+ return yield* Effect.fail(new PropertyInvariantViolation({
169
+ category: CATEGORY,
170
+ name: "authority-negative",
171
+ reason: "pre-handshake conversations/list returned success — expected typed denial",
172
+ }));
173
+ }
174
+ // Narrow the Left: must be a typed auth-shaped RpcResponseError
175
+ // (Unauthorized / Forbidden). A timeout or transport-close
176
+ // would also surface as `Left` but does NOT satisfy the
177
+ // property — it proves nothing about authorization.
178
+ if (outcome.left._tag !== "TestingRpcResponseError") {
179
+ return yield* Effect.fail(new PropertyInvariantViolation({
180
+ category: CATEGORY,
181
+ name: "authority-negative",
182
+ reason: `expected RpcResponseError, got ${outcome.left._tag}`,
183
+ }));
184
+ }
185
+ const code = outcome.left.code;
186
+ const isAuthShaped = code === ErrorCodes.Unauthorized || code === ErrorCodes.Forbidden;
187
+ if (!isAuthShaped) {
188
+ return yield* Effect.fail(new PropertyInvariantViolation({
189
+ category: CATEGORY,
190
+ name: "authority-negative",
191
+ reason: `expected Unauthorized/Forbidden code (${ErrorCodes.Unauthorized} / ${ErrorCodes.Forbidden}), got ${code}`,
192
+ }));
193
+ }
194
+ // Oracle cross-check: the model also predicts deny for this
195
+ // unauthenticated caller. Keeps the model honest alongside the
196
+ // server.
197
+ const modelVerdict = authorizationOutcome(initialReferenceState, { method: "conversations/list", params: {} }, "unknown-agent");
198
+ if (modelVerdict !== "deny-unauthenticated") {
199
+ return yield* Effect.fail(new PropertyInvariantViolation({
200
+ category: CATEGORY,
201
+ name: "authority-negative",
202
+ reason: `model oracle disagrees: expected deny-unauthenticated, got ${modelVerdict}`,
203
+ }));
204
+ }
205
+ })));
206
+ }
207
+ /**
208
+ * Request-IDs are unique per inbound response. Sends N RPCs and asserts
209
+ * every id in the captured response stream appears exactly once.
210
+ */
211
+ export function registerRequestIdUniqueness(ctx) {
212
+ registerProperty(ctx, CATEGORY, "request-id-uniqueness", "every request-id appears in exactly one response", assertProperty(CATEGORY, "request-id-uniqueness", () => fc.assert(
213
+ // #ignore-sloppy-code-next-line[async-keyword]: fast-check asyncProperty contract requires Promise-returning callback
214
+ fc.asyncProperty(fc.integer({ min: 2, max: 6 }), async (n) => {
215
+ const counts = await Effect.runPromise(Effect.scoped(Effect.gen(function* () {
216
+ const agent = yield* registerTestAgent({
217
+ baseUrl: ctx.realServer.baseUrl,
218
+ name: "ru",
219
+ });
220
+ const client = yield* makeTestClient({
221
+ serverUrl: ctx.realServer.wsUrl,
222
+ agentKey: agent.apiKey,
223
+ agentId: agent.agentId,
224
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
225
+ captureCapacity: n * 4,
226
+ });
227
+ // Snapshot the capture boundary after handshake so we
228
+ // only tally response ids for the N RPCs below — not
229
+ // the auto-connect reply.
230
+ const handshakeEnd = (yield* client.snapshot).length;
231
+ yield* Effect.forEach(Array.from({ length: n }, (_, i) => i), () => client
232
+ .sendRpc("conversations/list", {})
233
+ .pipe(Effect.either), { concurrency: n });
234
+ const snap = (yield* client.snapshot).slice(handshakeEnd);
235
+ const outboundIds = new Set();
236
+ const inboundIds = new Set();
237
+ let inboundCount = 0;
238
+ for (const entry of snap) {
239
+ if (entry.frame?.type !== "request" &&
240
+ entry.frame?.type !== "response")
241
+ continue;
242
+ if (entry.kind === "outbound" &&
243
+ entry.frame.type === "request") {
244
+ outboundIds.add(entry.frame.id);
245
+ }
246
+ if (entry.kind === "inbound" &&
247
+ entry.frame.type === "response") {
248
+ inboundIds.add(entry.frame.id);
249
+ inboundCount += 1;
250
+ }
251
+ }
252
+ return { outboundIds, inboundIds, inboundCount };
253
+ })));
254
+ // Architect §4.2 set-equality predicate. Conjunction:
255
+ // - outboundIds.size === n (driver produced n frames)
256
+ // - inboundIds.size === outboundIds.size (cardinality match)
257
+ // - every outbound id is matched inbound (no drops, no strays)
258
+ // - inboundCount === inboundIds.size (no inbound duplicates)
259
+ // Stray IDs, dropped replies, and id-reuse all fail the property.
260
+ const { outboundIds, inboundIds, inboundCount } = counts;
261
+ if (outboundIds.size !== n)
262
+ return false;
263
+ if (inboundIds.size !== outboundIds.size)
264
+ return false;
265
+ if (inboundCount !== inboundIds.size)
266
+ return false;
267
+ for (const id of outboundIds) {
268
+ if (!inboundIds.has(id))
269
+ return false;
270
+ }
271
+ return true;
272
+ }), { seed: ctx.seed, numRuns: ctx.opts.numRuns ?? 5 })));
273
+ }
274
+ /**
275
+ * Idempotent RPCs yield equivalent responses on replay. For every
276
+ * list-shaped method where empty params are valid and `isIdempotent`
277
+ * says replay is safe, sends the same params twice and asserts both
278
+ * succeed with **identical results** (not just identical tags).
279
+ *
280
+ * Architect §4.4: removed `.pipe(Effect.orElseSucceed(["skip","skip"]))`
281
+ * masking. Transport failures now surface as `PropertyUnavailable` so
282
+ * the runner reports them explicitly instead of folding them into a
283
+ * silent pass. Predicate compares response bodies via canonical JSON
284
+ * — spec B5 says "identical results", not "identical outcome kinds".
285
+ */
286
+ export function registerIdempotence(ctx) {
287
+ registerProperty(ctx, CATEGORY, "idempotence", "isIdempotent methods: two sends yield identical response bodies", Effect.gen(function* () {
288
+ const emptyParamIdempotents = [
289
+ "agents/list",
290
+ "conversations/list",
291
+ ];
292
+ for (const method of emptyParamIdempotents) {
293
+ if (!isIdempotent(method)) {
294
+ return yield* Effect.fail(new PropertyInvariantViolation({
295
+ category: CATEGORY,
296
+ name: "idempotence",
297
+ reason: `isIdempotent(${method}) is false — oracle disagreement`,
298
+ }));
299
+ }
300
+ const pair = yield* Effect.scoped(Effect.gen(function* () {
301
+ const agent = yield* registerTestAgent({
302
+ baseUrl: ctx.realServer.baseUrl,
303
+ name: "id",
304
+ });
305
+ const client = yield* makeTestClient({
306
+ serverUrl: ctx.realServer.wsUrl,
307
+ agentKey: agent.apiKey,
308
+ agentId: agent.agentId,
309
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
310
+ captureCapacity: DEFAULT_CAPTURE_CAPACITY,
311
+ });
312
+ const a = yield* client.sendRpc(method, {}).pipe(Effect.either);
313
+ const b = yield* client.sendRpc(method, {}).pipe(Effect.either);
314
+ return { a, b };
315
+ })).pipe(Effect.catchTags({
316
+ TestingAgentRegistrationError: (e) => Effect.fail(new PropertyUnavailable({
317
+ category: CATEGORY,
318
+ name: "idempotence",
319
+ reason: `register: ${e.body}`,
320
+ })),
321
+ TestingTransportIoError: (e) => Effect.fail(new PropertyUnavailable({
322
+ category: CATEGORY,
323
+ name: "idempotence",
324
+ reason: `transport io: ${String(e.cause)}`,
325
+ })),
326
+ TestingTransportClosedError: (e) => Effect.fail(new PropertyUnavailable({
327
+ category: CATEGORY,
328
+ name: "idempotence",
329
+ reason: `transport closed: ${e.reason}`,
330
+ })),
331
+ TestingRpcResponseError: (e) => Effect.fail(new PropertyUnavailable({
332
+ category: CATEGORY,
333
+ name: "idempotence",
334
+ reason: `rpc response error: ${e.message}`,
335
+ })),
336
+ }));
337
+ if (pair.a._tag !== pair.b._tag) {
338
+ return yield* Effect.fail(new PropertyInvariantViolation({
339
+ category: CATEGORY,
340
+ name: "idempotence",
341
+ reason: `${method}: replay outcome-tag mismatch ${pair.a._tag} → ${pair.b._tag}`,
342
+ }));
343
+ }
344
+ if (pair.a._tag === "Right" && pair.b._tag === "Right") {
345
+ // Canonical-projection comparison per architect #197 §3.3.
346
+ // Direct JSON.stringify on wire-derived values is byte-
347
+ // equality, not semantic equality; a conforming server may
348
+ // return the list in a different row order across replays.
349
+ const aCanon = canonIdempotenceResult(method, pair.a.right);
350
+ const bCanon = canonIdempotenceResult(method, pair.b.right);
351
+ if (aCanon !== bCanon) {
352
+ return yield* Effect.fail(new PropertyInvariantViolation({
353
+ category: CATEGORY,
354
+ name: "idempotence",
355
+ reason: `${method}: replay bodies diverge under canonical projection`,
356
+ }));
357
+ }
358
+ }
359
+ }
360
+ }));
361
+ void allRpcMethods;
362
+ }
363
+ /**
364
+ * Idempotence canonical projection — architect #197 §3.3.
365
+ *
366
+ * Spec B5: agents/list.agents and conversations/list.conversations are
367
+ * unordered row sets across replays. Every OTHER array (including any
368
+ * nested `participants`, future nested message lists, and every
369
+ * payload field that is not one of the two named arrays) remains
370
+ * order-sensitive.
371
+ *
372
+ * The projection sorts ONLY the specific top-level array the spec
373
+ * marks unordered, then finalizes via `canonicalJson` (which
374
+ * normalizes object-key order but preserves every remaining array's
375
+ * order). A real re-ordering regression inside nested arrays still
376
+ * fails the property.
377
+ */
378
+ function canonIdempotenceResult(method, result) {
379
+ if (method === "agents/list") {
380
+ const r = result;
381
+ return canonicalJson({
382
+ ...r,
383
+ agents: Array.isArray(r.agents) ? sortJsonArray(r.agents) : r.agents,
384
+ });
385
+ }
386
+ const r = result;
387
+ return canonicalJson({
388
+ ...r,
389
+ conversations: Array.isArray(r.conversations)
390
+ ? sortJsonArray(r.conversations)
391
+ : r.conversations,
392
+ });
393
+ }
394
+ //# sourceMappingURL=rpc-semantics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-semantics.js","sourceRoot":"","sources":["../../../src/testing/conformance/rpc-semantics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Conformance-suite runner.
3
+ *
4
+ * Orchestrates tiers A → E under one entrypoint so
5
+ * `pnpm -F @moltzap/protocol test:conformance` is the only command a CI
6
+ * job needs (AC11).
7
+ *
8
+ * Responsibilities:
9
+ * - receive a real MoltZap server handle (built externally to preserve
10
+ * AC13 one-way imports);
11
+ * - build a Toxiproxy client when Tier D is in scope;
12
+ * - pin fast-check seeds and export them on failure (AC10);
13
+ * - tear everything down in reverse order.
14
+ */
15
+ import { Effect, Ref, Scope } from "effect";
16
+ import { type ToxiproxyClient } from "../toxics/client.js";
17
+ import { RealServerAcquireError, ToxicControlError } from "../errors.js";
18
+ /**
19
+ * Opaque handle to a running real MoltZap server. The conformance runner
20
+ * accepts this as an injected dependency so the protocol package has no
21
+ * compile-time import of `packages/server` (AC13). The consuming suite
22
+ * file supplies a concrete value built from `startCoreTestServer`.
23
+ */
24
+ export interface RealServerHandle {
25
+ readonly wsUrl: string;
26
+ readonly baseUrl: string;
27
+ /** Teardown hook; the runner's Scope calls this on release. */
28
+ readonly close: () => Promise<void>;
29
+ }
30
+ export interface ConformanceRunOptions {
31
+ readonly tiers: ReadonlyArray<"A" | "B" | "C" | "D" | "E">;
32
+ /** Supplier for the real server; invoked once per run. */
33
+ readonly realServer: () => Promise<RealServerHandle>;
34
+ /** If provided, replay this exact fast-check seed (AC10 reproducibility). */
35
+ readonly replaySeed?: number;
36
+ /** Number of runs per property; fast-check default is 100. */
37
+ readonly numRuns?: number;
38
+ /** When `true`, bring up docker-compose Toxiproxy; else assume running. */
39
+ readonly manageToxiproxy?: boolean;
40
+ /** Toxiproxy control URL — defaults to `http://127.0.0.1:8474`. */
41
+ readonly toxiproxyUrl?: string;
42
+ /** Output directory for seed + toxic-config dump on failure. */
43
+ readonly artifactDir?: string;
44
+ }
45
+ export interface ConformanceRunContext {
46
+ readonly realServer: RealServerHandle;
47
+ readonly toxiproxy: ToxiproxyClient | null;
48
+ readonly opts: ConformanceRunOptions;
49
+ /** Seed to pin every property to. Exported on failure for replay. */
50
+ readonly seed: number;
51
+ /**
52
+ * Per-property artifact sink. The tier modules call `record` to stash a
53
+ * seed + toxic profile when a property fails; the suite post-process
54
+ * writes to `opts.artifactDir`.
55
+ */
56
+ readonly artifacts: Ref.Ref<ReadonlyArray<ConformanceArtifact>>;
57
+ }
58
+ export interface ConformanceArtifact {
59
+ readonly tierId: string;
60
+ readonly propId: string;
61
+ readonly seed: number;
62
+ readonly toxicProfile?: string;
63
+ readonly commandSequence?: ReadonlyArray<unknown>;
64
+ readonly captures?: ReadonlyArray<unknown>;
65
+ }
66
+ /**
67
+ * Acquire the full context (real server + optional Toxiproxy) under one
68
+ * Scope; Vitest's `beforeAll`/`afterAll` tick the scope.
69
+ */
70
+ export declare function acquireRunContext(opts: ConformanceRunOptions): Effect.Effect<ConformanceRunContext, ToxicControlError | RealServerAcquireError, Scope.Scope>;
71
+ /**
72
+ * Entry point the runner script calls. Iterates `opts.tiers` and writes a
73
+ * summary line per tier; the actual properties register themselves with
74
+ * Vitest via each tier module's `register*` functions — so this only
75
+ * orchestrates output + seed plumbing.
76
+ */
77
+ export declare function runConformance(ctx: ConformanceRunContext): Effect.Effect<void>;
78
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/testing/conformance/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGzE;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC3D,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrD,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,qBAAqB,GAC1B,MAAM,CAAC,MAAM,CACd,qBAAqB,EACrB,iBAAiB,GAAG,sBAAsB,EAC1C,KAAK,CAAC,KAAK,CACZ,CA2CA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,qBAAqB,GACzB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAMrB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Conformance-suite runner.
3
+ *
4
+ * Orchestrates tiers A → E under one entrypoint so
5
+ * `pnpm -F @moltzap/protocol test:conformance` is the only command a CI
6
+ * job needs (AC11).
7
+ *
8
+ * Responsibilities:
9
+ * - receive a real MoltZap server handle (built externally to preserve
10
+ * AC13 one-way imports);
11
+ * - build a Toxiproxy client when Tier D is in scope;
12
+ * - pin fast-check seeds and export them on failure (AC10);
13
+ * - tear everything down in reverse order.
14
+ */
15
+ import { Effect, Ref, Scope } from "effect";
16
+ import { makeToxiproxyClient } from "../toxics/client.js";
17
+ import { RealServerAcquireError, ToxicControlError } from "../errors.js";
18
+ import { conformanceNumRunsFromEnv } from "./env.js";
19
+ /**
20
+ * Acquire the full context (real server + optional Toxiproxy) under one
21
+ * Scope; Vitest's `beforeAll`/`afterAll` tick the scope.
22
+ */
23
+ export function acquireRunContext(opts) {
24
+ return Effect.gen(function* () {
25
+ const effectiveOpts = {
26
+ ...opts,
27
+ numRuns: opts.numRuns ?? conformanceNumRunsFromEnv(),
28
+ };
29
+ const seed = effectiveOpts.replaySeed ??
30
+ Number(process.env.FC_SEED ?? Date.now() & 0x7fffffff);
31
+ const artifacts = yield* Ref.make([]);
32
+ const realServer = yield* Effect.acquireRelease(Effect.tryPromise({
33
+ try: () => opts.realServer(),
34
+ catch: (cause) => new RealServerAcquireError({ cause }),
35
+ }), (handle) => Effect.tryPromise({
36
+ try: () => handle.close(),
37
+ catch: () => new Error("realServer.close() threw"),
38
+ }).pipe(Effect.orElseSucceed(() => undefined), Effect.asVoid));
39
+ let toxiproxy = null;
40
+ if (effectiveOpts.tiers.includes("D")) {
41
+ const url = effectiveOpts.toxiproxyUrl ?? "http://127.0.0.1:8474";
42
+ toxiproxy = yield* makeToxiproxyClient({ apiUrl: url });
43
+ yield* toxiproxy.ping.pipe(Effect.retry({ times: 10, schedule: undefined }));
44
+ }
45
+ return {
46
+ realServer,
47
+ toxiproxy,
48
+ opts: effectiveOpts,
49
+ seed,
50
+ artifacts,
51
+ };
52
+ });
53
+ }
54
+ /**
55
+ * Entry point the runner script calls. Iterates `opts.tiers` and writes a
56
+ * summary line per tier; the actual properties register themselves with
57
+ * Vitest via each tier module's `register*` functions — so this only
58
+ * orchestrates output + seed plumbing.
59
+ */
60
+ export function runConformance(ctx) {
61
+ return Effect.sync(() => {
62
+ console.log(`[conformance] seed=${ctx.seed} tiers=${ctx.opts.tiers.join(",")} toxiproxy=${ctx.toxiproxy !== null}`);
63
+ });
64
+ }
65
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/testing/conformance/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAwB,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAsDrD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAA2B;IAM3B,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzB,MAAM,aAAa,GAAG;YACpB,GAAG,IAAI;YACP,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,yBAAyB,EAAE;SACrD,CAAC;QACF,MAAM,IAAI,GACR,aAAa,CAAC,UAAU;YACxB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAqC,EAAE,CAAC,CAAC;QAE1E,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAC7C,MAAM,CAAC,UAAU,CAAC;YAChB,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE;YAC5B,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,sBAAsB,CAAC,EAAE,KAAK,EAAE,CAAC;SACxD,CAAC,EACF,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,UAAU,CAAC;YAChB,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE;YACzB,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC;SACnD,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EACrC,MAAM,CAAC,MAAM,CACd,CACJ,CAAC;QAEF,IAAI,SAAS,GAA2B,IAAI,CAAC;QAC7C,IAAI,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,MAAM,GAAG,GAAG,aAAa,CAAC,YAAY,IAAI,uBAAuB,CAAC;YAClE,SAAS,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACxD,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CACxB,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CACjD,CAAC;QACJ,CAAC;QAED,OAAO;YACL,UAAU;YACV,SAAS;YACT,IAAI,EAAE,aAAa;YACnB,IAAI;YACJ,SAAS;SACsB,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,GAA0B;IAE1B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACtB,OAAO,CAAC,GAAG,CACT,sBAAsB,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,SAAS,KAAK,IAAI,EAAE,CACvG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { ConformanceRunContext } from "./runner.js";
2
+ /**
3
+ * Valid request ⇒ valid-shape response. Drives fast-check RPC calls
4
+ * through a real TestClient against the real server and asserts every
5
+ * returned frame parses against `ResponseFrameSchema`.
6
+ */
7
+ export declare function registerRequestWellFormedness(ctx: ConformanceRunContext): void;
8
+ /**
9
+ * Valid event frame round-trips the codec cleanly.
10
+ *
11
+ * `@pure-codec` — does NOT drive a real server or real client. Spec A2's
12
+ * "accepted by a real client" assertion requires a TestServer + real
13
+ * client driver; that property lives in the consumer package (e.g.,
14
+ * `packages/client` or `moltzap-arena`) and is tracked under #186.
15
+ *
16
+ * Tightened per architect §4.4: predicate demands `Right` AND schema
17
+ * check of the specific event variant — the previous `Right || Left`
18
+ * shape was a tautology over the union.
19
+ */
20
+ export declare function registerEventWellFormedness(ctx: ConformanceRunContext): void;
21
+ /** parse(serialize(frame)) ≡ frame — pure codec round-trip. */
22
+ export declare function registerRoundTripIdentity(ctx: ConformanceRunContext): void;
23
+ /**
24
+ * Malformed bytes on the wire → the server drops or returns a typed
25
+ * error, never crashes. Drives `sendMalformed` through a real WS and
26
+ * asserts the observable outcome.
27
+ */
28
+ export declare function registerMalformedFrameHandling(ctx: ConformanceRunContext): void;
29
+ export declare function registerRpcMapCoverage(ctx: ConformanceRunContext): void;
30
+ //# sourceMappingURL=schema-conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-conformance.d.ts","sourceRoot":"","sources":["../../../src/testing/conformance/schema-conformance.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAWzD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,qBAAqB,GACzB,IAAI,CAqEN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAyB5E;AAED,+DAA+D;AAC/D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CA6B1E;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,qBAAqB,GACzB,IAAI,CAyDN;AAgBD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAqEvE"}