@classytic/arc 2.15.4 → 2.16.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 (160) hide show
  1. package/README.md +1 -0
  2. package/bin/arc.js +12 -0
  3. package/dist/{BaseController-dx3m2J8V.mjs → BaseController-Vk8I7C0x.mjs} +61 -19
  4. package/dist/{HookSystem-Iiebom92.mjs → HookSystem-Cmf7-Etp.mjs} +8 -4
  5. package/dist/{QueryCache-D41bfdBB.d.mts → QueryCache-8YmAQ-zW.d.mts} +1 -1
  6. package/dist/{ResourceRegistry-CTERg_2x.mjs → ResourceRegistry-CzSzVK1m.mjs} +55 -9
  7. package/dist/audit/index.d.mts +1 -1
  8. package/dist/audit/index.mjs +4 -2
  9. package/dist/auth/index.d.mts +4 -4
  10. package/dist/auth/index.mjs +4 -4
  11. package/dist/auth/redis-session.d.mts +1 -1
  12. package/dist/{betterAuthOpenApi--M_i87dQ.mjs → betterAuthOpenApi-ClWxaceA.mjs} +10 -6
  13. package/dist/buildHandler-C_SkBNF3.mjs +302 -0
  14. package/dist/cache/index.d.mts +3 -3
  15. package/dist/cache/index.mjs +3 -3
  16. package/dist/{caching-SM8gghN6.mjs → caching-8MfrrUYU.mjs} +1 -1
  17. package/dist/cli/commands/describe.d.mts +35 -1
  18. package/dist/cli/commands/describe.mjs +52 -12
  19. package/dist/cli/commands/docs.d.mts +1 -4
  20. package/dist/cli/commands/docs.mjs +4 -16
  21. package/dist/cli/commands/generate.d.mts +2 -20
  22. package/dist/cli/commands/generate.mjs +1 -546
  23. package/dist/cli/commands/init.d.mts +2 -40
  24. package/dist/cli/commands/init.mjs +1 -3045
  25. package/dist/cli/commands/introspect.mjs +53 -64
  26. package/dist/cli/index.d.mts +2 -2
  27. package/dist/cli/index.mjs +2 -2
  28. package/dist/{constants-Cxde4rpC.mjs → constants-TrJVIJl0.mjs} +7 -0
  29. package/dist/core/index.d.mts +3 -3
  30. package/dist/core/index.mjs +5 -5
  31. package/dist/{core-CvmOqEms.mjs → core-wKeGXn38.mjs} +222 -44
  32. package/dist/createActionRouter-eiOFtnC3.mjs +288 -0
  33. package/dist/{createAggregationRouter-B0bPDf5b.mjs → createAggregationRouter-C4unhBnV.mjs} +3 -2
  34. package/dist/{createApp-PFegs47-.mjs → createApp-DdPBtmzp.mjs} +16 -14
  35. package/dist/{defineEvent-D5h7EvAx.mjs → defineEvent-NPKUJRt8.mjs} +1 -1
  36. package/dist/docs/index.d.mts +2 -2
  37. package/dist/docs/index.mjs +1 -1
  38. package/dist/{errorHandler-Bk-AGhkU.mjs → errorHandler-DNPzqaTT.mjs} +17 -14
  39. package/dist/errors-4ZloYFvm.d.mts +91 -0
  40. package/dist/{eventPlugin-CaKTYkYM.mjs → eventPlugin-CnJCUyM0.mjs} +1 -1
  41. package/dist/{eventPlugin-qXpqTebY.d.mts → eventPlugin-DjEx_J3j.d.mts} +1 -1
  42. package/dist/events/index.d.mts +3 -3
  43. package/dist/events/index.mjs +5 -5
  44. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  45. package/dist/events/transports/redis.d.mts +1 -1
  46. package/dist/factory/index.d.mts +2 -2
  47. package/dist/factory/index.mjs +4 -3
  48. package/dist/fastify-augmentation-CJm0vh-l.d.mts +42 -0
  49. package/dist/{fields-COhcH3fk.d.mts → fields-DqZLp5d6.d.mts} +1 -1
  50. package/dist/generate-CcM24hoq.mjs +654 -0
  51. package/dist/generate-cRnsafMS.d.mts +38 -0
  52. package/dist/hooks/index.d.mts +1 -1
  53. package/dist/hooks/index.mjs +1 -1
  54. package/dist/idempotency/index.d.mts +2 -2
  55. package/dist/idempotency/index.mjs +1 -1
  56. package/dist/idempotency/redis.d.mts +1 -1
  57. package/dist/{index-BTqLEvhu.d.mts → index-3L-adFJO.d.mts} +12 -12
  58. package/dist/{index-BstGxcc3.d.mts → index-CC_pgZjY.d.mts} +88 -17
  59. package/dist/{index-BswOSJCE.d.mts → index-DBDgy6Hw.d.mts} +430 -19
  60. package/dist/index.d.mts +6 -6
  61. package/dist/index.mjs +7 -8
  62. package/dist/init-D-vrTZ1G.d.mts +71 -0
  63. package/dist/init-DYzfniuX.mjs +3098 -0
  64. package/dist/integrations/event-gateway.d.mts +2 -2
  65. package/dist/integrations/event-gateway.mjs +1 -1
  66. package/dist/integrations/index.d.mts +2 -2
  67. package/dist/integrations/jobs.mjs +3 -3
  68. package/dist/integrations/mcp/index.d.mts +239 -7
  69. package/dist/integrations/mcp/index.mjs +2 -528
  70. package/dist/integrations/mcp/testing.d.mts +2 -2
  71. package/dist/integrations/mcp/testing.mjs +6 -10
  72. package/dist/integrations/streamline.mjs +26 -1
  73. package/dist/integrations/websocket-redis.d.mts +1 -1
  74. package/dist/integrations/websocket.d.mts +1 -1
  75. package/dist/integrations/websocket.mjs +1 -0
  76. package/dist/loadResourcesFromEntry-DCjYMgfC.mjs +51 -0
  77. package/dist/{resourceToTools-tFYUNmM0.mjs → mcpPlugin-Dbgz9_Rj.mjs} +1021 -318
  78. package/dist/{memory-UBydS5ku.mjs → memory-QOLe11D5.mjs} +2 -0
  79. package/dist/middleware/index.d.mts +1 -1
  80. package/dist/middleware/index.mjs +1 -1
  81. package/dist/{openapi-BHXhoX8O.mjs → openapi-BRnd3pT7.mjs} +82 -44
  82. package/dist/permissions/index.d.mts +2 -2
  83. package/dist/permissions/index.mjs +1 -1
  84. package/dist/{permissions-ohQyv50e.mjs → permissions-CTxMrreC.mjs} +2 -2
  85. package/dist/{pipe-Zr0KXjQe.mjs → pipe-DiCyvyPN.mjs} +1 -0
  86. package/dist/pipeline/index.d.mts +1 -1
  87. package/dist/pipeline/index.mjs +1 -1
  88. package/dist/plugins/index.d.mts +5 -59
  89. package/dist/plugins/index.mjs +10 -10
  90. package/dist/plugins/response-cache.mjs +5 -5
  91. package/dist/plugins/tracing-entry.d.mts +1 -1
  92. package/dist/plugins/tracing-entry.mjs +1 -1
  93. package/dist/{pluralize-DQgqgifU.mjs → pluralize-B9M8xvy-.mjs} +2 -1
  94. package/dist/preloadResources-BOXzPhKU.mjs +45 -0
  95. package/dist/presets/filesUpload.d.mts +4 -4
  96. package/dist/presets/filesUpload.mjs +2 -2
  97. package/dist/presets/index.d.mts +1 -1
  98. package/dist/presets/index.mjs +1 -1
  99. package/dist/presets/multiTenant.d.mts +1 -1
  100. package/dist/presets/multiTenant.mjs +4 -3
  101. package/dist/presets/search.d.mts +2 -2
  102. package/dist/presets/search.mjs +1 -1
  103. package/dist/{presets-BbkjdPeH.mjs → presets-C9BE6WaZ.mjs} +2 -2
  104. package/dist/{queryCachePlugin-m1XsgAIJ.mjs → queryCachePlugin-B4XMSSe7.mjs} +2 -2
  105. package/dist/{queryCachePlugin-CqMdLI2-.d.mts → queryCachePlugin-Do4P_WBC.d.mts} +2 -2
  106. package/dist/{redis-DiMkdHEl.d.mts → redis-cpqVb85w.d.mts} +1 -1
  107. package/dist/{redis-stream-D6HzR1Z_.d.mts → redis-stream-BuiAS3aE.d.mts} +1 -1
  108. package/dist/registry/index.d.mts +341 -2
  109. package/dist/registry/index.mjs +3 -3
  110. package/dist/registry-BrlHkrRS.mjs +582 -0
  111. package/dist/{routerShared-DrOa-26E.mjs → routerShared-ClV4cCaa.mjs} +40 -16
  112. package/dist/scope/index.d.mts +3 -3
  113. package/dist/scope/index.mjs +3 -3
  114. package/dist/{sse-Bz-5ZeTt.mjs → sse-jh5OqFjR.mjs} +1 -1
  115. package/dist/testing/index.d.mts +2 -25
  116. package/dist/testing/index.mjs +17 -51
  117. package/dist/testing/storageContract.d.mts +1 -1
  118. package/dist/types/index.d.mts +5 -5
  119. package/dist/types/storage.d.mts +1 -1
  120. package/dist/{types-BQsjgQzS.d.mts → types-BD0BCdf6.d.mts} +106 -12
  121. package/dist/{types-C_s5moIu.mjs → types-Bi0r0vjG.mjs} +53 -1
  122. package/dist/{types-CTYvcwHe.d.mts → types-CfapW2t8.d.mts} +42 -1
  123. package/dist/{types-DrBaUwyV.d.mts → types-Dw--SyTq.d.mts} +57 -11
  124. package/dist/utils/index.d.mts +1287 -2
  125. package/dist/utils/index.mjs +1 -1
  126. package/dist/{utils-_h9B3c57.mjs → utils-DPXZnZUx.mjs} +158 -41
  127. package/dist/{buildHandler-CcFOpJLh.mjs → validate-DFIP2VrM.mjs} +73 -302
  128. package/dist/{versioning-hmkPcDlX.d.mts → versioning-5H4930tj.d.mts} +1 -1
  129. package/package.json +22 -29
  130. package/skills/arc/SKILL.md +300 -706
  131. package/skills/arc/references/auth.md +19 -7
  132. package/skills/arc-code-review/SKILL.md +1 -1
  133. package/skills/arc-code-review/references/arc-cheatsheet.md +100 -322
  134. package/dist/createActionRouter-S3MLVYot.mjs +0 -220
  135. package/dist/index-bRjYu21O.d.mts +0 -1320
  136. package/dist/org/index.d.mts +0 -66
  137. package/dist/org/index.mjs +0 -486
  138. package/dist/org/types.d.mts +0 -82
  139. package/dist/org/types.mjs +0 -1
  140. package/dist/registry-I-ogLgL9.mjs +0 -46
  141. /package/dist/{EventTransport-CT_52aWU.d.mts → EventTransport-B1GFiYUy.d.mts} +0 -0
  142. /package/dist/{EventTransport-DLWoUMHy.mjs → EventTransport-ClEDfiMS.mjs} +0 -0
  143. /package/dist/{actionPermissions-CyUkQu6O.mjs → actionPermissions-Bjmvn7Eb.mjs} +0 -0
  144. /package/dist/{elevation-DgoeTyfX.mjs → elevation-Dci0AYLT.mjs} +0 -0
  145. /package/dist/{elevation-BXOWoGCF.d.mts → elevation-DvwtjDwu.d.mts} +0 -0
  146. /package/dist/{errorHandler-DFr45ZG4.d.mts → errorHandler-DuqTqeqn.d.mts} +0 -0
  147. /package/dist/{externalPaths-BD5nw6St.d.mts → externalPaths-ClykOQqa.d.mts} +0 -0
  148. /package/dist/{interface-beEtJyWM.d.mts → interface-BVkZsvEe.d.mts} +0 -0
  149. /package/dist/{interface-DfLGcus7.d.mts → interface-DoE6UoC2.d.mts} +0 -0
  150. /package/dist/{keys-CGcCbNyu.mjs → keys-DopsCuyQ.mjs} +0 -0
  151. /package/dist/{loadResources-DBMQg_Aj.mjs → loadResources-fol6JuvW.mjs} +0 -0
  152. /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-B-PU4-Yu.mjs} +0 -0
  153. /package/dist/{replyHelpers-CK-FNO8E.mjs → replyHelpers-boS5Rx26.mjs} +0 -0
  154. /package/dist/{schemaIR-lYhC2gE5.mjs → schemaIR-DAOvBWgT.mjs} +0 -0
  155. /package/dist/{sessionManager-C4Le_UB3.d.mts → sessionManager-DlmaHUAl.d.mts} +0 -0
  156. /package/dist/{storage-Dfzt4VTl.d.mts → storage-HcAgP5Ni.d.mts} +0 -0
  157. /package/dist/{store-helpers-BkIN9-vu.mjs → store-helpers-5JgaxieH.mjs} +0 -0
  158. /package/dist/{tracing-QJVprktp.d.mts → tracing-bRqqUxFO.d.mts} +0 -0
  159. /package/dist/{versioning-BUrT5aP4.mjs → versioning-CuIwUQZ2.mjs} +0 -0
  160. /package/dist/{websocket-ChC2rqe1.d.mts → websocket-BJ0w-3Dt.d.mts} +0 -0
