@classytic/arc 2.34.0 → 2.36.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 (182) hide show
  1. package/dist/{BaseController-CbkuhNI2.mjs → BaseController-CTJKm6Cb.mjs} +95 -14
  2. package/dist/{EventTransport-tq4CEB-q.mjs → EventTransport-D23Uvhg4.mjs} +1 -1
  3. package/dist/{HookSystem-DqXkMXkB.mjs → HookSystem-DgwxNZTx.mjs} +6 -4
  4. package/dist/{ResourceRegistry-DoALUlOO.mjs → ResourceRegistry-DNuYVbmv.mjs} +2 -2
  5. package/dist/{pipeline-q69DZzgG.mjs → actionPermissions-D97DniUQ.mjs} +30 -7
  6. package/dist/audit/index.d.mts +2 -2
  7. package/dist/audit/index.mjs +2 -2
  8. package/dist/auth/audit.mjs +1 -1
  9. package/dist/auth/index.d.mts +2 -2
  10. package/dist/auth/index.mjs +6 -6
  11. package/dist/auth/redis-session.mjs +1 -1
  12. package/dist/{authorizationDecision-CMMLWmuZ.mjs → authorizationDecision-EsiY3nUu.mjs} +2 -2
  13. package/dist/{base-Csjc2oF-.d.mts → base-C-NL2fTi.d.mts} +16 -1
  14. package/dist/{buildHandler-BrdYrG_1.mjs → buildHandler-Dohd2JuY.mjs} +4 -4
  15. package/dist/cache/index.mjs +4 -4
  16. package/dist/{caching-BcGmvnHh.mjs → caching-CP3GLJ7U.mjs} +2 -2
  17. package/dist/cleanup/index.d.mts +2 -2
  18. package/dist/cleanup/index.mjs +4 -4
  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-BxCoxmiN.mjs → constants-DUoKAGYD.mjs} +1 -1
  28. package/dist/context/index.d.mts +16 -1
  29. package/dist/context/index.mjs +64 -4
  30. package/dist/core/index.d.mts +2 -2
  31. package/dist/core/index.mjs +7 -8
  32. package/dist/{core-BYKa8wHu.mjs → core-DTXsiNTJ.mjs} +3 -3
  33. package/dist/{createActionRouter-D6T0jWhS.mjs → createActionRouter-CZz6JO93.mjs} +27 -64
  34. package/dist/{createAggregationRouter-QLV2PrWP.mjs → createAggregationRouter-DKrGv_EC.mjs} +7 -7
  35. package/dist/defineAggregation-CpQfcM8R.mjs +25 -0
  36. package/dist/{defineResource-ZhuLonLm.mjs → defineResource-DWzjyxb2.mjs} +62 -66
  37. package/dist/discovery/index.mjs +1 -1
  38. package/dist/docs/index.d.mts +1 -1
  39. package/dist/docs/index.mjs +3 -3
  40. package/dist/{elevation-B0tlY8y1.mjs → elevation-D_cmo80j.mjs} +4 -4
  41. package/dist/encryption/index.mjs +3 -3
  42. package/dist/{errorHandler-C7xBqHsI.mjs → errorHandler-2RT0hLSI.mjs} +3 -3
  43. package/dist/{errors-Cd_yy7aW.mjs → errors-DDKni6Tz.mjs} +1 -1
  44. package/dist/{eventPlugin-DSNEZWfV.d.mts → eventPlugin-B47sfCJ8.d.mts} +1 -1
  45. package/dist/{eventPlugin-Dar8qRaj.mjs → eventPlugin-c3YwGzz9.mjs} +5 -5
  46. package/dist/events/index.d.mts +2 -2
  47. package/dist/events/index.mjs +5 -5
  48. package/dist/events/transports/redis-stream-entry.mjs +1 -1
  49. package/dist/events/transports/redis.mjs +1 -1
  50. package/dist/factory/index.d.mts +5 -5
  51. package/dist/factory/index.mjs +5 -6
  52. package/dist/{fastify-augmentation-DVsTAy6X.d.mts → fastify-augmentation-Bk_9PoiV.d.mts} +3 -3
  53. package/dist/{fields-CojeUkS4.mjs → fields-DdP225wt.mjs} +1 -1
  54. package/dist/{generate-DiB0nHPR.mjs → generate-B1bKdcV9.mjs} +2 -2
  55. package/dist/{headers-CveNO9gR.mjs → headers-DKslnhey.mjs} +2 -2
  56. package/dist/{health-CasG2A28.mjs → health-k6NODS8f.mjs} +1 -1
  57. package/dist/hooks/index.d.mts +1 -1
  58. package/dist/hooks/index.mjs +2 -2
  59. package/dist/idempotency/index.mjs +22 -56
  60. package/dist/idempotency/redis.mjs +1 -1
  61. package/dist/{index-B-DvUzsr.d.mts → index-BtYoMip1.d.mts} +21 -3
  62. package/dist/{index-BcR2bFZQ.d.mts → index-C01wWGJt.d.mts} +33 -105
  63. package/dist/{index-C5NnMEKF.d.mts → index-C50BUxKs.d.mts} +1 -1
  64. package/dist/{index-CFAJEWCX.d.mts → index-RdpLP71b.d.mts} +7 -30
  65. package/dist/{index-ugr1tQlW.d.mts → index-eyg5WEcy.d.mts} +1 -1
  66. package/dist/index.d.mts +5 -5
  67. package/dist/index.mjs +11 -12
  68. package/dist/{init-mdJ-v4Xp.mjs → init-LuGxIbQ_.mjs} +1 -1
  69. package/dist/integrations/event-gateway.mjs +2 -2
  70. package/dist/integrations/index.d.mts +2 -2
  71. package/dist/integrations/index.mjs +1 -1
  72. package/dist/integrations/jobs/index.d.mts +1 -1
  73. package/dist/integrations/jobs/index.mjs +2 -2
  74. package/dist/integrations/mcp/index.d.mts +4 -4
  75. package/dist/integrations/mcp/index.mjs +2 -2
  76. package/dist/integrations/mcp/testing.d.mts +1 -1
  77. package/dist/integrations/mcp/testing.mjs +3 -3
  78. package/dist/integrations/streamline.mjs +3 -3
  79. package/dist/integrations/webhooks.d.mts +4 -2
  80. package/dist/integrations/webhooks.mjs +28 -27
  81. package/dist/integrations/websocket-pushref-redis.mjs +1 -1
  82. package/dist/integrations/websocket-redis.mjs +1 -1
  83. package/dist/integrations/websocket.mjs +1 -1
  84. package/dist/{interface-DznJrm9R.mjs → interface-B7awDx3b.mjs} +1 -1
  85. package/dist/{jsonBody-CfGH-GxO.mjs → jsonBody-CiHih3ZU.mjs} +2 -2
  86. package/dist/{keys-WeKvY1dE.mjs → keys-BcNl12HN.mjs} +1 -1
  87. package/dist/{loadResources-Bj-aSsXi.mjs → loadResources-DGlfRQc9.mjs} +2 -2
  88. package/dist/{loadResourcesFromEntry-DwaxNcE2.mjs → loadResourcesFromEntry-VYPGSas8.mjs} +2 -2
  89. package/dist/logger/index.d.mts +23 -4
  90. package/dist/logger/index.mjs +50 -7
  91. package/dist/{mcpPlugin-DX3PHD7K.mjs → mcpPlugin-NxSlc-Ks.mjs} +15 -16
  92. package/dist/{memory-qYSB7rMQ.mjs → memory-BU-C-MV3.mjs} +2 -2
  93. package/dist/{metrics-D7uchLjN.mjs → metrics-7_1GbJpl.mjs} +2 -2
  94. package/dist/middleware/index.d.mts +1 -1
  95. package/dist/middleware/index.mjs +3 -3
  96. package/dist/migrations/index.mjs +7 -4
  97. package/dist/{module-CwKsgZXp.mjs → module-CQNHzE7g.mjs} +1 -1
  98. package/dist/{multipartBody-4w-S3-PU.mjs → multipartBody-Bi5yqW0M.mjs} +1 -1
  99. package/dist/{openapi-CkV5mQ53.mjs → openapi-RpNbPBL-.mjs} +6 -6
  100. package/dist/outbox-admin/index.d.mts +2 -2
  101. package/dist/outbox-admin/index.mjs +4 -4
  102. package/dist/{outbox-module-D1QfHqO4.mjs → outbox-module-ClcFrq98.mjs} +6 -4
  103. package/dist/{outbox-module-C1Bs_FXF.d.mts → outbox-module-b1TyDGGi.d.mts} +24 -1
  104. package/dist/permissions/index.d.mts +2 -2
  105. package/dist/permissions/index.mjs +5 -5
  106. package/dist/{permissions-CP47jdi7.mjs → permissions-DgPrZsJh.mjs} +36 -9
  107. package/dist/{pipe-BzzoEhHj.mjs → pipe-Cjy1UiXX.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 +92 -7
  111. package/dist/plugins/index.mjs +168 -17
  112. package/dist/plugins/response-cache.mjs +2 -2
  113. package/dist/plugins/tracing-entry.mjs +2 -2
  114. package/dist/{pluralize-B7xf8qZF.mjs → pluralize-B7m0dPm8.mjs} +1 -1
  115. package/dist/{preloadResources-g07ldtzh.d.mts → preloadResources-BuutdWgr.d.mts} +54 -270
  116. package/dist/{createApp-zR-DEesr.mjs → preloadResources-CjnW4iIX.mjs} +170 -34
  117. package/dist/presets/filesUpload.d.mts +3 -3
  118. package/dist/presets/filesUpload.mjs +5 -5
  119. package/dist/presets/index.d.mts +2 -2
  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 +9 -47
  124. package/dist/presets/search.mjs +2 -2
  125. package/dist/{presets-BAPijK_A.mjs → presets-CsGg8B58.mjs} +4 -4
  126. package/dist/{projection-BKM0Ui-s.mjs → projection-koISNyQo.mjs} +2 -2
  127. package/dist/{queryCachePlugin-DhsZ0ZIc.mjs → queryCachePlugin-DHueQT9O.mjs} +5 -5
  128. package/dist/{rateLimitKey-XngqVNEV.mjs → rateLimitKey-Bma8VXDO.mjs} +1 -1
  129. package/dist/{realtime-G1TC6Yzc.mjs → realtime-BBoC91Bz.mjs} +9 -9
  130. package/dist/{rateLimit-D4-ASwsI.mjs → registerRoute-BTgORTlR.mjs} +114 -3
  131. package/dist/registry/index.d.mts +2 -2
  132. package/dist/registry/index.mjs +3 -3
  133. package/dist/{registry-CLxCR5LF.mjs → registry-BzvRCYS6.mjs} +15 -56
  134. package/dist/{renewingLease-BnWtbA2U.mjs → renewingLease-CgIGh0Ab.mjs} +14 -2
  135. package/dist/{replyHelpers-BSBVCwL3.mjs → replyHelpers-BN16KPHr.mjs} +2 -2
  136. package/dist/{requestContext-uYE35JxI.mjs → requestContext-B93dmpf0.mjs} +1 -1
  137. package/dist/{rolldown-runtime-DNg-KNCk.mjs → rolldown-runtime-JJWfp8rp.mjs} +1 -1
  138. package/dist/{runtimeCapabilities-Dm88DaTW.mjs → runtimeCapabilities-jK99Ciw_.mjs} +1 -1
  139. package/dist/{schedules-CAcZgia0.mjs → schedules-CKKEL21P.mjs} +6 -4
  140. package/dist/{schemaConverter-XH1RZRyu.mjs → schemaConverter-gg0_aUPF.mjs} +19 -32
  141. package/dist/{schemaIR-CDvclAew.mjs → schemaIR-CngYvpCF.mjs} +2 -2
  142. package/dist/schemas/index.mjs +1 -1
  143. package/dist/scim/index.mjs +2 -2
  144. package/dist/scope/index.d.mts +1 -1
  145. package/dist/scope/index.mjs +5 -5
  146. package/dist/{scope-BaWcqBvr.mjs → scope-B1RsHdjF.mjs} +4 -4
  147. package/dist/simpleEqualityMatcher-_9NAMHUD.mjs +43 -0
  148. package/dist/{sse-Cf0jUHsh.mjs → sse-Bxt03Hk5.mjs} +5 -5
  149. package/dist/{sseStream-Bvpi-UXQ.mjs → sseStream-BMHTLlhR.mjs} +2 -2
  150. package/dist/{store-helpers-B88p99Z2.mjs → store-helpers-Brt8OxWZ.mjs} +1 -1
  151. package/dist/{streaming-DsT1B5zJ.mjs → streaming-CiTJW8kZ.mjs} +1 -1
  152. package/dist/{subscribe-helpers-CLIOHsOK.mjs → subscribe-helpers-B4fNHRNc.mjs} +21 -49
  153. package/dist/sync/changelog.mjs +1 -1
  154. package/dist/testing/cleanupStoreContract.mjs +1 -1
  155. package/dist/testing/index.d.mts +6 -6
  156. package/dist/testing/index.mjs +10 -11
  157. package/dist/testing/outboxStoreContract.mjs +1 -1
  158. package/dist/testing/storageContract.mjs +1 -1
  159. package/dist/{transactionContext-BYtWnwAS.mjs → transactionContext-D2HwJM2z.mjs} +1 -1
  160. package/dist/{typeGuards-jjKJDN13.mjs → typeGuards-IE1laMDf.mjs} +1 -1
  161. package/dist/types/index.d.mts +3 -3
  162. package/dist/types/index.mjs +1 -1
  163. package/dist/types/storage.mjs +1 -1
  164. package/dist/{types-CoqIRrkY.mjs → types-B8lwJv9Q.mjs} +10 -53
  165. package/dist/{types-BfC83KsP.d.mts → types-BXnTOsXP.d.mts} +1 -1
  166. package/dist/{types-BcTumAz_.d.mts → types-DDD5RKTu.d.mts} +30 -87
  167. package/dist/{types-ChuShpCP.d.mts → types-Ddl9OjmE.d.mts} +18 -121
  168. package/dist/usage/index.d.mts +2 -2
  169. package/dist/usage/index.mjs +0 -0
  170. package/dist/{userHelpers-CWF5pbZD.mjs → userHelpers-xQAi5bPF.mjs} +1 -1
  171. package/dist/utils/index.d.mts +16 -42
  172. package/dist/utils/index.mjs +11 -11
  173. package/dist/{utils-h1V_sT-t.mjs → utils-DgNFsJ2c.mjs} +3 -3
  174. package/dist/{validate-CdQlz52F.mjs → validate-DI3L5V9w.mjs} +2 -2
  175. package/dist/{versioning-rZbyLVD-.mjs → versioning-COpAyfpZ.mjs} +3 -3
  176. package/package.json +8 -8
  177. package/dist/actionPermissions-CUeCmpUd.mjs +0 -25
  178. package/dist/defineAggregation-Nv-DwfOf.mjs +0 -48
  179. package/dist/preloadResources-BkyqeTDz.mjs +0 -46
  180. package/dist/registerRoute-Ba8v0PCa.mjs +0 -113
  181. package/dist/repositoryFilter-BANpz6BX.mjs +0 -78
  182. package/dist/simpleEqualityMatcher-Se8VrsaP.mjs +0 -69
@@ -1,17 +1,92 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { h as SYSTEM_FIELDS, o as DEFAULT_TENANT_FIELD } from "./constants-BxCoxmiN.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { h as SYSTEM_FIELDS, o as DEFAULT_TENANT_FIELD } from "./constants-DUoKAGYD.mjs";
3
3
  import { arcLog } from "./logger/index.mjs";
4
- import { a as conjoinPolicyFilters } from "./authorizationDecision-CMMLWmuZ.mjs";
5
- import { d as createDomainError, f as createError, i as NotFoundError, p as isArcError, r as ForbiddenError } from "./errors-Cd_yy7aW.mjs";
6
- import { n as getUserRoles, t as getUserId } from "./userHelpers-CWF5pbZD.mjs";
7
- import { b as isElevated, c as getOrgId, n as PUBLIC_SCOPE, x as isMember } from "./types-CoqIRrkY.mjs";
8
- import { t as simpleEqualityMatcher } from "./simpleEqualityMatcher-Se8VrsaP.mjs";
9
- import { n as toRepositoryFilter } from "./repositoryFilter-BANpz6BX.mjs";
10
- import { i as resolveEffectiveRoles, n as applyFieldWritePermissions } from "./fields-CojeUkS4.mjs";
11
- import { g as ArcQueryParser, n as scheduleBackground } from "./utils-h1V_sT-t.mjs";
12
- import { t as buildQueryKey } from "./keys-WeKvY1dE.mjs";
4
+ import { a as conjoinPolicyFilters } from "./authorizationDecision-EsiY3nUu.mjs";
5
+ import { d as createDomainError, f as createError, i as NotFoundError, p as isArcError, r as ForbiddenError } from "./errors-DDKni6Tz.mjs";
6
+ import { n as getUserRoles, t as getUserId } from "./userHelpers-xQAi5bPF.mjs";
7
+ import { b as isElevated, c as getOrgId, n as PUBLIC_SCOPE, x as isMember } from "./types-B8lwJv9Q.mjs";
8
+ import { t as simpleEqualityMatcher } from "./simpleEqualityMatcher-_9NAMHUD.mjs";
9
+ import { i as resolveEffectiveRoles, n as applyFieldWritePermissions } from "./fields-DdP225wt.mjs";
10
+ import { g as ArcQueryParser, n as scheduleBackground } from "./utils-DgNFsJ2c.mjs";
11
+ import { t as buildQueryKey } from "./keys-BcNl12HN.mjs";
12
+ import { t as transactionContext } from "./transactionContext-D2HwJM2z.mjs";
13
+ import { policyRecordToFilter } from "@classytic/repo-core/filter";
13
14
  import { retryingTransaction } from "@classytic/repo-core/repository";
14
15
  import { isProductionEnv } from "@classytic/primitives/environment";
16
+ //#region src/core/repositoryFilter.ts
17
+ const NATIVE_FILTER_DIALECT = Symbol.for("@classytic/arc/native-filter-dialect");
18
+ /**
19
+ * Mark a server-owned policy as intentionally adapter-native. This is an
20
+ * explicit escape hatch for semantics absent from repo-core's universal IR
21
+ * (for example MongoDB `$elemMatch`). Never apply it to client input.
22
+ */
23
+ function nativePolicyFilter(dialect, record) {
24
+ return Object.freeze({
25
+ ...record,
26
+ [NATIVE_FILTER_DIALECT]: dialect
27
+ });
28
+ }
29
+ function nativeDialects(value, found = /* @__PURE__ */ new Set()) {
30
+ if (value === null || typeof value !== "object") return found;
31
+ const dialect = value[NATIVE_FILTER_DIALECT];
32
+ if (typeof dialect === "string") found.add(dialect);
33
+ if (Array.isArray(value)) for (const entry of value) nativeDialects(entry, found);
34
+ else for (const entry of Object.values(value)) nativeDialects(entry, found);
35
+ return found;
36
+ }
37
+ function stripNativeMarkers(value) {
38
+ if (Array.isArray(value)) return value.map(stripNativeMarkers);
39
+ if (value === null || typeof value !== "object" || value instanceof Date) return value;
40
+ const out = {};
41
+ for (const [key, entry] of Object.entries(value)) out[key] = stripNativeMarkers(entry);
42
+ return out;
43
+ }
44
+ const log$2 = arcLog("repository-filter");
45
+ let warnedUnconvertible = false;
46
+ /** True for a `{ $op: ... }` operator object (all keys `$`-prefixed). */
47
+ function isOperatorObject(value) {
48
+ if (value === null || typeof value !== "object") return false;
49
+ if (Array.isArray(value) || value instanceof Date) return false;
50
+ const keys = Object.keys(value);
51
+ return keys.length > 0 && keys.some((k) => k.startsWith("$"));
52
+ }
53
+ /**
54
+ * Does this compound filter contain any `$`-operator (top-level logical like
55
+ * `$and`/`$or`, or a field operator object like `{ $in: [...] }`)? If not, it is
56
+ * pure flat equality and portable as-is.
57
+ */
58
+ function filterHasDollarOperator(record) {
59
+ for (const [key, value] of Object.entries(record)) {
60
+ if (key.startsWith("$")) return true;
61
+ if (isOperatorObject(value)) return true;
62
+ }
63
+ return false;
64
+ }
65
+ /**
66
+ * Normalize a compound query/policy filter for the repository layer. Flat
67
+ * equality records pass through unchanged; anything carrying `$`-operators is
68
+ * converted to repo-core {@link Filter} IR so semantics stay explicit. Common
69
+ * operators compile identically across kits; capability-specific operators
70
+ * such as array-element matching fail loudly on adapters that cannot model them.
71
+ */
72
+ function toRepositoryFilter(record) {
73
+ const dialects = nativeDialects(record);
74
+ if (dialects.size > 0) {
75
+ if (dialects.size > 1) throw new Error(`Cannot compose native policy-filter dialects: ${[...dialects].sort().join(", ")}`);
76
+ return stripNativeMarkers(record);
77
+ }
78
+ if (!filterHasDollarOperator(record)) return record;
79
+ try {
80
+ return policyRecordToFilter(record);
81
+ } catch (err) {
82
+ if (!warnedUnconvertible) {
83
+ warnedUnconvertible = true;
84
+ log$2.warn(`A \`\$\`-operator filter could not be normalized to portable Filter IR (operator outside arc's policy dialect). Passing the raw record to the repository — MongoKit handles it; non-Mongo kits may not. (${err instanceof Error ? err.message : String(err)})`);
85
+ }
86
+ return record;
87
+ }
88
+ }
89
+ //#endregion
15
90
  //#region src/core/AccessControl.ts
16
91
  const log$1 = arcLog("access-control");
17
92
  var AccessControl = class {
@@ -1334,7 +1409,10 @@ var BaseCrudController = class {
1334
1409
  */
1335
1410
  runWritePersistence(fn) {
1336
1411
  if (!this._transactional) return fn(this.repository);
1337
- return retryingTransaction(this.repository, (txRepo, uow) => fn(txRepo, uow));
1412
+ return retryingTransaction(this.repository, (txRepo, uow) => {
1413
+ const run = () => fn(txRepo, uow);
1414
+ return uow?.session === void 0 ? run() : transactionContext.run(uow.session, run);
1415
+ });
1338
1416
  }
1339
1417
  /** Assemble the `WriteContext` a `create` verb receives. */
1340
1418
  writeContext(req, repo = this.repository, uow) {
@@ -1475,8 +1553,10 @@ var BaseCrudController = class {
1475
1553
  const options = this.queryResolver.resolve(req, this.meta(req));
1476
1554
  const cached = await this.withListCache(req, options);
1477
1555
  if (cached) return cached;
1556
+ const result = await this.executeListQuery(options, req);
1557
+ await this.runAfterHook(req, "list", result);
1478
1558
  return {
1479
- data: await this.executeListQuery(options, req),
1559
+ data: result,
1480
1560
  status: 200
1481
1561
  };
1482
1562
  }
@@ -1567,6 +1647,7 @@ var BaseCrudController = class {
1567
1647
  if (cached) return cached;
1568
1648
  const { doc, reason } = await this.executeGetQuery(id, options, req);
1569
1649
  if (!doc) this.throwNotFound(reason);
1650
+ await this.runAfterHook(req, "read", doc);
1570
1651
  return {
1571
1652
  data: doc,
1572
1653
  status: 200
@@ -2046,4 +2127,4 @@ function TreeMixin(Base) {
2046
2127
  */
2047
2128
  var BaseController = class extends SoftDeleteMixin(TreeMixin(SlugMixin(BulkMixin(BaseCrudController)))) {};
2048
2129
  //#endregion
2049
- export { BulkMixin as a, collectReadBlockedFields as c, isWriteVerbCapable as d, BodySanitizer as f, SlugMixin as i, isFieldReadable as l, AccessControl as m, TreeMixin as n, BaseCrudController as o, DEFAULT_FIELD_WRITE_DENIAL_POLICY as p, SoftDeleteMixin as r, QueryResolver as s, BaseController as t, detectOverriddenWriteSlots as u };
2130
+ export { BulkMixin as a, collectReadBlockedFields as c, isWriteVerbCapable as d, BodySanitizer as f, toRepositoryFilter as g, nativePolicyFilter as h, SlugMixin as i, isFieldReadable as l, AccessControl as m, TreeMixin as n, BaseCrudController as o, DEFAULT_FIELD_WRITE_DENIAL_POLICY as p, SoftDeleteMixin as r, QueryResolver as s, BaseController as t, detectOverriddenWriteSlots as u };
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  import { createEvent, matchEventPattern } from "@classytic/primitives/events";
3
3
  //#region src/events/EventTransport.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as buildRequestScopeProjection } from "./projection-BKM0Ui-s.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as buildRequestScopeProjection } from "./projection-koISNyQo.mjs";
3
3
  //#region src/hooks/HookSystem.ts
4
4
  /**
5
5
  * Hook System
@@ -116,9 +116,11 @@ var HookSystem = class {
116
116
  }
117
117
  async execute(ctx) {
118
118
  const key = this.getKey(ctx.resource, ctx.operation, ctx.phase);
119
- const hooks = this.hooks.get(key) ?? [];
119
+ const hooks = this.hooks.get(key);
120
120
  const wildcardKey = this.getKey("*", ctx.operation, ctx.phase);
121
- let allHooks = [...this.hooks.get(wildcardKey) ?? [], ...hooks];
121
+ const wildcardHooks = this.hooks.get(wildcardKey);
122
+ if (!hooks?.length && !wildcardHooks?.length) return ctx.data;
123
+ let allHooks = [...wildcardHooks ?? [], ...hooks ?? []];
122
124
  allHooks.sort((a, b) => a.priority - b.priority);
123
125
  if (allHooks.some((h) => h.dependsOn?.length)) allHooks = this.topologicalSort(allHooks);
124
126
  let result = ctx.data;
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import "./constants-BxCoxmiN.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import "./constants-DUoKAGYD.mjs";
3
3
  //#region src/registry/ResourceRegistry.ts
4
4
  /**
5
5
  * Resource Registry
@@ -1,9 +1,9 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { n as getUserRoles } from "./userHelpers-CWF5pbZD.mjs";
3
- import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-CoqIRrkY.mjs";
4
- import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-CojeUkS4.mjs";
5
- import { t as executePipeline } from "./pipe-BzzoEhHj.mjs";
6
- import { t as buildRequestScopeProjection } from "./projection-BKM0Ui-s.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { n as getUserRoles } from "./userHelpers-xQAi5bPF.mjs";
3
+ import { b as isElevated, n as PUBLIC_SCOPE, x as isMember } from "./types-B8lwJv9Q.mjs";
4
+ import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-DdP225wt.mjs";
5
+ import { t as executePipeline } from "./pipe-Cjy1UiXX.mjs";
6
+ import { t as buildRequestScopeProjection } from "./projection-koISNyQo.mjs";
7
7
  import { isPaginatedResult, toCanonicalList } from "@classytic/repo-core/pagination";
8
8
  //#region src/core/fastifyAdapter.ts
9
9
  /** Type guard for Mongoose-like documents with toObject() */
@@ -323,4 +323,27 @@ function buildActionPipelineHandler(handler, steps, operation, resourceName) {
323
323
  };
324
324
  }
325
325
  //#endregion
326
- export { createFastifyHandler as a, getControllerScope as c, createCrudHandlers as i, sendControllerResponse as l, buildPipelineHandler as n, createRequestContext as o, resolvePipelineSteps as r, getControllerContext as s, buildActionPipelineHandler as t };
326
+ //#region src/core/actionPermissions.ts
327
+ /**
328
+ * Return the effective `PermissionCheck` for a single action, or `undefined`
329
+ * when the resource declares no gate at any level.
330
+ *
331
+ * Callers decide what "no gate" means:
332
+ * - HTTP: boot-time throw in `normalizeActionsToRouterConfig`.
333
+ * - MCP: tool-generation throw in `resourceToTools` (mirrors HTTP — the
334
+ * two surfaces fail closed identically so MCP can't expose an
335
+ * unauthenticated mutating tool when the HTTP plugin lifecycle hasn't
336
+ * run).
337
+ * - OpenAPI: docs advertise the endpoint as unauthenticated.
338
+ */
339
+ function resolveActionPermission(input) {
340
+ const { action, resourcePermissions, resourceActionPermissions, globalAuth } = input;
341
+ const explicit = typeof action !== "function" && action.permissions ? action.permissions : void 0;
342
+ if (explicit) return explicit;
343
+ if (resourceActionPermissions) return resourceActionPermissions;
344
+ if (globalAuth) return globalAuth;
345
+ const updateFallback = resourcePermissions?.update;
346
+ if (updateFallback) return updateFallback;
347
+ }
348
+ //#endregion
349
+ export { createCrudHandlers as a, getControllerContext as c, resolvePipelineSteps as i, getControllerScope as l, buildActionPipelineHandler as n, createFastifyHandler as o, buildPipelineHandler as r, createRequestContext as s, resolveActionPermission as t, sendControllerResponse as u };
@@ -1,6 +1,6 @@
1
1
 
2
- import { d as UserBase } from "../base-Csjc2oF-.mjs";
3
- import "../index-BcR2bFZQ.mjs";
2
+ import { d as UserBase } from "../base-C-NL2fTi.mjs";
3
+ import "../index-C01wWGJt.mjs";
4
4
  import { FastifyPluginAsync } from "fastify";
5
5
  import { RepositoryLike } from "@classytic/repo-core/adapter";
6
6
  //#region src/audit/stores/interface.d.ts
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as transactionContext } from "../transactionContext-BYtWnwAS.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as transactionContext } from "../transactionContext-D2HwJM2z.mjs";
3
3
  import { and, anyOf, eq, gte, lt, lte } from "@classytic/repo-core/filter";
4
4
  import fp from "fastify-plugin";
5
5
  //#region src/audit/repository-audit-adapter.ts
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  //#region src/auth/audit.ts
3
3
  function compileGlobs(patterns) {
4
4
  if (patterns.length === 0) return () => false;
@@ -1,6 +1,6 @@
1
1
 
2
- import { l as PermissionCheck } from "../base-Csjc2oF-.mjs";
3
- import { Ft as AuthPluginOptions, Pt as AuthHelpers } from "../index-BcR2bFZQ.mjs";
2
+ import { l as PermissionCheck } from "../base-C-NL2fTi.mjs";
3
+ import { Ft as AuthPluginOptions, Pt as AuthHelpers } from "../index-C01wWGJt.mjs";
4
4
  import { t as ExternalOpenApiPaths } from "../externalPaths-CmGOxOtD.mjs";
5
5
  import { a as SessionManagerOptions, c as createSessionManager, i as SessionData, n as MemorySessionStoreOptions, o as SessionManagerResult, r as SessionCookieOptions, s as SessionStore, t as MemorySessionStore } from "../sessionManager-qimlKV0P.mjs";
6
6
  import { FastifyPluginAsync, FastifyReply as FastifyReply$1, FastifyRequest } from "fastify";
@@ -1,9 +1,9 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { d as createDomainError, l as UnauthorizedError, p as isArcError, t as ArcError } from "../errors-Cd_yy7aW.mjs";
3
- import { n as requireSingleHeaderValue } from "../headers-CveNO9gR.mjs";
4
- import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-CWF5pbZD.mjs";
5
- import { o as toJsonSchema } from "../schemaConverter-XH1RZRyu.mjs";
6
- import { E as requireOrgRole, T as requireOrgMembership, k as requireTeamMembership } from "../permissions-CP47jdi7.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { d as createDomainError, l as UnauthorizedError, p as isArcError, t as ArcError } from "../errors-DDKni6Tz.mjs";
3
+ import { n as requireSingleHeaderValue } from "../headers-DKslnhey.mjs";
4
+ import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-xQAi5bPF.mjs";
5
+ import { o as toJsonSchema } from "../schemaConverter-gg0_aUPF.mjs";
6
+ import { E as requireOrgRole, T as requireOrgMembership, k as requireTeamMembership } from "../permissions-DgPrZsJh.mjs";
7
7
  import { isProductionEnv } from "@classytic/primitives/environment";
8
8
  import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
9
9
  import fp from "fastify-plugin";
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  import sjson from "secure-json-parse";
3
3
  //#region src/auth/redis-session.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  import { arcLog } from "./logger/index.mjs";
3
- import { t as ArcError } from "./errors-Cd_yy7aW.mjs";
3
+ import { t as ArcError } from "./errors-DDKni6Tz.mjs";
4
4
  //#region src/permissions/filter-merge.ts
5
5
  /**
6
6
  * Policy-filter composition — logical AND, never last-writer-wins.
@@ -1,5 +1,5 @@
1
1
 
2
- import { i as RequestScope } from "./types-ChuShpCP.mjs";
2
+ import { i as RequestScope } from "./types-Ddl9OjmE.mjs";
3
3
  import { FastifyRequest } from "fastify";
4
4
  //#region src/utils/userHelpers.d.ts
5
5
  /**
@@ -169,6 +169,21 @@ type PermissionCheck<TDoc = Record<string, unknown>> = ((context: PermissionCont
169
169
  interface PermissionCheckMeta {
170
170
  /** Set by allowPublic() — marks the endpoint as publicly accessible */
171
171
  _isPublic?: boolean;
172
+ /**
173
+ * Set by `denyAll()` — nobody passes this gate, ever.
174
+ *
175
+ * Marked because `denyAll` used to return a BARE closure with no metadata, and
176
+ * introspection reads metadata: `describePermission` found no `_isPublic`, no
177
+ * `_roles` and no scope, and fell through to its last branch —
178
+ * `{ kind: "authenticated" }`. So the most restrictive gate in the library was
179
+ * published to permission UIs and audits as "any signed-in user may do this",
180
+ * which is the exact opposite of what it does.
181
+ *
182
+ * The enforcement path was always correct; only the DESCRIPTION lied. That is
183
+ * the dangerous direction: a dashboard renders the button, every click 403s,
184
+ * and an access audit reports a surface that does not exist.
185
+ */
186
+ _isDenied?: boolean;
172
187
  /**
173
188
  * Set by requireAuth() — a pure identity gate (must be signed in) that adds NO
174
189
  * row-level or environmental condition. Marked so `allOf` does not mistake it
@@ -1,7 +1,7 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { a as conjoinPolicyFilters } from "./authorizationDecision-CMMLWmuZ.mjs";
3
- import { n as toRepositoryFilter } from "./repositoryFilter-BANpz6BX.mjs";
4
- import { i as compileAggRequest, t as adapterSupportsAggregate } from "./validate-CdQlz52F.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { a as conjoinPolicyFilters } from "./authorizationDecision-EsiY3nUu.mjs";
3
+ import { g as toRepositoryFilter } from "./BaseController-CTJKm6Cb.mjs";
4
+ import { i as compileAggRequest, t as adapterSupportsAggregate } from "./validate-DI3L5V9w.mjs";
5
5
  //#region src/core/aggregation/buildHandler.ts
6
6
  /**
7
7
  * Framework-agnostic aggregation execution. Runs safety guards,
@@ -1,7 +1,7 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { i as versionKey, n as hashParams, r as tagVersionKey, t as buildQueryKey } from "../keys-WeKvY1dE.mjs";
3
- import { t as MemoryCacheStore } from "../memory-qYSB7rMQ.mjs";
4
- import { r as QueryCache, t as queryCachePlugin } from "../queryCachePlugin-DhsZ0ZIc.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { i as versionKey, n as hashParams, r as tagVersionKey, t as buildQueryKey } from "../keys-BcNl12HN.mjs";
3
+ import { t as MemoryCacheStore } from "../memory-BU-C-MV3.mjs";
4
+ import { r as QueryCache, t as queryCachePlugin } from "../queryCachePlugin-DHueQT9O.mjs";
5
5
  //#region src/cache/redis.ts
6
6
  /**
7
7
  * Redis-backed cache store.
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as __exportAll } from "./rolldown-runtime-DNg-KNCk.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as __exportAll } from "./rolldown-runtime-JJWfp8rp.mjs";
3
3
  import fp from "fastify-plugin";
4
4
  //#region src/plugins/caching.ts
5
5
  var caching_exports = /* @__PURE__ */ __exportAll({
@@ -1,7 +1,7 @@
1
1
 
2
- import { L as RequestWithExtras } from "../index-BcR2bFZQ.mjs";
2
+ import { L as RequestWithExtras } from "../index-C01wWGJt.mjs";
3
3
  import { A as CleanupStepResult, B as VerificationResult, C as CleanupResult, D as CleanupRunStore, E as CleanupRunStatus, F as PurgeEvidence, I as PurgeResourceResult, L as PurgeStrategyKind, M as CleanupWriteFence, N as DEFAULT_CLEANUP_LIMITS, O as CleanupRunTransitionPatch, P as PurgeActor, R as PurgeVerificationSummary, S as CleanupRecipe, T as CleanupRunCreateResult, _ as CleanupPermissions, a as CleanupEvidenceStore, b as CleanupPlanItem, c as CleanupInput, d as CleanupLease, f as CleanupLimits, g as CleanupPermissionCheck, h as CleanupOutcomeStatus, i as CleanupContext, j as CleanupStepRunStatus, k as CleanupStepProgress, l as CleanupJob, m as CleanupManifest, n as CLEANUP_TERMINAL_STATUSES, o as CleanupExecutionContext, p as CleanupLogger, r as CleanupCancelRequest, s as CleanupFinalizationPayload, t as Availability, u as CleanupJobQueue, v as CleanupPlan, w as CleanupRun, x as CleanupProgressSummary, y as CleanupPlanDraft, z as VerificationCheck } from "../types-DVLddu2q.mjs";
4
- import { t as ArcModule } from "../types-BcTumAz_.mjs";
4
+ import { t as ArcModule } from "../types-DDD5RKTu.mjs";
5
5
  import { PurgeStrategyKind as PurgeStrategyKind$1 } from "@classytic/primitives/retention";
6
6
  import { canonicalJson } from "@classytic/primitives/canonical";
7
7
  import { CleanupStep } from "@classytic/repo-core/cleanup";
@@ -1,7 +1,7 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { g as getUserId } from "../types-CoqIRrkY.mjs";
3
- import { t as defineResource } from "../defineResource-ZhuLonLm.mjs";
4
- import { t as defineModule } from "../module-CwKsgZXp.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { g as getUserId } from "../types-B8lwJv9Q.mjs";
3
+ import { t as defineResource } from "../defineResource-DWzjyxb2.mjs";
4
+ import { t as defineModule } from "../module-CQNHzE7g.mjs";
5
5
  import { createPurgeEvidence } from "@classytic/primitives/retention";
6
6
  import { canonicalJson, sha256Hex } from "@classytic/primitives/canonical";
7
7
  //#region src/cleanup/errors.ts
@@ -1,5 +1,5 @@
1
1
 
2
- import { Nt as RateLimitConfig, V as ResourceDefinition, et as RouteSchemaOptions } from "../../index-BcR2bFZQ.mjs";
2
+ import { Nt as RateLimitConfig, V as ResourceDefinition, et as RouteSchemaOptions } from "../../index-C01wWGJt.mjs";
3
3
  //#region src/cli/commands/describe.d.ts
4
4
  interface DescribedResource {
5
5
  name: string;
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as CRUD_OPERATIONS } from "../../constants-BxCoxmiN.mjs";
3
- import { n as stringifyMeasureMap } from "../../ResourceRegistry-DoALUlOO.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as CRUD_OPERATIONS } from "../../constants-DUoKAGYD.mjs";
3
+ import { n as stringifyMeasureMap } from "../../ResourceRegistry-DNuYVbmv.mjs";
4
4
  import { resolve } from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
6
  //#region src/cli/commands/describe.ts
@@ -1,6 +1,6 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as buildOpenApiSpec } from "../../openapi-CkV5mQ53.mjs";
3
- import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-DwaxNcE2.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as buildOpenApiSpec } from "../../openapi-RpNbPBL-.mjs";
3
+ import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-VYPGSas8.mjs";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { mkdirSync, writeFileSync } from "node:fs";
6
6
  //#region src/cli/commands/docs.ts
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  import { dirname, join, parse, resolve } from "node:path";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  //#region src/cli/commands/doctor.ts
@@ -1,3 +1,3 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as generate } from "../../generate-DiB0nHPR.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as generate } from "../../generate-B1bKdcV9.mjs";
3
3
  export { generate };
@@ -1,3 +1,3 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as init } from "../../init-mdJ-v4Xp.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as init } from "../../init-LuGxIbQ_.mjs";
3
3
  export { init };
@@ -1,5 +1,5 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-DwaxNcE2.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-VYPGSas8.mjs";
3
3
  //#region src/cli/commands/introspect.ts
4
4
  function describePermission(value) {
5
5
  if (!value) return "none";
@@ -1,8 +1,8 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  import { describe } from "./commands/describe.mjs";
3
3
  import { exportDocs } from "./commands/docs.mjs";
4
4
  import { doctor } from "./commands/doctor.mjs";
5
- import { t as generate } from "../generate-DiB0nHPR.mjs";
6
- import { t as init } from "../init-mdJ-v4Xp.mjs";
5
+ import { t as generate } from "../generate-B1bKdcV9.mjs";
6
+ import { t as init } from "../init-LuGxIbQ_.mjs";
7
7
  import { introspect } from "./commands/introspect.mjs";
8
8
  export { describe, doctor, exportDocs, generate, init, introspect };
@@ -1,4 +1,4 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
2
  //#region src/constants.ts
3
3
  /**
4
4
  * Arc Framework Constants — Single Source of Truth
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { AsyncLocalStorage } from "node:async_hooks";
3
+ import { CacheAdapter } from "@classytic/repo-core/cache";
3
4
  //#region src/context/requestContext.d.ts
4
5
  /**
5
6
  * Shape of the request-scoped context store.
@@ -85,6 +86,20 @@ declare const requestContext: {
85
86
  */
86
87
  declare function getTraceHeaders(): Record<string, string> | undefined;
87
88
  //#endregion
89
+ //#region src/context/requestScopedCache.d.ts
90
+ /**
91
+ * The cache for the CURRENT request, or `undefined` outside one.
92
+ *
93
+ * Lazily created on first use, so a request that never touches a cached
94
+ * repository allocates nothing.
95
+ */
96
+ declare function requestScopedCache(): CacheAdapter | undefined;
97
+ /**
98
+ * Whether the current request has allocated a cache yet. Diagnostics and
99
+ * tests only — never branch application behaviour on this.
100
+ */
101
+ declare function hasRequestScopedCache(): boolean;
102
+ //#endregion
88
103
  //#region src/context/transactionContext.d.ts
89
104
  /** DB session/transaction handle. Typed as unknown — arc is DB-agnostic. */
90
105
  type DbSession = unknown;
@@ -109,4 +124,4 @@ declare const transactionContext: {
109
124
  storage: AsyncLocalStorage<unknown>;
110
125
  };
111
126
  //#endregion
112
- export { type DbSession, type RequestStore, getTraceHeaders, requestContext, transactionContext };
127
+ export { type DbSession, type RequestStore, getTraceHeaders, hasRequestScopedCache, requestContext, requestScopedCache, transactionContext };
@@ -1,4 +1,64 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { n as requestContext, t as getTraceHeaders } from "../requestContext-uYE35JxI.mjs";
3
- import { t as transactionContext } from "../transactionContext-BYtWnwAS.mjs";
4
- export { getTraceHeaders, requestContext, transactionContext };
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { n as requestContext, t as getTraceHeaders } from "../requestContext-B93dmpf0.mjs";
3
+ import { t as transactionContext } from "../transactionContext-D2HwJM2z.mjs";
4
+ //#region src/context/requestScopedCache.ts
5
+ /**
6
+ * The slot the per-request store hangs off. Underscore-prefixed to sit apart
7
+ * from the fields arc's own hooks populate on `RequestStore`.
8
+ */
9
+ const SLOT = "_requestCache";
10
+ /**
11
+ * A `Map`-backed `CacheAdapter` with NO eviction and NO TTL — both deliberate.
12
+ *
13
+ * The store is unreachable once the request's async context ends, so it is
14
+ * garbage in milliseconds and bounded by what one request touches; an LRU
15
+ * would guard a lifetime that cannot occur. TTL is accepted and ignored
16
+ * because repo-core stamps freshness INTO the envelope and re-checks on read —
17
+ * honouring it here too would put two clocks on one question.
18
+ */
19
+ function createRequestCacheAdapter() {
20
+ const map = /* @__PURE__ */ new Map();
21
+ return {
22
+ async get(key) {
23
+ return map.get(key);
24
+ },
25
+ async set(key, value, _ttlSeconds) {
26
+ map.set(key, value);
27
+ },
28
+ async delete(key) {
29
+ map.delete(key);
30
+ },
31
+ /**
32
+ * Ignores the pattern and wipes the whole store. Over-invalidating within
33
+ * one request costs at most a re-read; pattern matching is complexity a
34
+ * store that dies in milliseconds does not earn.
35
+ */
36
+ async clear(_pattern) {
37
+ map.clear();
38
+ }
39
+ };
40
+ }
41
+ /**
42
+ * The cache for the CURRENT request, or `undefined` outside one.
43
+ *
44
+ * Lazily created on first use, so a request that never touches a cached
45
+ * repository allocates nothing.
46
+ */
47
+ function requestScopedCache() {
48
+ const store = requestContext.get();
49
+ if (!store) return void 0;
50
+ const existing = store[SLOT];
51
+ if (existing) return existing;
52
+ const created = createRequestCacheAdapter();
53
+ store[SLOT] = created;
54
+ return created;
55
+ }
56
+ /**
57
+ * Whether the current request has allocated a cache yet. Diagnostics and
58
+ * tests only — never branch application behaviour on this.
59
+ */
60
+ function hasRequestScopedCache() {
61
+ return requestContext.get()?.[SLOT] !== void 0;
62
+ }
63
+ //#endregion
64
+ export { getTraceHeaders, hasRequestScopedCache, requestContext, requestScopedCache, transactionContext };
@@ -1,4 +1,4 @@
1
1
 
2
- import { $t as AccessControlConfig, B as defineResource, Bt as BaseController, Cn as ControllerConstructionOptions, En as BodySanitizerConfig, Gt as SlugExt, Ht as SoftDeleteMixin, Jt as BulkMixin, Kt as SlugMixin, Qt as AccessControl, Sn as ControllerConfigurableOptions, Tn as BodySanitizer, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, Xt as QueryResolver, Yt as BaseCrudController, Zt as QueryResolverConfig, ct as AggMeasureShorthand, dt as AggregationDateRangeRequirement, ft as AggregationIndexHint, gt as AggregationsMap, ht as AggregationRateLimit, lt as AggregationCacheConfig, mt as AggregationMaterializedResult, pt as AggregationMaterializedContext, qt as BulkExt, st as AggMeasureInput, ut as AggregationConfig, wn as ListResult, xn as BaseControllerOptions } from "../index-BcR2bFZQ.mjs";
3
- import { A as CRUD_OPERATIONS, B as HookOperation, C as SeamedResourceConfig, D as createCrudRouter, E as defineAction, F as DEFAULT_SORT, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_TENANT_FIELD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_UPDATE_METHOD, M as DEFAULT_ID_FIELD, N as DEFAULT_LIMIT, O as createPermissionMiddleware, P as DEFAULT_MAX_LIMIT, R as HOOK_OPERATIONS, S as ResourceSeams, T as DefineActionConfig, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, _ as getEntityId, a as formatValidationErrors, b as defineResourceVariants, c as nativePolicyFilter, d as createCrudHandlers, f as createFastifyHandler, g as sendControllerResponse, h as getControllerScope, i as assertValidConfig, j as CrudOperation, k as defineAggregation, l as collectReadBlockedFields, m as getControllerContext, n as ValidateOptions, o as validateResourceConfig, p as createRequestContext, q as RESERVED_QUERY_PARAMS, r as ValidationResult, s as NativePolicyFilter, t as ConfigError, u as isFieldReadable, v as getEntityIdField, w as mergeResourceConfig, x as AdapterLike, y as getEntityQuery, z as HOOK_PHASES } from "../index-CFAJEWCX.mjs";
2
+ import { $t as AccessControlConfig, B as defineResource, Bt as BaseController, Cn as ControllerConstructionOptions, En as BodySanitizerConfig, Gt as SlugExt, Ht as SoftDeleteMixin, Jt as BulkMixin, Kt as SlugMixin, Qt as AccessControl, Sn as ControllerConfigurableOptions, Tn as BodySanitizer, Ut as TreeExt, V as ResourceDefinition, Vt as SoftDeleteExt, Wt as TreeMixin, Xt as QueryResolver, Yt as BaseCrudController, Zt as QueryResolverConfig, ct as AggMeasureShorthand, dt as AggregationDateRangeRequirement, ft as AggregationIndexHint, gt as AggregationsMap, ht as AggregationRateLimit, lt as AggregationCacheConfig, mt as AggregationMaterializedResult, pt as AggregationMaterializedContext, qt as BulkExt, st as AggMeasureInput, ut as AggregationConfig, wn as ListResult, xn as BaseControllerOptions } from "../index-C01wWGJt.mjs";
3
+ import { A as CRUD_OPERATIONS, B as HookOperation, C as SeamedResourceConfig, D as createCrudRouter, E as defineAction, F as DEFAULT_SORT, G as MUTATION_OPERATIONS, H as MAX_FILTER_DEPTH, I as DEFAULT_TENANT_FIELD, J as SYSTEM_FIELDS, K as MutationOperation, L as DEFAULT_UPDATE_METHOD, M as DEFAULT_ID_FIELD, N as DEFAULT_LIMIT, O as createPermissionMiddleware, P as DEFAULT_MAX_LIMIT, R as HOOK_OPERATIONS, S as ResourceSeams, T as DefineActionConfig, U as MAX_REGEX_LENGTH, V as HookPhase, W as MAX_SEARCH_LENGTH, _ as getEntityId, a as formatValidationErrors, b as defineResourceVariants, c as nativePolicyFilter, d as createCrudHandlers, f as createFastifyHandler, g as sendControllerResponse, h as getControllerScope, i as assertValidConfig, j as CrudOperation, k as defineAggregation, l as collectReadBlockedFields, m as getControllerContext, n as ValidateOptions, o as validateResourceConfig, p as createRequestContext, q as RESERVED_QUERY_PARAMS, r as ValidationResult, s as NativePolicyFilter, t as ConfigError, u as isFieldReadable, v as getEntityIdField, w as mergeResourceConfig, x as AdapterLike, y as getEntityQuery, z as HOOK_PHASES } from "../index-RdpLP71b.mjs";
4
4
  export { AccessControl, type AccessControlConfig, type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, BaseController, type BaseControllerOptions, BaseCrudController, BodySanitizer, type BodySanitizerConfig, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DefineActionConfig, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, type NativePolicyFilter, QueryResolver, type QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, type ResourceSeams, SYSTEM_FIELDS, type SeamedResourceConfig, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type ValidateOptions, type ValidationResult, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };
@@ -1,9 +1,8 @@
1
- /*! @classytic/arc v2.34.0 | MIT | https://classytic.com */
2
- import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-BxCoxmiN.mjs";
3
- import { t as nativePolicyFilter } from "../repositoryFilter-BANpz6BX.mjs";
4
- import { a as BulkMixin, c as collectReadBlockedFields, f as BodySanitizer, i as SlugMixin, l as isFieldReadable, m as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-CbkuhNI2.mjs";
5
- import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, o as createCrudRouter, r as formatValidationErrors, s as createPermissionMiddleware, t as defineResource } from "../defineResource-ZhuLonLm.mjs";
6
- import { a as createFastifyHandler, c as getControllerScope, i as createCrudHandlers, l as sendControllerResponse, o as createRequestContext, s as getControllerContext } from "../pipeline-q69DZzgG.mjs";
7
- import { t as defineAggregation } from "../defineAggregation-Nv-DwfOf.mjs";
8
- import { a as mergeResourceConfig, i as defineResourceVariants, n as getEntityIdField, o as defineAction, r as getEntityQuery, t as getEntityId } from "../core-BYKa8wHu.mjs";
1
+ /*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
2
+ import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-DUoKAGYD.mjs";
3
+ import { a as BulkMixin, c as collectReadBlockedFields, f as BodySanitizer, h as nativePolicyFilter, i as SlugMixin, l as isFieldReadable, m as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-CTJKm6Cb.mjs";
4
+ import { a as ResourceDefinition, i as validateResourceConfig, n as assertValidConfig, o as createCrudRouter, r as formatValidationErrors, s as createPermissionMiddleware, t as defineResource } from "../defineResource-DWzjyxb2.mjs";
5
+ import { a as createCrudHandlers, c as getControllerContext, l as getControllerScope, o as createFastifyHandler, s as createRequestContext, u as sendControllerResponse } from "../actionPermissions-D97DniUQ.mjs";
6
+ import { t as defineAggregation } from "../defineAggregation-CpQfcM8R.mjs";
7
+ import { a as mergeResourceConfig, i as defineResourceVariants, n as getEntityIdField, o as defineAction, r as getEntityQuery, t as getEntityId } from "../core-DTXsiNTJ.mjs";
9
8
  export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, nativePolicyFilter, sendControllerResponse, validateResourceConfig };