@classytic/arc 2.38.0 → 2.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/{BaseController-CYaDvmOB.mjs → BaseController-BqJtbiUA.mjs} +107 -23
  2. package/dist/{EventTransport-Cx60_s-6.d.mts → EventTransport-BPOQsEer.d.mts} +8 -0
  3. package/dist/{EventTransport-Gq7JWbWw.mjs → EventTransport-BUkTwY_x.mjs} +13 -2
  4. package/dist/{HookSystem-C0ikzqQf.mjs → HookSystem-96nzZLmk.mjs} +2 -2
  5. package/dist/{ResourceRegistry-DPcX--zk.mjs → ResourceRegistry-B9WnuG2Q.mjs} +2 -2
  6. package/dist/{actionPermissions-jlFZ1it4.mjs → actionPermissions-4OGbe3Hf.mjs} +6 -6
  7. package/dist/audit/index.d.mts +1 -1
  8. package/dist/audit/index.mjs +2 -2
  9. package/dist/auth/audit.mjs +1 -1
  10. package/dist/auth/index.d.mts +1 -1
  11. package/dist/auth/index.mjs +6 -6
  12. package/dist/auth/redis-session.mjs +1 -1
  13. package/dist/{authorizationDecision-BP8GHtjc.mjs → authorizationDecision-D_LFvMlm.mjs} +2 -2
  14. package/dist/{buildHandler-DjXOqIvX.mjs → buildHandler-BG_CHXqQ.mjs} +4 -4
  15. package/dist/cache/index.mjs +4 -4
  16. package/dist/{caching-a3ZEcJJs.mjs → caching-Bqcn3Brl.mjs} +2 -2
  17. package/dist/cleanup/index.d.mts +2 -2
  18. package/dist/cleanup/index.mjs +21 -5
  19. package/dist/cli/commands/describe.d.mts +1 -1
  20. package/dist/cli/commands/describe.mjs +3 -3
  21. package/dist/cli/commands/docs.mjs +3 -3
  22. package/dist/cli/commands/doctor.mjs +1 -1
  23. package/dist/cli/commands/generate.mjs +2 -2
  24. package/dist/cli/commands/init.mjs +2 -2
  25. package/dist/cli/commands/introspect.mjs +2 -2
  26. package/dist/cli/index.mjs +3 -3
  27. package/dist/{constants-BONghE1Y.mjs → constants-BQ2FbhPB.mjs} +1 -1
  28. package/dist/context/index.d.mts +34 -6
  29. package/dist/context/index.mjs +12 -19
  30. package/dist/core/index.d.mts +2 -2
  31. package/dist/core/index.mjs +7 -7
  32. package/dist/{core-8She7FgF.mjs → core-CsZR037F.mjs} +3 -3
  33. package/dist/{createActionRouter-Bqi6Bhhx.mjs → createActionRouter-BR93gCKg.mjs} +7 -7
  34. package/dist/{createAggregationRouter-BsYO7ktd.mjs → createAggregationRouter-CF40Aw95.mjs} +7 -7
  35. package/dist/createMcpServer-BVTs2S5G.d.mts +48 -0
  36. package/dist/{defineAggregation-0KBvqEEC.mjs → defineAggregation-BDA2Tw7v.mjs} +1 -1
  37. package/dist/{defineResource-BMdyRelW.mjs → defineResource-DaIySrQr.mjs} +20 -22
  38. package/dist/discovery/index.mjs +1 -1
  39. package/dist/docs/index.d.mts +1 -1
  40. package/dist/docs/index.mjs +3 -3
  41. package/dist/{elevation-C6woysGC.mjs → elevation-CZy6n50b.mjs} +4 -4
  42. package/dist/encryption/index.mjs +3 -3
  43. package/dist/{errorHandler-DI5AN2b5.d.mts → errorHandler--4rSMMvq.d.mts} +7 -1
  44. package/dist/{errorHandler-BdmIWPba.mjs → errorHandler-By9keRvX.mjs} +3 -3
  45. package/dist/{errors-2ExmOgIJ.mjs → errors-BHD3L8of.mjs} +1 -1
  46. package/dist/{eventPlugin-DJwpGMzx.mjs → eventPlugin-DB26V7uX.mjs} +5 -5
  47. package/dist/{eventPlugin-DFvHa4Nf.d.mts → eventPlugin-DfHaKEWQ.d.mts} +1 -1
  48. package/dist/events/index.d.mts +4 -4
  49. package/dist/events/index.mjs +5 -5
  50. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  51. package/dist/events/transports/redis-stream-entry.mjs +21 -20
  52. package/dist/events/transports/redis.d.mts +1 -1
  53. package/dist/events/transports/redis.mjs +11 -8
  54. package/dist/factory/index.d.mts +4 -4
  55. package/dist/factory/index.mjs +5 -5
  56. package/dist/{fastify-augmentation-jYA2oHyL.d.mts → fastify-augmentation-HncZMmze.d.mts} +3 -3
  57. package/dist/{fields-Cha2QCKH.mjs → fields-fA-Dkou5.mjs} +1 -1
  58. package/dist/{generate-BUP4Oydg.mjs → generate-BSSdtiOy.mjs} +4 -3
  59. package/dist/{headers-DeXNifVj.mjs → headers-BFEEshDS.mjs} +2 -2
  60. package/dist/{health-Bh0N_FLk.mjs → health-BlGHjkqZ.mjs} +1 -1
  61. package/dist/hooks/index.d.mts +1 -1
  62. package/dist/hooks/index.mjs +2 -2
  63. package/dist/idempotency/index.mjs +4 -4
  64. package/dist/idempotency/redis.mjs +1 -1
  65. package/dist/{index-B78WZom8.d.mts → index-D3sIPcD4.d.mts} +47 -11
  66. package/dist/{index-D2uIUSQk.d.mts → index-DbMglURO.d.mts} +2 -2
  67. package/dist/{index-BRoDtjek.d.mts → index-SCsOJxWB.d.mts} +2 -2
  68. package/dist/index.d.mts +3 -3
  69. package/dist/index.mjs +11 -11
  70. package/dist/{init-Dg_Am2o_.mjs → init-pl88PHzb.mjs} +9 -9
  71. package/dist/integrations/event-gateway.d.mts +1 -1
  72. package/dist/integrations/event-gateway.mjs +2 -2
  73. package/dist/integrations/index.d.mts +1 -1
  74. package/dist/integrations/index.mjs +1 -1
  75. package/dist/integrations/jobs/index.mjs +2 -2
  76. package/dist/integrations/mcp/index.d.mts +3 -46
  77. package/dist/integrations/mcp/index.mjs +2 -2
  78. package/dist/integrations/mcp/testing.d.mts +22 -2
  79. package/dist/integrations/mcp/testing.mjs +55 -33
  80. package/dist/integrations/streamline.mjs +3 -3
  81. package/dist/integrations/webhooks.d.mts +2 -2
  82. package/dist/integrations/webhooks.mjs +3 -3
  83. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  84. package/dist/integrations/websocket-redis.mjs +1 -1
  85. package/dist/integrations/websocket.mjs +13 -6
  86. package/dist/{interface-DYPVscCU.mjs → interface-DjtFnZxH.mjs} +1 -1
  87. package/dist/{jsonBody-DVui0uJl.mjs → jsonBody-Dx6jH_Nb.mjs} +2 -2
  88. package/dist/{keys-BSuxGS-B.mjs → keys-Ds3ekBiu.mjs} +1 -1
  89. package/dist/{loadResources-CNd1DWnK.mjs → loadResources-E5UFlRrT.mjs} +2 -2
  90. package/dist/{loadResourcesFromEntry-DNj8cpiY.mjs → loadResourcesFromEntry-C2jrJbWG.mjs} +2 -2
  91. package/dist/logger/index.mjs +1 -1
  92. package/dist/{mcpPlugin-KWsezMx7.mjs → mcpPlugin-D-3OLxNz.mjs} +75 -31
  93. package/dist/{memory-BiPVaCPg.mjs → memory-CNvjxzB2.mjs} +2 -2
  94. package/dist/{metrics-CsWaIVTa.mjs → metrics-P37sNV5H.mjs} +2 -2
  95. package/dist/middleware/index.d.mts +1 -1
  96. package/dist/middleware/index.mjs +3 -3
  97. package/dist/migrations/index.mjs +2 -2
  98. package/dist/{module-BQXHxMEk.mjs → module-CNcwCKUJ.mjs} +1 -1
  99. package/dist/{multipartBody-u6VrS_iH.mjs → multipartBody-Bl_gU3Wg.mjs} +1 -1
  100. package/dist/{openapi-Dxc8RLy_.mjs → openapi-BYrL8zvY.mjs} +6 -6
  101. package/dist/outbox-admin/index.d.mts +1 -1
  102. package/dist/outbox-admin/index.mjs +4 -4
  103. package/dist/{outbox-module-DyIqA5vo.mjs → outbox-module-6DMC_WNu.mjs} +40 -21
  104. package/dist/{outbox-module-CQXu_O6o.d.mts → outbox-module-CzsKRBvO.d.mts} +11 -2
  105. package/dist/permissions/index.mjs +5 -5
  106. package/dist/{permissions-H7Zcb82Z.mjs → permissions-C0GpDsB_.mjs} +6 -6
  107. package/dist/{pipe-SunhEaZ6.mjs → pipe-4_XamfxI.mjs} +2 -2
  108. package/dist/pipeline/index.d.mts +1 -1
  109. package/dist/pipeline/index.mjs +2 -2
  110. package/dist/plugins/index.d.mts +5 -5
  111. package/dist/plugins/index.mjs +17 -16
  112. package/dist/plugins/response-cache.mjs +2 -2
  113. package/dist/plugins/tracing-entry.mjs +2 -2
  114. package/dist/{pluralize-Da7IT_qJ.mjs → pluralize-BaQ62hOW.mjs} +1 -1
  115. package/dist/{preloadResources-DlhH81py.mjs → preloadResources-BAx5s9EF.mjs} +70 -21
  116. package/dist/{preloadResources-BbBkNkqK.d.mts → preloadResources-DVgPCNcD.d.mts} +7 -7
  117. package/dist/presets/filesUpload.d.mts +1 -1
  118. package/dist/presets/filesUpload.mjs +5 -5
  119. package/dist/presets/index.d.mts +1 -1
  120. package/dist/presets/index.mjs +2 -2
  121. package/dist/presets/multiTenant.d.mts +1 -1
  122. package/dist/presets/multiTenant.mjs +3 -3
  123. package/dist/presets/search.d.mts +1 -1
  124. package/dist/presets/search.mjs +2 -2
  125. package/dist/{presets-CNyfaxGL.mjs → presets-CAaqVVcW.mjs} +4 -4
  126. package/dist/{projection-DSfEoooA.mjs → projection-qbCOEvsh.mjs} +2 -2
  127. package/dist/{queryCachePlugin-oTsmVyEQ.mjs → queryCachePlugin-2Pp9w-8D.mjs} +5 -5
  128. package/dist/rateLimitKey-umrS6-vu.mjs +41 -0
  129. package/dist/{realtime-CPmjjgqd.mjs → realtime-zzoNLDtj.mjs} +9 -9
  130. package/dist/{redis-stream-eh0eOtjh.d.mts → redis-stream-DSsPyYzd.d.mts} +7 -2
  131. package/dist/{registerRoute-XvcI_3sh.mjs → registerRoute-_6zHiz0x.mjs} +6 -6
  132. package/dist/registry/index.d.mts +2 -2
  133. package/dist/registry/index.mjs +3 -3
  134. package/dist/{registry-UFEJQN8R.mjs → registry-CEpoRpLP.mjs} +2 -2
  135. package/dist/{renewingLease-DuRGVOMe.mjs → renewingLease-B5Grm0pI.mjs} +1 -1
  136. package/dist/{replyHelpers-BHebarf0.mjs → replyHelpers-9h-a592u.mjs} +2 -2
  137. package/dist/{requestContext-DpmntRZy.mjs → requestContext-D4PuGhEw.mjs} +1 -1
  138. package/dist/{rolldown-runtime-Add2L50I.mjs → rolldown-runtime-DzE6ikSH.mjs} +1 -1
  139. package/dist/{runtimeCapabilities-D793Pxci.mjs → runtimeCapabilities-Bo7rSKjm.mjs} +1 -1
  140. package/dist/{schedules-DthM8Qag.mjs → schedules-Dm21pqHU.mjs} +8 -4
  141. package/dist/{schemaConverter-Db-MMsH6.mjs → schemaConverter-DENbixyA.mjs} +1 -1
  142. package/dist/{schemaIR-CIXShch7.mjs → schemaIR-C2qUNzC6.mjs} +2 -2
  143. package/dist/schemas/index.mjs +1 -1
  144. package/dist/scim/index.mjs +2 -2
  145. package/dist/scope/index.mjs +5 -5
  146. package/dist/{scope-D03sk17n.mjs → scope-CdYxQVxt.mjs} +4 -4
  147. package/dist/{simpleEqualityMatcher-B7qVjQBv.mjs → simpleEqualityMatcher-Cldubvul.mjs} +1 -1
  148. package/dist/{sse-D4MYqkic.mjs → sse-DbyXoQun.mjs} +5 -5
  149. package/dist/{sseStream-BuMNPR6r.mjs → sseStream-BfZtL5-m.mjs} +2 -2
  150. package/dist/{store-helpers-CIF4RG8s.mjs → store-helpers-BfyOd5i6.mjs} +1 -1
  151. package/dist/{streaming-DkpW1HwJ.mjs → streaming-CFwCzEvU.mjs} +1 -1
  152. package/dist/{subscribe-helpers-CBZOi6pk.mjs → subscribe-helpers-KgVEcn8L.mjs} +2 -2
  153. package/dist/sync/changelog.mjs +1 -1
  154. package/dist/testing/cleanupStoreContract.mjs +1 -1
  155. package/dist/testing/index.d.mts +4 -4
  156. package/dist/testing/index.mjs +10 -10
  157. package/dist/testing/outboxStoreContract.mjs +14 -3
  158. package/dist/testing/storageContract.mjs +1 -1
  159. package/dist/{transactionContext-DMmvcfdo.mjs → transactionContext-46KyUADP.mjs} +1 -1
  160. package/dist/{typeGuards-DHTnEs5X.mjs → typeGuards-t_CVgRXN.mjs} +1 -1
  161. package/dist/types/index.d.mts +1 -1
  162. package/dist/types/index.mjs +1 -1
  163. package/dist/types/storage.mjs +1 -1
  164. package/dist/{types-LQFwC37d.d.mts → types-9rvxn5Ym.d.mts} +46 -1
  165. package/dist/{types-BRU-Kd3t.d.mts → types-BVlowlm7.d.mts} +2 -2
  166. package/dist/{types-BqLyyH0o.mjs → types-CNQyOrLk.mjs} +4 -4
  167. package/dist/usage/index.mjs +0 -0
  168. package/dist/{userHelpers-CXySQFRg.mjs → userHelpers-DLueLQdQ.mjs} +1 -1
  169. package/dist/utils/index.d.mts +4 -4
  170. package/dist/utils/index.mjs +11 -11
  171. package/dist/{utils-BbGG8XNT.mjs → utils-CUFBrhq-.mjs} +14 -6
  172. package/dist/{validate-CidSeUrx.mjs → validate-DV3hRbsz.mjs} +2 -2
  173. package/dist/{versioning-C2r0eOZ4.mjs → versioning-BXwmj5SD.mjs} +3 -3
  174. package/dist/{versioning-B843jOYX.d.mts → versioning-P3V6ATyC.d.mts} +1 -1
  175. package/dist/workScope-CoGpuzDX.mjs +42 -0
  176. package/package.json +48 -39
  177. package/skills/arc/references/mcp.md +20 -0
  178. package/skills/arc/references/testing.md +0 -12
  179. package/skills/arc-code-review/references/anti-patterns.md +1 -1
  180. package/skills/arc-code-review/references/migration-recipes.md +0 -60
  181. package/skills/arc-code-review/references/mongokit-migration.md +0 -27
  182. package/skills/arc-module-publishing/references/package-manifest.md +3 -1
  183. package/dist/rateLimitKey-CewdR-m6.mjs +0 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc",