@@ -1,5 +1,5 @@
1
- import { r as CacheStore } from "./interface-beEtJyWM.mjs";
2
- import { i as QueryCache } from "./QueryCache-D41bfdBB.mjs";
1
+ import { r as CacheStore } from "./interface-BVkZsvEe.mjs";
2
+ import { i as QueryCache } from "./QueryCache-8YmAQ-zW.mjs";
3
3
  import { FastifyPluginAsync } from "fastify";
4
4
 
5
5
  //#region src/cache/queryCachePlugin.d.ts
@@ -1,4 +1,4 @@
1
- import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-DfLGcus7.mjs";
1
+ import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-DoE6UoC2.mjs";
2
2
 
3
3
  //#region src/idempotency/stores/redis.d.ts
4
4
  interface RedisClient {
@@ -1,4 +1,4 @@
1
- import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-CT_52aWU.mjs";
1
+ import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-B1GFiYUy.mjs";
2
2
 
3
3
  //#region src/events/transports/redis-stream.d.ts
4
4
  interface RedisStreamLike {
@@ -1,8 +1,347 @@
1
- import { R as RegisterOptions, k as IntrospectionPluginOptions, z as ResourceRegistry } from "../index-BswOSJCE.mjs";
1
+ import { J as CrudRouteKey, R as RegisterOptions, V as ResourceDefinition, at as ResolvedTenantPurge, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-DBDgy6Hw.mjs";
2
2
  import { FastifyPluginAsync } from "fastify";
3
+ import { TenantPurgeProgress, TenantPurgeStrategy } from "@classytic/repo-core/repository";
3
4
 
5
+ //#region src/registry/assertNoTenantData.d.ts
6
+ interface AssertNoTenantDataOptions {
7
+ readonly organizationId: string;
8
+ /**
9
+ * Limit the check to a subset of resources. Default: every cascading
10
+ * resource (matches the cascade runner's filter).
11
+ */
12
+ readonly only?: readonly string[];
13
+ /**
14
+ * Skip resources whose strategy is `anonymize` (the rows legitimately
15
+ * remain). Default `true` — the smoke test focuses on "did data leave?"
16
+ * not "did anonymize keep rows?". Set `false` for a full pass.
17
+ */
18
+ readonly skipAnonymize?: boolean;
19
+ }
20
+ interface TenantDataLeak {
21
+ readonly resource: string;
22
+ readonly tenantField: string;
23
+ /**
24
+ * Full `TenantPurgeStrategy` discriminated union — not just `.type`.
25
+ * `anonymize` carries the field map; `custom` carries the handler
26
+ * descriptor; auditors get the actionable signal without re-resolving
27
+ * the resource definition. Narrow on `.strategy.type` for typed
28
+ * access.
29
+ */
30
+ readonly strategy: TenantPurgeStrategy;
31
+ readonly expected: number;
32
+ readonly actual: number;
33
+ readonly reason?: string;
34
+ }
35
+ interface AssertNoTenantDataReport {
36
+ readonly ok: boolean;
37
+ readonly organizationId: string;
38
+ readonly checked: number;
39
+ readonly skipped: readonly {
40
+ resource: string;
41
+ reason: string;
42
+ }[];
43
+ readonly leaks: readonly TenantDataLeak[];
44
+ }
45
+ /**
46
+ * Walk every cascading resource, run a tenant-scoped count, compare
47
+ * against the strategy's expected outcome.
48
+ *
49
+ * Designed for use inside compliance tests:
50
+ *
51
+ * ```ts
52
+ * import { assertNoTenantData } from '@classytic/arc/registry';
53
+ *
54
+ * it('after org delete, no tenant data leaks', async () => {
55
+ * await cascadeDeleteForOrganization(arc.registry, { organizationId: 'test-org' });
56
+ * const report = await assertNoTenantData(arc.registry, { organizationId: 'test-org' });
57
+ * expect(report.ok).toBe(true);
58
+ * expect(report.leaks).toHaveLength(0);
59
+ * });
60
+ * ```
61
+ */
62
+ declare function assertNoTenantData(registry: ResourceRegistry, options: AssertNoTenantDataOptions): Promise<AssertNoTenantDataReport>;
63
+ //#endregion
64
+ //#region src/registry/purgeResource.d.ts
65
+ /**
66
+ * Outcome for one resource. Wider than `TenantPurgeResult` because it
67
+ * carries the resource name + tenantField for the aggregate report,
68
+ * and a `path` discriminator so audit consumers can tell which code
69
+ * path ran.
70
+ */
71
+ interface PurgeResourceOutcome {
72
+ readonly resource: string;
73
+ readonly tenantField: string;
74
+ /**
75
+ * Full `TenantPurgeStrategy` discriminated union. Audit consumers
76
+ * narrow on `.strategy.type` for typed access — `skip` carries the
77
+ * mandatory `reason`, `anonymize` carries the field map, `custom`
78
+ * carries the handler descriptor. Pre-2.17 this was the `.type` tag
79
+ * only, which dropped the audit-critical `reason` field.
80
+ */
81
+ readonly strategy: TenantPurgeStrategy;
82
+ readonly processed: number;
83
+ readonly ok: boolean;
84
+ readonly path: "purgeByField" | "legacy-deleteMany" | "skipped" | "unsupported";
85
+ readonly skipReason?: string;
86
+ readonly error?: {
87
+ code?: string;
88
+ message: string;
89
+ };
90
+ readonly durationMs?: number;
91
+ }
92
+ //#endregion
93
+ //#region src/registry/cascadeOrgDelete.d.ts
94
+ /**
95
+ * Per-resource result row. One entry for every resource Arc attempted to
96
+ * cascade-delete for the given org. `deletedCount: -1` means the adapter
97
+ * doesn't surface a row count (the delete still ran).
98
+ */
99
+ interface CascadeResourceReport {
100
+ readonly resource: string;
101
+ readonly tenantField: string;
102
+ /**
103
+ * Rows processed. For `hard` strategy this equals rows that no longer
104
+ * exist; for `soft`/`anonymize` it's rows touched (still present).
105
+ * `-1` only on legacy `deleteMany` adapters that don't surface a count.
106
+ */
107
+ readonly deletedCount: number;
108
+ /**
109
+ * Full `TenantPurgeStrategy` that ran for this resource. Branch on
110
+ * `.strategy.type` (`'hard'` / `'soft'` / `'anonymize'` / `'skip'` /
111
+ * `'custom'`) to answer "did data physically leave the system?". The
112
+ * `skip` variant carries the mandatory `reason`; `anonymize` carries
113
+ * the field map; `custom` carries the handler descriptor.
114
+ */
115
+ readonly strategy?: TenantPurgeStrategy;
116
+ /**
117
+ * Where the strategy came from — `'declared'` (host wrote
118
+ * `onTenantDelete`) or `'disabled'` (filtered out before reaching
119
+ * this report). Future sources may be added; treat the field as a
120
+ * read-only audit signal.
121
+ */
122
+ readonly strategySource?: ResolvedTenantPurge["source"];
123
+ /**
124
+ * Code path that executed — `'purgeByField'` (preferred, chunked),
125
+ * `'legacy-deleteMany'` (single-shot fallback for old adapters),
126
+ * `'skipped'` (skip strategy), `'unsupported'` (adapter can't run
127
+ * the declared strategy — surfaces in `failures`).
128
+ */
129
+ readonly path?: PurgeResourceOutcome["path"];
130
+ /** Echoed for `skip` strategy — the declared reason. */
131
+ readonly skipReason?: string;
132
+ readonly error?: {
133
+ code?: string;
134
+ message: string;
135
+ };
136
+ }
137
+ /** Aggregate report — splits successful and failed resources for the caller. */
138
+ interface CascadeReport {
139
+ readonly organizationId: string;
140
+ readonly resources: readonly CascadeResourceReport[];
141
+ readonly successes: readonly CascadeResourceReport[];
142
+ readonly failures: readonly CascadeResourceReport[];
143
+ readonly totalDeleted: number;
144
+ readonly durationMs: number;
145
+ }
146
+ /** Lightweight logger shape — `fastify.log`, `pino`, or `console` all fit. */
147
+ interface CascadeLogger {
148
+ info?: (obj: unknown, msg?: string) => void;
149
+ warn?: (obj: unknown, msg?: string) => void;
150
+ error?: (obj: unknown, msg?: string) => void;
151
+ }
152
+ interface CascadeOptions {
153
+ /** Organization id whose tenant-scoped rows should be deleted. */
154
+ readonly organizationId: string;
155
+ /**
156
+ * Skip these resources even if they declare `onTenantDelete`.
157
+ * Useful for stage-gated rollouts ("cascade everything except `audit_log`
158
+ * — we want to keep the trail").
159
+ */
160
+ readonly skip?: readonly string[];
161
+ /**
162
+ * Resource names to LIMIT cascade to. When set, only these resources
163
+ * cascade — useful for partial-cleanup scripts and the test path that
164
+ * verifies one resource at a time.
165
+ */
166
+ readonly only?: readonly string[];
167
+ /** Optional logger — info on each resource, warn/error on failures. */
168
+ readonly logger?: CascadeLogger;
169
+ /**
170
+ * Forwarded to each resource's `purgeByField` — emits per-chunk
171
+ * progress. The event includes the resource name so a single
172
+ * progress handler can drive a multi-resource progress UI.
173
+ */
174
+ readonly onProgress?: (event: TenantPurgeProgress & {
175
+ resource: string;
176
+ }) => void | Promise<void>;
177
+ /**
178
+ * Forwarded to each resource's `purgeByField`. The runner checks
179
+ * between resources too — aborting mid-cascade stops the next
180
+ * resource from starting, in addition to stopping the currently-
181
+ * running purge between chunks.
182
+ */
183
+ readonly signal?: AbortSignal;
184
+ /**
185
+ * Global override for per-resource batchSize. Per-resource declarations
186
+ * (`onTenantDelete.batchSize`) win when set; this is the fallback.
187
+ */
188
+ readonly batchSize?: number;
189
+ /**
190
+ * Run up to `concurrency` resources in parallel. **Priority groups
191
+ * remain barriers** — all priority-10 resources finish before any
192
+ * priority-50 resource starts. Within a priority, resources run
193
+ * concurrently up to this cap. Default `1` (sequential, safest).
194
+ *
195
+ * Resources are independent (different collections / tables, no
196
+ * cross-resource constraints), so parallelism is safe — but oplog
197
+ * pressure / connection-pool exhaustion / replication lag scale with
198
+ * concurrency. Tune per environment; `4` is usually fine for cloud
199
+ * Mongo + small connection pools, `8`–`16` for high-throughput tiers.
200
+ */
201
+ readonly concurrency?: number;
202
+ /**
203
+ * Cascade-level checkpoint — survive a crash mid-cascade and resume
204
+ * from the last completed resource. `read()` returns the last cascade
205
+ * state (or `undefined` for a fresh run); `write()` persists state
206
+ * after each resource completes. Hosts plumb to Redis / a status
207
+ * table / a dedicated checkpoint store.
208
+ *
209
+ * Per-purge checkpointing is intentionally NOT offered — the chunked
210
+ * primitive is already idempotent (re-running a partially-completed
211
+ * cascade is safe because already-deleted rows don't match the next
212
+ * SELECT). The cascade-level checkpoint just skips entire resources
213
+ * known-completed in the prior pass — wasteful round-trips, not
214
+ * wasteful writes.
215
+ */
216
+ readonly checkpoint?: CascadeCheckpoint;
217
+ }
218
+ /** Cascade resume state. Persist between runs; rehydrate on retry. */
219
+ interface CascadeCheckpointState {
220
+ /** Names of resources fully completed in a prior pass. Skipped on resume. */
221
+ readonly completedResources: readonly string[];
222
+ }
223
+ interface CascadeCheckpoint {
224
+ /** Load the prior cascade state for this org. Return `undefined` for a fresh run. */
225
+ read(): Promise<CascadeCheckpointState | undefined>;
226
+ /** Persist updated state after a resource finishes. */
227
+ write(state: CascadeCheckpointState): Promise<void>;
228
+ }
229
+ /**
230
+ * Names of resources flagged for cascade — used by audit scripts.
231
+ * A resource is cascading when its resolved strategy isn't `disabled`
232
+ * (i.e. the host declared `onTenantDelete`).
233
+ */
234
+ declare function getCascadingResources(registry: ResourceRegistry): readonly string[];
235
+ /**
236
+ * Rich introspection — returns the resolved strategy + source per
237
+ * cascading resource. Use for audit dashboards that answer "what
238
+ * happens to this resource on org-delete?" without grepping the
239
+ * source.
240
+ *
241
+ * **Returns the full `TenantPurgeStrategy` discriminated union**, not
242
+ * just its `type` tag. The `skip` variant carries a required `reason`
243
+ * field — auditors need it to sign off on every "we deliberately don't
244
+ * purge this" entry. Anonymize carries the field map. Custom carries
245
+ * the handler reference. Narrow on `.strategy.type` for typed access.
246
+ */
247
+ declare function getCascadingResourcesWithMetadata(registry: ResourceRegistry): readonly {
248
+ name: string;
249
+ tenantField: string;
250
+ strategy: TenantPurgeStrategy;
251
+ source: ResolvedTenantPurge["source"];
252
+ priority: number;
253
+ }[];
254
+ /**
255
+ * Cascade-cleanup every tenant-scoped resource for the given organization.
256
+ * Walks the registry in **ascending priority order** (`onTenantDelete.priority`
257
+ * — leaf data first, references last), runs each resource's resolved
258
+ * strategy via `purgeByField` when available (chunked, progress, abort),
259
+ * and returns a structured report.
260
+ *
261
+ * **Strategy resolution** lives in `resolveTenantPurge.ts` — this runner
262
+ * just reads `resource.resolvedTenantPurge` (computed once at boot).
263
+ *
264
+ * **Per-resource execution** lives in `purgeResource.ts` — preferred
265
+ * path is the kit's `purgeByField` (chunked + plugin-composed); falls
266
+ * back to legacy `deleteMany` only for `hard` strategy on adapters that
267
+ * haven't been upgraded.
268
+ *
269
+ * **Failure semantics**: continues on per-resource error, returns the
270
+ * full report. Hosts decide whether a partial cascade is a hard
271
+ * failure (re-throw) or degraded mode (log + alert).
272
+ *
273
+ * @param registry The arc resource registry (`fastify.arc.registry`).
274
+ * @param options Org id + filters + logger + progress + signal.
275
+ */
276
+ declare function cascadeDeleteForOrganization(registry: ResourceRegistry, options: CascadeOptions): Promise<CascadeReport>;
277
+ //#endregion
4
278
  //#region src/registry/introspectionPlugin.d.ts
5
279
  declare const introspectionPlugin: FastifyPluginAsync<IntrospectionPluginOptions>;
6
280
  declare const _default: FastifyPluginAsync<IntrospectionPluginOptions>;
7
281
  //#endregion
8
- export { type IntrospectionPluginOptions, type RegisterOptions, ResourceRegistry, _default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
282
+ //#region src/registry/manifest.d.ts
283
+ /** Mount-point string the FE uses to derive the URL for an action call. */
284
+ type ActionMount = "/:id/action" | "/action";
285
+ /**
286
+ * One action entry in a resource manifest. `requiresId` is the boolean
287
+ * the FE checks to decide whether its helper takes `(id, body)` or just
288
+ * `(body)`; `mount` is the URL suffix to append to the resource prefix.
289
+ */
290
+ interface ActionManifestEntry {
291
+ readonly name: string;
292
+ readonly mount: ActionMount;
293
+ readonly requiresId: boolean;
294
+ readonly description?: string;
295
+ }
296
+ /** Aggregation entry — one per `defineAggregation()` declaration. */
297
+ interface AggregationManifestEntry {
298
+ readonly name: string;
299
+ readonly path: string;
300
+ readonly summary?: string;
301
+ readonly description?: string;
302
+ }
303
+ /** Custom (non-CRUD, non-action) route entry. */
304
+ interface CustomRouteManifestEntry {
305
+ readonly method: string;
306
+ readonly path: string;
307
+ readonly operation?: string;
308
+ readonly summary?: string;
309
+ }
310
+ /**
311
+ * Single resource manifest. Everything an FE codegen needs to wire a
312
+ * typed client over the resource's HTTP surface.
313
+ */
314
+ interface ResourceManifest {
315
+ readonly name: string;
316
+ readonly displayName: string;
317
+ readonly prefix: string;
318
+ readonly idField: string;
319
+ /** Update method used for `/:id` PATCH / PUT routes. */
320
+ readonly updateMethod: "PUT" | "PATCH" | "both";
321
+ /** Enabled CRUD operations — filtered by `disabledRoutes` and `disableDefaultRoutes`. */
322
+ readonly crudOps: readonly CrudRouteKey[];
323
+ readonly actions: readonly ActionManifestEntry[];
324
+ readonly aggregations: readonly AggregationManifestEntry[];
325
+ readonly customRoutes: readonly CustomRouteManifestEntry[];
326
+ /** Tenant scoping field (when set) — surfaces for FE callers that need to send `x-organization-id`. */
327
+ readonly tenantField?: string | false;
328
+ }
329
+ /**
330
+ * Build a manifest from a `ResourceDefinition` (the value returned by
331
+ * `defineResource(...)`). Use at build time when you have direct access
332
+ * to the resource module — typically the simplest codegen path.
333
+ */
334
+ declare function buildResourceManifest(resource: ResourceDefinition): ResourceManifest;
335
+ /**
336
+ * Build a manifest from a `RegistryEntry` — use when the resource is
337
+ * already registered (introspection endpoint, runtime audit script).
338
+ *
339
+ * Equivalent to {@link buildResourceManifest} but reads from the projected
340
+ * registry shape, so a host that doesn't have the original `defineResource`
341
+ * value in scope (e.g. an FE-gen sidecar that scrapes a running server's
342
+ * `/_resources` endpoint) gets the same output without dragging the resource
343
+ * module into the codegen path.
344
+ */
345
+ declare function buildResourceManifestFromRegistry(entry: RegistryEntry): ResourceManifest;
346
+ //#endregion
347
+ export { type ActionManifestEntry, type ActionMount, type AggregationManifestEntry, type AssertNoTenantDataOptions, type AssertNoTenantDataReport, type CascadeCheckpoint, type CascadeCheckpointState, type CascadeOptions, type CascadeReport, type CascadeResourceReport, type CustomRouteManifestEntry, type IntrospectionPluginOptions, type RegisterOptions, type ResourceManifest, ResourceRegistry, type TenantDataLeak, assertNoTenantData, buildResourceManifest, buildResourceManifestFromRegistry, cascadeDeleteForOrganization, getCascadingResources, getCascadingResourcesWithMetadata, _default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
@@ -1,3 +1,3 @@
1
- import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-I-ogLgL9.mjs";
2
- import { t as ResourceRegistry } from "../ResourceRegistry-CTERg_2x.mjs";
3
- export { ResourceRegistry, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
1
+ import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-BrlHkrRS.mjs";
2
+ import { t as ResourceRegistry } from "../ResourceRegistry-CzSzVK1m.mjs";
3
+ export { ResourceRegistry, assertNoTenantData, buildResourceManifest, buildResourceManifestFromRegistry, cascadeDeleteForOrganization, getCascadingResources, getCascadingResourcesWithMetadata, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };