@opensaas/stack-core 0.37.0 → 0.39.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 (226) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +191 -0
  3. package/CLAUDE.md +42 -3
  4. package/dist/access/access-filter.d.ts +70 -113
  5. package/dist/access/access-filter.d.ts.map +1 -1
  6. package/dist/access/access-filter.js +183 -210
  7. package/dist/access/access-filter.js.map +1 -1
  8. package/dist/access/access-filter.test.js +148 -188
  9. package/dist/access/access-filter.test.js.map +1 -1
  10. package/dist/access/declared-dependencies.d.ts +66 -26
  11. package/dist/access/declared-dependencies.d.ts.map +1 -1
  12. package/dist/access/declared-dependencies.js +62 -17
  13. package/dist/access/declared-dependencies.js.map +1 -1
  14. package/dist/access/declared-dependencies.test.d.ts +2 -0
  15. package/dist/access/declared-dependencies.test.d.ts.map +1 -0
  16. package/dist/access/declared-dependencies.test.js +226 -0
  17. package/dist/access/declared-dependencies.test.js.map +1 -0
  18. package/dist/access/depth-limits.d.ts +8 -7
  19. package/dist/access/depth-limits.d.ts.map +1 -1
  20. package/dist/access/depth-limits.js +8 -7
  21. package/dist/access/depth-limits.js.map +1 -1
  22. package/dist/access/engine.d.ts +0 -20
  23. package/dist/access/engine.d.ts.map +1 -1
  24. package/dist/access/engine.js +0 -25
  25. package/dist/access/engine.js.map +1 -1
  26. package/dist/access/errors.d.ts +61 -8
  27. package/dist/access/errors.d.ts.map +1 -1
  28. package/dist/access/errors.js +91 -12
  29. package/dist/access/errors.js.map +1 -1
  30. package/dist/access/field-access.d.ts +39 -1
  31. package/dist/access/field-access.d.ts.map +1 -1
  32. package/dist/access/field-access.js +108 -42
  33. package/dist/access/field-access.js.map +1 -1
  34. package/dist/access/field-access.test.js +229 -2
  35. package/dist/access/field-access.test.js.map +1 -1
  36. package/dist/access/field-transforms.d.ts +0 -27
  37. package/dist/access/field-transforms.d.ts.map +1 -1
  38. package/dist/access/field-visibility.d.ts +2 -5
  39. package/dist/access/field-visibility.d.ts.map +1 -1
  40. package/dist/access/field-visibility.js +89 -41
  41. package/dist/access/field-visibility.js.map +1 -1
  42. package/dist/access/index.d.ts +6 -3
  43. package/dist/access/index.d.ts.map +1 -1
  44. package/dist/access/index.js +12 -2
  45. package/dist/access/index.js.map +1 -1
  46. package/dist/access/query-validation.d.ts +121 -0
  47. package/dist/access/query-validation.d.ts.map +1 -0
  48. package/dist/access/query-validation.js +292 -0
  49. package/dist/access/query-validation.js.map +1 -0
  50. package/dist/access/relationship-count.d.ts +1 -1
  51. package/dist/access/relationship-count.d.ts.map +1 -1
  52. package/dist/access/relationship-count.js +2 -10
  53. package/dist/access/relationship-count.js.map +1 -1
  54. package/dist/access/relationship-label-filter.d.ts +23 -23
  55. package/dist/access/relationship-label-filter.d.ts.map +1 -1
  56. package/dist/access/relationship-label-filter.js +5 -76
  57. package/dist/access/relationship-label-filter.js.map +1 -1
  58. package/dist/access/relationship-label-filter.test.js +19 -56
  59. package/dist/access/relationship-label-filter.test.js.map +1 -1
  60. package/dist/access/transaction-registry.d.ts +45 -0
  61. package/dist/access/transaction-registry.d.ts.map +1 -0
  62. package/dist/access/transaction-registry.js +37 -0
  63. package/dist/access/transaction-registry.js.map +1 -0
  64. package/dist/access/types.d.ts +55 -59
  65. package/dist/access/types.d.ts.map +1 -1
  66. package/dist/config/index.d.ts +9 -7
  67. package/dist/config/index.d.ts.map +1 -1
  68. package/dist/config/index.js +10 -18
  69. package/dist/config/index.js.map +1 -1
  70. package/dist/config/label.d.ts +6 -13
  71. package/dist/config/label.d.ts.map +1 -1
  72. package/dist/config/label.js +6 -13
  73. package/dist/config/label.js.map +1 -1
  74. package/dist/config/nav-count.d.ts +11 -19
  75. package/dist/config/nav-count.d.ts.map +1 -1
  76. package/dist/config/nav-count.js +11 -19
  77. package/dist/config/nav-count.js.map +1 -1
  78. package/dist/config/plugin-engine.d.ts +0 -10
  79. package/dist/config/plugin-engine.d.ts.map +1 -1
  80. package/dist/config/plugin-engine.js +1 -37
  81. package/dist/config/plugin-engine.js.map +1 -1
  82. package/dist/config/types.d.ts +94 -109
  83. package/dist/config/types.d.ts.map +1 -1
  84. package/dist/context/apply-defaults.d.ts +8 -31
  85. package/dist/context/apply-defaults.d.ts.map +1 -1
  86. package/dist/context/apply-defaults.js +12 -41
  87. package/dist/context/apply-defaults.js.map +1 -1
  88. package/dist/context/hook-pipeline.d.ts +4 -29
  89. package/dist/context/hook-pipeline.d.ts.map +1 -1
  90. package/dist/context/hook-pipeline.js +8 -41
  91. package/dist/context/hook-pipeline.js.map +1 -1
  92. package/dist/context/index.d.ts +4 -15
  93. package/dist/context/index.d.ts.map +1 -1
  94. package/dist/context/index.js +223 -215
  95. package/dist/context/index.js.map +1 -1
  96. package/dist/context/nested-operations.d.ts +7 -26
  97. package/dist/context/nested-operations.d.ts.map +1 -1
  98. package/dist/context/nested-operations.js +73 -171
  99. package/dist/context/nested-operations.js.map +1 -1
  100. package/dist/context/transaction-boundary.d.ts +36 -47
  101. package/dist/context/transaction-boundary.d.ts.map +1 -1
  102. package/dist/context/transaction-boundary.js +92 -79
  103. package/dist/context/transaction-boundary.js.map +1 -1
  104. package/dist/context/write-pipeline.d.ts +25 -64
  105. package/dist/context/write-pipeline.d.ts.map +1 -1
  106. package/dist/context/write-pipeline.js +81 -111
  107. package/dist/context/write-pipeline.js.map +1 -1
  108. package/dist/fields/format-prisma-default.d.ts.map +1 -1
  109. package/dist/fields/format-prisma-default.js +4 -7
  110. package/dist/fields/format-prisma-default.js.map +1 -1
  111. package/dist/fields/index.d.ts +17 -2
  112. package/dist/fields/index.d.ts.map +1 -1
  113. package/dist/fields/index.js +136 -147
  114. package/dist/fields/index.js.map +1 -1
  115. package/dist/filter/collect.d.ts +26 -3
  116. package/dist/filter/collect.d.ts.map +1 -1
  117. package/dist/filter/collect.js +30 -12
  118. package/dist/filter/collect.js.map +1 -1
  119. package/dist/filter/filter.test.js +98 -15
  120. package/dist/filter/filter.test.js.map +1 -1
  121. package/dist/filter/index.d.ts +1 -0
  122. package/dist/filter/index.d.ts.map +1 -1
  123. package/dist/filter/index.js.map +1 -1
  124. package/dist/filter/map.d.ts.map +1 -1
  125. package/dist/filter/map.js +0 -5
  126. package/dist/filter/map.js.map +1 -1
  127. package/dist/filter/parse.d.ts.map +1 -1
  128. package/dist/filter/parse.js +2 -9
  129. package/dist/filter/parse.js.map +1 -1
  130. package/dist/filter/serialize.d.ts.map +1 -1
  131. package/dist/filter/serialize.js +2 -4
  132. package/dist/filter/serialize.js.map +1 -1
  133. package/dist/hooks/index.d.ts +4 -42
  134. package/dist/hooks/index.d.ts.map +1 -1
  135. package/dist/hooks/index.js +5 -59
  136. package/dist/hooks/index.js.map +1 -1
  137. package/dist/index.d.ts +3 -1
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +20 -4
  140. package/dist/index.js.map +1 -1
  141. package/dist/internal.d.ts +1 -0
  142. package/dist/internal.d.ts.map +1 -1
  143. package/dist/internal.js +4 -0
  144. package/dist/internal.js.map +1 -1
  145. package/dist/lib/case-utils.d.ts +0 -32
  146. package/dist/lib/case-utils.d.ts.map +1 -1
  147. package/dist/lib/case-utils.js +0 -32
  148. package/dist/lib/case-utils.js.map +1 -1
  149. package/dist/mcp/handler.d.ts +0 -4
  150. package/dist/mcp/handler.d.ts.map +1 -1
  151. package/dist/mcp/handler.js +12 -69
  152. package/dist/mcp/handler.js.map +1 -1
  153. package/dist/query/index.d.ts +55 -227
  154. package/dist/query/index.d.ts.map +1 -1
  155. package/dist/query/index.js +41 -117
  156. package/dist/query/index.js.map +1 -1
  157. package/dist/query/relationship-options.d.ts +1 -1
  158. package/dist/query/relationship-options.js +1 -1
  159. package/dist/utils/password.d.ts +0 -68
  160. package/dist/utils/password.d.ts.map +1 -1
  161. package/dist/utils/password.js +7 -76
  162. package/dist/utils/password.js.map +1 -1
  163. package/dist/validation/field-config.d.ts.map +1 -1
  164. package/dist/validation/field-config.js +0 -6
  165. package/dist/validation/field-config.js.map +1 -1
  166. package/dist/validation/schema.d.ts +0 -7
  167. package/dist/validation/schema.d.ts.map +1 -1
  168. package/dist/validation/schema.js +0 -10
  169. package/dist/validation/schema.js.map +1 -1
  170. package/package.json +1 -1
  171. package/src/access/access-filter.test.ts +205 -275
  172. package/src/access/access-filter.ts +236 -272
  173. package/src/access/declared-dependencies.test.ts +277 -0
  174. package/src/access/declared-dependencies.ts +117 -37
  175. package/src/access/depth-limits.ts +8 -7
  176. package/src/access/engine.ts +0 -25
  177. package/src/access/errors.ts +97 -12
  178. package/src/access/field-access.test.ts +312 -2
  179. package/src/access/field-access.ts +118 -42
  180. package/src/access/field-transforms.ts +8 -39
  181. package/src/access/field-visibility.ts +99 -45
  182. package/src/access/index.ts +17 -5
  183. package/src/access/query-validation.ts +359 -0
  184. package/src/access/relationship-count.ts +3 -11
  185. package/src/access/relationship-label-filter.test.ts +19 -68
  186. package/src/access/relationship-label-filter.ts +27 -104
  187. package/src/access/transaction-registry.ts +58 -0
  188. package/src/access/types.ts +83 -86
  189. package/src/config/index.ts +10 -22
  190. package/src/config/label.ts +6 -13
  191. package/src/config/nav-count.ts +11 -19
  192. package/src/config/plugin-engine.ts +1 -37
  193. package/src/config/types.ts +95 -110
  194. package/src/context/apply-defaults.ts +12 -44
  195. package/src/context/hook-pipeline.ts +12 -67
  196. package/src/context/index.ts +311 -276
  197. package/src/context/nested-operations.ts +94 -226
  198. package/src/context/transaction-boundary.ts +113 -109
  199. package/src/context/write-pipeline.ts +99 -155
  200. package/src/fields/format-prisma-default.ts +4 -7
  201. package/src/fields/index.ts +155 -147
  202. package/src/filter/collect.ts +48 -12
  203. package/src/filter/filter.test.ts +153 -15
  204. package/src/filter/index.ts +1 -0
  205. package/src/filter/map.ts +0 -5
  206. package/src/filter/parse.ts +2 -9
  207. package/src/filter/serialize.ts +2 -4
  208. package/src/hooks/index.ts +5 -59
  209. package/src/index.ts +23 -4
  210. package/src/internal.ts +5 -0
  211. package/src/lib/case-utils.ts +0 -32
  212. package/src/mcp/handler.ts +13 -71
  213. package/src/query/index.ts +82 -235
  214. package/src/query/relationship-options.ts +1 -1
  215. package/src/utils/password.ts +7 -76
  216. package/src/validation/field-config.ts +0 -6
  217. package/src/validation/schema.ts +0 -10
  218. package/tests/access-relationships.test.ts +18 -16
  219. package/tests/computed-field-selective-evaluation.test.ts +418 -0
  220. package/tests/context.test.ts +727 -1
  221. package/tests/field-types.test.ts +222 -0
  222. package/tests/mcp-handler.test.ts +34 -0
  223. package/tests/needs-declared-dependencies.test.ts +7 -4
  224. package/tests/resolve-chain.test.ts +11 -11
  225. package/tests/transaction-boundary-outermost.test.ts +530 -0
  226. package/tsconfig.tsbuildinfo +1 -1
@@ -1,147 +1,40 @@
1
1
  import { checkAccess, getRelatedListConfig } from './engine.js';
2
2
  import { READ_INCLUDE_MAX_DEPTH } from './depth-limits.js';
3
- import { AccessScopeDepthExceededError } from './errors.js';
4
- /**
5
- * Collapse a rich, provenance-carrying include entry down to the plain
6
- * Prisma-shaped form. A `nested` result that is `depth-exceeded` or
7
- * `nothing-to-scope` contributes no `include` key this is the AUTO-include
8
- * silently stopping, which is correct when no caller asked for anything past
9
- * this point (see `AccessIncludeResult` doc comment).
10
- */
11
- function toPrismaEntry(entry) {
12
- const result = {};
13
- if (entry.where)
14
- result.where = entry.where;
15
- if (entry.nested.kind === 'scoped') {
16
- const nestedInclude = toPrismaInclude(entry.nested);
17
- if (nestedInclude && Object.keys(nestedInclude).length > 0) {
18
- result.include = nestedInclude;
19
- }
20
- }
21
- return Object.keys(result).length > 0 ? result : true;
22
- }
23
- /**
24
- * Collapse an `AccessIncludeResult` to the plain Prisma `include` shape used
25
- * when there is no caller-supplied include to merge against (the direct
26
- * auto-include path). `nothing-to-scope` and `depth-exceeded` both become
27
- * `undefined` here — at this call site nothing was explicitly requested past
28
- * either boundary, so there is nothing to deny.
29
- */
30
- export function toPrismaInclude(result) {
31
- if (result.kind !== 'scoped')
32
- return undefined;
33
- const out = {};
34
- for (const [key, entry] of Object.entries(result.include)) {
35
- out[key] = toPrismaEntry(entry);
36
- }
37
- return out;
38
- }
39
- /**
40
- * Build the access-controlled include for a list's fields.
41
- *
42
- * This allows us to filter relationships at the database level instead of in
43
- * memory. Returns an {@link AccessIncludeResult} rather than a plain include
44
- * object so that `mergeIncludeWithAccessControl` can tell a genuine "nothing
45
- * to scope" apart from "the engine hit its depth cap" (see that type's doc
46
- * comment and ADR-0022).
47
- */
48
- export async function buildIncludeWithAccessControl(fieldConfigs, args, config, depth = 0,
49
- // List names already on the path from the root to here. Used to detect
50
- // relationship cycles (A → B → … → A) and stop the auto-include from
51
- // re-descending them. Seed it with the root list name at the call site.
52
- visitedLists = []) {
53
- if (depth >= READ_INCLUDE_MAX_DEPTH) {
54
- return { kind: 'depth-exceeded' };
55
- }
56
- // Inside a resolveOutput/virtual-field context we still scope each immediate
57
- // relation (its own access `where`), but do not auto-expand INTO its nested
58
- // relations — this keeps a single hook-issued read's include from growing
59
- // depth-first. Correction (ADR-0023): this does NOT by itself terminate a
60
- // cycle, despite what an earlier version of this comment claimed. A
61
- // self-referential relation read from inside a hook is a NEW top-level
62
- // read, invisible to this function's own recursion — the loop runs through
63
- // the hook↔read boundary, not through repeated calls to
64
- // `buildIncludeWithAccessControl`. Loop termination is the resolve chain's
65
- // job: `field-visibility.ts`'s `resolveReadableFieldValue` refuses to
66
- // re-enter a `(list, field)` pair already on the chain. What this check
67
- // still does correctly is row-scope the immediate relation rather than
68
- // skipping scoping altogether (issue #830's second trigger).
69
- const insideResolveOutput = args.context._resolveOutputChain.length > 0;
70
- const include = {};
71
- let hasRelationships = false;
72
- for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
73
- if (fieldConfig?.type === 'relationship' && 'ref' in fieldConfig && fieldConfig.ref) {
74
- hasRelationships = true;
75
- const relatedConfig = getRelatedListConfig(fieldConfig.ref, config);
76
- if (relatedConfig) {
77
- // Check query access for the related list
78
- const queryAccess = relatedConfig.listConfig.access?.operation?.query;
79
- const accessResult = await checkAccess(queryAccess, {
80
- session: args.session,
81
- context: args.context,
82
- });
83
- // If access is completely denied, exclude this relationship
84
- if (accessResult === false) {
85
- continue;
86
- }
87
- const where = typeof accessResult === 'object' ? accessResult : undefined;
88
- // Cycle guard: if the related list already appears on the path from the
89
- // root, DO NOT auto-include its relationships again. On a cyclic
90
- // readable-relationship graph (A → B → … → A) the depth-first walk would
91
- // otherwise re-descend the cycle on every branch, and — combined with the
92
- // bare-`true` leaf re-expansion in `mergeIncludeWithAccessControl` — build
93
- // an include tree deep/large enough to overflow the call stack in
94
- // downstream processing (the RSC serializer's recursive `Map.set`). This
95
- // extends the SF-20 (#566) fix: a bare-`true` leaf must resolve to a
96
- // genuine single-level fetch, not a re-expansion of the full auto-include.
97
- // The relation itself is still included (as a FLAT fetch of its own
98
- // columns); only its onward relationships are pruned at the back-edge.
99
- let nested = { kind: 'nothing-to-scope' };
100
- const relatedListName = relatedConfig.listName;
101
- if (!insideResolveOutput && !visitedLists.includes(relatedListName)) {
102
- nested = await buildIncludeWithAccessControl(relatedConfig.listConfig.fields, args, config, depth + 1, [...visitedLists, relatedListName]);
103
- }
104
- include[fieldName] = { where, nested };
105
- }
106
- }
107
- }
108
- return hasRelationships ? { kind: 'scoped', include } : { kind: 'nothing-to-scope' };
3
+ import { AccessScopeDepthExceededError, RelationFilterAccessDeniedError } from './errors.js';
4
+ import { LOGICAL_OPERATORS, RELATION_QUANTIFIERS, resolveQueryField, walkWhereReadAccess, } from './query-validation.js';
5
+ /** A plain object — excludes `null` and arrays, which `typeof x === 'object'` alone would admit. */
6
+ function isPlainObject(value) {
7
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
109
8
  }
