@volter/twin-standard 1.0.149 → 1.0.151

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 (83) hide show
  1. package/README.md +12 -3
  2. package/client-sdks/bun.lock +0 -32
  3. package/client-sdks/package.json +0 -2
  4. package/dist/client-sdks/bun.lock +0 -32
  5. package/dist/client-sdks/package.json +0 -2
  6. package/dist/src/assessment.d.ts +5 -4
  7. package/dist/src/assessment.js +2 -1
  8. package/dist/src/cli.js +21 -6
  9. package/dist/src/clients/harness.d.ts +3 -1
  10. package/dist/src/clients/harness.js +4 -2
  11. package/dist/src/clients/jira.d.ts +2 -0
  12. package/dist/src/clients/jira.js +71 -0
  13. package/dist/src/clients/polar.d.ts +2 -0
  14. package/dist/src/clients/polar.js +73 -0
  15. package/dist/src/clients/resend.js +38 -0
  16. package/dist/src/clients/run.js +1 -1
  17. package/dist/src/clients/sentry.js +1 -26
  18. package/dist/src/clients/smtp.d.ts +2 -0
  19. package/dist/src/clients/smtp.js +54 -0
  20. package/dist/src/clients/stripe.js +1 -1
  21. package/dist/src/clients/volteridentity.js +4 -3
  22. package/dist/src/clients/x.d.ts +2 -0
  23. package/dist/src/clients/x.js +64 -0
  24. package/dist/src/conformance.d.ts +4 -1
  25. package/dist/src/conformance.js +256 -6
  26. package/dist/src/consumer.js +5 -1
  27. package/dist/src/create-pack.d.ts +5 -0
  28. package/dist/src/create-pack.js +31 -3
  29. package/dist/src/protocol-3.js +30 -2
  30. package/dist/src/spec-ir.d.ts +2 -0
  31. package/dist/src/spec-ir.js +43 -0
  32. package/dist/src/tools/judge-brief.d.ts +1 -0
  33. package/dist/src/tools/judge-brief.js +67 -0
  34. package/dist/src/tools/life-coverage-walk.d.ts +2 -0
  35. package/dist/src/tools/life-coverage-walk.js +220 -0
  36. package/dist/src/tools/life-coverage.d.ts +2 -0
  37. package/dist/src/tools/life-coverage.js +271 -0
  38. package/dist/src/tools/packs-root.d.ts +9 -0
  39. package/dist/src/tools/packs-root.js +17 -0
  40. package/dist/src/tools/run-tool.d.ts +1 -0
  41. package/dist/src/tools/run-tool.js +18 -0
  42. package/dist/src/tools/score-pack.d.ts +2 -0
  43. package/dist/src/tools/score-pack.js +264 -0
  44. package/dist/src/tools/vendor-examples.d.ts +2 -0
  45. package/dist/src/tools/vendor-examples.js +1493 -0
  46. package/dist/src/verdict.js +1 -1
  47. package/dist/src/walk/behavior-journey.d.ts +6 -0
  48. package/dist/src/walk/behavior-journey.js +8 -6
  49. package/dist/src/walk/journey-kit.d.ts +2 -0
  50. package/dist/src/walk/journey-kit.js +6 -2
  51. package/dist/src/walk/rendered-scalar.d.ts +3 -0
  52. package/dist/src/walk/rendered-scalar.js +23 -0
  53. package/dist/src/walk/sse-example.js +45 -0
  54. package/package.json +2 -2
  55. package/src/assessment.ts +2 -1
  56. package/src/cli.ts +15 -2
  57. package/src/clients/harness.ts +4 -2
  58. package/src/clients/jira.ts +73 -0
  59. package/src/clients/polar.ts +73 -0
  60. package/src/clients/resend.ts +32 -0
  61. package/src/clients/run.ts +2 -2
  62. package/src/clients/sentry.ts +1 -25
  63. package/src/clients/smtp.ts +49 -0
  64. package/src/clients/stripe.ts +1 -1
  65. package/src/clients/volteridentity.ts +4 -3
  66. package/src/clients/x.ts +66 -0
  67. package/src/conformance.ts +192 -8
  68. package/src/consumer.ts +5 -1
  69. package/src/create-pack.ts +27 -3
  70. package/src/protocol-3.ts +24 -2
  71. package/src/spec-ir.ts +31 -0
  72. package/src/tools/judge-brief.ts +63 -0
  73. package/src/tools/life-coverage-walk.ts +173 -0
  74. package/src/tools/life-coverage.ts +237 -0
  75. package/src/tools/packs-root.ts +21 -0
  76. package/src/tools/run-tool.ts +10 -0
  77. package/src/tools/score-pack.ts +244 -0
  78. package/src/tools/vendor-examples.ts +1250 -0
  79. package/src/verdict.ts +1 -1
  80. package/src/walk/behavior-journey.ts +6 -2
  81. package/src/walk/journey-kit.ts +7 -2
  82. package/src/walk/rendered-scalar.ts +17 -0
  83. package/src/walk/sse-example.ts +37 -0
package/README.md CHANGED
@@ -17,6 +17,11 @@ twin-standard check-sources <pack or lane dir> [--recheck] # fetch and record
17
17
  twin-standard facts <pack dir> [--out <file>] # package-local facts from its descriptor
18
18
  twin-standard prepare-consumer <pack dir> --app <new dir> --cli <volter executable> --integrity <sha512> --out <json>
19
19
  twin-standard assess <pack dir> --prepared-consumer <json> [--browser] [--out <file>] # inside a World
20
+ twin-standard conform <pack dir> | <tarball> | <name>@<version> # the one conformance command (contributor, admission, re-assessment)
21
+ twin-standard walk <vendor> [--write] [--report <file>] # the journey test: the life twice on fresh Worlds, its coverage, the examples
22
+ twin-standard examples <vendor> [--sweep] # the vendor's published examples (journeys/vendor-examples.json) replayed
23
+ twin-standard coverage <vendor> [--write | --out <file>] # the code and state logic the life and the examples reach
24
+ twin-standard judge-brief <vendor> --authors <names> # what an independent judge of the journeys reads and writes
20
25
  twin-standard --version # this package's version and each standard's