3
- "version": "2.38.0",
3
+ "version": "2.40.0",
4
4
  "description": "Resource-oriented backend framework for Fastify - clean, minimal, powerful, tree-shakable",
5
5
  "type": "module",
6
6
  "exports": {
@@ -353,20 +353,22 @@
353
353
  "node": ">=22"
354
354
  },
355
355
  "peerDependencies": {
356
- "@classytic/primitives": ">=0.26.4",
357
- "@classytic/repo-core": ">=0.26.0",
356
+ "@classytic/primitives": ">=0.27.0",
357
+ "@classytic/repo-core": ">=0.27.0",
358
358
  "@classytic/streamline": ">=2.8.0",
359
359
  "@fastify/cors": ">=11.0.0",
360
360
  "@fastify/helmet": ">=13.0.0",
361
361
  "@fastify/jwt": ">=10.0.0",
362
- "@fastify/multipart": ">=9.0.0",
363
- "@fastify/rate-limit": ">=10.0.0",
362
+ "@fastify/multipart": ">=10.0.0",
363
+ "@fastify/rate-limit": ">=11.0.0",
364
364
  "@fastify/sensible": ">=6.0.0",
365
- "@fastify/static": ">=8.0.0",
365
+ "@fastify/static": ">=10.0.0",
366
366
  "@fastify/type-provider-typebox": ">=6.0.0",
367
367
  "@fastify/under-pressure": ">=9.0.0",
368
368
  "@fastify/websocket": ">=11.0.0",
369
- "@modelcontextprotocol/sdk": ">=1.28.0",
369
+ "@modelcontextprotocol/client": ">=2.0.0",
370
+ "@modelcontextprotocol/node": ">=2.0.0",
371
+ "@modelcontextprotocol/server": ">=2.0.0",
370
372
  "@opentelemetry/api": ">=1.9.0",
371
373
  "@opentelemetry/auto-instrumentations-node": ">=0.40.0",
372
374
  "@opentelemetry/exporter-trace-otlp-http": ">=0.50.0",
@@ -374,19 +376,18 @@
374
376
  "@opentelemetry/instrumentation-mongodb": ">=0.40.0",
375
377
  "@opentelemetry/sdk-node": ">=0.50.0",
376
378
  "better-auth": ">=1.7.0",
377
- "bullmq": ">=5.0.0",
379
+ "bullmq": ">=6.0.0",
378
380
  "fastify": ">=5.12.0",
379
381
  "fastify-raw-body": ">=5.0.0",
380
382
  "h3-js": ">=4.0.0",
381
- "ioredis": ">=5.0.0",
382
- "jose": ">=5.0.0",
383
+ "ioredis": ">=6.0.0",
384
+ "jose": ">=6.0.0",
383
385
  "pino-pretty": ">=13.0.0",
384
386
  "typebox": ">=1.0.0",
385
- "vitest": ">=3.0.0",
386
387
  "zod": ">=4.4.0"
387
388
  },
388
389
  "peerDependenciesMeta": {
389
- "better-auth": {
390
+ "@classytic/streamline": {
390
391
  "optional": true
391
392
  },
392
393
  "@fastify/cors": {
@@ -398,34 +399,40 @@
398
399
  "@fastify/jwt": {
399
400
  "optional": true
400
401
  },
402
+ "@fastify/multipart": {
403
+ "optional": true
404
+ },
401
405
  "@fastify/rate-limit": {
402
406
  "optional": true
403
407
  },
404
408
  "@fastify/sensible": {
405
409
  "optional": true
406
410
  },
407
- "@fastify/under-pressure": {
411
+ "@fastify/static": {
408
412
  "optional": true
409
413
  },
410
- "@fastify/multipart": {
414
+ "@fastify/type-provider-typebox": {
415
+ "optional": true
416
+ },
417
+ "@fastify/under-pressure": {
411
418
  "optional": true
412
419
  },
413
420
  "@fastify/websocket": {
414
421
  "optional": true
415
422
  },
416
- "fastify-raw-body": {
423
+ "@modelcontextprotocol/client": {
417
424
  "optional": true
418
425
  },
419
- "h3-js": {
426
+ "@modelcontextprotocol/node": {
420
427
  "optional": true
421
428
  },
422
- "pino-pretty": {
429
+ "@modelcontextprotocol/server": {
423
430
  "optional": true
424
431
  },
425
432
  "@opentelemetry/api": {
426
433
  "optional": true
427
434
  },
428
- "@opentelemetry/sdk-node": {
435
+ "@opentelemetry/auto-instrumentations-node": {
429
436
  "optional": true
430
437
  },
431
438
  "@opentelemetry/exporter-trace-otlp-http": {
@@ -437,43 +444,40 @@
437
444
  "@opentelemetry/instrumentation-mongodb": {
438
445
  "optional": true
439
446
  },
440
- "@opentelemetry/auto-instrumentations-node": {
441
- "optional": true
442
- },
443
- "ioredis": {
447
+ "@opentelemetry/sdk-node": {
444
448
  "optional": true
445
449
  },
446
- "jose": {
450
+ "better-auth": {
447
451
  "optional": true
448
452
  },
449
- "typebox": {
453
+ "bullmq": {
450
454
  "optional": true
451
455
  },
452
- "@fastify/type-provider-typebox": {
456
+ "fastify-raw-body": {
453
457
  "optional": true
454
458
  },
455
- "bullmq": {
459
+ "h3-js": {
456
460
  "optional": true
457
461
  },
458
- "@classytic/streamline": {
462
+ "ioredis": {
459
463
  "optional": true
460
464
  },
461
- "zod": {
465
+ "jose": {
462
466
  "optional": true
463
467
  },
464
- "@modelcontextprotocol/sdk": {
468
+ "pino-pretty": {
465
469
  "optional": true
466
470
  },
467
- "@fastify/static": {
471
+ "typebox": {
468
472
  "optional": true
469
473
  },
470
- "vitest": {
474
+ "zod": {
471
475
  "optional": true
472
476
  }
473
477
  },
474
478
  "dependencies": {
475
479
  "fastify-plugin": "^6.0.0",
476
- "qs": "^6.15.2",
480
+ "qs": "^6.16.0",
477
481
  "secure-json-parse": "^4.1.0"
478
482
  },
479
483
  "devDependencies": {
@@ -485,8 +489,8 @@
485
489
  "@classytic/gitkit": ">=0.1.0",
486
490
  "@classytic/mongokit": "^3.33.0",
487
491
  "@classytic/pgkit": "^0.1.0",
488
- "@classytic/primitives": "^0.26.4",
489
- "@classytic/repo-core": "^0.26.0",
492
+ "@classytic/primitives": "^0.27.0",
493
+ "@classytic/repo-core": "^0.27.0",
490
494
  "@classytic/sqlitekit": "^0.9.0",
491
495
  "@classytic/streamline": "^2.8.2",
492
496
  "@electric-sql/pglite": "^0.5.4",
@@ -500,13 +504,15 @@
500
504
  "@fastify/type-provider-typebox": "^6.1.0",
501
505
  "@fastify/under-pressure": "^9.0.3",
502
506
  "@fastify/websocket": "^11.2.0",
503
- "@modelcontextprotocol/sdk": "^1.29.0",
507
+ "@modelcontextprotocol/client": "^2.0.0",
508
+ "@modelcontextprotocol/node": "^2.0.0",
509
+ "@modelcontextprotocol/server": "^2.0.0",
504
510
  "@opentelemetry/api": "^1.9.1",
505
511
  "@types/node": "^22.19.21",
506
512
  "@types/qs": "^6.15.1",
507
- "@vitest/coverage-v8": "^4.1.9",
513
+ "@vitest/coverage-v8": "^5.0.0",
508
514
  "ajv": "^8.20.0",
509
- "better-auth": "^1.7.2",
515
+ "better-auth": "^1.7.3",
510
516
  "better-sqlite3": "^13.0.3",
511
517
  "bullmq": "^6.1.2",
512
518
  "dotenv": "^17.4.2",
@@ -526,7 +532,7 @@
526
532
  "tsdown": "^0.22.14",
527
533
  "typebox": "^1.3.6",
528
534
  "typescript": "^7.0.2",
529
- "vitest": "^4.1.10",
535
+ "vitest": "^5.0.0",
530
536
  "ws": "^8.21.0",
531
537
  "zod": "^4.4.3"
532
538
  },
@@ -560,6 +566,9 @@
560
566
  "url": "git+https://github.com/classytic/arc.git"
561
567
  },
562
568
  "overrides": {
563
- "better-sqlite3": "$better-sqlite3"
569
+ "better-sqlite3": "$better-sqlite3",
570
+ "better-auth": {
571
+ "vitest": "$vitest"
572
+ }
564
573
  }
565
574
  }
@@ -133,6 +133,26 @@ await app.register(mcpPlugin, { resources: catalogResources, prefix: '/mcp/catal
133
133
  await app.register(mcpPlugin, { resources: orderResources, prefix: '/mcp/orders' });
134
134
  ```
135
135
 
136
+ ## DNS-rebinding protection (`Host` / `Origin`)
137
+
138
+ An MCP endpoint on loopback is reachable from any page the developer visits: if
139
+ an attacker-controlled DNS name resolves to `127.0.0.1`, the browser treats the
140
+ reply as same-origin and can read every tool's output. Validating `Host` breaks
141
+ the chain.
142
+
143
+ `dnsRebindingProtection` **defaults on when `auth: false`** (the local shape the
144
+ attack targets) and **off when auth is configured** (a real deployment's `Host`
145
+ is its own domain — defaulting on would 403 it; credentials are the gate there).
146
+
147
+ ```typescript
148
+ mcpPlugin({ resources, auth, dnsRebindingProtection: {} }); // localhost + auth
149
+ mcpPlugin({ resources, dnsRebindingProtection: { allowedHosts: ['mcp.example.com'] } });
150
+ mcpPlugin({ resources, auth: false, dnsRebindingProtection: false }); // deliberately public
151
+ ```
152
+
153
+ An absent `Origin` passes — non-browser MCP clients send none. A present but
154
+ unlisted one is refused. `${prefix}/health` is exempt so probes keep working.
155
+
136
156
  ## Auth — Three Modes
137
157
 
138
158
  Arc doesn't enforce an auth strategy. You choose what fits.
@@ -198,15 +198,3 @@ runStorageContract(async () => {
198
198
  3. **Use `ctx.fixtures.clear()` in `afterEach`** — destroyers handle dependency order.
199
199
  4. **Test permission denials explicitly** — `expectArc(res).forbidden()` beats status-code assertions.
200
200
  5. **Reach for `createHttpTestHarness` first** — 16 tests for one function call.
201
-
202
- ## Migration from pre-2.11 testing APIs
203
-
204
- | Pre-2.11 | 2.11 |
205
- |---|---|
206
- | `TestHarness` / `createTestHarness` | `createHttpTestHarness(resource, ctxFn)` |
207
- | `TestAppResult` | `TestAppContext` |
208
- | `testApp.mongoUri` | `ctx.dbUri` |
209
- | `createJwtAuthProvider` / `createBetterAuthProvider` (as `HttpTestHarness` imports) | `ctx.auth` from `createTestApp` (or direct factory import) |
210
- | `withTestDb()` | `createTestApp({ db: 'in-memory' })` + `ctx.dbUri` |
211
- | `TestDatabase` / `TestSeeder` / `TestTransaction` | `createTestFixtures` + kit-level cleanup |
212
- | `setupBetterAuthOrg` | `setupBetterAuthTestApp` + `helpers.signUpWithOrg` |
@@ -831,7 +831,7 @@ output_mode: content
831
831
 
832
832
  Also: adapter contract types imported from arc — `import type { DataAdapter, AdapterRepositoryInput, AdapterFactory, OpenApiSchemas, SchemaMetadata, FieldMetadata, RelationMetadata, AdapterValidationResult, AdapterSchemaContext } from '@classytic/arc'` (any subpath). And: `mergeFieldRuleConstraints` from `@classytic/arc/adapters`. Any `from '@classytic/arc/adapters'` import — the entire subpath was removed in arc 2.12.
833
833
 
834
- **Why critical:** This only worked in arc ≤ 2.x. Arc 2.12 moved every kit-specific adapter (Mongoose, Drizzle, Prisma) into its kit and the cross-framework adapter contract into `@classytic/repo-core/adapter`. The `@classytic/arc/adapters` subpath was removed entirely. Importing these names from arc fails to resolve on 3.x — the build breaks at install time. The new shape is **strict**: kit-specific things MUST come from the kit; the contract MUST come from repo-core.
834
+ **Why critical:** `@classytic/arc/adapters` does not exist. Kit-specific adapters (Mongoose, Drizzle, Prisma) live in their kit; the cross-framework contract lives in `@classytic/repo-core/adapter`. Importing these names from arc fails to resolve — the build breaks at install time. The rule is **strict**: kit-specific things come from the kit, the contract comes from repo-core.
835
835
 
836
836
  **Fix:**
837
837
  ```typescript
@@ -4,66 +4,6 @@ Concrete diffs for the most common transformations. Apply in the order listed in
4
4
 
5
5
  ---
6
6
 
7
- ## §0. arc 2.x → 3.0 — every kit-specific adapter moves to its kit
8
-
9
- **Why:** Through arc 2.12, kit-specific adapter factories (`createMongooseAdapter`, `createDrizzleAdapter`, `createPrismaAdapter`) shipped from `@classytic/arc` and arc had a peer dep on `@classytic/mongokit`. This coupled arc's release cadence to every kit's, dragged mongoose into every arc consumer's resolution graph (even Drizzle/Prisma users), and double-published the adapter contract types.
10
-
11
- In arc 2.12:
12
- - Adapter contract → `@classytic/repo-core/adapter` (new subpath in repo-core 0.4.0).
13
- - Mongoose adapter → `@classytic/mongokit/adapter` (3.13.0).
14
- - Drizzle adapter → `@classytic/sqlitekit/adapter` (0.3.0).
15
- - Prisma adapter → `@classytic/prismakit/adapter` (0.1.0 — new kit).
16
- - `mergeFieldRuleConstraints` + `applyNullable` → `@classytic/repo-core/schema`.
17
- - `@classytic/mongokit`, `@prisma/client`, `mongoose` all dropped from arc's `peerDependencies`. Arc 2.12 has zero kit- or driver-bound peers.
18
- - The `@classytic/arc/adapters` subpath was removed entirely. The `src/adapters/` directory inside arc is gone.
19
- - `RepositoryLike` is still re-exported from `@classytic/arc` for convenience.
20
- - Custom kits implementing `DataAdapter<TDoc>` plug in identically — same contract, no special-casing.
21
-
22
- ### Coordinated versions
23
-
24
- These are the floors the adapter SPLIT requires — fixed history, safe to rely on:
25
-
26
- | Package | Min (adapter split) |
27
- |---|---|
28
- | `@classytic/arc` | 2.12.0 |
29
- | `@classytic/repo-core` | 0.4.0 |
30
- | `@classytic/mongokit` | 3.13.0 |
31
- | `@classytic/sqlitekit` | 0.3.0 |
32
- | `@classytic/prismakit` | 0.1.0 (not published to npm — build from source) |
33
-
34
- A second "current best-practice floor" column used to sit here and is gone: it named
35
- arc 2.21.0 while arc shipped 2.37, and sqlitekit 0.7.0 against a published 0.9.0. A
36
- version restated in a skill is wrong within a release and teaches nothing (CLAUDE.md,
37
- "no rotting metrics") — worse, it reads as researched. **For current floors read
38
- `peerDependencies` in arc's `package.json` and each kit's own README**; for what a
39
- given arc version added, [CHANGELOG.md](../../../CHANGELOG.md) is the index.
40
-
41
- ### Import migration table
42
-
43
- | Old (arc 2.11.x) | New (arc 2.12+) |
44
- |---|---|
45
- | `import { createMongooseAdapter } from '@classytic/arc'` | `import { createMongooseAdapter } from '@classytic/mongokit/adapter'` |
46
- | `import { createMongooseAdapter } from '@classytic/arc/adapters'` | `import { createMongooseAdapter } from '@classytic/mongokit/adapter'` |
47
- | `import { createDrizzleAdapter } from '@classytic/arc/adapters'` | `import { createDrizzleAdapter } from '@classytic/sqlitekit/adapter'` |
48
- | `import { createPrismaAdapter } from '@classytic/arc/adapters'` | `import { createPrismaAdapter } from '@classytic/prismakit/adapter'` |
49
- | `import type { DataAdapter, RepositoryLike, AdapterRepositoryInput } from '@classytic/arc'` | `import type { DataAdapter, RepositoryLike, AdapterRepositoryInput } from '@classytic/repo-core/adapter'` |
50
- | `import type { ... } from '@classytic/arc/adapters'` (any contract type) | `import type { ... } from '@classytic/repo-core/adapter'` |
51
- | `import type { InferMongooseDoc } from '@classytic/arc/adapters'` | `import type { InferMongooseDoc } from '@classytic/mongokit/adapter'` |
52
- | `import { mergeFieldRuleConstraints } from '@classytic/arc/adapters'` | `import { mergeFieldRuleConstraints } from '@classytic/repo-core/schema'` |
53
- | `MongooseAdapter`, `DrizzleAdapter`, `PrismaAdapter` (classes) | Same path moves: `@classytic/mongokit/adapter` / `@classytic/sqlitekit/adapter` / `@classytic/prismakit/adapter` |
54
- | Any `from '@classytic/arc/adapters'` import | The subpath was removed in arc 2.12 — re-route to the kit or repo-core per the rows above. |
55
-
56
- ### Mechanical steps
57
-
58
- 1. Bump versions in `package.json` to the matrix above. Drop `mongoose` from explicit deps if you only used it for the adapter — mongokit will pull it as its own peer.
59
- 2. Run a project-wide find/replace using the table above. Detection regex: see anti-patterns.md §32g.
60
- 3. `npx tsc --noEmit` — zero errors.
61
- 4. Smoke test the resource OpenAPI endpoint and one MCP tool — confirm the schema is non-empty (still requires `schemaGenerator`).
62
-
63
- No runtime behavior change — the symbols are identical, only their package paths moved.
64
-
65
- ---
66
-
67
7
  ## §1. Manual CRUD module → `defineResource()`
68
8
 
69
9
  **Scope:** typically 5 routes (`GET`, `GET /:id`, `POST`, `PATCH /:id`, `DELETE /:id`) + ~150 LOC of pagination/validation/permission glue per resource.
@@ -347,33 +347,6 @@ If consumers see `as unknown as RepositoryLike<T>` casts when wiring a repo into
347
347
 
348
348
  In the client project, prefer `createMongooseAdapter({ model, repository })` from `@classytic/mongokit/adapter` over manual `RepositoryLike` shaping — it accepts mongokit-native repos with no casts, and since mongokit 3.21 `schemaGenerator` defaults to `buildCrudSchemasFromModel` (`schemaGenerator: false` opts out — see anti-patterns §32f before recommending that).
349
349
 
350
- ## arc 2.12 / mongokit 3.13.0 — adapter split
351
-
352
- Through mongokit 3.12 / arc 2.11, `createMongooseAdapter` shipped from `@classytic/arc`. In mongokit 3.13.0 + arc 2.12, the adapter lives in mongokit at `@classytic/mongokit/adapter`. Coordinated minimums:
353
-
354
- | Package | Min |
355
- |---|---|
356
- | `@classytic/arc` | 2.12.0 |
357
- | `@classytic/mongokit` | 3.13.0 |
358
- | `@classytic/repo-core` | 0.4.0 |
359
-
360
- Migration shape:
361
-
362
- ```typescript
363
- // arc 2.x
364
- import { createMongooseAdapter } from '@classytic/arc';
365
- import type { DataAdapter, RepositoryLike, AdapterRepositoryInput } from '@classytic/arc';
366
- import type { InferMongooseDoc, MongooseAdapterOptions } from '@classytic/arc/adapters';
367
-
368
- // arc 2.12+
369
- import { createMongooseAdapter } from '@classytic/mongokit/adapter';
370
- import type { DataAdapter, RepositoryLike, AdapterRepositoryInput } from '@classytic/repo-core/adapter';
371
- import type { InferMongooseDoc, MongooseAdapterOptions } from '@classytic/mongokit/adapter';
372
- ```
373
-
374
- The kit owns mongoose as its peer dep; arc dropped both `@classytic/mongokit` and `mongoose` from its `peerDependencies`. Hosts depend on `@classytic/mongokit` directly, which transitively pulls mongoose. Detection regex for stragglers: see `references/anti-patterns.md` §32g.
375
-
376
- ---
377
350
 
378
351
  ## What mongokit does NOT do
379
352
 
@@ -46,7 +46,9 @@ optional-peer typing pattern. Values below are the real shapes shipped by
46
46
  },
47
47
 
48
48
  // Optional peers: declared here AND marked optional below. Host installs only if used.
49
- // "peerDependencies": { ..., "zod": ">=3.23.0", "ioredis": ">=5.0.0" },
49
+ // The floor is the major YOUR suite runs — never one below it. A floor you never test
50
+ // is a compatibility claim, not a fact (arc shipped seven of those until 2.40).
51
+ // "peerDependencies": { ..., "zod": ">=4.4.0", "ioredis": ">=6.0.0" },
50
52
  // "peerDependenciesMeta": {
51
53
  // "zod": { "optional": true },
52
54
  // "ioredis": { "optional": true }
@@ -1,15 +0,0 @@
1
- /*! @classytic/arc v2.38.0 | MIT | https://classytic.com */
2
- //#region src/scope/rateLimitKey.ts
3
- function createTenantKeyGenerator(opts) {
4
- if (opts?.strategy) return opts.strategy;
5
- return (ctx) => {
6
- const scope = ctx.scope;
7
- if (!scope || scope.kind === "public") return ctx.ip;
8
- if (scope.kind === "member") return scope.organizationId;
9
- if (scope.kind === "service") return scope.organizationId;
10
- if (scope.kind === "elevated") return scope.organizationId ?? scope.userId ?? ctx.ip;
11
- return scope.userId ?? ctx.ip;
12
- };
13
- }
14
- //#endregion
15
- export { createTenantKeyGenerator as t };