@classytic/arc 2.11.4 → 2.13.1

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 (166) hide show
  1. package/README.md +16 -12
  2. package/dist/{BaseController-swXruJ2_.mjs → BaseController-DX_T-bDB.mjs} +388 -423
  3. package/dist/EventTransport-CT_52aWU.d.mts +34 -0
  4. package/dist/EventTransport-DLWoUMHy.mjs +103 -0
  5. package/dist/{ResourceRegistry-DkAeAuTX.mjs → ResourceRegistry-CTERg_2x.mjs} +139 -66
  6. package/dist/audit/index.d.mts +2 -2
  7. package/dist/audit/index.mjs +1 -1
  8. package/dist/auth/audit.d.mts +199 -0
  9. package/dist/auth/audit.mjs +288 -0
  10. package/dist/auth/index.d.mts +3 -3
  11. package/dist/auth/index.mjs +117 -191
  12. package/dist/{betterAuthOpenApi-DwxtK3uG.mjs → betterAuthOpenApi--M_i87dQ.mjs} +1 -1
  13. package/dist/buildHandler-olo-gt94.mjs +610 -0
  14. package/dist/cache/index.mjs +3 -3
  15. package/dist/cli/commands/describe.d.mts +89 -13
  16. package/dist/cli/commands/describe.mjs +56 -2
  17. package/dist/cli/commands/docs.mjs +2 -2
  18. package/dist/cli/commands/generate.mjs +147 -48
  19. package/dist/cli/commands/init.d.mts +13 -0
  20. package/dist/cli/commands/init.mjs +130 -87
  21. package/dist/cli/commands/introspect.mjs +8 -1
  22. package/dist/context/index.mjs +1 -1
  23. package/dist/core/index.d.mts +3 -3
  24. package/dist/core/index.mjs +5 -5
  25. package/dist/core-D72ia0EH.mjs +1399 -0
  26. package/dist/{createActionRouter-CIKOcNA7.mjs → createActionRouter-CEvzKcy8.mjs} +7 -20
  27. package/dist/createAggregationRouter-CyecOxnO.mjs +114 -0
  28. package/dist/{createApp-C9bRrqlX.mjs → createApp-XX2-N0Yd.mjs} +28 -22
  29. package/dist/{defineEvent-D1Ky9M1D.mjs → defineEvent-D5h7EvAx.mjs} +1 -1
  30. package/dist/docs/index.d.mts +1 -1
  31. package/dist/docs/index.mjs +2 -2
  32. package/dist/{elevation-DOFoxoDs.mjs → elevation-DgoeTyfX.mjs} +1 -1
  33. package/dist/errorHandler-Bk-AGhkU.mjs +174 -0
  34. package/dist/errorHandler-DFr45ZG4.d.mts +45 -0
  35. package/dist/errors-j4aJm1Wg.mjs +184 -0
  36. package/dist/{eventPlugin-Cts2-Tfj.mjs → eventPlugin-CaKTYkYM.mjs} +28 -4
  37. package/dist/{eventPlugin-DDJoNEPL.d.mts → eventPlugin-qXpqTebY.d.mts} +24 -1
  38. package/dist/events/index.d.mts +6 -6
  39. package/dist/events/index.mjs +11 -35
  40. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  41. package/dist/events/transports/redis.d.mts +1 -1
  42. package/dist/factory/index.d.mts +2 -2
  43. package/dist/factory/index.mjs +2 -2
  44. package/dist/{fields-BRjxOAFp.d.mts → fields-COhcH3fk.d.mts} +23 -2
  45. package/dist/hooks/index.d.mts +1 -1
  46. package/dist/hooks/index.mjs +1 -1
  47. package/dist/idempotency/index.d.mts +1 -1
  48. package/dist/idempotency/index.mjs +1 -20
  49. package/dist/idempotency/redis.mjs +1 -1
  50. package/dist/{index-rHjXmJar.d.mts → index-BTqLEvhu.d.mts} +163 -3
  51. package/dist/{index-CXXRbnf8.d.mts → index-BtW7qYwa.d.mts} +660 -326
  52. package/dist/{index-m8mOOlFW.d.mts → index-Ds61mrJE.d.mts} +50 -4
  53. package/dist/{index-D9t1KNaB.d.mts → index-Dz5IKsrE.d.mts} +360 -219
  54. package/dist/index.d.mts +6 -7
  55. package/dist/index.mjs +9 -10
  56. package/dist/integrations/event-gateway.d.mts +1 -1
  57. package/dist/integrations/event-gateway.mjs +1 -1
  58. package/dist/integrations/index.d.mts +1 -1
  59. package/dist/integrations/mcp/index.d.mts +2 -2
  60. package/dist/integrations/mcp/index.mjs +1 -1
  61. package/dist/integrations/mcp/testing.d.mts +1 -1
  62. package/dist/integrations/mcp/testing.mjs +1 -1
  63. package/dist/integrations/streamline.d.mts +60 -11
  64. package/dist/integrations/streamline.mjs +75 -85
  65. package/dist/integrations/websocket.mjs +2 -8
  66. package/dist/middleware/index.d.mts +1 -1
  67. package/dist/middleware/index.mjs +2 -2
  68. package/dist/migrations/index.d.mts +23 -3
  69. package/dist/migrations/index.mjs +0 -7
  70. package/dist/{multipartBody-CvTR1Un6.mjs → multipartBody-BOvVSVCD.mjs} +11 -8
  71. package/dist/{openapi-D7G1V7ex.mjs → openapi-CiOMVW1p.mjs} +143 -13
  72. package/dist/org/index.d.mts +2 -2
  73. package/dist/org/index.mjs +1 -1
  74. package/dist/permissions/index.d.mts +3 -3
  75. package/dist/permissions/index.mjs +3 -3
  76. package/dist/{permissions-gd_aUWrR.mjs → permissions-ohQyv50e.mjs} +404 -176
  77. package/dist/{pipe-DVoIheVC.mjs → pipe-Zr0KXjQe.mjs} +1 -1
  78. package/dist/pipeline/index.d.mts +1 -1
  79. package/dist/pipeline/index.mjs +1 -1
  80. package/dist/plugins/index.d.mts +16 -31
  81. package/dist/plugins/index.mjs +33 -13
  82. package/dist/plugins/response-cache.mjs +1 -1
  83. package/dist/plugins/tracing-entry.mjs +1 -1
  84. package/dist/presets/filesUpload.d.mts +4 -4
  85. package/dist/presets/filesUpload.mjs +6 -9
  86. package/dist/presets/index.d.mts +1 -1
  87. package/dist/presets/index.mjs +1 -1
  88. package/dist/presets/multiTenant.d.mts +1 -1
  89. package/dist/presets/multiTenant.mjs +2 -2
  90. package/dist/presets/search.d.mts +2 -2
  91. package/dist/presets/search.mjs +6 -8
  92. package/dist/{presets-Z7P5w4gF.mjs → presets-BbkjdPeH.mjs} +6 -28
  93. package/dist/{queryCachePlugin-Bq6bO6vc.mjs → queryCachePlugin-m1XsgAIJ.mjs} +3 -3
  94. package/dist/{redis-stream-xTGxB2bm.d.mts → redis-stream-D6HzR1Z_.d.mts} +1 -1
  95. package/dist/registry/index.d.mts +1 -1
  96. package/dist/registry/index.mjs +2 -2
  97. package/dist/{replyHelpers-ByllIXXV.mjs → replyHelpers-CK-FNO8E.mjs} +3 -21
  98. package/dist/{resourceToTools-CxNmI6xF.mjs → resourceToTools-C5coh64w.mjs} +224 -71
  99. package/dist/{routerShared-BqLRb5l7.mjs → routerShared-D6_fEGHh.mjs} +40 -36
  100. package/dist/{schemaIR-Dy2p4MxS.mjs → schemaIR-7Vl611Qs.mjs} +1 -1
  101. package/dist/schemas/index.d.mts +100 -30
  102. package/dist/schemas/index.mjs +86 -29
  103. package/dist/scim/index.d.mts +264 -0
  104. package/dist/scim/index.mjs +963 -0
  105. package/dist/scope/index.d.mts +3 -3
  106. package/dist/scope/index.mjs +4 -4
  107. package/dist/{sse-V7aXc3bW.mjs → sse-Bz-5ZeTt.mjs} +1 -1
  108. package/dist/{store-helpers-Cp4uKC1U.mjs → store-helpers-BkIN9-vu.mjs} +1 -1
  109. package/dist/testing/index.d.mts +2 -8
  110. package/dist/testing/index.mjs +16 -24
  111. package/dist/types/index.d.mts +4 -4
  112. package/dist/{types-D7KpfiL1.d.mts → types-BvqwCCSx.d.mts} +73 -25
  113. package/dist/{types-DDyTPc6y.d.mts → types-CTYvcwHe.d.mts} +195 -1
  114. package/dist/{types-AOD8fxIw.mjs → types-C_s5moIu.mjs} +117 -1
  115. package/dist/{types-BQ9TJQNy.d.mts → types-DQHFc8PM.d.mts} +1 -1
  116. package/dist/utils/index.d.mts +2 -2
  117. package/dist/utils/index.mjs +5 -5
  118. package/dist/{utils-CcYTj09l.mjs → utils-_h9B3c57.mjs} +1269 -1334
  119. package/dist/{versioning-DsglKfM_.d.mts → versioning-DTTvc80y.d.mts} +1 -1
  120. package/package.json +24 -34
  121. package/skills/arc/SKILL.md +147 -51
  122. package/skills/arc/references/agent-auth.md +238 -0
  123. package/skills/arc/references/api-reference.md +187 -0
  124. package/skills/arc/references/auth.md +354 -7
  125. package/skills/arc/references/enterprise-auth.md +94 -0
  126. package/skills/arc/references/events.md +8 -6
  127. package/skills/arc/references/mcp.md +2 -2
  128. package/skills/arc/references/multi-tenancy.md +11 -2
  129. package/skills/arc/references/production.md +10 -9
  130. package/skills/arc/references/scim.md +247 -0
  131. package/skills/arc/references/testing.md +1 -1
  132. package/skills/arc-code-review/SKILL.md +141 -0
  133. package/skills/arc-code-review/references/anti-patterns.md +911 -0
  134. package/skills/arc-code-review/references/arc-cheatsheet.md +380 -0
  135. package/skills/arc-code-review/references/migration-recipes.md +700 -0
  136. package/skills/arc-code-review/references/mongokit-migration.md +386 -0
  137. package/skills/arc-code-review/references/scaffolding.md +230 -0
  138. package/skills/arc-code-review/references/severity.md +127 -0
  139. package/dist/EventTransport-BFQjw9pB.mjs +0 -133
  140. package/dist/EventTransport-CYNUXdCJ.d.mts +0 -293
  141. package/dist/adapters/index.d.mts +0 -3
  142. package/dist/adapters/index.mjs +0 -2
  143. package/dist/adapters-DUUiiimH.mjs +0 -964
  144. package/dist/auth/mongoose.d.mts +0 -191
  145. package/dist/auth/mongoose.mjs +0 -73
  146. package/dist/core-CbcQRIch.mjs +0 -1054
  147. package/dist/errorHandler-BQm8ZxTK.mjs +0 -173
  148. package/dist/errorHandler-DEWmGWPz.d.mts +0 -114
  149. package/dist/errors-D5c-5BJL.mjs +0 -232
  150. package/dist/index-Rg8axYPz.d.mts +0 -370
  151. /package/dist/{HookSystem-CGsMd6oK.mjs → HookSystem-Iiebom92.mjs} +0 -0
  152. /package/dist/{actionPermissions-sUUKDhtP.mjs → actionPermissions-CyUkQu6O.mjs} +0 -0
  153. /package/dist/{caching-CheW3m-S.mjs → caching-SM8gghN6.mjs} +0 -0
  154. /package/dist/{constants-BhY1OHoH.mjs → constants-Cxde4rpC.mjs} +0 -0
  155. /package/dist/{elevation-BQQXZ_VR.d.mts → elevation-BXOWoGCF.d.mts} +0 -0
  156. /package/dist/{keys-CARyUjiR.mjs → keys-CGcCbNyu.mjs} +0 -0
  157. /package/dist/{loadResources-CPpkyKfM.mjs → loadResources-DBMQg_Aj.mjs} +0 -0
  158. /package/dist/{memory-DikHSvWa.mjs → memory-UBydS5ku.mjs} +0 -0
  159. /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
  160. /package/dist/{pluralize-CWP6MB39.mjs → pluralize-DQgqgifU.mjs} +0 -0
  161. /package/dist/{registry-D63ee7fl.mjs → registry-I-ogLgL9.mjs} +0 -0
  162. /package/dist/{requestContext-C5XeK3VA.mjs → requestContext-SSaaTgW8.mjs} +0 -0
  163. /package/dist/{schemaConverter-B0oKLuqI.mjs → schemaConverter-De34B1ZG.mjs} +0 -0
  164. /package/dist/{typeGuards-CcFZXgU7.mjs → typeGuards-BzkXkvVv.mjs} +0 -0
  165. /package/dist/{types-DV9WDfeg.mjs → types-D57iXYb8.mjs} +0 -0
  166. /package/dist/{versioning-CGPjkqAg.mjs → versioning-BUrT5aP4.mjs} +0 -0