21
26
  ```
22
27
 
@@ -24,8 +29,12 @@ The commands run with this package and its `@volter/world-core` peer installed.
24
29
  optional peer, needed only to serve or walk a pack whose descriptor declares a `managedDatabase` (`conform`, `assess`):
25
30
  install it beside this package for those, which name it when it is absent.
26
31
 
27
- What each criterion asks, and the rules for changing one, are twin-world's
28
- [architecture, "The grade"](https://github.com/volter-ai/twin-world/blob/main/docs/contributing/architecture.md#the-grade).
32
+ `walk`, `examples`, `coverage` and `judge-brief` take a vendor's directory name and run from the root of the repository
33
+ that holds it (`<your repository>/<vendor>/`), so a contributor runs the same journey test Volter's own packs are built
34
+ with, against whichever `@volter/world-core` their repository installs. The walk names that kernel in its report.
35
+
36
+ What each criterion asks, and the rules for changing one, are the platform's
37
+ [architecture, "The grade"](https://world-docs.volter.ai/docs/contributing/architecture#the-grade).
29
38
  A changed criterion is a release of this package: a criterion's id never changes meaning; a changed criterion takes a
30
39
  new id and a new standard version, and a tightened check names what newly fails.
31
40
 
@@ -46,5 +55,5 @@ prepared app's dependencies. Installed readiness requires ordinary CLI initializ
46
55
  SDK assertions, read-only state inspection after stop/resume for stored workflows, and verified teardown. A
47
56
  stateless workflow records why retained-state inspection does not apply. Empty SDK case execution fails.
48
57
 
49
- The [canonical pack procedure](https://github.com/volter-ai/twin-world/blob/main/docs/contributing/architecture.md#creating-a-pack)
58
+ The [canonical pack procedure](https://world-docs.volter.ai/docs/contributing/architecture#creating-a-pack)
50
59
  owns the recipe format and completion requirements. Catalog controllers own provenance, admission and publication.
@@ -10,11 +10,9 @@
10
10
  "@sentry/core": "10.38.0",
11
11
  "@sentry/node": "10.38.0",
12
12
  "resend": "6.6.0",
13
- "sentry-browser-postiz": "npm:@sentry/browser@10.56.0",
14
13
  "sentry-browser-twenty": "npm:@sentry/browser@10.59.0",
15
14
  "sentry-node-cal": "npm:@sentry/node@9.46.0",
16
15
  "sentry-node-cal-web": "npm:@sentry/node@10.33.0",
17
- "sentry-node-postiz": "npm:@sentry/node@10.56.0",
18
16
  "sentry-node-twenty": "npm:@sentry/node@10.73.0",
19
17
  },
20
18
  },
@@ -106,8 +104,6 @@
106
104
 
107
105
  "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.38.0", "", { "dependencies": { "@sentry-internal/replay": "10.38.0", "@sentry/core": "10.38.0" } }, "sha512-OXWM9jEqNYh4VTvrMu7v+z1anz+QKQ/fZXIZdsO7JTT2lGNZe58UUMeoq386M+Saxen8F9SUH7yTORy/8KI5qw=="],
108
106
 
109
- "@sentry-internal/server-utils": ["@sentry-internal/server-utils@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-6kuZI/vAjyVKMm1cTzc2pdUmVR4Px4etMG6wnCPyFnwEaGbUKQnTynUBFpTuo/q6Js6QBQvhLNoAnO4YsOfW4w=="],
110
-
111
107
  "@sentry/browser": ["@sentry/browser@10.38.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.38.0", "@sentry-internal/feedback": "10.38.0", "@sentry-internal/replay": "10.38.0", "@sentry-internal/replay-canvas": "10.38.0", "@sentry/core": "10.38.0" } }, "sha512-3phzp1YX4wcQr9mocGWKbjv0jwtuoDBv7+Y6Yfrys/kwyaL84mDLjjQhRf4gL5SX7JdYkhBp4WaiNlR0UC4kTA=="],
112
108
 
113
109
  "@sentry/browser-utils": ["@sentry/browser-utils@10.59.0", "", { "dependencies": { "@sentry/core": "10.59.0" } }, "sha512-DpJIrNi0Hsj/YONTZ8km1wv7ue2NzrTmFKJ3lRW8Q2nS/mrMeP3LCvjreLtKheTouB4go58NxM68AEFbXk4rPg=="],
@@ -212,16 +208,12 @@
212
208
 
213
209
  "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
214
210
 
215
- "sentry-browser-postiz": ["@sentry/browser@10.56.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.56.0", "@sentry-internal/feedback": "10.56.0", "@sentry-internal/replay": "10.56.0", "@sentry-internal/replay-canvas": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-80X3NmsGB6tLmfzXYdjzWWdVAdL5CRukGKLcRWIcNhgGjtskOmnzaGb93egEZGI5bUTbtONJ0oyscQ3Z9yoAtQ=="],
216
-
217
211
  "sentry-browser-twenty": ["@sentry/browser@10.59.0", "", { "dependencies": { "@sentry/browser-utils": "10.59.0", "@sentry/core": "10.59.0", "@sentry/feedback": "10.59.0", "@sentry/replay": "10.59.0", "@sentry/replay-canvas": "10.59.0" } }, "sha512-d0o0oc78KNWCZ6yq9gREf9BPXWza/Wj9W+nCm0CvPD5k2IbouD/eJsm2Mb+d53YfEm12L+SePfgOx01KbbVx4A=="],
218
212
 
219
213
  "sentry-node-cal": ["@sentry/node@9.46.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.2", "@opentelemetry/instrumentation-amqplib": "^0.46.1", "@opentelemetry/instrumentation-connect": "0.43.1", "@opentelemetry/instrumentation-dataloader": "0.16.1", "@opentelemetry/instrumentation-express": "0.47.1", "@opentelemetry/instrumentation-fs": "0.19.1", "@opentelemetry/instrumentation-generic-pool": "0.43.1", "@opentelemetry/instrumentation-graphql": "0.47.1", "@opentelemetry/instrumentation-hapi": "0.45.2", "@opentelemetry/instrumentation-http": "0.57.2", "@opentelemetry/instrumentation-ioredis": "0.47.1", "@opentelemetry/instrumentation-kafkajs": "0.7.1", "@opentelemetry/instrumentation-knex": "0.44.1", "@opentelemetry/instrumentation-koa": "0.47.1", "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", "@opentelemetry/instrumentation-mongodb": "0.52.0", "@opentelemetry/instrumentation-mongoose": "0.46.1", "@opentelemetry/instrumentation-mysql": "0.45.1", "@opentelemetry/instrumentation-mysql2": "0.45.2", "@opentelemetry/instrumentation-pg": "0.51.1", "@opentelemetry/instrumentation-redis-4": "0.46.1", "@opentelemetry/instrumentation-tedious": "0.18.1", "@opentelemetry/instrumentation-undici": "0.10.1", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.34.0", "@prisma/instrumentation": "6.11.1", "@sentry/core": "9.46.0", "@sentry/node-core": "9.46.0", "@sentry/opentelemetry": "9.46.0", "import-in-the-middle": "^1.14.2", "minimatch": "^9.0.0" } }, "sha512-pRLqAcd7GTGvN8gex5FtkQR5Mcol8gOy1WlyZZFq4rBbVtMbqKOQRhohwqnb+YrnmtFpj7IZ7KNDo077MvNeOQ=="],
220
214
 
221
215
  "sentry-node-cal-web": ["@sentry/node@10.33.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^2.2.0", "@opentelemetry/core": "^2.2.0", "@opentelemetry/instrumentation": "^0.208.0", "@opentelemetry/instrumentation-amqplib": "0.55.0", "@opentelemetry/instrumentation-connect": "0.52.0", "@opentelemetry/instrumentation-dataloader": "0.26.0", "@opentelemetry/instrumentation-express": "0.57.0", "@opentelemetry/instrumentation-fs": "0.28.0", "@opentelemetry/instrumentation-generic-pool": "0.52.0", "@opentelemetry/instrumentation-graphql": "0.56.0", "@opentelemetry/instrumentation-hapi": "0.55.0", "@opentelemetry/instrumentation-http": "0.208.0", "@opentelemetry/instrumentation-ioredis": "0.56.0", "@opentelemetry/instrumentation-kafkajs": "0.18.0", "@opentelemetry/instrumentation-knex": "0.53.0", "@opentelemetry/instrumentation-koa": "0.57.0", "@opentelemetry/instrumentation-lru-memoizer": "0.53.0", "@opentelemetry/instrumentation-mongodb": "0.61.0", "@opentelemetry/instrumentation-mongoose": "0.55.0", "@opentelemetry/instrumentation-mysql": "0.54.0", "@opentelemetry/instrumentation-mysql2": "0.55.0", "@opentelemetry/instrumentation-pg": "0.61.0", "@opentelemetry/instrumentation-redis": "0.57.0", "@opentelemetry/instrumentation-tedious": "0.27.0", "@opentelemetry/instrumentation-undici": "0.19.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-trace-base": "^2.2.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@prisma/instrumentation": "6.19.0", "@sentry/core": "10.33.0", "@sentry/node-core": "10.33.0", "@sentry/opentelemetry": "10.33.0", "import-in-the-middle": "^2.0.1", "minimatch": "^9.0.0" } }, "sha512-HZ7U0igIXs8nHSeh0YAe9C3eE/fjkHOprctQHwoYpRrZelsKO8NsvZU0K/1+knFr36vFj7jtt1QlF/UjCQZD+Q=="],
222
216
 
223
- "sentry-node-postiz": ["@sentry/node@10.56.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/core": "^2.6.1", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@sentry-internal/server-utils": "10.56.0", "@sentry/core": "10.56.0", "@sentry/node-core": "10.56.0", "@sentry/opentelemetry": "10.56.0", "import-in-the-middle": "^3.0.0" } }, "sha512-qvgtXHkcR4CH3fh0VEVyw4Ysc6MMiAnm727NdTTm0yU5e53erCeo2521+yfJkqmRTGiOSgwA7B5Bs+ot9j0vFQ=="],
224
-
225
217
  "sentry-node-twenty": ["@sentry/node@10.73.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/instrumentation": "^0.220.0", "@opentelemetry/sdk-trace-base": "^2.9.0", "@sentry/conventions": "^0.16.0", "@sentry/core": "10.73.0", "@sentry/node-core": "10.73.0", "@sentry/opentelemetry": "10.73.0", "@sentry/server-utils": "10.73.0", "import-in-the-middle": "^3.0.0" } }, "sha512-jiMJ6GgXDw6UMGzJY+o0c8OoeA9OfHqZ/xEpHfDqy75hn+9CEkRkbNGCIdMvsc7wW/Se1Os394hHfTpU+YEskg=="],
226
218
 
227
219
  "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="],
@@ -246,8 +238,6 @@
246
238
 
247
239
  "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.207.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.207.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA=="],
248
240
 
249
- "@sentry-internal/server-utils/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
250
-
251
241
  "@sentry/browser-utils/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
252
242
 
253
243
  "@sentry/feedback/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
@@ -266,16 +256,6 @@
266
256
 
267
257
  "@types/tedious/@types/node": ["@types/node@26.6.4", "", { "dependencies": { "undici-types": "~8.9.0" } }, "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg=="],
268
258
 
269
- "sentry-browser-postiz/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-I8tZWAFg8SZpD8BFUpglEtSTzhZjacmcThB5/Mlq/iFiiT8mBPG4ZWDWssSfmIBKvZywJZJ83uDA0+uiJU73Tw=="],
270
-
271
- "sentry-browser-postiz/@sentry-internal/feedback": ["@sentry-internal/feedback@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-fkRR9JroESTIlErkht3OrH4DXKd/DbPozr2KLdX7boMo31hPu4cL9fuqzwOrwyDPRq9B4j+qEgIWB8JrTbgvmg=="],
272
-
273
- "sentry-browser-postiz/@sentry-internal/replay": ["@sentry-internal/replay@10.56.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-DjF09hpy3TF7Km/kOZc73YJmBqcbPCxuZ5rtRs+KtVHu3Vq48xeW83qKUcFEZv20ur9UD99OAJ/gaEt//1Qbwg=="],
274
-
275
- "sentry-browser-postiz/@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.56.0", "", { "dependencies": { "@sentry-internal/replay": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-SDg2K0CAZT/TnhrixQGwXoi6ZsWUB+DQy3UUk0bSQm6c/5k5zFBpGOiughQN+DYsDilKREfPKmUEEnqvUjm1HQ=="],
276
-
277
- "sentry-browser-postiz/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
278
-
279
259
  "sentry-browser-twenty/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
280
260
 
281
261
  "sentry-node-cal/@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@1.30.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA=="],
@@ -394,16 +374,6 @@
394
374
 
395
375
  "sentry-node-cal-web/@sentry/opentelemetry": ["@sentry/opentelemetry@10.33.0", "", { "dependencies": { "@sentry/core": "10.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/semantic-conventions": "^1.37.0" } }, "sha512-v/6mAYLxtfcKLCw6Ktk46T6fWEQBVWB9Ah81axr8OvuIomK71jkv1zb0v7D8ot0ESesJ3JF6I/aKhfxpyLInSQ=="],
396
376
 
397
- "sentry-node-postiz/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w=="],
398
-
399
- "sentry-node-postiz/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
400
-
401
- "sentry-node-postiz/@sentry/node-core": ["@sentry/node-core@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0", "@sentry/opentelemetry": "10.56.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/core", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/instrumentation", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-61lD2Wjtv5Lw2F3lJarcD0ORjR4GlVxrEd6w6Of/uF3DH73dD6K3n/3wXEeCIRfV/kgiCFIrCIq76nz0LVgE5g=="],
402
-
403
- "sentry-node-postiz/@sentry/opentelemetry": ["@sentry/opentelemetry@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-PtMudApHMHvttjos3b7JZ2gJ+nstHAOYE3vKPYB5o0WQO95ldiaYnpLKMCRIGZWF3Dk7ynrqqnBpn8LZLt+Mrg=="],
404
-
405
- "sentry-node-postiz/import-in-the-middle": ["import-in-the-middle@3.5.2", "", { "dependencies": { "cjs-module-lexer": "^2.2.0", "es-module-lexer": "^3.0.2", "module-details-from-path": "^1.0.4" } }, "sha512-WseIA/4o56+GYO3RmlOPvejYi771OFeJEeK/ejROsr9bdjW+E5NXTOD1Di8TL40Qgg3JJX9aa97Hf8iiSVIKZw=="],
406
-
407
377
  "sentry-node-twenty/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.220.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.220.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw=="],
408
378
 
409
379
  "sentry-node-twenty/@sentry/core": ["@sentry/core@10.73.0", "", { "dependencies": { "@sentry/conventions": "^0.16.0" } }, "sha512-FLO1UgH19RyasVpofu612WCOgb2nEH0dZy+R72d7p65XU9i0wxlMKm3+sgfwKmiSJp1Qhilaaxs4Jg6BbiM5HA=="],
@@ -464,8 +434,6 @@
464
434
 
465
435
  "sentry-node-cal/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
466
436
 
467
- "sentry-node-postiz/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA=="],
468
-
469
437
  "sentry-node-twenty/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.220.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w=="],
470
438
 
471
439
  "@opentelemetry/instrumentation-redis-4/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
@@ -6,11 +6,9 @@
6
6
  "@sentry/browser": "10.38.0",
7
7
  "@sentry/core": "10.38.0",
8
8
  "@sentry/node": "10.38.0",
9
- "sentry-browser-postiz": "npm:@sentry/browser@10.56.0",
10
9
  "sentry-browser-twenty": "npm:@sentry/browser@10.59.0",
11
10
  "sentry-node-cal": "npm:@sentry/node@9.46.0",
12
11
  "sentry-node-cal-web": "npm:@sentry/node@10.33.0",
13
- "sentry-node-postiz": "npm:@sentry/node@10.56.0",
14
12
  "sentry-node-twenty": "npm:@sentry/node@10.73.0",
15
13
  "resend": "6.6.0",
16
14
  "@linear/sdk": "86.0.0"
@@ -10,11 +10,9 @@
10
10
  "@sentry/core": "10.38.0",
11
11
  "@sentry/node": "10.38.0",
12
12
  "resend": "6.6.0",
13
- "sentry-browser-postiz": "npm:@sentry/browser@10.56.0",
14
13
  "sentry-browser-twenty": "npm:@sentry/browser@10.59.0",
15
14
  "sentry-node-cal": "npm:@sentry/node@9.46.0",
16
15
  "sentry-node-cal-web": "npm:@sentry/node@10.33.0",
17
- "sentry-node-postiz": "npm:@sentry/node@10.56.0",
18
16
  "sentry-node-twenty": "npm:@sentry/node@10.73.0",
19
17
  },
20
18
  },
@@ -106,8 +104,6 @@
106
104
 
107
105
  "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.38.0", "", { "dependencies": { "@sentry-internal/replay": "10.38.0", "@sentry/core": "10.38.0" } }, "sha512-OXWM9jEqNYh4VTvrMu7v+z1anz+QKQ/fZXIZdsO7JTT2lGNZe58UUMeoq386M+Saxen8F9SUH7yTORy/8KI5qw=="],
108
106
 
109
- "@sentry-internal/server-utils": ["@sentry-internal/server-utils@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-6kuZI/vAjyVKMm1cTzc2pdUmVR4Px4etMG6wnCPyFnwEaGbUKQnTynUBFpTuo/q6Js6QBQvhLNoAnO4YsOfW4w=="],
110
-
111
107
  "@sentry/browser": ["@sentry/browser@10.38.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.38.0", "@sentry-internal/feedback": "10.38.0", "@sentry-internal/replay": "10.38.0", "@sentry-internal/replay-canvas": "10.38.0", "@sentry/core": "10.38.0" } }, "sha512-3phzp1YX4wcQr9mocGWKbjv0jwtuoDBv7+Y6Yfrys/kwyaL84mDLjjQhRf4gL5SX7JdYkhBp4WaiNlR0UC4kTA=="],
112
108
 
113
109
  "@sentry/browser-utils": ["@sentry/browser-utils@10.59.0", "", { "dependencies": { "@sentry/core": "10.59.0" } }, "sha512-DpJIrNi0Hsj/YONTZ8km1wv7ue2NzrTmFKJ3lRW8Q2nS/mrMeP3LCvjreLtKheTouB4go58NxM68AEFbXk4rPg=="],
@@ -212,16 +208,12 @@
212
208
 
213
209
  "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
214
210
 
215
- "sentry-browser-postiz": ["@sentry/browser@10.56.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.56.0", "@sentry-internal/feedback": "10.56.0", "@sentry-internal/replay": "10.56.0", "@sentry-internal/replay-canvas": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-80X3NmsGB6tLmfzXYdjzWWdVAdL5CRukGKLcRWIcNhgGjtskOmnzaGb93egEZGI5bUTbtONJ0oyscQ3Z9yoAtQ=="],
216
-
217
211
  "sentry-browser-twenty": ["@sentry/browser@10.59.0", "", { "dependencies": { "@sentry/browser-utils": "10.59.0", "@sentry/core": "10.59.0", "@sentry/feedback": "10.59.0", "@sentry/replay": "10.59.0", "@sentry/replay-canvas": "10.59.0" } }, "sha512-d0o0oc78KNWCZ6yq9gREf9BPXWza/Wj9W+nCm0CvPD5k2IbouD/eJsm2Mb+d53YfEm12L+SePfgOx01KbbVx4A=="],
218
212
 
219
213
  "sentry-node-cal": ["@sentry/node@9.46.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.2", "@opentelemetry/instrumentation-amqplib": "^0.46.1", "@opentelemetry/instrumentation-connect": "0.43.1", "@opentelemetry/instrumentation-dataloader": "0.16.1", "@opentelemetry/instrumentation-express": "0.47.1", "@opentelemetry/instrumentation-fs": "0.19.1", "@opentelemetry/instrumentation-generic-pool": "0.43.1", "@opentelemetry/instrumentation-graphql": "0.47.1", "@opentelemetry/instrumentation-hapi": "0.45.2", "@opentelemetry/instrumentation-http": "0.57.2", "@opentelemetry/instrumentation-ioredis": "0.47.1", "@opentelemetry/instrumentation-kafkajs": "0.7.1", "@opentelemetry/instrumentation-knex": "0.44.1", "@opentelemetry/instrumentation-koa": "0.47.1", "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", "@opentelemetry/instrumentation-mongodb": "0.52.0", "@opentelemetry/instrumentation-mongoose": "0.46.1", "@opentelemetry/instrumentation-mysql": "0.45.1", "@opentelemetry/instrumentation-mysql2": "0.45.2", "@opentelemetry/instrumentation-pg": "0.51.1", "@opentelemetry/instrumentation-redis-4": "0.46.1", "@opentelemetry/instrumentation-tedious": "0.18.1", "@opentelemetry/instrumentation-undici": "0.10.1", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.34.0", "@prisma/instrumentation": "6.11.1", "@sentry/core": "9.46.0", "@sentry/node-core": "9.46.0", "@sentry/opentelemetry": "9.46.0", "import-in-the-middle": "^1.14.2", "minimatch": "^9.0.0" } }, "sha512-pRLqAcd7GTGvN8gex5FtkQR5Mcol8gOy1WlyZZFq4rBbVtMbqKOQRhohwqnb+YrnmtFpj7IZ7KNDo077MvNeOQ=="],
220
214
 
221
215
  "sentry-node-cal-web": ["@sentry/node@10.33.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^2.2.0", "@opentelemetry/core": "^2.2.0", "@opentelemetry/instrumentation": "^0.208.0", "@opentelemetry/instrumentation-amqplib": "0.55.0", "@opentelemetry/instrumentation-connect": "0.52.0", "@opentelemetry/instrumentation-dataloader": "0.26.0", "@opentelemetry/instrumentation-express": "0.57.0", "@opentelemetry/instrumentation-fs": "0.28.0", "@opentelemetry/instrumentation-generic-pool": "0.52.0", "@opentelemetry/instrumentation-graphql": "0.56.0", "@opentelemetry/instrumentation-hapi": "0.55.0", "@opentelemetry/instrumentation-http": "0.208.0", "@opentelemetry/instrumentation-ioredis": "0.56.0", "@opentelemetry/instrumentation-kafkajs": "0.18.0", "@opentelemetry/instrumentation-knex": "0.53.0", "@opentelemetry/instrumentation-koa": "0.57.0", "@opentelemetry/instrumentation-lru-memoizer": "0.53.0", "@opentelemetry/instrumentation-mongodb": "0.61.0", "@opentelemetry/instrumentation-mongoose": "0.55.0", "@opentelemetry/instrumentation-mysql": "0.54.0", "@opentelemetry/instrumentation-mysql2": "0.55.0", "@opentelemetry/instrumentation-pg": "0.61.0", "@opentelemetry/instrumentation-redis": "0.57.0", "@opentelemetry/instrumentation-tedious": "0.27.0", "@opentelemetry/instrumentation-undici": "0.19.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-trace-base": "^2.2.0", "@opentelemetry/semantic-conventions": "^1.37.0", "@prisma/instrumentation": "6.19.0", "@sentry/core": "10.33.0", "@sentry/node-core": "10.33.0", "@sentry/opentelemetry": "10.33.0", "import-in-the-middle": "^2.0.1", "minimatch": "^9.0.0" } }, "sha512-HZ7U0igIXs8nHSeh0YAe9C3eE/fjkHOprctQHwoYpRrZelsKO8NsvZU0K/1+knFr36vFj7jtt1QlF/UjCQZD+Q=="],
222
216
 
223
- "sentry-node-postiz": ["@sentry/node@10.56.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/core": "^2.6.1", "@opentelemetry/instrumentation": "^0.214.0", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@sentry-internal/server-utils": "10.56.0", "@sentry/core": "10.56.0", "@sentry/node-core": "10.56.0", "@sentry/opentelemetry": "10.56.0", "import-in-the-middle": "^3.0.0" } }, "sha512-qvgtXHkcR4CH3fh0VEVyw4Ysc6MMiAnm727NdTTm0yU5e53erCeo2521+yfJkqmRTGiOSgwA7B5Bs+ot9j0vFQ=="],
224
-
225
217
  "sentry-node-twenty": ["@sentry/node@10.73.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.1", "@opentelemetry/instrumentation": "^0.220.0", "@opentelemetry/sdk-trace-base": "^2.9.0", "@sentry/conventions": "^0.16.0", "@sentry/core": "10.73.0", "@sentry/node-core": "10.73.0", "@sentry/opentelemetry": "10.73.0", "@sentry/server-utils": "10.73.0", "import-in-the-middle": "^3.0.0" } }, "sha512-jiMJ6GgXDw6UMGzJY+o0c8OoeA9OfHqZ/xEpHfDqy75hn+9CEkRkbNGCIdMvsc7wW/Se1Os394hHfTpU+YEskg=="],
226
218
 
227
219
  "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="],
@@ -246,8 +238,6 @@
246
238
 
247
239
  "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.207.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.207.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA=="],
248
240
 
249
- "@sentry-internal/server-utils/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
250
-
251
241
  "@sentry/browser-utils/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
252
242
 
253
243
  "@sentry/feedback/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
@@ -266,16 +256,6 @@
266
256
 
267
257
  "@types/tedious/@types/node": ["@types/node@26.6.4", "", { "dependencies": { "undici-types": "~8.9.0" } }, "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg=="],
268
258
 
269
- "sentry-browser-postiz/@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-I8tZWAFg8SZpD8BFUpglEtSTzhZjacmcThB5/Mlq/iFiiT8mBPG4ZWDWssSfmIBKvZywJZJ83uDA0+uiJU73Tw=="],
270
-
271
- "sentry-browser-postiz/@sentry-internal/feedback": ["@sentry-internal/feedback@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" } }, "sha512-fkRR9JroESTIlErkht3OrH4DXKd/DbPozr2KLdX7boMo31hPu4cL9fuqzwOrwyDPRq9B4j+qEgIWB8JrTbgvmg=="],
272
-
273
- "sentry-browser-postiz/@sentry-internal/replay": ["@sentry-internal/replay@10.56.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-DjF09hpy3TF7Km/kOZc73YJmBqcbPCxuZ5rtRs+KtVHu3Vq48xeW83qKUcFEZv20ur9UD99OAJ/gaEt//1Qbwg=="],
274
-
275
- "sentry-browser-postiz/@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.56.0", "", { "dependencies": { "@sentry-internal/replay": "10.56.0", "@sentry/core": "10.56.0" } }, "sha512-SDg2K0CAZT/TnhrixQGwXoi6ZsWUB+DQy3UUk0bSQm6c/5k5zFBpGOiughQN+DYsDilKREfPKmUEEnqvUjm1HQ=="],
276
-
277
- "sentry-browser-postiz/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
278
-
279
259
  "sentry-browser-twenty/@sentry/core": ["@sentry/core@10.59.0", "", {}, "sha512-QeG7XZL5j6CkToYCE7OwCerb/r742Tjj9p1BBohBKcypYTPRuqfD+A3FeUj7pk5CGO6Vj1/gOAmdbuuNbR51dQ=="],
280
260
 
281
261
  "sentry-node-cal/@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@1.30.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA=="],
@@ -394,16 +374,6 @@
394
374
 
395
375
  "sentry-node-cal-web/@sentry/opentelemetry": ["@sentry/opentelemetry@10.33.0", "", { "dependencies": { "@sentry/core": "10.33.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0 || ^2.2.0", "@opentelemetry/semantic-conventions": "^1.37.0" } }, "sha512-v/6mAYLxtfcKLCw6Ktk46T6fWEQBVWB9Ah81axr8OvuIomK71jkv1zb0v7D8ot0ESesJ3JF6I/aKhfxpyLInSQ=="],
396
376
 
397
- "sentry-node-postiz/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w=="],
398
-
399
- "sentry-node-postiz/@sentry/core": ["@sentry/core@10.56.0", "", {}, "sha512-L+u1dIz5SANrmST5jhIwETtt4apILgKrylv12X4hKJU0PvZl+NorjeV/ty3MwzpKQPg6b6q6qMOSLc1rLpy3iQ=="],
400
-
401
- "sentry-node-postiz/@sentry/node-core": ["@sentry/node-core@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0", "@sentry/opentelemetry": "10.56.0", "import-in-the-middle": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1", "@opentelemetry/instrumentation": ">=0.57.1 <1", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/core", "@opentelemetry/exporter-trace-otlp-http", "@opentelemetry/instrumentation", "@opentelemetry/sdk-trace-base", "@opentelemetry/semantic-conventions"] }, "sha512-61lD2Wjtv5Lw2F3lJarcD0ORjR4GlVxrEd6w6Of/uF3DH73dD6K3n/3wXEeCIRfV/kgiCFIrCIq76nz0LVgE5g=="],
402
-
403
- "sentry-node-postiz/@sentry/opentelemetry": ["@sentry/opentelemetry@10.56.0", "", { "dependencies": { "@sentry/core": "10.56.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0" } }, "sha512-PtMudApHMHvttjos3b7JZ2gJ+nstHAOYE3vKPYB5o0WQO95ldiaYnpLKMCRIGZWF3Dk7ynrqqnBpn8LZLt+Mrg=="],
404
-
405
- "sentry-node-postiz/import-in-the-middle": ["import-in-the-middle@3.5.2", "", { "dependencies": { "cjs-module-lexer": "^2.2.0", "es-module-lexer": "^3.0.2", "module-details-from-path": "^1.0.4" } }, "sha512-WseIA/4o56+GYO3RmlOPvejYi771OFeJEeK/ejROsr9bdjW+E5NXTOD1Di8TL40Qgg3JJX9aa97Hf8iiSVIKZw=="],
406
-
407
377
  "sentry-node-twenty/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.220.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.220.0", "import-in-the-middle": "^3.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw=="],
408
378
 
409
379
  "sentry-node-twenty/@sentry/core": ["@sentry/core@10.73.0", "", { "dependencies": { "@sentry/conventions": "^0.16.0" } }, "sha512-FLO1UgH19RyasVpofu612WCOgb2nEH0dZy+R72d7p65XU9i0wxlMKm3+sgfwKmiSJp1Qhilaaxs4Jg6BbiM5HA=="],
@@ -464,8 +434,6 @@
464
434
 
465
435
  "sentry-node-cal/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
466
436
 
467
- "sentry-node-postiz/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA=="],
468
-
469
437
  "sentry-node-twenty/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.220.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-CmVa4ImJ+ynfrPMNaAXHET6Bhb44SwzmfyVJFq9ni2jgXJR/l7C6gfVFddNmHP+ZOkP9cf4f9DBe68qVLTHc9w=="],
470
438
 
471
439
  "@opentelemetry/instrumentation-redis-4/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
@@ -6,11 +6,9 @@
6
6
  "@sentry/browser": "10.38.0",
7
7
  "@sentry/core": "10.38.0",
8
8
  "@sentry/node": "10.38.0",
9
- "sentry-browser-postiz": "npm:@sentry/browser@10.56.0",
10
9
  "sentry-browser-twenty": "npm:@sentry/browser@10.59.0",
11
10
  "sentry-node-cal": "npm:@sentry/node@9.46.0",
12
11
  "sentry-node-cal-web": "npm:@sentry/node@10.33.0",
13
- "sentry-node-postiz": "npm:@sentry/node@10.56.0",
14
12
  "sentry-node-twenty": "npm:@sentry/node@10.73.0",
15
13
  "resend": "6.6.0",
16
14
  "@linear/sdk": "86.0.0"
@@ -6,10 +6,6 @@ export type AssessmentOptions = {
6
6
  };
7
7
  /** Surface coverage counts actual kernel dispatch, and retains every declared gap in the denominator. */
8
8
  export declare function assessPack(packDir: string, options?: AssessmentOptions): Promise<{
9
- schemaVersion: number;
10
- vendor: string;
11
- package: any;
12
- version: any;
13
9
  ready: boolean;
14
10
  gates: {
15
11
  unit: string;
@@ -111,4 +107,9 @@ export declare function assessPack(packDir: string, options?: AssessmentOptions)
111
107
  passed: boolean;
112
108
  failures: string[];
113
109
  };
110
+ integrity?: string | undefined;
111
+ schemaVersion: number;
112
+ vendor: string;
113
+ package: any;
114
+ version: any;
114
115
  }>;
@@ -128,5 +128,6 @@ export async function assessPack(packDir, options = {}) {
128
128
  consumer = { measured: false, passed: false, failures: [error.message] };
129
129
  }
130
130
  const ready = gates.length > 0 && gates.every((gate) => !gate.failures.length) && !quick.failures.length && replayEqual && conform !== null && conform.length > 0 && conform.every((result) => !result.failures.length) && consumer.measured && consumer.passed && (!options.browser || !httpOnly || browser.measured === true && browser.failures.length === 0 && browser.replay.equal);
131
- return { schemaVersion: 1, vendor, package: manifest.name, version: manifest.version, ready, gates: gates.map((gate) => ({ ...gate, unit: gate.unit === packDir ? vendor : `${vendor}/${gate.unit.slice(packDir.length + 1)}` })), quick, browser, conformance: conform, consumer };
131
+ // the artifact assessed, by the integrity its prepared consumer verified the installed candidate against (consumer.ts)
132
+ return { schemaVersion: 1, vendor, package: manifest.name, version: manifest.version, ...(consumer.integrity ? { integrity: consumer.integrity } : {}), ready, gates: gates.map((gate) => ({ ...gate, unit: gate.unit === packDir ? vendor : `${vendor}/${gate.unit.slice(packDir.length + 1)}` })), quick, browser, conformance: conform, consumer };
132
133
  }
package/dist/src/cli.js CHANGED
@@ -21,6 +21,12 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
21
21
  // the pack served and read as an application and the
22
22
  // catalog meet it (conformance.ts): a checkout, or a
23
23
  // published version as the catalog admits it; or exit 1
24
+ // twin-standard walk <vendor> [--write] [--report <file>] the journey test, from the pack repository's root: the
25
+ // life walked on a fresh World (twice, the same), its
26
+ // coverage and the published examples (tools/score-pack.ts)
27
+ // twin-standard examples <vendor> [--sweep] the vendor's published examples replayed (tools/vendor-examples.ts)
28
+ // twin-standard coverage <vendor> [--write | --out <file>] the code and state logic the walks reach (tools/life-coverage.ts)
29
+ // twin-standard judge-brief <vendor> --authors <names> what an independent judge reads and writes (tools/judge-brief.ts)
24
30
  // twin-standard --version the package's version and each standard's
25
31
  import { existsSync, readFileSync } from 'node:fs';
26
32
  import { relative, resolve } from 'node:path';
@@ -31,7 +37,7 @@ import { standardPackageFile } from "./package-file.js";
31
37
  import { gatePublished } from "./published.js";
32
38
  const [command, ...args] = process.argv.slice(2);
33
39
  const usage = () => {
34
- console.error('usage: twin-standard gate <repo> [units…] | gate-published <name>@<version>… [--registry <url>] | grade <unit>… [--static] [--form] | derive <unit> [--out <dir>] | read-page <url> [--raw] | check-sources <unit> [--recheck] | conform <pack dir> | <name>@<version> [--registry <url>] | create <dir> --init <vendor> --package <@scope/name> | create <unit> --index [--building] | facts <pack dir> [--out <file>] | prepare-consumer <pack dir> --app <new dir> --cli <volter executable> --integrity <sha512> --out <json> [--candidate <tgz>] | walk-consumer <pack dir> --prepared-consumer <json> [--out <file>] | assess <pack dir> --prepared-consumer <json> [--browser] [--out <file>] | --version');
40
+ console.error('usage: twin-standard gate <repo> [units…] | gate-published <name>@<version>… [--registry <url>] | grade <unit>… [--static] [--form] | derive <unit> [--out <dir>] | read-page <url> [--raw] | check-sources <unit> [--recheck] | conform <pack dir> | <name>@<version> [--registry <url>] | create <dir> --init <vendor> --package <@scope/name> | create <unit> --index [--building] | facts <pack dir> [--out <file>] | prepare-consumer <pack dir> --app <new dir> --cli <volter executable> --integrity <sha512> --out <json> [--candidate <tgz>] | walk-consumer <pack dir> --prepared-consumer <json> [--out <file>] | assess <pack dir> --prepared-consumer <json> [--browser] [--out <file>] | walk <vendor> [--write] [--report <file>] | examples <vendor> [--sweep] | coverage <vendor> [--write | --out <file>] | judge-brief <vendor> --authors <names> | --version');
35
41
  process.exit(2);
36
42
  };
37
43
  if (command === '--version') {
@@ -190,23 +196,32 @@ else if (command === 'facts') {
190
196
  writeFileSync(out, renderPackFacts(facts));
191
197
  console.log(out);
192
198
  }
199
+ else if (command === 'walk' || command === 'examples' || command === 'coverage' || command === 'judge-brief') {
200
+ // the contributor's journey tools, run from the pack repository's root (tools/packs-root.ts), each a script over
201
+ // process.argv whose first argument is the vendor
202
+ if (!args[0] || args[0].startsWith('-'))
203
+ usage();
204
+ const tool = { walk: 'score-pack', examples: 'vendor-examples', coverage: 'life-coverage', 'judge-brief': 'judge-brief' }[command];
205
+ process.argv = [process.argv[0], process.argv[1], ...args];
206
+ await import(__rewriteRelativeImportExtension((await import('./tools/packs-root.ts')).toolPath(tool)));
207
+ }
193
208
  else if (command === 'derive') {
194
209
  if (!args[0])
195
210
  usage();
196
211
  // the derivation is a script over process.argv: it reads the unit from its first argument
197
212
  process.argv = [process.argv[0], process.argv[1], ...args];
198
- await import("./derive.js");
213
+ await import('./derive.ts');
199
214
  }
200
215
  else if (command === 'check-sources') {
201
216
  if (!args[0])
202
217
  usage();
203
- await (await import("./check-sources.js")).checkSources(args);
218
+ await (await import('./check-sources.ts')).checkSources(args);
204
219
  }
205
220
  else if (command === 'read-page') {
206
221
  // a documentation page's text, read as the citation check reads it: where an author finds the vendor's examples and words
207
222
  if (!args[0])
208
223
  usage();
209
- const { status, readable, raw, error } = await (await import("./check-sources.js")).readPage(args[0]);
224
+ const { status, readable, raw, error } = await (await import('./check-sources.ts')).readPage(args[0]);
210
225
  if (status !== 200) {
211
226
  console.error(`read-page: ${args[0]} answered ${status || 'nothing'}${error ? `: ${error}` : ''}`);
212
227
  process.exit(1);
@@ -226,8 +241,8 @@ else if (command === 'conform') {
226
241
  // `.tgz` the tarball `npm pack` makes of one, the bytes a publish would send
227
242
  const published = target.endsWith('.tgz') || (!existsSync(target) && /^@?[^@]+@[^@]+$/.test(target));
228
243
  const results = published
229
- ? await (await import("./published.js")).conformPublished(target, at >= 0 ? { registry: args[at + 1] } : {})
230
- : await (await import("./conformance.js")).conformance(target);
244
+ ? await (await import('./published.ts')).conformPublished(target, at >= 0 ? { registry: args[at + 1] } : {})
245
+ : await (await import('./conformance.ts')).conformance(target, { onCheck: (id) => console.error(` … ${id} (${new Date().toISOString().slice(11, 19)})`) });
231
246
  for (const r of results) {
232
247
  console.log(`${r.failures.length ? '✗' : '✓'} ${r.id.padEnd(15)} ${r.asks}${r.note ? ` (${r.note})` : ''}`);
233
248
  for (const f of r.failures)
@@ -36,4 +36,6 @@ export declare function worldProxy(served: number): Promise<number>;
36
36
  * its caller's abort signal retires that request, including an unfinished response body. */
37
37
  export declare function servedHttpFetch(port: number): typeof fetch;
38
38
  /** The context for a pack reached at `port` of this machine (the World's proxy in front of it). */
39
- export declare function clientContext(port: number, host: string, env: Record<string, string>, scenarioPath: string): ClientContext;
39
+ /** `raw`: a raw protocol's served port (SMTP's listener), which a connection reaches directly, as a World passes a raw TCP
40
+ * connection through untouched; the proxy speaks HTTP only. */
41
+ export declare function clientContext(port: number, host: string, env: Record<string, string>, scenarioPath: string, raw?: number): ClientContext;
@@ -85,13 +85,15 @@ export function servedHttpFetch(port) {
85
85
  });
86
86
  }
87
87
  /** The context for a pack reached at `port` of this machine (the World's proxy in front of it). */
88
- export function clientContext(port, host, env, scenarioPath) {
88
+ /** `raw`: a raw protocol's served port (SMTP's listener), which a connection reaches directly, as a World passes a raw TCP
89
+ * connection through untouched; the proxy speaks HTTP only. */
90
+ export function clientContext(port, host, env, scenarioPath, raw) {
89
91
  const agent = new (class extends HttpsAgent {
90
92
  createConnection() { return connect(port, '127.0.0.1'); }
91
93
  })({ keepAlive: false });
92
94
  return {
93
95
  host, env, fetch: servedHttpFetch(port), agent,
94
- connect: () => connect(port, '127.0.0.1'),
96
+ connect: () => connect(raw ?? port, '127.0.0.1'),
95
97
  scenario: (doc) => writeFileSync(scenarioPath, JSON.stringify(doc)),
96
98
  };
97
99
  }
@@ -0,0 +1,2 @@
1
+ import type { ClientCase } from './harness.js';
2
+ export declare const cases: ClientCase[];
@@ -0,0 +1,71 @@
1
+ const README = 'https://www.npmjs.com/package/jira.js/v/5.4.0';
2
+ const CREATE = 'https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-post';
3
+ const ADF = 'https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/';
4
+ /** A site named `slug`, its admin, the admin's API token and a project OPS led by them; the client on the site's URL. */
5
+ async function site(c, slug, apiToken) {
6
+ const door = async (path, body) => {
7
+ const answer = await c.fetch(`https://${c.host}${path}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) });
8
+ if (answer.status !== 201)
9
+ throw new Error(`${path} answered ${answer.status}`);
10
+ return (await answer.json());
11
+ };
12
+ const email = `admin@${slug}.example`;
13
+ const made = await door('/_twin/sites', { name: slug, admin: { name: 'Admin', email, password: 'sdk-case-2026' } });
14
+ const token = apiToken ?? (await door('/_twin/api-token', { site: slug, email, password: 'sdk-case-2026' })).apiToken;
15
+ const { Version3Client } = await import('jira.js');
16
+ const jira = new Version3Client({ host: `https://${slug}.atlassian.net`, authentication: { basic: { email, apiToken: token } }, baseRequestConfig: { httpsAgent: c.agent } });
17
+ return { jira, admin: made.admin };
18
+ }
19
+ export const cases = [
20
+ {
21
+ id: 'create-issue-string-description',
22
+ asks: "an issue filed as the on-call agent files it, its description a plain string the client sends as an ADF document, answers its id, key and self, and reads back with that text",
23
+ source: `${CREATE} "Creates an issue or, where the option to create subtasks is enabled in Jira, a subtask."`,
24
+ async run(c) {
25
+ const { jira, admin } = await site(c, 'sdk-file');
26
+ await jira.projects.createProject({ key: 'OPS', name: 'Operations', projectTypeKey: 'software', leadAccountId: admin });
27
+ const filed = await jira.issues.createIssue({ fields: { project: { key: 'OPS' }, issuetype: { name: 'Task' }, summary: 'acme/web#1: checkout fails', description: 'SEVERITY: high — checkout fails' } });
28
+ const failures = [];
29
+ if (!/^OPS-\d+$/.test(String(filed.key)) || !filed.id || !String(filed.self).includes(`/rest/api/3/issue/${filed.id}`))
30
+ failures.push(`createIssue answered ${JSON.stringify(filed)}`);
31
+ const read = await jira.issues.getIssue({ issueIdOrKey: String(filed.key), fields: ['summary', 'description'] });
32
+ const text = JSON.stringify(read.fields.description ?? null);
33
+ if (read.fields.summary !== 'acme/web#1: checkout fails')
34
+ failures.push(`the issue reads back summary ${JSON.stringify(read.fields.summary)}`);
35
+ if (!text.includes('"type":"doc"') || !text.includes('SEVERITY: high — checkout fails'))
36
+ failures.push(`the description reads back ${text.slice(0, 160)}, not the ADF document of the text sent`);
37
+ return failures;
38
+ },
39
+ },
40
+ {
41
+ id: 'adf-document-shape',
42
+ asks: 'a description read back is an ADF document: type doc, version 1, its paragraph holding the text node',
43
+ source: `${ADF} "Atlassian Document Format (ADF) represents rich text stored in Atlassian products."`,
44
+ async run(c) {
45
+ const { jira, admin } = await site(c, 'sdk-adf');
46
+ await jira.projects.createProject({ key: 'OPS', name: 'Operations', projectTypeKey: 'software', leadAccountId: admin });
47
+ const filed = await jira.issues.createIssue({ fields: { project: { key: 'OPS' }, issuetype: { name: 'Task' }, summary: 'shape', description: 'one line' } });
48
+ const doc = (await jira.issues.getIssue({ issueIdOrKey: String(filed.key), fields: ['description'] })).fields.description;
49
+ return doc?.type === 'doc' && doc.version === 1 && doc.content?.[0]?.type === 'paragraph' && doc.content[0].content?.[0]?.type === 'text' && doc.content[0].content[0].text === 'one line'
50
+ ? [] : [`the description is ${JSON.stringify(doc).slice(0, 200)}`];
51
+ },
52
+ },
53
+ {
54
+ id: 'wrong-token-http-exception',
55
+ asks: 'a request with an API token the account never made is refused, and the client throws its HttpException carrying the status',
56
+ source: `${README} "\`HttpException\`: Server responded with an error (includes parsed error details)"`,
57
+ async run(c) {
58
+ const { HttpException } = await import('jira.js');
59
+ const { jira } = await site(c, 'sdk-refused', 'ATATT-not-a-token-this-account-made');
60
+ try {
61
+ await jira.projects.searchProjects({ maxResults: 50 });
62
+ return ['the made-up token was accepted'];
63
+ }
64
+ catch (error) {
65
+ if (!(error instanceof HttpException))
66
+ return [`the refusal is not an HttpException: ${String(error).slice(0, 160)}`];
67
+ return error.status === 401 ? [] : [`the refusal's status is ${error.status}, not 401`];
68
+ }
69
+ },
70
+ },
71
+ ];
@@ -0,0 +1,2 @@
1
+ import type { ClientCase } from './harness.js';
2
+ export declare const cases: ClientCase[];
@@ -0,0 +1,73 @@
1
+ const INGEST = 'https://polar.sh/docs/api-reference/events/ingest';
2
+ const STATE = 'https://polar.sh/docs/api-reference/customers/state-external';
3
+ const PRODUCTS = 'https://polar.sh/docs/api-reference/products/create';
4
+ async function client(c) {
5
+ globalThis.fetch = c.fetch;
6
+ const { Polar } = await import('@polar-sh/sdk');
7
+ return new Polar({ accessToken: c.env.POLAR_ACCESS_TOKEN, server: 'production' });
8
+ }
9
+ export const cases = [
10
+ {
11
+ id: 'catalog-bootstrap',
12
+ asks: "the billing app's boot: a meter made by its filter and aggregation, and a monthly product priced fixed and per metered unit with a trial, each read back by name in the SDK's own models",
13
+ source: `${PRODUCTS} "plus any number of metered prices"`,
14
+ async run(c) {
15
+ const polar = await client(c);
16
+ const meter = await polar.meters.create({ name: 'case_world_hours', filter: { conjunction: 'and', clauses: [{ property: 'name', operator: 'eq', value: 'world.hour' }] }, aggregation: { func: 'sum', property: 'units' } });
17
+ const product = await polar.products.create({
18
+ name: 'Case Team', recurringInterval: 'month', description: 'A case plan',
19
+ prices: [{ amountType: 'fixed', priceAmount: 4900, priceCurrency: 'usd' }, { amountType: 'metered_unit', unitAmount: '2', meterId: meter.id }],
20
+ trialInterval: 'day', trialIntervalCount: 14,
21
+ });
22
+ const failures = [];
23
+ const meters = await polar.meters.list({ limit: 100 });
24
+ if (!meters.result.items.some((m) => m.id === meter.id && m.name === 'case_world_hours'))
25
+ failures.push('the made meter is not listed by its name');
26
+ const products = await polar.products.list({ limit: 100 });
27
+ const listed = products.result.items.find((p) => p.id === product.id);
28
+ if (!listed || listed.name !== 'Case Team' || listed.isArchived)
29
+ failures.push(`the made product lists as ${JSON.stringify(listed && { name: listed.name, isArchived: listed.isArchived })}`);
30
+ if (product.prices.length !== 2)
31
+ failures.push(`the product holds ${product.prices.length} prices, not its fixed and metered two`);
32
+ if (product.trialInterval !== 'day' || product.trialIntervalCount !== 14)
33
+ failures.push(`the product's trial is ${String(product.trialIntervalCount)} ${String(product.trialInterval)}`);
34
+ return failures;
35
+ },
36
+ },
37
+ {
38
+ id: 'unknown-customer-state-not-found',
39
+ asks: "an organization with no customer reads as the SDK's ResourceNotFound (404), which the billing app takes as Free",
40
+ source: `${STATE} "Customer not found."`,
41
+ async run(c) {
42
+ const polar = await client(c);
43
+ const { ResourceNotFound } = await import('@polar-sh/sdk/models/errors/resourcenotfound.js');
44
+ try {
45
+ await polar.customers.getStateExternal({ externalId: 'org_never_a_customer' });
46
+ return ['an unknown external id read as a customer'];
47
+ }
48
+ catch (error) {
49
+ return error instanceof ResourceNotFound ? [] : [`the refusal is not ResourceNotFound: ${String(error).slice(0, 160)}`];
50
+ }
51
+ },
52
+ },
53
+ {
54
+ id: 'ingest-deduplicates-by-external-id',
55
+ asks: 'an event sent again with the same external_id (a tick retried after a timeout) is skipped as a duplicate, not counted twice',
56
+ source: `${INGEST} "Number of duplicate events skipped."`,
57
+ async run(c) {
58
+ const polar = await client(c);
59
+ const customer = await polar.customers.create({ email: 'ops@case-ingest.example', externalId: 'org_case_ingest' });
60
+ const event = { name: 'world.hour', externalCustomerId: 'org_case_ingest', externalId: 'tick-2026-01-14T10', metadata: { units: 1 } };
61
+ const first = await polar.events.ingest({ events: [event] });
62
+ const again = await polar.events.ingest({ events: [event] });
63
+ const failures = [];
64
+ if (first.inserted !== 1 || first.duplicates !== 0)
65
+ failures.push(`the first send answered ${JSON.stringify(first)}`);
66
+ if (again.inserted !== 0 || again.duplicates !== 1)
67
+ failures.push(`the retried send answered ${JSON.stringify(again)}, not one duplicate skipped`);
68
+ if (!customer.id)
69
+ failures.push('the customer was made with no id');
70
+ return failures;
71
+ },
72
+ },
73
+ ];