@yolk-sdk/emulators 0.1.0-canary.96

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 (333) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2135 -0
  3. package/dist/anthropic.d.mts +269 -0
  4. package/dist/anthropic.d.mts.map +1 -0
  5. package/dist/anthropic.mjs +177 -0
  6. package/dist/anthropic.mjs.map +1 -0
  7. package/dist/chat-completions.d.mts +288 -0
  8. package/dist/chat-completions.d.mts.map +1 -0
  9. package/dist/chat-completions.mjs +451 -0
  10. package/dist/chat-completions.mjs.map +1 -0
  11. package/dist/codex.d.mts +265 -0
  12. package/dist/codex.d.mts.map +1 -0
  13. package/dist/codex.mjs +199 -0
  14. package/dist/codex.mjs.map +1 -0
  15. package/dist/dropbox/api.d.mts +63 -0
  16. package/dist/dropbox/api.d.mts.map +1 -0
  17. package/dist/dropbox/api.mjs +565 -0
  18. package/dist/dropbox/api.mjs.map +1 -0
  19. package/dist/dropbox/state.d.mts +136 -0
  20. package/dist/dropbox/state.d.mts.map +1 -0
  21. package/dist/dropbox/state.mjs +209 -0
  22. package/dist/dropbox/state.mjs.map +1 -0
  23. package/dist/dropbox.d.mts +79 -0
  24. package/dist/dropbox.d.mts.map +1 -0
  25. package/dist/dropbox.mjs +124 -0
  26. package/dist/dropbox.mjs.map +1 -0
  27. package/dist/email-fixtures.d.mts +36 -0
  28. package/dist/email-fixtures.d.mts.map +1 -0
  29. package/dist/email-fixtures.mjs +1080 -0
  30. package/dist/email-fixtures.mjs.map +1 -0
  31. package/dist/email.d.mts +160 -0
  32. package/dist/email.d.mts.map +1 -0
  33. package/dist/email.mjs +608 -0
  34. package/dist/email.mjs.map +1 -0
  35. package/dist/emulator-compose.d.mts +40 -0
  36. package/dist/emulator-compose.d.mts.map +1 -0
  37. package/dist/emulator-compose.mjs +91 -0
  38. package/dist/emulator-compose.mjs.map +1 -0
  39. package/dist/emulator-http.d.mts +53 -0
  40. package/dist/emulator-http.d.mts.map +1 -0
  41. package/dist/emulator-http.mjs +117 -0
  42. package/dist/emulator-http.mjs.map +1 -0
  43. package/dist/emulator-kernel.d.mts +176 -0
  44. package/dist/emulator-kernel.d.mts.map +1 -0
  45. package/dist/emulator-kernel.mjs +413 -0
  46. package/dist/emulator-kernel.mjs.map +1 -0
  47. package/dist/fixture-route.d.mts +129 -0
  48. package/dist/fixture-route.d.mts.map +1 -0
  49. package/dist/fixture-route.mjs +257 -0
  50. package/dist/fixture-route.mjs.map +1 -0
  51. package/dist/fortnox/api.d.mts +92 -0
  52. package/dist/fortnox/api.d.mts.map +1 -0
  53. package/dist/fortnox/api.mjs +750 -0
  54. package/dist/fortnox/api.mjs.map +1 -0
  55. package/dist/fortnox/state.d.mts +533 -0
  56. package/dist/fortnox/state.d.mts.map +1 -0
  57. package/dist/fortnox/state.mjs +612 -0
  58. package/dist/fortnox/state.mjs.map +1 -0
  59. package/dist/fortnox.d.mts +128 -0
  60. package/dist/fortnox.d.mts.map +1 -0
  61. package/dist/fortnox.mjs +403 -0
  62. package/dist/fortnox.mjs.map +1 -0
  63. package/dist/gateway-evaluate-recordings.d.mts +12 -0
  64. package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
  65. package/dist/gateway-evaluate-recordings.mjs +128 -0
  66. package/dist/gateway-evaluate-recordings.mjs.map +1 -0
  67. package/dist/gateway.d.mts +272 -0
  68. package/dist/gateway.d.mts.map +1 -0
  69. package/dist/gateway.mjs +400 -0
  70. package/dist/gateway.mjs.map +1 -0
  71. package/dist/github/api.d.mts +63 -0
  72. package/dist/github/api.d.mts.map +1 -0
  73. package/dist/github/api.mjs +527 -0
  74. package/dist/github/api.mjs.map +1 -0
  75. package/dist/github/state.d.mts +272 -0
  76. package/dist/github/state.d.mts.map +1 -0
  77. package/dist/github/state.mjs +303 -0
  78. package/dist/github/state.mjs.map +1 -0
  79. package/dist/github.d.mts +77 -0
  80. package/dist/github.d.mts.map +1 -0
  81. package/dist/github.mjs +180 -0
  82. package/dist/github.mjs.map +1 -0
  83. package/dist/google/calendar.d.mts +10 -0
  84. package/dist/google/calendar.d.mts.map +1 -0
  85. package/dist/google/calendar.mjs +252 -0
  86. package/dist/google/calendar.mjs.map +1 -0
  87. package/dist/google/drive.d.mts +8 -0
  88. package/dist/google/drive.d.mts.map +1 -0
  89. package/dist/google/drive.mjs +252 -0
  90. package/dist/google/drive.mjs.map +1 -0
  91. package/dist/google/gmail.d.mts +10 -0
  92. package/dist/google/gmail.d.mts.map +1 -0
  93. package/dist/google/gmail.mjs +591 -0
  94. package/dist/google/gmail.mjs.map +1 -0
  95. package/dist/google/shared.d.mts +107 -0
  96. package/dist/google/shared.d.mts.map +1 -0
  97. package/dist/google/shared.mjs +146 -0
  98. package/dist/google/shared.mjs.map +1 -0
  99. package/dist/google/state.d.mts +385 -0
  100. package/dist/google/state.d.mts.map +1 -0
  101. package/dist/google/state.mjs +496 -0
  102. package/dist/google/state.mjs.map +1 -0
  103. package/dist/google.d.mts +75 -0
  104. package/dist/google.d.mts.map +1 -0
  105. package/dist/google.mjs +210 -0
  106. package/dist/google.mjs.map +1 -0
  107. package/dist/linkedin-search/api.d.mts +45 -0
  108. package/dist/linkedin-search/api.d.mts.map +1 -0
  109. package/dist/linkedin-search/api.mjs +181 -0
  110. package/dist/linkedin-search/api.mjs.map +1 -0
  111. package/dist/linkedin-search/state.d.mts +123 -0
  112. package/dist/linkedin-search/state.d.mts.map +1 -0
  113. package/dist/linkedin-search/state.mjs +261 -0
  114. package/dist/linkedin-search/state.mjs.map +1 -0
  115. package/dist/linkedin-search.d.mts +69 -0
  116. package/dist/linkedin-search.d.mts.map +1 -0
  117. package/dist/linkedin-search.mjs +158 -0
  118. package/dist/linkedin-search.mjs.map +1 -0
  119. package/dist/mcp/api.d.mts +44 -0
  120. package/dist/mcp/api.d.mts.map +1 -0
  121. package/dist/mcp/api.mjs +557 -0
  122. package/dist/mcp/api.mjs.map +1 -0
  123. package/dist/mcp/recordings.d.mts +40 -0
  124. package/dist/mcp/recordings.d.mts.map +1 -0
  125. package/dist/mcp/recordings.mjs +2390 -0
  126. package/dist/mcp/recordings.mjs.map +1 -0
  127. package/dist/mcp/state.d.mts +71 -0
  128. package/dist/mcp/state.d.mts.map +1 -0
  129. package/dist/mcp/state.mjs +83 -0
  130. package/dist/mcp/state.mjs.map +1 -0
  131. package/dist/mcp.d.mts +84 -0
  132. package/dist/mcp.d.mts.map +1 -0
  133. package/dist/mcp.mjs +241 -0
  134. package/dist/mcp.mjs.map +1 -0
  135. package/dist/messages.d.mts +183 -0
  136. package/dist/messages.d.mts.map +1 -0
  137. package/dist/messages.mjs +532 -0
  138. package/dist/messages.mjs.map +1 -0
  139. package/dist/microsoft/api.d.mts +47 -0
  140. package/dist/microsoft/api.d.mts.map +1 -0
  141. package/dist/microsoft/api.mjs +178 -0
  142. package/dist/microsoft/api.mjs.map +1 -0
  143. package/dist/microsoft/calendar.d.mts +30 -0
  144. package/dist/microsoft/calendar.d.mts.map +1 -0
  145. package/dist/microsoft/calendar.mjs +271 -0
  146. package/dist/microsoft/calendar.mjs.map +1 -0
  147. package/dist/microsoft/drive.d.mts +36 -0
  148. package/dist/microsoft/drive.d.mts.map +1 -0
  149. package/dist/microsoft/drive.mjs +298 -0
  150. package/dist/microsoft/drive.mjs.map +1 -0
  151. package/dist/microsoft/graph.d.mts +198 -0
  152. package/dist/microsoft/graph.d.mts.map +1 -0
  153. package/dist/microsoft/graph.mjs +264 -0
  154. package/dist/microsoft/graph.mjs.map +1 -0
  155. package/dist/microsoft/mail.d.mts +48 -0
  156. package/dist/microsoft/mail.d.mts.map +1 -0
  157. package/dist/microsoft/mail.mjs +488 -0
  158. package/dist/microsoft/mail.mjs.map +1 -0
  159. package/dist/microsoft/state.d.mts +480 -0
  160. package/dist/microsoft/state.d.mts.map +1 -0
  161. package/dist/microsoft/state.mjs +625 -0
  162. package/dist/microsoft/state.mjs.map +1 -0
  163. package/dist/microsoft.d.mts +168 -0
  164. package/dist/microsoft.d.mts.map +1 -0
  165. package/dist/microsoft.mjs +483 -0
  166. package/dist/microsoft.mjs.map +1 -0
  167. package/dist/node.d.mts +47 -0
  168. package/dist/node.d.mts.map +1 -0
  169. package/dist/node.mjs +178 -0
  170. package/dist/node.mjs.map +1 -0
  171. package/dist/notion/api.d.mts +51 -0
  172. package/dist/notion/api.d.mts.map +1 -0
  173. package/dist/notion/api.mjs +507 -0
  174. package/dist/notion/api.mjs.map +1 -0
  175. package/dist/notion/state.d.mts +329 -0
  176. package/dist/notion/state.d.mts.map +1 -0
  177. package/dist/notion/state.mjs +432 -0
  178. package/dist/notion/state.mjs.map +1 -0
  179. package/dist/notion.d.mts +72 -0
  180. package/dist/notion.d.mts.map +1 -0
  181. package/dist/notion.mjs +127 -0
  182. package/dist/notion.mjs.map +1 -0
  183. package/dist/openai.d.mts +165 -0
  184. package/dist/openai.d.mts.map +1 -0
  185. package/dist/openai.mjs +141 -0
  186. package/dist/openai.mjs.map +1 -0
  187. package/dist/opencode-recordings.d.mts +7 -0
  188. package/dist/opencode-recordings.d.mts.map +1 -0
  189. package/dist/opencode-recordings.mjs +222 -0
  190. package/dist/opencode-recordings.mjs.map +1 -0
  191. package/dist/opencode.d.mts +70 -0
  192. package/dist/opencode.d.mts.map +1 -0
  193. package/dist/opencode.mjs +217 -0
  194. package/dist/opencode.mjs.map +1 -0
  195. package/dist/r2-fixtures.d.mts +36 -0
  196. package/dist/r2-fixtures.d.mts.map +1 -0
  197. package/dist/r2-fixtures.mjs +245 -0
  198. package/dist/r2-fixtures.mjs.map +1 -0
  199. package/dist/r2-guard.d.mts +43 -0
  200. package/dist/r2-guard.d.mts.map +1 -0
  201. package/dist/r2-guard.mjs +215 -0
  202. package/dist/r2-guard.mjs.map +1 -0
  203. package/dist/r2.d.mts +166 -0
  204. package/dist/r2.d.mts.map +1 -0
  205. package/dist/r2.mjs +517 -0
  206. package/dist/r2.mjs.map +1 -0
  207. package/dist/responses.d.mts +231 -0
  208. package/dist/responses.d.mts.map +1 -0
  209. package/dist/responses.mjs +556 -0
  210. package/dist/responses.mjs.map +1 -0
  211. package/dist/route-evidence.d.mts +45 -0
  212. package/dist/route-evidence.d.mts.map +1 -0
  213. package/dist/route-evidence.mjs +56 -0
  214. package/dist/route-evidence.mjs.map +1 -0
  215. package/dist/router.d.mts +93 -0
  216. package/dist/router.d.mts.map +1 -0
  217. package/dist/router.mjs +259 -0
  218. package/dist/router.mjs.map +1 -0
  219. package/dist/stateful-core.d.mts +17 -0
  220. package/dist/stateful-core.d.mts.map +1 -0
  221. package/dist/stateful-core.mjs +41 -0
  222. package/dist/stateful-core.mjs.map +1 -0
  223. package/dist/stateful-emulator.d.mts +565 -0
  224. package/dist/stateful-emulator.d.mts.map +1 -0
  225. package/dist/stateful-emulator.mjs +1228 -0
  226. package/dist/stateful-emulator.mjs.map +1 -0
  227. package/dist/stateful-secrets.d.mts +84 -0
  228. package/dist/stateful-secrets.d.mts.map +1 -0
  229. package/dist/stateful-secrets.mjs +216 -0
  230. package/dist/stateful-secrets.mjs.map +1 -0
  231. package/dist/subscription-usage-recordings.d.mts +9 -0
  232. package/dist/subscription-usage-recordings.d.mts.map +1 -0
  233. package/dist/subscription-usage-recordings.mjs +53 -0
  234. package/dist/subscription-usage-recordings.mjs.map +1 -0
  235. package/dist/subscription-usage.d.mts +53 -0
  236. package/dist/subscription-usage.d.mts.map +1 -0
  237. package/dist/subscription-usage.mjs +21 -0
  238. package/dist/subscription-usage.mjs.map +1 -0
  239. package/dist/telegram/api.d.mts +34 -0
  240. package/dist/telegram/api.d.mts.map +1 -0
  241. package/dist/telegram/api.mjs +257 -0
  242. package/dist/telegram/api.mjs.map +1 -0
  243. package/dist/telegram/state.d.mts +128 -0
  244. package/dist/telegram/state.d.mts.map +1 -0
  245. package/dist/telegram/state.mjs +154 -0
  246. package/dist/telegram/state.mjs.map +1 -0
  247. package/dist/telegram.d.mts +62 -0
  248. package/dist/telegram.d.mts.map +1 -0
  249. package/dist/telegram.mjs +127 -0
  250. package/dist/telegram.mjs.map +1 -0
  251. package/dist/todoist/api.d.mts +55 -0
  252. package/dist/todoist/api.d.mts.map +1 -0
  253. package/dist/todoist/api.mjs +415 -0
  254. package/dist/todoist/api.mjs.map +1 -0
  255. package/dist/todoist/state.d.mts +275 -0
  256. package/dist/todoist/state.d.mts.map +1 -0
  257. package/dist/todoist/state.mjs +345 -0
  258. package/dist/todoist/state.mjs.map +1 -0
  259. package/dist/todoist.d.mts +68 -0
  260. package/dist/todoist.d.mts.map +1 -0
  261. package/dist/todoist.mjs +181 -0
  262. package/dist/todoist.mjs.map +1 -0
  263. package/dist/xai.d.mts +267 -0
  264. package/dist/xai.d.mts.map +1 -0
  265. package/dist/xai.mjs +252 -0
  266. package/dist/xai.mjs.map +1 -0
  267. package/package.json +157 -0
  268. package/src/anthropic.ts +289 -0
  269. package/src/chat-completions.ts +924 -0
  270. package/src/codex.ts +296 -0
  271. package/src/dropbox/api.ts +1084 -0
  272. package/src/dropbox/state.ts +364 -0
  273. package/src/dropbox.ts +203 -0
  274. package/src/email-fixtures.ts +1297 -0
  275. package/src/email.ts +1108 -0
  276. package/src/emulator-compose.ts +147 -0
  277. package/src/emulator-http.ts +184 -0
  278. package/src/emulator-kernel.ts +844 -0
  279. package/src/fixture-route.ts +561 -0
  280. package/src/fortnox/api.ts +1352 -0
  281. package/src/fortnox/state.ts +798 -0
  282. package/src/fortnox.ts +801 -0
  283. package/src/gateway-evaluate-recordings.ts +153 -0
  284. package/src/gateway.ts +530 -0
  285. package/src/github/api.ts +986 -0
  286. package/src/github/state.ts +439 -0
  287. package/src/github.ts +271 -0
  288. package/src/google/calendar.ts +486 -0
  289. package/src/google/drive.ts +471 -0
  290. package/src/google/gmail.ts +1011 -0
  291. package/src/google/shared.ts +321 -0
  292. package/src/google/state.ts +686 -0
  293. package/src/google.ts +298 -0
  294. package/src/linkedin-search/api.ts +363 -0
  295. package/src/linkedin-search/state.ts +373 -0
  296. package/src/linkedin-search.ts +241 -0
  297. package/src/mcp/api.ts +995 -0
  298. package/src/mcp/recordings.ts +2665 -0
  299. package/src/mcp/state.ts +125 -0
  300. package/src/mcp.ts +319 -0
  301. package/src/messages.ts +844 -0
  302. package/src/microsoft/api.ts +426 -0
  303. package/src/microsoft/calendar.ts +491 -0
  304. package/src/microsoft/drive.ts +541 -0
  305. package/src/microsoft/graph.ts +550 -0
  306. package/src/microsoft/mail.ts +833 -0
  307. package/src/microsoft/state.ts +822 -0
  308. package/src/microsoft.ts +982 -0
  309. package/src/node.ts +293 -0
  310. package/src/notion/api.ts +976 -0
  311. package/src/notion/state.ts +512 -0
  312. package/src/notion.ts +210 -0
  313. package/src/openai.ts +198 -0
  314. package/src/opencode-recordings.ts +257 -0
  315. package/src/opencode.ts +271 -0
  316. package/src/r2-fixtures.ts +295 -0
  317. package/src/r2-guard.ts +323 -0
  318. package/src/r2.ts +890 -0
  319. package/src/responses.ts +901 -0
  320. package/src/route-evidence.ts +90 -0
  321. package/src/router.ts +490 -0
  322. package/src/stateful-core.ts +70 -0
  323. package/src/stateful-emulator.ts +2571 -0
  324. package/src/stateful-secrets.ts +299 -0
  325. package/src/subscription-usage-recordings.ts +77 -0
  326. package/src/subscription-usage.ts +68 -0
  327. package/src/telegram/api.ts +437 -0
  328. package/src/telegram/state.ts +229 -0
  329. package/src/telegram.ts +227 -0
  330. package/src/todoist/api.ts +736 -0
  331. package/src/todoist/state.ts +456 -0
  332. package/src/todoist.ts +316 -0
  333. package/src/xai.ts +341 -0
@@ -0,0 +1,1297 @@
1
+ /**
2
+ * The email conformance fixtures, copied as data (internal; re-exported by `email.ts`).
3
+ *
4
+ * Emulators never import SDK code: this is a verbatim copy of `emailConformanceFixtures` from
5
+ * `@yolk-sdk/connectors/email/conformance` (synthetic `PortFixture`s; none observed live).
6
+ * `test/email-conformance.test.ts` fails when the two drift apart; update both together.
7
+ */
8
+ import type * as Schema from 'effect/Schema'
9
+
10
+ /** A port failure as a fixture records it (mirrors `PortFailure` in `@yolk-sdk/conformance`). */
11
+ export type EmailEmulatorFailure = {
12
+ readonly kind: 'expected' | 'error'
13
+ readonly code: string
14
+ readonly message: string
15
+ readonly status?: number
16
+ }
17
+
18
+ type EmailEmulatorFixtureFields = {
19
+ readonly id: string
20
+ readonly port: string
21
+ readonly method: string
22
+ readonly request: Schema.Json
23
+ readonly observed?: { readonly account: string; readonly date: string }
24
+ readonly note?: string
25
+ }
26
+
27
+ /**
28
+ * One recorded `EmailClient` call (the plain-JSON shape of a `PortFixture`): exactly one of
29
+ * `response` or `failure`.
30
+ */
31
+ export type EmailEmulatorFixture =
32
+ | (EmailEmulatorFixtureFields & { readonly response: Schema.Json; readonly failure?: never })
33
+ | (EmailEmulatorFixtureFields & {
34
+ readonly failure: EmailEmulatorFailure
35
+ readonly response?: never
36
+ })
37
+
38
+ export const emailEmulatorFixtures: ReadonlyArray<EmailEmulatorFixture> = [
39
+ {
40
+ id: 'email.imap.list-and-get-headers.list.synthetic',
41
+ port: 'EmailClient',
42
+ method: 'listMessages',
43
+ request: {
44
+ connection: {
45
+ protocol: 'imap',
46
+ host: 'imap.example.test',
47
+ port: 993,
48
+ security: 'tls'
49
+ },
50
+ limit: 50
51
+ },
52
+ response: {
53
+ messages: [
54
+ {
55
+ id: '1700000001:41',
56
+ subject: 'Synthetic welcome',
57
+ from: [
58
+ {
59
+ address: 'sender@example.test',
60
+ name: 'Synthetic Sender'
61
+ }
62
+ ],
63
+ to: [
64
+ {
65
+ address: 'practice@example.test'
66
+ }
67
+ ],
68
+ sentAt: '2026-09-28T08:00:00.000Z',
69
+ receivedAt: '2026-09-28T08:00:05.000Z',
70
+ snippet: 'Welcome to the synthetic practice mailbox.',
71
+ hasAttachments: false,
72
+ isRead: false,
73
+ isFlagged: false
74
+ },
75
+ {
76
+ id: '1700000001:42',
77
+ subject: 'Synthetic weekly summary',
78
+ from: [
79
+ {
80
+ address: 'sender@example.test',
81
+ name: 'Synthetic Sender'
82
+ }
83
+ ],
84
+ to: [
85
+ {
86
+ address: 'practice@example.test'
87
+ }
88
+ ],
89
+ sentAt: '2026-09-29T08:00:00.000Z',
90
+ receivedAt: '2026-09-29T08:00:04.000Z',
91
+ snippet: 'Nothing happened this synthetic week.',
92
+ hasAttachments: false,
93
+ isRead: true,
94
+ isFlagged: false
95
+ }
96
+ ]
97
+ },
98
+ note: 'Unfiltered INBOX list: the seeded unread message and one read message. Synthetic.'
99
+ },
100
+ {
101
+ id: 'email.imap.list-and-get-headers.get.synthetic',
102
+ port: 'EmailClient',
103
+ method: 'getMessage',
104
+ request: {
105
+ connection: {
106
+ protocol: 'imap',
107
+ host: 'imap.example.test',
108
+ port: 993,
109
+ security: 'tls'
110
+ },
111
+ messageId: '1700000001:41'
112
+ },
113
+ response: {
114
+ message: {
115
+ id: '1700000001:41',
116
+ messageId: '<welcome.0001@example.test>',
117
+ subject: 'Synthetic welcome',
118
+ from: [
119
+ {
120
+ address: 'sender@example.test',
121
+ name: 'Synthetic Sender'
122
+ }
123
+ ],
124
+ to: [
125
+ {
126
+ address: 'practice@example.test'
127
+ }
128
+ ],
129
+ cc: [],
130
+ bcc: [],
131
+ replyTo: [],
132
+ sentAt: '2026-09-28T08:00:00.000Z',
133
+ receivedAt: '2026-09-28T08:00:05.000Z',
134
+ body: {
135
+ text: 'Welcome to the synthetic practice mailbox.'
136
+ },
137
+ attachments: [],
138
+ isRead: false,
139
+ isFlagged: false,
140
+ headers: [
141
+ {
142
+ name: 'Date',
143
+ value: 'Mon, 28 Sep 2026 08:00:00 +0000'
144
+ },
145
+ {
146
+ name: 'From',
147
+ value: 'Synthetic Sender <sender@example.test>'
148
+ },
149
+ {
150
+ name: 'To',
151
+ value: 'practice@example.test'
152
+ },
153
+ {
154
+ name: 'Subject',
155
+ value: 'Synthetic welcome'
156
+ },
157
+ {
158
+ name: 'Message-ID',
159
+ value: '<welcome.0001@example.test>'
160
+ }
161
+ ]
162
+ }
163
+ },
164
+ note: 'Get of the seeded unread message with its header fields (BODY.PEEK[HEADER]). Synthetic.'
165
+ },
166
+ {
167
+ id: 'email.imap.list-and-get-headers.list-again.synthetic',
168
+ port: 'EmailClient',
169
+ method: 'listMessages',
170
+ request: {
171
+ connection: {
172
+ protocol: 'imap',
173
+ host: 'imap.example.test',
174
+ port: 993,
175
+ security: 'tls'
176
+ },
177
+ limit: 50
178
+ },
179
+ response: {
180
+ messages: [
181
+ {
182
+ id: '1700000001:41',
183
+ subject: 'Synthetic welcome',
184
+ from: [
185
+ {
186
+ address: 'sender@example.test',
187
+ name: 'Synthetic Sender'
188
+ }
189
+ ],
190
+ to: [
191
+ {
192
+ address: 'practice@example.test'
193
+ }
194
+ ],
195
+ sentAt: '2026-09-28T08:00:00.000Z',
196
+ receivedAt: '2026-09-28T08:00:05.000Z',
197
+ snippet: 'Welcome to the synthetic practice mailbox.',
198
+ hasAttachments: false,
199
+ isRead: false,
200
+ isFlagged: false
201
+ },
202
+ {
203
+ id: '1700000001:42',
204
+ subject: 'Synthetic weekly summary',
205
+ from: [
206
+ {
207
+ address: 'sender@example.test',
208
+ name: 'Synthetic Sender'
209
+ }
210
+ ],
211
+ to: [
212
+ {
213
+ address: 'practice@example.test'
214
+ }
215
+ ],
216
+ sentAt: '2026-09-29T08:00:00.000Z',
217
+ receivedAt: '2026-09-29T08:00:04.000Z',
218
+ snippet: 'Nothing happened this synthetic week.',
219
+ hasAttachments: false,
220
+ isRead: true,
221
+ isFlagged: false
222
+ }
223
+ ]
224
+ },
225
+ note: 'The same INBOX list after the get: the message is still unread. Synthetic.'
226
+ },
227
+ {
228
+ id: 'email.imap.filtered-list-no-fallback.list-unread.synthetic',
229
+ port: 'EmailClient',
230
+ method: 'listMessagesFiltered',
231
+ request: {
232
+ connection: {
233
+ protocol: 'imap',
234
+ host: 'imap.example.test',
235
+ port: 993,
236
+ security: 'tls'
237
+ },
238
+ limit: 50,
239
+ isRead: false
240
+ },
241
+ response: {
242
+ messages: [
243
+ {
244
+ id: '1700000001:41',
245
+ subject: 'Synthetic welcome',
246
+ from: [
247
+ {
248
+ address: 'sender@example.test',
249
+ name: 'Synthetic Sender'
250
+ }
251
+ ],
252
+ to: [
253
+ {
254
+ address: 'practice@example.test'
255
+ }
256
+ ],
257
+ sentAt: '2026-09-28T08:00:00.000Z',
258
+ receivedAt: '2026-09-28T08:00:05.000Z',
259
+ snippet: 'Welcome to the synthetic practice mailbox.',
260
+ hasAttachments: false,
261
+ isRead: false,
262
+ isFlagged: false
263
+ }
264
+ ]
265
+ },
266
+ note: 'Filtered INBOX list (UID SEARCH UNSEEN): only the seeded unread message. Synthetic.'
267
+ },
268
+ {
269
+ id: 'email.imap.draft-drafts-discovery.create.synthetic',
270
+ port: 'EmailClient',
271
+ method: 'createDraft',
272
+ request: {
273
+ connection: {
274
+ protocol: 'imap',
275
+ host: 'imap.example.test',
276
+ port: 993,
277
+ security: 'tls'
278
+ },
279
+ message: {
280
+ to: [],
281
+ subject: 'yolk-conformance draft discovery: safe to delete',
282
+ body: {
283
+ text: 'Synthetic conformance draft; never sent.'
284
+ }
285
+ }
286
+ },
287
+ response: {
288
+ saved: true,
289
+ folder: 'Saved Drafts',
290
+ draftId: '1700000002:7'
291
+ },
292
+ note: 'APPEND (\\Draft) to the mailbox LIST advertises as \\Drafts; UIDPLUS APPENDUID gives the id. Synthetic.'
293
+ },
294
+ {
295
+ id: 'email.imap.draft-drafts-discovery.get.synthetic',
296
+ port: 'EmailClient',
297
+ method: 'getMessage',
298
+ request: {
299
+ connection: {
300
+ protocol: 'imap',
301
+ host: 'imap.example.test',
302
+ port: 993,
303
+ security: 'tls'
304
+ },
305
+ messageId: '1700000002:7',
306
+ folder: 'Saved Drafts'
307
+ },
308
+ response: {
309
+ message: {
310
+ id: '1700000002:7',
311
+ messageId: '<draft.0007@example.test>',
312
+ subject: 'yolk-conformance draft discovery: safe to delete',
313
+ from: [
314
+ {
315
+ address: 'practice@example.test'
316
+ }
317
+ ],
318
+ to: [],
319
+ cc: [],
320
+ bcc: [],
321
+ replyTo: [],
322
+ sentAt: '2026-09-30T09:00:00.000Z',
323
+ body: {
324
+ text: 'Synthetic conformance draft; never sent.'
325
+ },
326
+ attachments: [],
327
+ isRead: true,
328
+ isFlagged: false,
329
+ headers: [
330
+ {
331
+ name: 'Date',
332
+ value: 'Wed, 30 Sep 2026 09:00:00 +0000'
333
+ },
334
+ {
335
+ name: 'From',
336
+ value: 'practice@example.test'
337
+ },
338
+ {
339
+ name: 'Subject',
340
+ value: 'yolk-conformance draft discovery: safe to delete'
341
+ },
342
+ {
343
+ name: 'Message-ID',
344
+ value: '<draft.0007@example.test>'
345
+ }
346
+ ]
347
+ }
348
+ },
349
+ note: 'The saved draft read back by its draftId. Synthetic.'
350
+ },
351
+ {
352
+ id: 'email.imap.draft-drafts-discovery.delete.synthetic',
353
+ port: 'EmailClient',
354
+ method: 'deletePermanently',
355
+ request: {
356
+ connection: {
357
+ protocol: 'imap',
358
+ host: 'imap.example.test',
359
+ port: 993,
360
+ security: 'tls'
361
+ },
362
+ messageIds: ['1700000002:7'],
363
+ folder: 'Saved Drafts'
364
+ },
365
+ response: {
366
+ results: [
367
+ {
368
+ messageId: '1700000002:7',
369
+ status: 'succeeded'
370
+ }
371
+ ],
372
+ summary: {
373
+ requested: 1,
374
+ succeeded: 1,
375
+ failed: 0,
376
+ unknown: 0,
377
+ notAttempted: 0
378
+ }
379
+ },
380
+ note: 'Restore: UID-scoped permanent delete of the case-created draft. Synthetic.'
381
+ },
382
+ {
383
+ id: 'email.imap.set-read-and-flag.get-before.synthetic',
384
+ port: 'EmailClient',
385
+ method: 'getMessage',
386
+ request: {
387
+ connection: {
388
+ protocol: 'imap',
389
+ host: 'imap.example.test',
390
+ port: 993,
391
+ security: 'tls'
392
+ },
393
+ messageId: '1700000001:41'
394
+ },
395
+ response: {
396
+ message: {
397
+ id: '1700000001:41',
398
+ messageId: '<welcome.0001@example.test>',
399
+ subject: 'Synthetic welcome',
400
+ from: [
401
+ {
402
+ address: 'sender@example.test',
403
+ name: 'Synthetic Sender'
404
+ }
405
+ ],
406
+ to: [
407
+ {
408
+ address: 'practice@example.test'
409
+ }
410
+ ],
411
+ cc: [],
412
+ bcc: [],
413
+ replyTo: [],
414
+ sentAt: '2026-09-28T08:00:00.000Z',
415
+ receivedAt: '2026-09-28T08:00:05.000Z',
416
+ body: {
417
+ text: 'Welcome to the synthetic practice mailbox.'
418
+ },
419
+ attachments: [],
420
+ isRead: false,
421
+ isFlagged: false,
422
+ headers: [
423
+ {
424
+ name: 'Date',
425
+ value: 'Mon, 28 Sep 2026 08:00:00 +0000'
426
+ },
427
+ {
428
+ name: 'From',
429
+ value: 'Synthetic Sender <sender@example.test>'
430
+ },
431
+ {
432
+ name: 'To',
433
+ value: 'practice@example.test'
434
+ },
435
+ {
436
+ name: 'Subject',
437
+ value: 'Synthetic welcome'
438
+ },
439
+ {
440
+ name: 'Message-ID',
441
+ value: '<welcome.0001@example.test>'
442
+ }
443
+ ]
444
+ }
445
+ },
446
+ note: 'Get of the seeded message (read false, flagged false). Synthetic.'
447
+ },
448
+ {
449
+ id: 'email.imap.set-read-and-flag.set-read.synthetic',
450
+ port: 'EmailClient',
451
+ method: 'setRead',
452
+ request: {
453
+ connection: {
454
+ protocol: 'imap',
455
+ host: 'imap.example.test',
456
+ port: 993,
457
+ security: 'tls'
458
+ },
459
+ messageId: '1700000001:41',
460
+ folder: 'INBOX',
461
+ isRead: true
462
+ },
463
+ response: {
464
+ messageId: '1700000001:41',
465
+ isRead: true
466
+ },
467
+ note: 'UID STORE +FLAGS.SILENT (\\Seen). Synthetic.'
468
+ },
469
+ {
470
+ id: 'email.imap.set-read-and-flag.get-read.synthetic',
471
+ port: 'EmailClient',
472
+ method: 'getMessage',
473
+ request: {
474
+ connection: {
475
+ protocol: 'imap',
476
+ host: 'imap.example.test',
477
+ port: 993,
478
+ security: 'tls'
479
+ },
480
+ messageId: '1700000001:41'
481
+ },
482
+ response: {
483
+ message: {
484
+ id: '1700000001:41',
485
+ messageId: '<welcome.0001@example.test>',
486
+ subject: 'Synthetic welcome',
487
+ from: [
488
+ {
489
+ address: 'sender@example.test',
490
+ name: 'Synthetic Sender'
491
+ }
492
+ ],
493
+ to: [
494
+ {
495
+ address: 'practice@example.test'
496
+ }
497
+ ],
498
+ cc: [],
499
+ bcc: [],
500
+ replyTo: [],
501
+ sentAt: '2026-09-28T08:00:00.000Z',
502
+ receivedAt: '2026-09-28T08:00:05.000Z',
503
+ body: {
504
+ text: 'Welcome to the synthetic practice mailbox.'
505
+ },
506
+ attachments: [],
507
+ isRead: true,
508
+ isFlagged: false,
509
+ headers: [
510
+ {
511
+ name: 'Date',
512
+ value: 'Mon, 28 Sep 2026 08:00:00 +0000'
513
+ },
514
+ {
515
+ name: 'From',
516
+ value: 'Synthetic Sender <sender@example.test>'
517
+ },
518
+ {
519
+ name: 'To',
520
+ value: 'practice@example.test'
521
+ },
522
+ {
523
+ name: 'Subject',
524
+ value: 'Synthetic welcome'
525
+ },
526
+ {
527
+ name: 'Message-ID',
528
+ value: '<welcome.0001@example.test>'
529
+ }
530
+ ]
531
+ }
532
+ },
533
+ note: 'Get of the seeded message (read true, flagged false). Synthetic.'
534
+ },
535
+ {
536
+ id: 'email.imap.set-read-and-flag.set-flag.synthetic',
537
+ port: 'EmailClient',
538
+ method: 'setFlag',
539
+ request: {
540
+ connection: {
541
+ protocol: 'imap',
542
+ host: 'imap.example.test',
543
+ port: 993,
544
+ security: 'tls'
545
+ },
546
+ messageId: '1700000001:41',
547
+ folder: 'INBOX',
548
+ isFlagged: true
549
+ },
550
+ response: {
551
+ messageId: '1700000001:41',
552
+ isFlagged: true
553
+ },
554
+ note: 'UID STORE +FLAGS.SILENT (\\Flagged). Synthetic.'
555
+ },
556
+ {
557
+ id: 'email.imap.set-read-and-flag.get-flagged.synthetic',
558
+ port: 'EmailClient',
559
+ method: 'getMessage',
560
+ request: {
561
+ connection: {
562
+ protocol: 'imap',
563
+ host: 'imap.example.test',
564
+ port: 993,
565
+ security: 'tls'
566
+ },
567
+ messageId: '1700000001:41'
568
+ },
569
+ response: {
570
+ message: {
571
+ id: '1700000001:41',
572
+ messageId: '<welcome.0001@example.test>',
573
+ subject: 'Synthetic welcome',
574
+ from: [
575
+ {
576
+ address: 'sender@example.test',
577
+ name: 'Synthetic Sender'
578
+ }
579
+ ],
580
+ to: [
581
+ {
582
+ address: 'practice@example.test'
583
+ }
584
+ ],
585
+ cc: [],
586
+ bcc: [],
587
+ replyTo: [],
588
+ sentAt: '2026-09-28T08:00:00.000Z',
589
+ receivedAt: '2026-09-28T08:00:05.000Z',
590
+ body: {
591
+ text: 'Welcome to the synthetic practice mailbox.'
592
+ },
593
+ attachments: [],
594
+ isRead: true,
595
+ isFlagged: true,
596
+ headers: [
597
+ {
598
+ name: 'Date',
599
+ value: 'Mon, 28 Sep 2026 08:00:00 +0000'
600
+ },
601
+ {
602
+ name: 'From',
603
+ value: 'Synthetic Sender <sender@example.test>'
604
+ },
605
+ {
606
+ name: 'To',
607
+ value: 'practice@example.test'
608
+ },
609
+ {
610
+ name: 'Subject',
611
+ value: 'Synthetic welcome'
612
+ },
613
+ {
614
+ name: 'Message-ID',
615
+ value: '<welcome.0001@example.test>'
616
+ }
617
+ ]
618
+ }
619
+ },
620
+ note: 'Get of the seeded message (read true, flagged true). Synthetic.'
621
+ },
622
+ {
623
+ id: 'email.imap.set-read-and-flag.restore-read.synthetic',
624
+ port: 'EmailClient',
625
+ method: 'setRead',
626
+ request: {
627
+ connection: {
628
+ protocol: 'imap',
629
+ host: 'imap.example.test',
630
+ port: 993,
631
+ security: 'tls'
632
+ },
633
+ messageId: '1700000001:41',
634
+ folder: 'INBOX',
635
+ isRead: false
636
+ },
637
+ response: {
638
+ messageId: '1700000001:41',
639
+ isRead: false
640
+ },
641
+ note: 'UID STORE -FLAGS.SILENT (\\Seen). Synthetic.'
642
+ },
643
+ {
644
+ id: 'email.imap.set-read-and-flag.restore-flag.synthetic',
645
+ port: 'EmailClient',
646
+ method: 'setFlag',
647
+ request: {
648
+ connection: {
649
+ protocol: 'imap',
650
+ host: 'imap.example.test',
651
+ port: 993,
652
+ security: 'tls'
653
+ },
654
+ messageId: '1700000001:41',
655
+ folder: 'INBOX',
656
+ isFlagged: false
657
+ },
658
+ response: {
659
+ messageId: '1700000001:41',
660
+ isFlagged: false
661
+ },
662
+ note: 'UID STORE -FLAGS.SILENT (\\Flagged). Synthetic.'
663
+ },
664
+ {
665
+ id: 'email.imap.set-read-and-flag.get-restored.synthetic',
666
+ port: 'EmailClient',
667
+ method: 'getMessage',
668
+ request: {
669
+ connection: {
670
+ protocol: 'imap',
671
+ host: 'imap.example.test',
672
+ port: 993,
673
+ security: 'tls'
674
+ },
675
+ messageId: '1700000001:41'
676
+ },
677
+ response: {
678
+ message: {
679
+ id: '1700000001:41',
680
+ messageId: '<welcome.0001@example.test>',
681
+ subject: 'Synthetic welcome',
682
+ from: [
683
+ {
684
+ address: 'sender@example.test',
685
+ name: 'Synthetic Sender'
686
+ }
687
+ ],
688
+ to: [
689
+ {
690
+ address: 'practice@example.test'
691
+ }
692
+ ],
693
+ cc: [],
694
+ bcc: [],
695
+ replyTo: [],
696
+ sentAt: '2026-09-28T08:00:00.000Z',
697
+ receivedAt: '2026-09-28T08:00:05.000Z',
698
+ body: {
699
+ text: 'Welcome to the synthetic practice mailbox.'
700
+ },
701
+ attachments: [],
702
+ isRead: false,
703
+ isFlagged: false,
704
+ headers: [
705
+ {
706
+ name: 'Date',
707
+ value: 'Mon, 28 Sep 2026 08:00:00 +0000'
708
+ },
709
+ {
710
+ name: 'From',
711
+ value: 'Synthetic Sender <sender@example.test>'
712
+ },
713
+ {
714
+ name: 'To',
715
+ value: 'practice@example.test'
716
+ },
717
+ {
718
+ name: 'Subject',
719
+ value: 'Synthetic welcome'
720
+ },
721
+ {
722
+ name: 'Message-ID',
723
+ value: '<welcome.0001@example.test>'
724
+ }
725
+ ]
726
+ }
727
+ },
728
+ note: 'Get of the seeded message (read false, flagged false). Synthetic.'
729
+ },
730
+ {
731
+ id: 'email.imap.trash-untrash-to-inbox.create.synthetic',
732
+ port: 'EmailClient',
733
+ method: 'createDraft',
734
+ request: {
735
+ connection: {
736
+ protocol: 'imap',
737
+ host: 'imap.example.test',
738
+ port: 993,
739
+ security: 'tls'
740
+ },
741
+ message: {
742
+ to: [],
743
+ subject: 'yolk-conformance trash probe: safe to delete',
744
+ body: {
745
+ text: 'Synthetic conformance draft; never sent.'
746
+ }
747
+ },
748
+ folder: 'Saved Drafts'
749
+ },
750
+ response: {
751
+ saved: true,
752
+ folder: 'Saved Drafts',
753
+ draftId: '1700000002:8'
754
+ },
755
+ note: 'The case-owned draft in the seeded Drafts mailbox. Synthetic.'
756
+ },
757
+ {
758
+ id: 'email.imap.trash-untrash-to-inbox.trash.synthetic',
759
+ port: 'EmailClient',
760
+ method: 'trash',
761
+ request: {
762
+ connection: {
763
+ protocol: 'imap',
764
+ host: 'imap.example.test',
765
+ port: 993,
766
+ security: 'tls'
767
+ },
768
+ messageId: '1700000002:8',
769
+ folder: 'Saved Drafts'
770
+ },
771
+ response: {
772
+ moved: true,
773
+ folder: 'Deleted Items',
774
+ messageId: '1700000004:3'
775
+ },
776
+ note: 'UID MOVE to the mailbox LIST advertises as \\Trash; COPYUID gives the destination id. Synthetic.'
777
+ },
778
+ {
779
+ id: 'email.imap.trash-untrash-to-inbox.untrash.synthetic',
780
+ port: 'EmailClient',
781
+ method: 'untrash',
782
+ request: {
783
+ connection: {
784
+ protocol: 'imap',
785
+ host: 'imap.example.test',
786
+ port: 993,
787
+ security: 'tls'
788
+ },
789
+ messageId: '1700000004:3',
790
+ folder: 'Deleted Items',
791
+ destinationFolder: 'INBOX'
792
+ },
793
+ response: {
794
+ moved: true,
795
+ folder: 'INBOX',
796
+ messageId: '1700000001:43'
797
+ },
798
+ note: 'Restore defaults to INBOX, not the original Drafts mailbox. Synthetic.'
799
+ },
800
+ {
801
+ id: 'email.imap.trash-untrash-to-inbox.get.synthetic',
802
+ port: 'EmailClient',
803
+ method: 'getMessage',
804
+ request: {
805
+ connection: {
806
+ protocol: 'imap',
807
+ host: 'imap.example.test',
808
+ port: 993,
809
+ security: 'tls'
810
+ },
811
+ messageId: '1700000001:43'
812
+ },
813
+ response: {
814
+ message: {
815
+ id: '1700000001:43',
816
+ messageId: '<draft.0008@example.test>',
817
+ subject: 'yolk-conformance trash probe: safe to delete',
818
+ from: [
819
+ {
820
+ address: 'practice@example.test'
821
+ }
822
+ ],
823
+ to: [],
824
+ cc: [],
825
+ bcc: [],
826
+ replyTo: [],
827
+ sentAt: '2026-09-30T09:00:00.000Z',
828
+ body: {
829
+ text: 'Synthetic conformance draft; never sent.'
830
+ },
831
+ attachments: [],
832
+ isRead: true,
833
+ isFlagged: false,
834
+ headers: [
835
+ {
836
+ name: 'Date',
837
+ value: 'Wed, 30 Sep 2026 09:00:00 +0000'
838
+ },
839
+ {
840
+ name: 'From',
841
+ value: 'practice@example.test'
842
+ },
843
+ {
844
+ name: 'Subject',
845
+ value: 'yolk-conformance trash probe: safe to delete'
846
+ },
847
+ {
848
+ name: 'Message-ID',
849
+ value: '<draft.0008@example.test>'
850
+ }
851
+ ]
852
+ }
853
+ },
854
+ note: 'The restored message read back in INBOX by its new id. Synthetic.'
855
+ },
856
+ {
857
+ id: 'email.imap.trash-untrash-to-inbox.delete.synthetic',
858
+ port: 'EmailClient',
859
+ method: 'deletePermanently',
860
+ request: {
861
+ connection: {
862
+ protocol: 'imap',
863
+ host: 'imap.example.test',
864
+ port: 993,
865
+ security: 'tls'
866
+ },
867
+ messageIds: ['1700000001:43'],
868
+ folder: 'INBOX'
869
+ },
870
+ response: {
871
+ results: [
872
+ {
873
+ messageId: '1700000001:43',
874
+ status: 'succeeded'
875
+ }
876
+ ],
877
+ summary: {
878
+ requested: 1,
879
+ succeeded: 1,
880
+ failed: 0,
881
+ unknown: 0,
882
+ notAttempted: 0
883
+ }
884
+ },
885
+ note: 'Restore: UID-scoped permanent delete where the message ended up. Synthetic.'
886
+ },
887
+ {
888
+ id: 'email.imap.move-destination-ids.create.synthetic',
889
+ port: 'EmailClient',
890
+ method: 'createDraft',
891
+ request: {
892
+ connection: {
893
+ protocol: 'imap',
894
+ host: 'imap.example.test',
895
+ port: 993,
896
+ security: 'tls'
897
+ },
898
+ message: {
899
+ to: [],
900
+ subject: 'yolk-conformance move probe: safe to delete',
901
+ body: {
902
+ text: 'Synthetic conformance draft; never sent.'
903
+ }
904
+ },
905
+ folder: 'Saved Drafts'
906
+ },
907
+ response: {
908
+ saved: true,
909
+ folder: 'Saved Drafts',
910
+ draftId: '1700000002:9'
911
+ },
912
+ note: 'The case-owned draft in the seeded Drafts mailbox. Synthetic.'
913
+ },
914
+ {
915
+ id: 'email.imap.move-destination-ids.move.synthetic',
916
+ port: 'EmailClient',
917
+ method: 'move',
918
+ request: {
919
+ connection: {
920
+ protocol: 'imap',
921
+ host: 'imap.example.test',
922
+ port: 993,
923
+ security: 'tls'
924
+ },
925
+ messageId: '1700000002:9',
926
+ folder: 'Saved Drafts',
927
+ destinationFolder: 'Archive'
928
+ },
929
+ response: {
930
+ moved: true,
931
+ folder: 'Archive',
932
+ messageId: '1700000005:12'
933
+ },
934
+ note: 'UID MOVE (RFC 6851); COPYUID gives the destination UIDVALIDITY:UID. Synthetic.'
935
+ },
936
+ {
937
+ id: 'email.imap.move-destination-ids.get-destination.synthetic',
938
+ port: 'EmailClient',
939
+ method: 'getMessage',
940
+ request: {
941
+ connection: {
942
+ protocol: 'imap',
943
+ host: 'imap.example.test',
944
+ port: 993,
945
+ security: 'tls'
946
+ },
947
+ messageId: '1700000005:12',
948
+ folder: 'Archive'
949
+ },
950
+ response: {
951
+ message: {
952
+ id: '1700000005:12',
953
+ messageId: '<draft.0009@example.test>',
954
+ subject: 'yolk-conformance move probe: safe to delete',
955
+ from: [
956
+ {
957
+ address: 'practice@example.test'
958
+ }
959
+ ],
960
+ to: [],
961
+ cc: [],
962
+ bcc: [],
963
+ replyTo: [],
964
+ sentAt: '2026-09-30T09:00:00.000Z',
965
+ body: {
966
+ text: 'Synthetic conformance draft; never sent.'
967
+ },
968
+ attachments: [],
969
+ isRead: true,
970
+ isFlagged: false,
971
+ headers: [
972
+ {
973
+ name: 'Date',
974
+ value: 'Wed, 30 Sep 2026 09:00:00 +0000'
975
+ },
976
+ {
977
+ name: 'From',
978
+ value: 'practice@example.test'
979
+ },
980
+ {
981
+ name: 'Subject',
982
+ value: 'yolk-conformance move probe: safe to delete'
983
+ },
984
+ {
985
+ name: 'Message-ID',
986
+ value: '<draft.0009@example.test>'
987
+ }
988
+ ]
989
+ }
990
+ },
991
+ note: 'The moved message read back by its destination id. Synthetic.'
992
+ },
993
+ {
994
+ id: 'email.imap.move-destination-ids.get-stale-source.synthetic',
995
+ port: 'EmailClient',
996
+ method: 'getMessage',
997
+ request: {
998
+ connection: {
999
+ protocol: 'imap',
1000
+ host: 'imap.example.test',
1001
+ port: 993,
1002
+ security: 'tls'
1003
+ },
1004
+ messageId: '1700000002:9',
1005
+ folder: 'Saved Drafts'
1006
+ },
1007
+ failure: {
1008
+ kind: 'expected',
1009
+ code: 'message_not_found',
1010
+ message: 'No message with that UID in the mailbox.'
1011
+ },
1012
+ note: 'The stale source id no longer resolves after the move. Synthetic.'
1013
+ },
1014
+ {
1015
+ id: 'email.imap.move-destination-ids.delete.synthetic',
1016
+ port: 'EmailClient',
1017
+ method: 'deletePermanently',
1018
+ request: {
1019
+ connection: {
1020
+ protocol: 'imap',
1021
+ host: 'imap.example.test',
1022
+ port: 993,
1023
+ security: 'tls'
1024
+ },
1025
+ messageIds: ['1700000005:12'],
1026
+ folder: 'Archive'
1027
+ },
1028
+ response: {
1029
+ results: [
1030
+ {
1031
+ messageId: '1700000005:12',
1032
+ status: 'succeeded'
1033
+ }
1034
+ ],
1035
+ summary: {
1036
+ requested: 1,
1037
+ succeeded: 1,
1038
+ failed: 0,
1039
+ unknown: 0,
1040
+ notAttempted: 0
1041
+ }
1042
+ },
1043
+ note: 'Restore: UID-scoped permanent delete in the destination. Synthetic.'
1044
+ },
1045
+ {
1046
+ id: 'email.pop3.rejects-folders-drafts-mutations.list.synthetic',
1047
+ port: 'EmailClient',
1048
+ method: 'listMessages',
1049
+ request: {
1050
+ connection: {
1051
+ protocol: 'pop3',
1052
+ host: 'pop3.example.test',
1053
+ port: 995,
1054
+ security: 'tls'
1055
+ },
1056
+ limit: 50
1057
+ },
1058
+ response: {
1059
+ messages: [
1060
+ {
1061
+ id: 'uidl-synthetic-0041',
1062
+ subject: 'Synthetic welcome',
1063
+ from: [
1064
+ {
1065
+ address: 'sender@example.test',
1066
+ name: 'Synthetic Sender'
1067
+ }
1068
+ ],
1069
+ to: [
1070
+ {
1071
+ address: 'practice@example.test'
1072
+ }
1073
+ ],
1074
+ sentAt: '2026-09-28T08:00:00.000Z',
1075
+ hasAttachments: false
1076
+ },
1077
+ {
1078
+ id: 'uidl-synthetic-0042',
1079
+ subject: 'Synthetic weekly summary',
1080
+ from: [
1081
+ {
1082
+ address: 'sender@example.test',
1083
+ name: 'Synthetic Sender'
1084
+ }
1085
+ ],
1086
+ to: [
1087
+ {
1088
+ address: 'practice@example.test'
1089
+ }
1090
+ ],
1091
+ sentAt: '2026-09-29T08:00:00.000Z',
1092
+ hasAttachments: false
1093
+ }
1094
+ ]
1095
+ },
1096
+ note: 'POP3 maildrop list (UIDL plus TOP headers); POP3 has no read or flagged state. Synthetic.'
1097
+ },
1098
+ {
1099
+ id: 'email.smtp.sent-copy-statuses.send-saved.synthetic',
1100
+ port: 'EmailClient',
1101
+ method: 'sendMessage',
1102
+ request: {
1103
+ connection: {
1104
+ protocol: 'smtp',
1105
+ host: 'smtp.example.test',
1106
+ port: 587,
1107
+ security: 'starttls'
1108
+ },
1109
+ message: {
1110
+ to: [
1111
+ {
1112
+ address: 'practice@example.test'
1113
+ }
1114
+ ],
1115
+ subject: 'yolk-conformance send: saved copy',
1116
+ body: {
1117
+ text: 'Synthetic conformance message to the practice mailbox.'
1118
+ }
1119
+ },
1120
+ sentCopy: {
1121
+ connection: {
1122
+ protocol: 'imap',
1123
+ host: 'imap.example.test',
1124
+ port: 993,
1125
+ security: 'tls'
1126
+ }
1127
+ }
1128
+ },
1129
+ response: {
1130
+ accepted: true,
1131
+ submissionId: 'synthetic-submission-0001',
1132
+ sentCopy: {
1133
+ status: 'saved',
1134
+ folder: 'Sent Items'
1135
+ }
1136
+ },
1137
+ note: 'SMTP 250 after DATA, then APPEND of the same bytes to the mailbox LIST advertises as \\Sent. Synthetic.'
1138
+ },
1139
+ {
1140
+ id: 'email.smtp.sent-copy-statuses.send-skipped.synthetic',
1141
+ port: 'EmailClient',
1142
+ method: 'sendMessage',
1143
+ request: {
1144
+ connection: {
1145
+ protocol: 'smtp',
1146
+ host: 'smtp.example.test',
1147
+ port: 587,
1148
+ security: 'starttls'
1149
+ },
1150
+ message: {
1151
+ to: [
1152
+ {
1153
+ address: 'practice@example.test'
1154
+ }
1155
+ ],
1156
+ subject: 'yolk-conformance send: copy skipped',
1157
+ body: {
1158
+ text: 'Synthetic conformance message to the practice mailbox.'
1159
+ }
1160
+ }
1161
+ },
1162
+ response: {
1163
+ accepted: true,
1164
+ submissionId: 'synthetic-submission-0002'
1165
+ },
1166
+ note: 'No sentCopy requested, none reported; the action synthesizes skipped. Synthetic.'
1167
+ },
1168
+ {
1169
+ id: 'email.smtp.sent-copy-statuses.send-failed.synthetic',
1170
+ port: 'EmailClient',
1171
+ method: 'sendMessage',
1172
+ request: {
1173
+ connection: {
1174
+ protocol: 'smtp',
1175
+ host: 'smtp.example.test',
1176
+ port: 587,
1177
+ security: 'starttls'
1178
+ },
1179
+ message: {
1180
+ to: [
1181
+ {
1182
+ address: 'practice@example.test'
1183
+ }
1184
+ ],
1185
+ subject: 'yolk-conformance send: copy fails',
1186
+ body: {
1187
+ text: 'Synthetic conformance message to the practice mailbox.'
1188
+ }
1189
+ },
1190
+ sentCopy: {
1191
+ connection: {
1192
+ protocol: 'imap',
1193
+ host: 'imap.example.test',
1194
+ port: 993,
1195
+ security: 'tls'
1196
+ },
1197
+ folder: 'yolk-conformance-missing-sent-folder'
1198
+ }
1199
+ },
1200
+ response: {
1201
+ accepted: true,
1202
+ submissionId: 'synthetic-submission-0003',
1203
+ sentCopy: {
1204
+ status: 'failed',
1205
+ folder: 'yolk-conformance-missing-sent-folder'
1206
+ }
1207
+ },
1208
+ note: 'SMTP accepted; APPEND answered NO [TRYCREATE], so the copy failed (never resend). Synthetic.'
1209
+ },
1210
+ {
1211
+ id: 'email.smtp.legacy-host-sent-copy.send-requested.synthetic',
1212
+ port: 'EmailClient',
1213
+ method: 'sendMessage',
1214
+ request: {
1215
+ connection: {
1216
+ protocol: 'smtp',
1217
+ host: 'smtp.example.test',
1218
+ port: 587,
1219
+ security: 'starttls'
1220
+ },
1221
+ message: {
1222
+ to: [
1223
+ {
1224
+ address: 'practice@example.test'
1225
+ }
1226
+ ],
1227
+ subject: 'yolk-conformance send: legacy host, copy requested',
1228
+ body: {
1229
+ text: 'Synthetic legacy-host conformance message.'
1230
+ }
1231
+ }
1232
+ },
1233
+ response: {
1234
+ accepted: true,
1235
+ submissionId: 'synthetic-submission-0004'
1236
+ },
1237
+ note: 'What the host sees behind the legacy shim: no sentCopy in, none out. Synthetic.'
1238
+ },
1239
+ {
1240
+ id: 'email.smtp.legacy-host-sent-copy.send-disabled.synthetic',
1241
+ port: 'EmailClient',
1242
+ method: 'sendMessage',
1243
+ request: {
1244
+ connection: {
1245
+ protocol: 'smtp',
1246
+ host: 'smtp.example.test',
1247
+ port: 587,
1248
+ security: 'starttls'
1249
+ },
1250
+ message: {
1251
+ to: [
1252
+ {
1253
+ address: 'practice@example.test'
1254
+ }
1255
+ ],
1256
+ subject: 'yolk-conformance send: legacy host, copy disabled',
1257
+ body: {
1258
+ text: 'Synthetic legacy-host conformance message.'
1259
+ }
1260
+ }
1261
+ },
1262
+ response: {
1263
+ accepted: true,
1264
+ submissionId: 'synthetic-submission-0005'
1265
+ },
1266
+ note: 'What the host sees behind the legacy shim: no sentCopy in, none out. Synthetic.'
1267
+ },
1268
+ {
1269
+ id: 'email.smtp.acceptance-not-delivery.send.synthetic',
1270
+ port: 'EmailClient',
1271
+ method: 'sendMessage',
1272
+ request: {
1273
+ connection: {
1274
+ protocol: 'smtp',
1275
+ host: 'smtp.example.test',
1276
+ port: 587,
1277
+ security: 'starttls'
1278
+ },
1279
+ message: {
1280
+ to: [
1281
+ {
1282
+ address: 'nobody@undeliverable.example.test'
1283
+ }
1284
+ ],
1285
+ subject: 'yolk-conformance send: accepted, undeliverable',
1286
+ body: {
1287
+ text: 'Synthetic conformance message to an undeliverable address.'
1288
+ }
1289
+ }
1290
+ },
1291
+ response: {
1292
+ accepted: true,
1293
+ submissionId: 'synthetic-submission-0006'
1294
+ },
1295
+ note: 'SMTP 250 for the submission; the bounce (DSN) would arrive later. Synthetic.'
1296
+ }
1297
+ ]