@@ -0,0 +1,238 @@
1
+ # Agent Auth — DPoP + Capability Mandates
2
+
3
+ The 2025 stack for AI-agent-led actions on protected resources: **OAuth 2.1** (RFC 9700), **DPoP** (RFC 9449), **OAuth Protected Resource Metadata** (RFC 9728), **AP2** (Google + Anthropic + Stripe Agent Payments Protocol), **Stripe x402 / Agentic Commerce**, **MCP authorization**.
4
+
5
+ Arc 2.13 adds three permission helpers and two scope fields to model these patterns cleanly. **Arc doesn't parse JWTs or verify DPoP proofs** — that's a 1-2 line `jose` call in your authenticate function. Arc validates *what's already proved* against the action being attempted.
6
+
7
+ ## The two new scope fields
8
+
9
+ `RequestScope.service` gains two optional fields (additive, no breaking change):
10
+
11
+ ```typescript
12
+ {
13
+ kind: 'service',
14
+ clientId,
15
+ organizationId,
16
+ scopes,
17
+ // ── new in 2.13 ──
18
+ mandate?: Mandate, // capability mandate (AP2 / x402 / MCP)
19
+ dpopJkt?: string, // DPoP key thumbprint (RFC 7638)
20
+ // existing fields preserved
21
+ }
22
+ ```
23
+
24
+ The `Mandate` type:
25
+
26
+ ```typescript
27
+ interface Mandate {
28
+ id: string; // jti
29
+ capability: string; // 'payment.charge' / 'data.export' / 'inbox.send'
30
+ cap?: number; // numeric ceiling
31
+ currency?: string; // ISO 4217 when monetary
32
+ expiresAt?: number; // epoch ms
33
+ parent?: string; // delegation chain
34
+ audience?: string; // 'invoice:INV-7' — resource binding
35
+ meta?: Record<string, unknown>; // verifier-supplied extras
36
+ }
37
+ ```
38
+
39
+ Read with `getMandate(scope)` / `getDPoPJkt(scope)` from `@classytic/arc/scope`.
40
+
41
+ ## Permission helpers
42
+
43
+ Three new combinators in `@classytic/arc/permissions`:
44
+
45
+ ### `requireDPoP()` — sender-constrained credentials
46
+
47
+ The inbound credential must be DPoP-bound. Arc reads `scope.dpopJkt`; your authenticate function performs `jose.dpop.verify()` and sets the field.
48
+
49
+ ```typescript
50
+ import { requireDPoP } from "@classytic/arc/permissions";
51
+
52
+ permissions: {
53
+ charge: allOf(requireServiceScope("payment.write"), requireDPoP()),
54
+ }
55
+ ```
56
+
57
+ Pass behavior: service scope with `dpopJkt` set → grant. Elevated → grant. Anything else → deny.
58
+
59
+ ### `requireMandate(capability, opts?)` — capability-scoped authorization
60
+
61
+ The presented mandate must:
62
+ 1. Authorize the requested `capability`
63
+ 2. Not be expired (with optional grace window)
64
+ 3. Be bound to the right resource (when `audience` opt is set)
65
+ 4. Pass `validateAmount(ctx, mandate)` (when set)
66
+
67
+ ```typescript
68
+ import { requireMandate } from "@classytic/arc/permissions";
69
+
70
+ permissions: {
71
+ pay: requireMandate("payment.charge", {
72
+ audience: (ctx) => `invoice:${ctx.params?.id}`,
73
+ validateAmount: (ctx, mandate) => {
74
+ const amount = (ctx.data as { amount?: number })?.amount ?? 0;
75
+ if (amount <= (mandate.cap ?? 0)) return true;
76
+ return `Amount ${amount} exceeds mandate cap ${mandate.cap}`;
77
+ },
78
+ ttlGraceMs: 30_000, // default: 30s clock skew
79
+ noElevatedBypass: false, // platform admins normally bypass; set true for break-glass audit flows
80
+ }),
81
+ }
82
+ ```
83
+
84
+ ### `requireAgentScope(opts)` — composite gate
85
+
86
+ Bundles the three things every high-value agent endpoint needs (service identity + capability mandate + DPoP binding) into one call:
87
+
88
+ ```typescript
89
+ import { requireAgentScope } from "@classytic/arc/permissions";
90
+
91
+ defineResource({
92
+ name: "invoice",
93
+ actions: {
94
+ pay: {
95
+ handler: payInvoice,
96
+ permissions: requireAgentScope({
97
+ capability: "payment.charge",
98
+ scopes: ["payment.write"], // OAuth `scopes` the client must hold
99
+ requireDPoP: true, // default true
100
+ audience: (ctx) => `invoice:${ctx.params?.id}`,
101
+ validateAmount: (ctx, m) => (ctx.data as { amount: number }).amount <= (m.cap ?? 0),
102
+ }),
103
+ },
104
+ },
105
+ });
106
+ ```
107
+
108
+ Use this instead of hand-composing `allOf(requireServiceScope(...), requireMandate(...), requireDPoP())` — fewer ways to misconfigure, one metadata tag downstream tools (audit, MCP, OpenAPI) can read.
109
+
110
+ ## Wiring — the authenticate callback
111
+
112
+ Arc takes no position on which credential format you use. Whatever your verifier produces — JWT, JWT-VC mandate, opaque API key with metadata sidecar — populates `RequestScope.service`:
113
+
114
+ ```typescript
115
+ import { jwtVerify, createRemoteJWKSet } from "jose";
116
+
117
+ const JWKS = createRemoteJWKSet(new URL("https://idp.example.com/.well-known/jwks.json"));
118
+
119
+ await createApp({
120
+ auth: {
121
+ type: "authenticator",
122
+ authenticate: async (request) => {
123
+ const auth = request.headers.authorization?.split(" ");
124
+ if (auth?.[0] !== "Mandate") return null;
125
+
126
+ // 1. Verify the mandate JWT (signature, iss, aud, exp)
127
+ const { payload } = await jwtVerify(auth[1], JWKS, {
128
+ issuer: "https://idp.example.com",
129
+ audience: "https://api.example.com",
130
+ });
131
+
132
+ // 2. Verify the DPoP proof header (RFC 9449)
133
+ // — pseudocode; use jose.dpop.verify() in production
134
+ const dpopJkt = await verifyDPoPProof(request, payload.cnf?.jkt);
135
+ if (!dpopJkt) return null;
136
+
137
+ // 3. Populate scope with mandate + DPoP fingerprint
138
+ request.scope = {
139
+ kind: "service",
140
+ clientId: payload.iss as string,
141
+ organizationId: (payload.org as string) ?? "",
142
+ scopes: ((payload.scope as string) ?? "").split(" ").filter(Boolean),
143
+ mandate: {
144
+ id: payload.jti as string,
145
+ capability: payload.cap as string,
146
+ cap: payload.amount as number | undefined,
147
+ currency: payload.currency as string | undefined,
148
+ expiresAt: (payload.exp as number) * 1000,
149
+ audience: payload.aud as string | undefined,
150
+ parent: payload.parent as string | undefined,
151
+ },
152
+ dpopJkt,
153
+ };
154
+
155
+ return { id: payload.iss as string };
156
+ },
157
+ },
158
+ });
159
+ ```
160
+
161
+ ## Mandate flow — typical AP2 / x402 sequence
162
+
163
+ ```
164
+ ┌──────────────┐
165
+ user grants │ │
166
+ "charge up to │ Customer │
167
+ $50 on inv 7" │ │
168
+ └──────┬───────┘
169
+
170
+ ┌─────────▼──────────┐
171
+ │ Issues mandate │
172
+ │ - cap: 50 USD │
173
+ │ - audience: │
174
+ │ "invoice:INV-7" │
175
+ │ - exp: now + 60s │
176
+ │ - cnf.jkt: agent │
177
+ └─────────┬──────────┘
178
+
179
+
180
+ ┌──────────────────────┐
181
+ │ AI Agent │
182
+ │ signs + presents │
183
+ │ mandate via DPoP │
184
+ └──────────┬───────────┘
185
+
186
+
187
+ ┌──────────────────────┐
188
+ │ Arc app │
189
+ │ authenticate fn: │
190
+ │ - verify mandate │
191
+ │ - verify DPoP │
192
+ │ - set scope.mandate │
193
+ │ + scope.dpopJkt │
194
+ └──────────┬───────────┘
195
+
196
+
197
+ ┌──────────────────────┐
198
+ │ requireAgentScope: │
199
+ │ - cap satisfied? │
200
+ │ - audience match? │
201
+ │ - DPoP bound? │
202
+ │ - not expired? │
203
+ └──────────┬───────────┘
204
+
205
+ ✓ allow / ✗ deny
206
+ ```
207
+
208
+ ## Audit — every gated action gets a row
209
+
210
+ Pair with `@classytic/arc/auth/audit` to record every agent action through the canonical `auditPlugin` store. Mandate id, audience, cap, dpopJkt all flow into `metadata` on the audit row — full forensic chain.
211
+
212
+ ```typescript
213
+ auditPlugin({
214
+ actor: (request) =>
215
+ request.scope?.kind === "service"
216
+ ? {
217
+ kind: "service",
218
+ clientId: getClientId(request.scope),
219
+ mandateId: getMandate(request.scope)?.id,
220
+ dpopJkt: getDPoPJkt(request.scope),
221
+ }
222
+ : { kind: "user", userId: getUserId(request.scope) },
223
+ });
224
+ ```
225
+
226
+ ## What's NOT in arc (deliberate)
227
+
228
+ - **DPoP proof verification** — one `jose.dpop.verify()` call in your authenticate function. Arc would have to peer-dep `jose`; the host already has it.
229
+ - **JWT-VC mandate parser** — host's verifier (your IdP / AP2 issuer / custom).
230
+ - **Mandate issuance** — that's the IdP's job (or your token endpoint when you mint per-action mandates).
231
+ - **Risk scoring / device trust** — out of framework scope. Layer Castle / Stytch / Auth0 Risk separately.
232
+
233
+ ## See also
234
+
235
+ - [enterprise-auth.md](enterprise-auth.md) — full enterprise-auth surface
236
+ - [scim.md](scim.md) — IdP provisioning (the user-creation path agents authenticate against)
237
+ - [auth.md](auth.md) — Better Auth + service identity setup
238
+ - [`playground/enterprise-auth/`](../../../playground/enterprise-auth/) — runnable smoke
@@ -0,0 +1,187 @@
1
+ # Subpath Imports — Full Enumeration
2
+
3
+ Arc ships heavily tree-shaken: every feature has its own subpath. Pay only for what you import.
4
+
5
+ ## Core
6
+
7
+ ```typescript
8
+ import { defineResource, BaseController, BaseCrudController, allowPublic } from '@classytic/arc';
9
+ import { createApp, loadResources } from '@classytic/arc/factory';
10
+ ```
11
+
12
+ ## Adapters (kit-owned, never arc)
13
+
14
+ ```typescript
15
+ import { createMongooseAdapter } from '@classytic/mongokit/adapter';
16
+ import { createDrizzleAdapter } from '@classytic/sqlitekit/adapter';
17
+ import { createPrismaAdapter } from '@classytic/prismakit/adapter';
18
+
19
+ import type {
20
+ DataAdapter,
21
+ RepositoryLike,
22
+ AdapterRepositoryInput,
23
+ AdapterFactory,
24
+ OpenApiSchemas,
25
+ SchemaMetadata,
26
+ FieldMetadata,
27
+ RelationMetadata,
28
+ } from '@classytic/repo-core/adapter';
29
+ import { asRepositoryLike, isRepository } from '@classytic/repo-core/adapter';
30
+ ```
31
+
32
+ `MinimalRepo` / `StandardRepo` import directly from `@classytic/repo-core/repository`.
33
+
34
+ ## Auth
35
+
36
+ ```typescript
37
+ import { createBetterAuthAdapter, extractBetterAuthOpenApi } from '@classytic/arc/auth';
38
+
39
+ // Kit-owned BA overlays:
40
+ import { createBetterAuthOverlay, registerBetterAuthStubs } from '@classytic/mongokit/better-auth';
41
+ import { resolveBetterAuthCollections, BA_COLLECTIONS_BY_PLUGIN } from '@classytic/repo-core/better-auth';
42
+ ```
43
+
44
+ ## Permissions + scope
45
+
46
+ ```typescript
47
+ import {
48
+ allowPublic, requireAuth, requireRoles, requireOwnership,
49
+ requireOrgMembership, requireOrgRole, requireTeamMembership,
50
+ requireServiceScope, requireScopeContext, requireOrgInScope,
51
+ // Agent-auth (2.13) — DPoP + capability mandates (AP2 / x402 / MCP)
52
+ requireAgentScope, requireMandate, requireDPoP,
53
+ type RequireAgentScopeOptions, type RequireMandateOptions,
54
+ allOf, anyOf, when, denyAll,
55
+ createDynamicPermissionMatrix, createRoleHierarchy,
56
+ fields, roles,
57
+ } from '@classytic/arc/permissions';
58
+
59
+ import {
60
+ isMember, isService, isElevated, isAuthenticated, hasOrgAccess,
61
+ getUserId, getUserRoles, getOrgId, getOrgRoles, getTeamId, getClientId,
62
+ getServiceScopes, getScopeContext, getScopeContextMap,
63
+ getAncestorOrgIds, isOrgInScope, getRequestScope,
64
+ // Agent-auth scope accessors (2.13)
65
+ getMandate, getDPoPJkt, type Mandate,
66
+ requireUserId, requireClientId, // throw 401 (UnauthorizedError) if absent
67
+ requireOrgId, requireTeamId, // throw 403 (OrgRequiredError) if absent
68
+ createTenantKeyGenerator,
69
+ } from '@classytic/arc/scope';
70
+ ```
71
+
72
+ ## Cache
73
+
74
+ ```typescript
75
+ // HOST-LEVEL cache (action results, custom routes — NOT repo-bound paths)
76
+ import { MemoryCacheStore, RedisCacheStore, QueryCache } from '@classytic/arc/cache';
77
+
78
+ // REPO-BOUND cache (canonical) — getById/getAll/aggregate/count/etc
79
+ // Install once on the kit's repo; arc forwards declarative `cache:`
80
+ // config to req.cache automatically.
81
+ import { cachePlugin, type CacheOptions } from '@classytic/repo-core/cache';
82
+ // Per-call shape (TanStack-shaped):
83
+ // { staleTime, gcTime, swr, tags, bypass, enabled, key }
84
+ ```
85
+
86
+ ## Events
87
+
88
+ ```typescript
89
+ import { eventPlugin, EventOutbox, MemoryOutboxStore } from '@classytic/arc/events';
90
+ import { RedisEventTransport } from '@classytic/arc/events/redis';
91
+ import { RedisStreamEventTransport } from '@classytic/arc/events/redis-stream';
92
+
93
+ // Event types live in primitives, NOT arc:
94
+ import type { EventMeta, DomainEvent, EventTransport, EventHandler } from '@classytic/primitives/events';
95
+ import { createEvent, createChildEvent, matchEventPattern } from '@classytic/primitives/events';
96
+ ```
97
+
98
+ ## Plugins
99
+
100
+ ```typescript
101
+ import {
102
+ healthPlugin, gracefulShutdownPlugin, ssePlugin,
103
+ metricsPlugin, versioningPlugin,
104
+ } from '@classytic/arc/plugins';
105
+ import { tracingPlugin } from '@classytic/arc/plugins/tracing';
106
+ import { auditPlugin } from '@classytic/arc/audit';
107
+ import { idempotencyPlugin } from '@classytic/arc/idempotency';
108
+ ```
109
+
110
+ ## Integrations
111
+
112
+ ```typescript
113
+ import { jobsPlugin } from '@classytic/arc/integrations/jobs';
114
+ import { websocketPlugin } from '@classytic/arc/integrations/websocket';
115
+ import { eventGatewayPlugin } from '@classytic/arc/integrations/event-gateway';
116
+ import { webhookPlugin } from '@classytic/arc/integrations/webhooks';
117
+ import { mcpPlugin, defineTool, definePrompt, fieldRulesToZod, resourceToTools } from '@classytic/arc/mcp';
118
+ ```
119
+
120
+ ## Enterprise auth (2.13)
121
+
122
+ ```typescript
123
+ // SCIM 2.0 — IdP provisioning
124
+ import {
125
+ scimPlugin,
126
+ type ScimPluginOptions,
127
+ type ScimResourceMapping,
128
+ parseScimFilter, parseScimPatch,
129
+ DEFAULT_USER_MAPPING, DEFAULT_GROUP_MAPPING,
130
+ SCIM_USER_SCHEMA, SCIM_GROUP_SCHEMA,
131
+ ScimError,
132
+ } from '@classytic/arc/scim';
133
+
134
+ // Better Auth → arc audit bridge
135
+ import {
136
+ wireBetterAuthAudit,
137
+ type AuthEvent, type AuthEventName,
138
+ type WireBetterAuthAuditOptions,
139
+ } from '@classytic/arc/auth/audit';
140
+ ```
141
+
142
+ ## Hooks + presets
143
+
144
+ ```typescript
145
+ import { createHookSystem, beforeCreate, afterCreate, beforeUpdate, afterUpdate } from '@classytic/arc/hooks';
146
+ import {
147
+ bulkPreset, softDeletePreset, slugLookupPreset, treePreset,
148
+ ownedByUserPreset, multiTenantPreset, auditedPreset, searchPreset,
149
+ filesUploadPreset,
150
+ type TenantFieldSpec,
151
+ } from '@classytic/arc/presets';
152
+ ```
153
+
154
+ ## Testing
155
+
156
+ ```typescript
157
+ import {
158
+ createTestApp, expectArc, createHttpTestHarness,
159
+ TestAuthSession, TestAuthProvider, TestFixtures,
160
+ runStorageContract,
161
+ } from '@classytic/arc/testing';
162
+ ```
163
+
164
+ ## Utilities
165
+
166
+ ```typescript
167
+ import {
168
+ createStateMachine, CircuitBreaker, withCompensation, defineGuard,
169
+ retry, queryParser,
170
+ } from '@classytic/arc/utils';
171
+ import { defineMigration, MigrationRunner } from '@classytic/arc/migrations';
172
+ import { Type, ArcListResponse } from '@classytic/arc/schemas';
173
+ ```
174
+
175
+ ## Type-only barrel
176
+
177
+ ```typescript
178
+ // Type-only — produces `export {}` at runtime; this is correct
179
+ import type { ArcRequest, IRequestContext, IControllerResponse } from '@classytic/arc/types';
180
+ ```
181
+
182
+ ## Notes
183
+
184
+ - **No default exports** outside Fastify plugin entry files (`auditPlugin`, `authPlugin`, `eventPlugin`, `idempotencyPlugin`, `introspectionPlugin`).
185
+ - **Type-only subpaths** produce `export {}` at runtime — interfaces are erased.
186
+ - **Adapters live in kits**, not arc. Arc 2.12+ ships zero kit-bound adapters.
187
+ - **Event types live in `@classytic/primitives/events`**, not `@classytic/arc/events`. Arc re-exports the runtime `MemoryEventTransport` only.