110
9
  /**
111
10
  * Narrow an unknown include value to the structured object form (vs bare `true`
112
11
  * or any other primitive). Caller-supplied includes arrive untyped at the
113
- * runtime boundary, so we validate the shape here rather than casting.
12
+ * runtime boundary: narrow to a plain object first, then validate each field's
13
+ * own type before trusting it, rather than casting the whole value wholesale.
114
14
  *
115
15
  * A numeric `take` on a to-many relation include (a caller-supplied row bound,
116
16
  * issue #752) is carried through: it only ever NARROWS the fetched rows and can
117
- * never widen past the access `where`, so preserving it is access-neutral. The
118
- * access-controlled include never sets `take` itself — it originates solely
119
- * from the caller — so `mergeIncludeWithAccessControl` re-attaches it below.
17
+ * never widen past the access `where`, so preserving it is access-neutral.
120
18
  */
121
19
  function asEntryObject(value) {
122
- if (value && typeof value === 'object') {
123
- const obj = value;
124
- const where = obj.where;
125
- const include = obj.include;
126
- const take = obj.take;
127
- const entry = {};
128
- if (where && typeof where === 'object')
129
- entry.where = where;
130
- if (include && typeof include === 'object')
131
- entry.include = include;
132
- if (typeof take === 'number')
133
- entry.take = take;
134
- return entry;
135
- }
136
- return null;
20
+ if (!isPlainObject(value))
21
+ return null;
22
+ const { where, include, take } = value;
23
+ const entry = {};
24
+ if (isPlainObject(where))
25
+ entry.where = where;
26
+ if (isPlainObject(include))
27
+ entry.include = include;
28
+ if (typeof take === 'number')
29
+ entry.take = take;
30
+ return entry;
137
31
  }
138
32
  /**
139
33
  * AND-combine an access `where` with a caller-supplied nested `where`.
140
34
  *
141
35
  * The access filter is authoritative: the caller's filter may only NARROW the
142
36
  * result further, never widen past what access permits. We therefore wrap both
143
- * in a Prisma `AND` so neither can override the other. If only one side is
144
- * present, it is returned as-is; if neither is present, the result is undefined.
37
+ * in a Prisma `AND` so neither can override the other.
145
38
  */
146
39
  function andWhere(accessWhere, callerWhere) {
147
40
  if (accessWhere && callerWhere) {
@@ -150,104 +43,185 @@ function andWhere(accessWhere, callerWhere) {
150
43
  return accessWhere ?? callerWhere;
151
44
  }
152
45
  /**
153
- * Merge a caller-supplied `include` with the access-controlled include — phase-1
154
- * row/relation scoping for explicit caller selections.
155
- *
156
- * The caller's `include` decides WHICH relations to fetch; access control decides
157
- * WHETHER each relation may be fetched and WITH WHAT filter. Replacing the
158
- * access-controlled include with the caller's wholesale (the bug in #566) drops
159
- * every per-relation access `where` and denied-relation exclusion, silently
160
- * bypassing row-level access on any non-sudo read that passes `include`.
46
+ * Build the access-scoped `include` for exactly the relations a read
47
+ * requested, recursing only into branches `requestedInclude` itself names.
161
48
  *
162
- * For each relation the caller asks to include:
163
- * - If the relation is a config-declared relationship but is ABSENT from the
164
- * access-controlled include, its `query` access returned `false` it is DROPPED
165
- * (not fetched).
166
- * - If it is present (allowed, possibly with a filter), the access entry is used
167
- * as the base: the access `where` is AND-combined with any caller-supplied
168
- * nested `where`, and nested includes are recursively merged using the related
169
- * list's field configs (so deeply-nested selections are filtered at every
170
- * level). A bare caller `true` becomes the access-controlled shape (filter +
171
- * nested filtered include), never bare `true`.
172
- * - If the caller names a key that is NOT a config-declared relationship, it is
173
- * passed through unchanged (access control does not govern it).
49
+ * For each key in `requestedInclude`:
50
+ * - Not a config-declared relationship access control does not govern it;
51
+ * passed through unchanged (e.g. a fragment/caller key that isn't a
52
+ * relationship at all).
53
+ * - A declared relationship whose related list's `query` access denies it
54
+ * (`=== false`) dropped entirely, no matter what the request asked for
55
+ * nested beneath it (#566): the caller chooses *which* relations, access
56
+ * control chooses *whether* and *with what filter*.
57
+ * - Otherwise the access `where` is AND-combined with any caller-supplied
58
+ * nested `where` (never replaced — the other half of #566), a
59
+ * caller-supplied `take` rides through unchanged (#752), and the "One
60
+ * hop" rule (ADR-0026) nested relations are scoped ONLY if
61
+ * `requestedInclude` itself named a nested `include` here. A bare relation
62
+ * (or one with no nested `include`) fetches its own columns and stops: no
63
+ * recursive call, no access evaluation on anything beneath it.
174
64
  *
175
- * `accessControlledInclude` is the {@link AccessIncludeResult} for THIS level:
176
- * - `nothing-to-scope` nothing to merge against (the list has no
177
- * relationships, or we're inside a resolveOutput context where the caller
178
- * include is irrelevant to begin with). Pass the caller's include through
179
- * unchanged this is a non-denial outcome, not "every relation denied".
180
- * - `depth-exceeded` the engine could not compute a scope for THIS level at
181
- * all because it sits at or past `READ_INCLUDE_MAX_DEPTH`. If the caller
182
- * named anything here, that is exactly the case that used to pass through
183
- * unscoped (issue #830): throw `AccessScopeDepthExceededError` instead. An
184
- * empty caller include at this level (nothing further requested) is not an
185
- * error — there's simply nothing to do.
186
- * - `scoped` → the normal per-relation merge below: a declared relationship
187
- * ABSENT from the access include was denied (drop it); one PRESENT is used
188
- * as the base, AND-combining `where`s and recursing into nested includes.
189
- *
190
- * `listKey` and `depth` are carried only to build a useful
191
- * `AccessScopeDepthExceededError` message; they do not affect merge behaviour.
65
+ * **Depth is a cost limit, not a cycle guard (ADR-0026).** A `requestedInclude`
66
+ * is always a finite literal the caller's own object, or
67
+ * `foldDeclaredDependencies`'s already-cycle-guarded fold so this recursion
68
+ * cannot loop unboundedly on its own; nothing here walks the relationship
69
+ * graph unprompted. `READ_INCLUDE_MAX_DEPTH` still bounds how deep a request
70
+ * may reach, fail-closed per ADR-0022: a request naming anything at or past
71
+ * the cap throws `AccessScopeDepthExceededError` rather than silently
72
+ * returning less than what was asked for.
192
73
  */
193
- export function mergeIncludeWithAccessControl(callerInclude, accessControlledInclude, fieldConfigs, config, listKey, depth = 0) {
194
- if (accessControlledInclude.kind === 'nothing-to-scope') {
195
- return callerInclude;
196
- }
197
- if (accessControlledInclude.kind === 'depth-exceeded') {
198
- const [firstRelationName] = Object.keys(callerInclude);
199
- if (firstRelationName !== undefined) {
200
- throw new AccessScopeDepthExceededError(listKey, firstRelationName, depth);
201
- }
202
- return {};
74
+ export async function buildAccessScopedInclude(requestedInclude, fieldConfigs, args, config, listKey, depth = 0) {
75
+ const requestedKeys = Object.keys(requestedInclude);
76
+ if (depth >= READ_INCLUDE_MAX_DEPTH && requestedKeys.length > 0) {
77
+ throw new AccessScopeDepthExceededError(listKey, requestedKeys[0], depth);
203
78
  }
204
- const merged = {};
205
- const accessInclude = accessControlledInclude.include;
206
- for (const [relationName, callerValue] of Object.entries(callerInclude)) {
79
+ const result = {};
80
+ for (const [relationName, requestedValue] of Object.entries(requestedInclude)) {
207
81
  const fieldConfig = fieldConfigs[relationName];
208
82
  const isDeclaredRelationship = fieldConfig?.type === 'relationship' && 'ref' in fieldConfig && !!fieldConfig.ref;
209
- // Not a config-declared relationship → access control does not govern it; pass through unchanged.
210
83
  if (!isDeclaredRelationship) {
211
- merged[relationName] = callerValue;
212
- continue;
213
- }
214
- const accessEntry = accessInclude[relationName];
215
- // Declared relationship absent from the access include → query access denied → drop it.
216
- if (accessEntry === undefined) {
84
+ result[relationName] = requestedValue;
217
85
  continue;
218
86
  }
219
- const callerEntry = asEntryObject(callerValue);
220
- // Resolve the related list's field configs so nested includes merge recursively.
221
87
  const relatedConfig = getRelatedListConfig(fieldConfig.ref, config);
222
- const relatedFields = relatedConfig?.listConfig.fields;
223
- const mergedWhere = andWhere(accessEntry.where, callerEntry?.where);
224
- let mergedNested;
225
- if (callerEntry?.include && relatedFields && relatedConfig) {
226
- // Recurse: scope the caller's nested selection against the nested access
227
- // result. If that result is 'depth-exceeded', the recursive call itself
228
- // throws — the caller named something the engine cannot scope.
229
- mergedNested = mergeIncludeWithAccessControl(callerEntry.include, accessEntry.nested, relatedFields, config, relatedConfig.listName, depth + 1);
88
+ if (!relatedConfig)
89
+ continue;
90
+ const queryAccess = relatedConfig.listConfig.access?.operation?.query;
91
+ const accessResult = await checkAccess(queryAccess, {
92
+ session: args.session,
93
+ context: args.context,
94
+ });
95
+ if (accessResult === false) {
96
+ continue;
230
97
  }
231
- else if (accessEntry.nested.kind === 'scoped') {
232
- // Caller selected the relation bare (no nested include); keep the
233
- // access-controlled nested include so deeper relations stay filtered.
234
- mergedNested = toPrismaInclude(accessEntry.nested);
98
+ const accessWhere = typeof accessResult === 'object' ? accessResult : undefined;
99
+ const requestedEntry = asEntryObject(requestedValue);
100
+ const mergedWhere = andWhere(accessWhere, requestedEntry?.where);
101
+ let nestedInclude;
102
+ if (requestedEntry?.include) {
103
+ nestedInclude = await buildAccessScopedInclude(requestedEntry.include, relatedConfig.listConfig.fields, args, config, relatedConfig.listName, depth + 1);
235
104
  }
236
- // If the caller's entry has no nested include, a 'depth-exceeded' nested
237
- // result is silent here too — nothing was asked for past this point.
238
105
  const entry = {};
239
106
  if (mergedWhere)
240
107
  entry.where = mergedWhere;
241
- if (mergedNested && Object.keys(mergedNested).length > 0)
242
- entry.include = mergedNested;
243
- // Preserve a caller-supplied row bound on the relation (issue #752). It only
244
- // narrows, never widens, so it rides on top of the access `where`/include.
245
- if (callerEntry?.take !== undefined)
246
- entry.take = callerEntry.take;
247
- // A bare-`true` relation with no access filter, nested include, or row bound stays `true`.
248
- merged[relationName] = Object.keys(entry).length > 0 ? entry : true;
108
+ if (nestedInclude && Object.keys(nestedInclude).length > 0)
109
+ entry.include = nestedInclude;
110
+ if (requestedEntry?.take !== undefined)
111
+ entry.take = requestedEntry.take;
112
+ result[relationName] = Object.keys(entry).length > 0 ? entry : true;
113
+ }
114
+ return result;
115
+ }
116
+ /**
117
+ * Scope every relation filter (`some`/`every`/`none`/`is`/`isNot`) nested in a
118
+ * caller's `where` by the related list's own `query` access — the `where`
119
+ * counterpart to `buildAccessScopedInclude` above, closing #916 (the
120
+ * "unclosed half of ADR-0022"). `include` and `where` are fundamentally
121
+ * different requests (which relations come back, vs. which parent rows
122
+ * match), so this is a distinct function, but it shares every primitive that
123
+ * matters: `checkAccess`/`getRelatedListConfig` (the same access-evaluation
124
+ * calls `buildAccessScopedInclude` makes), `andWhere` (the same AND-fold), and
125
+ * `resolveQueryField`/`LOGICAL_OPERATORS`/`RELATION_QUANTIFIERS`/
126
+ * `walkWhereReadAccess` (the same shape-recognition and field-read check
127
+ * `query-validation.ts` already uses for #912/#915) — there is no second,
128
+ * parallel implementation of any of those decisions.
129
+ *
130
+ * For each relationship key found (at any depth — the walk recurses through
131
+ * `AND`/`OR`/`NOT` and through every hop of a chain):
132
+ * - Not a declared relationship, or the key #912 already rejected (this walk
133
+ * runs strictly after that check) → passed through unchanged.
134
+ * - The related list's `query` access denies it (`=== false`) → THROWS
135
+ * `RelationFilterAccessDeniedError`. Unlike `buildAccessScopedInclude`'s
136
+ * silent drop, this is a loud failure: a `where` predicate has no neutral
137
+ * "not requested" outcome the way a missing `include` key does, so a
138
+ * silently-empty match would itself be a distinguishable signal (ADR-0022).
139
+ * - Otherwise → the access filter (if any) is AND-combined into the relation
140
+ * quantifier's nested clause (never replacing the caller's own condition,
141
+ * mirroring `andWhere`'s include-side contract), keys inside that nested
142
+ * clause are checked against the RELATED list's field-level `read` access
143
+ * (`walkWhereReadAccess`, closing #915's stated gap for this path), and the
144
+ * walk recurses into the related list's own fields for a further hop.
145
+ *
146
+ * One quantifier is deliberately conservative rather than exactly precise:
147
+ * folding the access filter into `every`'s nested clause with a plain AND
148
+ * makes `every` require every related row to be BOTH access-visible AND
149
+ * matching, not "every access-visible row matches" (the latter needs a
150
+ * `NOT`/`OR` transform this does not attempt). The conservative version can
151
+ * only reject a query that the precise version would allow — it never
152
+ * widens what a caller can learn — so it is the safe direction to ship; a
153
+ * caller can observe that an inaccessible related row exists (an `every`
154
+ * that "should" pass instead fails), but never that row's field values,
155
+ * which is the property this ticket exists to close.
156
+ */
157
+ export async function buildAccessScopedWhere(where,
158
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ListConfig must accept any TypeInfo
159
+ listConfig, listName, config, args) {
160
+ if (where === null || typeof where !== 'object')
161
+ return where;
162
+ if (Array.isArray(where)) {
163
+ return Promise.all(where.map((entry) => buildAccessScopedWhere(entry, listConfig, listName, config, args)));
249
164
  }
250
- return merged;
165
+ const result = {};
166
+ for (const [key, value] of Object.entries(where)) {
167
+ if (LOGICAL_OPERATORS.has(key)) {
168
+ result[key] = await buildAccessScopedWhere(value, listConfig, listName, config, args);
169
+ continue;
170
+ }
171
+ const resolved = resolveQueryField(key, listConfig.fields);
172
+ if (!resolved ||
173
+ !resolved.isRelationship ||
174
+ value === null ||
175
+ typeof value !== 'object' ||
176
+ Array.isArray(value)) {
177
+ result[key] = value;
178
+ continue;
179
+ }
180
+ const related = getRelatedListConfig(resolved.fieldConfig.ref, config);
181
+ if (!related) {
182
+ result[key] = value;
183
+ continue;
184
+ }
185
+ const queryAccess = related.listConfig.access?.operation?.query;
186
+ const accessResult = await checkAccess(queryAccess, {
187
+ session: args.session,
188
+ context: args.context,
189
+ });
190
+ if (accessResult === false) {
191
+ throw new RelationFilterAccessDeniedError(listName, key, related.listName);
192
+ }
193
+ const accessWhere = typeof accessResult === 'object' ? accessResult : undefined;
194
+ const relationEntries = Object.entries(value);
195
+ const hasQuantifier = relationEntries.some(([k]) => RELATION_QUANTIFIERS.has(k));
196
+ if (hasQuantifier) {
197
+ const nestedEntry = {};
198
+ for (const [quantifier, quantifierValue] of relationEntries) {
199
+ if (!RELATION_QUANTIFIERS.has(quantifier)) {
200
+ nestedEntry[quantifier] = quantifierValue;
201
+ continue;
202
+ }
203
+ await walkWhereReadAccess(quantifierValue, related.listConfig, related.listName, args);
204
+ const scopedNested = await buildAccessScopedWhere(quantifierValue, related.listConfig, related.listName, config, args);
205
+ nestedEntry[quantifier] = accessWhere
206
+ ? andWhere(accessWhere, scopedNested)
207
+ : scopedNested;
208
+ }
209
+ result[key] = nestedEntry;
210
+ }
211
+ else {
212
+ // Prisma's direct-nesting to-one form: the whole value IS the nested
213
+ // WHERE clause, with no `is` wrapper. Only wrap it in `is` when there is
214
+ // an access filter to fold in — an unwrapped value that needs no fold
215
+ // (fully-allowed related list) is returned exactly as the caller wrote
216
+ // it, so an already-permitted query is not perturbed by this pass.
217
+ await walkWhereReadAccess(value, related.listConfig, related.listName, args);
218
+ const scopedNested = await buildAccessScopedWhere(value, related.listConfig, related.listName, config, args);
219
+ result[key] = accessWhere
220
+ ? { is: andWhere(accessWhere, scopedNested) }
221
+ : scopedNested;
222
+ }
223
+ }
224
+ return result;
251
225
  }
252
226
  /**
253
227
  * Remove keys that correspond to `virtual` fields from a Prisma `include`
@@ -271,7 +245,6 @@ export function stripVirtualFieldsFromInclude(include, fieldConfigs, config) {
271
245
  const result = {};
272
246
  for (const [key, value] of Object.entries(include)) {
273
247
  const fieldConfig = fieldConfigs[key];
274
- // Virtual fields have no database column — drop them from the include.
275
248
  if (fieldConfig?.virtual)
276
249
  continue;
277
250
  const isDeclaredRelationship = fieldConfig?.type === 'relationship' && 'ref' in fieldConfig && !!fieldConfig.ref;
@@ -1 +1 @@
1
- {"version":3,"file":"access-filter.js","sourceRoot":"","sources":["../../src/access/access-filter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"access-filter.js","sourceRoot":"","sources":["../../src/access/access-filter.ts"],"names":[],"mappings":"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"}