@opensaas/stack-core 0.33.0 → 0.35.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 (66) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +82 -0
  3. package/CLAUDE.md +4 -0
  4. package/dist/access/access-filter.d.ts.map +1 -1
  5. package/dist/access/access-filter.js +12 -7
  6. package/dist/access/access-filter.js.map +1 -1
  7. package/dist/access/access-filter.test.js +5 -1
  8. package/dist/access/access-filter.test.js.map +1 -1
  9. package/dist/access/depth-limits.d.ts +14 -0
  10. package/dist/access/depth-limits.d.ts.map +1 -1
  11. package/dist/access/depth-limits.js +14 -0
  12. package/dist/access/depth-limits.js.map +1 -1
  13. package/dist/access/errors.d.ts +24 -0
  14. package/dist/access/errors.d.ts.map +1 -1
  15. package/dist/access/errors.js +26 -0
  16. package/dist/access/errors.js.map +1 -1
  17. package/dist/access/field-visibility.d.ts.map +1 -1
  18. package/dist/access/field-visibility.js +72 -17
  19. package/dist/access/field-visibility.js.map +1 -1
  20. package/dist/access/index.d.ts +1 -0
  21. package/dist/access/index.d.ts.map +1 -1
  22. package/dist/access/index.js +2 -0
  23. package/dist/access/index.js.map +1 -1
  24. package/dist/access/multi-column-read-write.test.js +1 -1
  25. package/dist/access/multi-column-read-write.test.js.map +1 -1
  26. package/dist/access/relationship-count.test.js +1 -1
  27. package/dist/access/relationship-count.test.js.map +1 -1
  28. package/dist/access/relationship-label-filter.test.js +1 -1
  29. package/dist/access/relationship-label-filter.test.js.map +1 -1
  30. package/dist/access/types.d.ts +15 -7
  31. package/dist/access/types.d.ts.map +1 -1
  32. package/dist/context/index.d.ts.map +1 -1
  33. package/dist/context/index.js +73 -36
  34. package/dist/context/index.js.map +1 -1
  35. package/dist/context/write-pipeline.d.ts.map +1 -1
  36. package/dist/context/write-pipeline.js +5 -4
  37. package/dist/context/write-pipeline.js.map +1 -1
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +4 -0
  41. package/dist/index.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/access/access-filter.test.ts +5 -1
  44. package/src/access/access-filter.ts +12 -7
  45. package/src/access/depth-limits.ts +15 -0
  46. package/src/access/errors.ts +30 -0
  47. package/src/access/field-visibility.ts +87 -18
  48. package/src/access/index.ts +2 -0
  49. package/src/access/multi-column-read-write.test.ts +1 -1
  50. package/src/access/relationship-count.test.ts +1 -1
  51. package/src/access/relationship-label-filter.test.ts +1 -1
  52. package/src/access/types.ts +12 -5
  53. package/src/context/index.ts +99 -53
  54. package/src/context/write-pipeline.ts +5 -4
  55. package/src/index.ts +5 -0
  56. package/tests/access-relationships.test.ts +1 -1
  57. package/tests/bare-read-scalars.test.ts +147 -0
  58. package/tests/context.test.ts +2 -2
  59. package/tests/default-value-create.test.ts +1 -1
  60. package/tests/hook-pipeline.test.ts +1 -1
  61. package/tests/nav-count.test.ts +2 -2
  62. package/tests/nested-access-and-hooks.test.ts +10 -0
  63. package/tests/resolve-chain.test.ts +411 -0
  64. package/tests/singleton.test.ts +83 -0
  65. package/tests/write-pipeline.test.ts +1 -1
  66. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"write-pipeline.js","sourceRoot":"","sources":["../../src/context/write-pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"write-pipeline.js","sourceRoot":"","sources":["../../src/context/write-pipeline.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { getLabelFieldName, getItemLabel } from './config/label.js';
8
8
  export { resolveNavCounts, isListQueryStaticallyDenied } from './config/nav-count.js';
9
9
  export { ValidationError } from './hooks/index.js';
10
10
  export { AccessScopeDepthExceededError } from './access/index.js';
11
+ export { ResolveOutputCycleError } from './access/index.js';
11
12
  export { validateFieldConfig, validateConfigFields } from './validation/field-config.js';
12
13
  export type { FieldConfigValidationError } from './validation/field-config.js';
13
14
  export { defineFragment, runQuery, runQueryOne } from './query/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAKhD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAIf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAG1B,YAAY,EACV,aAAa,EACb,WAAW,EACX,OAAO,EACP,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAK5E,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAInE,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAGrF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAMlD,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAMjE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACxF,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAQ9E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAK7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACxE,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAOlG,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,cAAc,EACd,WAAW,EACX,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAM1B,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAMvC,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,uCAAuC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AAKhD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAIf,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAG1B,YAAY,EACV,aAAa,EACb,WAAW,EACX,OAAO,EACP,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAK5E,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAInE,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAGrF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAMlD,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAKjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAM3D,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACxF,YAAY,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAQ9E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAK7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AACxE,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAOlG,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,cAAc,EACd,WAAW,EACX,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAM1B,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAMvC,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,uCAAuC,CAAA"}
package/dist/index.js CHANGED
@@ -27,6 +27,10 @@ export { ValidationError } from './hooks/index.js';
27
27
  // `ValidationError` — this is the engine refusing to return unscoped data, not
28
28
  // a user-input validation failure.
29
29
  export { AccessScopeDepthExceededError } from './access/index.js';
30
+ // Thrown by a `resolveOutput` hook whose own read cycles back into a
31
+ // `(list, field)` pair already on its resolve chain (see ADR-0023). Distinct
32
+ // from `ValidationError` for the same reason as `AccessScopeDepthExceededError`.
33
+ export { ResolveOutputCycleError } from './access/index.js';
30
34
  // Field self-containment validation — checks each field implements the
31
35
  // generation contract (getPrismaType / getTypeScriptType / getZodSchema, or
32
36
  // getPrismaRelation for relationships) so a misimplemented field fails early
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,8CAA8C;AAC9C,EAAE;AACF,kEAAkE;AAClE,gEAAgE;AAChE,gEAAgE;AAChE,6DAA6D;AAC7D,yEAAyE;AACzE,kEAAkE;AAElE,kBAAkB;AAClB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AA8BhD,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAO/C,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5E,0EAA0E;AAC1E,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEnE,yEAAyE;AACzE,gFAAgF;AAChF,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAErF,gDAAgD;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,4EAA4E;AAC5E,wEAAwE;AACxE,+EAA+E;AAC/E,mCAAmC;AACnC,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAEjE,uEAAuE;AACvE,4EAA4E;AAC5E,6EAA6E;AAC7E,oEAAoE;AACpE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAGxF,qEAAqE;AACrE,wEAAwE;AACxE,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,gEAAgE;AAChE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGxE,qEAAqE;AACrE,6EAA6E;AAC7E,yEAAyE;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAGxE,0EAA0E;AAC1E,0EAA0E;AAC1E,6EAA6E;AAC7E,4EAA4E;AAC5E,0DAA0D;AAC1D,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAW1B,4EAA4E;AAC5E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAEvC,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,uCAAuC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,8CAA8C;AAC9C,EAAE;AACF,kEAAkE;AAClE,gEAAgE;AAChE,gEAAgE;AAChE,6DAA6D;AAC7D,yEAAyE;AACzE,kEAAkE;AAElE,kBAAkB;AAClB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAA;AA8BhD,kBAAkB;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAO/C,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5E,0EAA0E;AAC1E,yEAAyE;AACzE,2DAA2D;AAC3D,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEnE,yEAAyE;AACzE,gFAAgF;AAChF,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAErF,gDAAgD;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAElD,4EAA4E;AAC5E,wEAAwE;AACxE,+EAA+E;AAC/E,mCAAmC;AACnC,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAA;AAEjE,qEAAqE;AACrE,6EAA6E;AAC7E,iFAAiF;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAE3D,uEAAuE;AACvE,4EAA4E;AAC5E,6EAA6E;AAC7E,oEAAoE;AACpE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAGxF,qEAAqE;AACrE,wEAAwE;AACxE,4EAA4E;AAC5E,6EAA6E;AAC7E,+EAA+E;AAC/E,gEAAgE;AAChE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGxE,qEAAqE;AACrE,6EAA6E;AAC7E,yEAAyE;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAGxE,0EAA0E;AAC1E,0EAA0E;AAC1E,6EAA6E;AAC7E,4EAA4E;AAC5E,0DAA0D;AAC1D,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAA;AAW1B,4EAA4E;AAC5E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,OAAO,EACL,4BAA4B,EAC5B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAEvC,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,uCAAuC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensaas/stack-core",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "Core stack for OpenSaas - schema definition, access control, and runtime utilities",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -50,10 +50,14 @@ function cyclicConfig(): OpenSaasConfig {
50
50
  }
51
51
 
52
52
  function makeContext(resolveOutputDepth = 0): AccessContext {
53
+ const chain = Array.from({ length: resolveOutputDepth }, (_, i) => ({
54
+ listKey: 'TestHook',
55
+ fieldKey: `hook${i}`,
56
+ }))
53
57
  return {
54
58
  session: null,
55
59
  _isSudo: false,
56
- _resolveOutputCounter: { depth: resolveOutputDepth },
60
+ _resolveOutputChain: chain,
57
61
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- minimal context for unit test
58
62
  } as any
59
63
  }
@@ -117,13 +117,18 @@ export async function buildIncludeWithAccessControl(
117
117
 
118
118
  // Inside a resolveOutput/virtual-field context we still scope each immediate
119
119
  // relation (its own access `where`), but do not auto-expand INTO its nested
120
- // relations — no recursive call is made, so a self-referential relation
121
- // terminates after one level regardless of cycles. This prevents the
122
- // infinite loops the original passthrough guarded against (hooks making DB
123
- // queries that include relationships back to the same entity), while still
124
- // row-scoping the relation itself rather than skipping scoping altogether
125
- // (issue #830's second trigger).
126
- const insideResolveOutput = args.context._resolveOutputCounter.depth > 0
120
+ // relations — this keeps a single hook-issued read's include from growing
121
+ // depth-first. Correction (ADR-0023): this does NOT by itself terminate a
122
+ // cycle, despite what an earlier version of this comment claimed. A
123
+ // self-referential relation read from inside a hook is a NEW top-level
124
+ // read, invisible to this function's own recursion the loop runs through
125
+ // the hook↔read boundary, not through repeated calls to
126
+ // `buildIncludeWithAccessControl`. Loop termination is the resolve chain's
127
+ // job: `field-visibility.ts`'s `resolveReadableFieldValue` refuses to
128
+ // re-enter a `(list, field)` pair already on the chain. What this check
129
+ // still does correctly is row-scope the immediate relation rather than
130
+ // skipping scoping altogether (issue #830's second trigger).
131
+ const insideResolveOutput = args.context._resolveOutputChain.length > 0
127
132
 
128
133
  const include: RichIncludeObject = {}
129
134
  let hasRelationships = false
@@ -9,3 +9,18 @@
9
9
  * than passed through unscoped — see ADR-0022 and issue #830.
10
10
  */
11
11
  export const READ_INCLUDE_MAX_DEPTH = 5
12
+
13
+ /**
14
+ * Maximum length of the resolve chain — the ordered sequence of `resolveOutput`
15
+ * hooks a read has entered, each entry extended by a hook that issues its own
16
+ * read (see `_resolveOutputChain` on `AccessContext`).
17
+ *
18
+ * This is a COST limit, not an access-control boundary: an acyclic chain
19
+ * genuinely can exceed it and still be correct (e.g. a virtual `Order.total`
20
+ * reading a virtual `LineItem.subtotal` reading further virtuals), so
21
+ * exceeding it omits the field and emits a single `console.warn` rather than
22
+ * throwing. Termination itself is guaranteed by the separate cycle guard,
23
+ * which refuses to re-enter a `(list, field)` pair already on the chain
24
+ * regardless of this cap. See ADR-0023.
25
+ */
26
+ export const RESOLVE_CHAIN_MAX_LENGTH = 5
@@ -30,3 +30,33 @@ export class AccessScopeDepthExceededError extends Error {
30
30
  this.depth = depth
31
31
  }
32
32
  }
33
+
34
+ /**
35
+ * Thrown when a `resolveOutput` hook re-enters a `(list, field)` pair already
36
+ * on its own resolve chain — a hook whose own read (directly or transitively)
37
+ * comes back around to itself. Deliberately distinct from `ValidationError`
38
+ * (same reasoning as `AccessScopeDepthExceededError`): this is not bad user
39
+ * input, it is the engine refusing to run a hook chain that cannot terminate.
40
+ *
41
+ * This is a loud failure, not a Silent one, on purpose: a repeated pair never
42
+ * terminated before this guard existed, so no working application can depend
43
+ * on the old (hanging) behaviour, and staying silent here would return
44
+ * `undefined` for a field with nothing in the logs to explain why. Contrast
45
+ * with exceeding `RESOLVE_CHAIN_MAX_LENGTH`, which can happen on a chain that
46
+ * would otherwise terminate correctly and therefore only warns. See ADR-0023.
47
+ */
48
+ export class ResolveOutputCycleError extends Error {
49
+ public chain: readonly { listKey: string; fieldKey: string }[]
50
+
51
+ constructor(chain: readonly { listKey: string; fieldKey: string }[]) {
52
+ const path = chain.map((link) => `${link.listKey}.${link.fieldKey}`).join(' → ')
53
+ super(
54
+ `resolveOutput cycle detected: ${path}. A hook that re-enters a (list, field) pair ` +
55
+ `already on its own resolve chain cannot terminate, so the read is refused rather than ` +
56
+ `left to recurse until the process runs out of memory. Restructure the hooks so the read ` +
57
+ `does not loop back into itself.`,
58
+ )
59
+ this.name = 'ResolveOutputCycleError'
60
+ this.chain = chain
61
+ }
62
+ }
@@ -2,6 +2,15 @@ import type { Session, AccessContext } from './types.js'
2
2
  import type { OpenSaasConfig, FieldConfig } from '../config/types.js'
3
3
  import { getRelatedListConfig } from './engine.js'
4
4
  import { checkFieldAccess } from './field-access.js'
5
+ import { RESOLVE_CHAIN_MAX_LENGTH } from './depth-limits.js'
6
+ import { ResolveOutputCycleError } from './errors.js'
7
+ // NOTE: `context/index.ts` imports `filterReadableFields` from this module
8
+ // (via the `access/index.ts` barrel) — this is an intentional cyclic
9
+ // dependency, the same shape and for the same reason as the one documented in
10
+ // `context/write-pipeline.ts`. `buildDbDelegate` is only INVOKED when a
11
+ // `resolveOutput` hook actually runs (never during module evaluation), so by
12
+ // the time it runs the export is fully initialised.
13
+ import { buildDbDelegate } from '../context/index.js'
5
14
 
6
15
  /**
7
16
  * Field Visibility — phase 2 of the two-phase read (post-query).
@@ -36,6 +45,44 @@ type FieldVisibilityArgs = {
36
45
  context: AccessContext & { _isSudo?: boolean }
37
46
  }
38
47
 
48
+ /**
49
+ * Derive the context passed to a single `resolveOutput` hook invocation: a
50
+ * NEW context object whose `_resolveOutputChain` extends the caller's chain
51
+ * with this hook's own `(list, field)` link. The chain is never mutated in
52
+ * place — this is what lets concurrent hook invocations (e.g. sibling rows in
53
+ * a to-many relation, filtered via `Promise.all`) each see their own chain
54
+ * rather than racing on one shared value (ADR-0023).
55
+ *
56
+ * A plain `{ ...context, _resolveOutputChain }` spread is not enough on its
57
+ * own: `context.db`'s operations capture their `context` at construction
58
+ * (see `populateDbDelegate`), so a hook that calls `context.db.x.findMany(…)`
59
+ * would otherwise reach the ORIGINAL closures — bound to the ORIGINAL
60
+ * context — and its read would silently fall back to the un-extended chain,
61
+ * defeating the cycle guard entirely. Rebuilding `db` via `buildDbDelegate`
62
+ * against the derived context is what makes a hook-issued read's own nested
63
+ * hooks actually observe the extended chain.
64
+ *
65
+ * `config` is required to rebuild `db`; callers that cannot supply one (e.g. a
66
+ * narrow unit test exercising field access in isolation) still get a correct
67
+ * chain for THIS hook's own cycle/cap check, but a read that hook issues
68
+ * would not carry the chain any further — those callers are not exercising
69
+ * the read pipeline, so there is nothing for it to reach.
70
+ */
71
+ function deriveResolveOutputContext(
72
+ context: AccessContext & { _isSudo?: boolean },
73
+ link: { listKey: string; fieldKey: string },
74
+ config: OpenSaasConfig | undefined,
75
+ ): AccessContext & { _isSudo?: boolean } {
76
+ const derived: AccessContext & { _isSudo?: boolean } = {
77
+ ...context,
78
+ _resolveOutputChain: [...context._resolveOutputChain, link],
79
+ }
80
+ if (config) {
81
+ derived.db = buildDbDelegate(config, context.prisma, derived)
82
+ }
83
+ return derived
84
+ }
85
+
39
86
  /**
40
87
  * The core Field Visibility step for a single field: check read access and, if
41
88
  * granted, produce the output value by running any `resolveOutput` hook.
@@ -58,8 +105,9 @@ async function resolveReadableFieldValue(params: {
58
105
  hookItem: Record<string, unknown>
59
106
  listKey: string | undefined
60
107
  args: FieldVisibilityArgs
108
+ config: OpenSaasConfig | undefined
61
109
  }): Promise<{ readable: false } | { readable: true; value: unknown }> {
62
- const { fieldConfig, fieldName, value, accessItem, hookItem, listKey, args } = params
110
+ const { fieldConfig, fieldName, value, accessItem, hookItem, listKey, args, config } = params
63
111
 
64
112
  // Check field access (checkFieldAccess already handles sudo mode)
65
113
  const canRead = await checkFieldAccess(fieldConfig?.access, 'read', {
@@ -76,25 +124,44 @@ async function resolveReadableFieldValue(params: {
76
124
  // Cast to runtime type for generic execution
77
125
  // At runtime, the hook will receive the correct value type for the field
78
126
  const hook = fieldConfig.hooks.resolveOutput as unknown as ResolveOutputHookRuntime
79
- // Increment depth counter to prevent infinite loops from hooks making DB queries
80
- // that include relationships back to the same entity
81
- args.context._resolveOutputCounter.depth++
82
- try {
83
- // Use Promise.resolve() to handle both sync and async hooks
84
- const resolved = await Promise.resolve(
85
- hook({
86
- value,
87
- operation: 'query',
88
- fieldName,
89
- listKey,
90
- item: hookItem,
91
- context: args.context,
92
- }),
127
+ const link = { listKey, fieldKey: fieldName }
128
+ const chain = args.context._resolveOutputChain
129
+
130
+ // Cycle guard: a hook that would re-enter a (list, field) pair already on
131
+ // its own chain cannot terminate refuse loudly rather than recurse
132
+ // until the process runs out of memory (issue #844, ADR-0023).
133
+ const alreadyOnChain = chain.some(
134
+ (entry) => entry.listKey === link.listKey && entry.fieldKey === link.fieldKey,
135
+ )
136
+ if (alreadyOnChain) {
137
+ throw new ResolveOutputCycleError([...chain, link])
138
+ }
139
+
140
+ // Cost cap: a chain this long is refused only as a cost limit, never a
141
+ // correctness one — an acyclic chain that works today can legitimately
142
+ // reach this. Omit the field and warn instead of throwing.
143
+ if (chain.length >= RESOLVE_CHAIN_MAX_LENGTH) {
144
+ const path = [...chain, link].map((entry) => `${entry.listKey}.${entry.fieldKey}`).join(' → ')
145
+ console.warn(
146
+ `resolveOutput: omitting "${listKey}.${fieldName}" — its resolve chain exceeded ` +
147
+ `RESOLVE_CHAIN_MAX_LENGTH (${RESOLVE_CHAIN_MAX_LENGTH}): ${path}. This is a cost limit, ` +
148
+ `not an access denial.`,
93
149
  )
94
- return { readable: true, value: resolved }
95
- } finally {
96
- args.context._resolveOutputCounter.depth--
150
+ return { readable: false }
97
151
  }
152
+
153
+ // Use Promise.resolve() to handle both sync and async hooks
154
+ const resolved = await Promise.resolve(
155
+ hook({
156
+ value,
157
+ operation: 'query',
158
+ fieldName,
159
+ listKey,
160
+ item: hookItem,
161
+ context: deriveResolveOutputContext(args.context, link, config),
162
+ }),
163
+ )
164
+ return { readable: true, value: resolved }
98
165
  }
99
166
 
100
167
  return { readable: true, value }
@@ -227,6 +294,7 @@ export async function filterReadableFields<T extends Record<string, unknown>>(
227
294
  hookItem: workingItem,
228
295
  listKey,
229
296
  args,
297
+ config,
230
298
  })
231
299
 
232
300
  if (result.readable) {
@@ -265,6 +333,7 @@ export async function filterReadableFields<T extends Record<string, unknown>>(
265
333
  hookItem: filtered,
266
334
  listKey,
267
335
  args,
336
+ config,
268
337
  })
269
338
 
270
339
  if (result.readable) {
@@ -33,3 +33,5 @@ export type { AccessIncludeResult } from './access-filter.js'
33
33
  export { filterReadableFields } from './field-visibility.js'
34
34
  // Thrown when a caller include reaches past the depth the Access Filter can scope.
35
35
  export { AccessScopeDepthExceededError } from './errors.js'
36
+ // Thrown when a resolveOutput hook's own resolve chain cycles back into itself.
37
+ export { ResolveOutputCycleError } from './errors.js'
@@ -52,7 +52,7 @@ function makeContext(overrides: { isSudo?: boolean } = {}): AccessContext {
52
52
  return {
53
53
  session: null,
54
54
  _isSudo: overrides.isSudo ?? false,
55
- _resolveOutputCounter: { depth: 0 },
55
+ _resolveOutputChain: [],
56
56
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- minimal context for unit test
57
57
  } as any
58
58
  }
@@ -51,7 +51,7 @@ function makeContext(
51
51
  return {
52
52
  session: null,
53
53
  _isSudo: false,
54
- _resolveOutputCounter: { depth: 0 },
54
+ _resolveOutputChain: [],
55
55
  db: findMany ? { user: { findMany } } : {},
56
56
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- minimal context for unit test
57
57
  } as any
@@ -46,7 +46,7 @@ function makeContext(): AccessContext {
46
46
  return {
47
47
  session: null,
48
48
  _isSudo: false,
49
- _resolveOutputCounter: { depth: 0 },
49
+ _resolveOutputChain: [],
50
50
  db: {},
51
51
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- minimal context for unit test
52
52
  } as any
@@ -290,12 +290,19 @@ export interface AccessContext<TPrisma extends PrismaClientLike = PrismaClientLi
290
290
  plugins: Record<string, unknown>
291
291
  _isSudo: boolean
292
292
  /**
293
- * Internal mutable counter to track resolveOutput hook depth.
294
- * When depth > 0, we skip auto-including relationships to prevent infinite loops
295
- * when hooks make database queries that include relationships back to the original entity.
296
- * We use a mutable object so that spreading the context preserves the reference.
293
+ * The resolve chain: the ordered sequence of `resolveOutput` hook
294
+ * `(listKey, fieldKey)` pairs a read has entered on the way to here. A
295
+ * top-level read starts with an empty chain. Each hook invocation is given
296
+ * a NEW context whose chain extends this one by its own pair — the chain is
297
+ * never mutated in place, so concurrent hook invocations (e.g. sibling rows
298
+ * in a to-many relation processed via `Promise.all`) never observe each
299
+ * other's chain. A hook that would re-enter a pair already on its own chain
300
+ * is refused (`ResolveOutputCycleError`) rather than left to recurse
301
+ * forever; a chain longer than `RESOLVE_CHAIN_MAX_LENGTH` is a separate,
302
+ * non-fatal cost limit. See ADR-0023 and the "Resolve chain" glossary entry
303
+ * in CONTEXT.md.
297
304
  */
298
- _resolveOutputCounter: { depth: number }
305
+ _resolveOutputChain: readonly { listKey: string; fieldKey: string }[]
299
306
  }
300
307
 
301
308
  /**
@@ -7,7 +7,6 @@ import {
7
7
  buildIncludeWithAccessControl,
8
8
  mergeIncludeWithAccessControl,
9
9
  stripVirtualFieldsFromInclude,
10
- toPrismaInclude,
11
10
  } from '../access/index.js'
12
11
  import { ValidationError, DatabaseError } from '../hooks/index.js'
13
12
  import { getDbKey } from '../lib/case-utils.js'
@@ -434,7 +433,7 @@ export function getContext<
434
433
  // client, otherwise start empty and populate via plugin runtimes below.
435
434
  plugins: _sharedPlugins ?? {},
436
435
  _isSudo,
437
- _resolveOutputCounter: { depth: 0 },
436
+ _resolveOutputChain: [],
438
437
  }
439
438
 
440
439
  // Create access-controlled operations for each list, populating `db` in place.
@@ -978,8 +977,13 @@ function createFindUnique<TPrisma extends PrismaClientLike>(
978
977
  // Sudo bypasses access control entirely — the caller's include is trusted
979
978
  // and used as-is (matching the prior behaviour); no per-relation filtering.
980
979
  include = args.include
981
- } else {
982
- // Build include with access control filters
980
+ } else if (args.include) {
981
+ // Caller named relations to fetch — build the access-controlled include
982
+ // and MERGE (not replace) it with the caller's: the caller selects WHICH
983
+ // relations to fetch, access control decides WHETHER and WITH WHAT
984
+ // filter (#566). A caller include naming a relation past the depth the
985
+ // engine can scope throws `AccessScopeDepthExceededError` (issue #830)
986
+ // rather than being returned unscoped.
983
987
  const accessControlledInclude = await buildIncludeWithAccessControl(
984
988
  listConfig.fields,
985
989
  {
@@ -992,22 +996,19 @@ function createFindUnique<TPrisma extends PrismaClientLike>(
992
996
  // to it (self-referential or longer) stops re-descending.
993
997
  [listName],
994
998
  )
995
- // MERGE (not replace) a caller-supplied include with the access-controlled
996
- // include: the caller selects WHICH relations to fetch, access control
997
- // decides WHETHER and WITH WHAT filter (#566). A bare auto-include (no
998
- // caller include) still uses the access-controlled include directly. A
999
- // caller include naming a relation past the depth the engine can scope
1000
- // throws `AccessScopeDepthExceededError` (issue #830) rather than being
1001
- // returned unscoped.
1002
- include = args.include
1003
- ? mergeIncludeWithAccessControl(
1004
- args.include,
1005
- accessControlledInclude,
1006
- listConfig.fields,
1007
- config,
1008
- listName,
1009
- )
1010
- : toPrismaInclude(accessControlledInclude)
999
+ include = mergeIncludeWithAccessControl(
1000
+ args.include,
1001
+ accessControlledInclude,
1002
+ listConfig.fields,
1003
+ config,
1004
+ listName,
1005
+ )
1006
+ } else {
1007
+ // A bare read (no caller `include`) fetches the row's own columns only,
1008
+ // matching Prisma's semantics for the same call (ADR-0024). Relations
1009
+ // are fetched only when a caller names them. This also means no related
1010
+ // list's operation-level `query` access is evaluated on a bare read.
1011
+ include = undefined
1011
1012
  }
1012
1013
 
1013
1014
  // Virtual fields have no database column. Whichever path produced
@@ -1116,8 +1117,13 @@ function createFindMany<TPrisma extends PrismaClientLike>(
1116
1117
  // Sudo bypasses access control entirely — the caller's include is trusted
1117
1118
  // and used as-is (matching the prior behaviour); no per-relation filtering.
1118
1119
  include = args?.include
1119
- } else {
1120
- // Build include with access control filters
1120
+ } else if (args?.include) {
1121
+ // Caller named relations to fetch — build the access-controlled include
1122
+ // and MERGE (not replace) it with the caller's: the caller selects WHICH
1123
+ // relations to fetch, access control decides WHETHER and WITH WHAT
1124
+ // filter (#566). A caller include naming a relation past the depth the
1125
+ // engine can scope throws `AccessScopeDepthExceededError` (issue #830)
1126
+ // rather than being returned unscoped.
1121
1127
  const accessControlledInclude = await buildIncludeWithAccessControl(
1122
1128
  listConfig.fields,
1123
1129
  {
@@ -1130,22 +1136,19 @@ function createFindMany<TPrisma extends PrismaClientLike>(
1130
1136
  // to it (self-referential or longer) stops re-descending.
1131
1137
  [listName],
1132
1138
  )
1133
- // MERGE (not replace) a caller-supplied include with the access-controlled
1134
- // include: the caller selects WHICH relations to fetch, access control
1135
- // decides WHETHER and WITH WHAT filter (#566). A bare auto-include (no
1136
- // caller include) still uses the access-controlled include directly. A
1137
- // caller include naming a relation past the depth the engine can scope
1138
- // throws `AccessScopeDepthExceededError` (issue #830) rather than being
1139
- // returned unscoped.
1140
- include = args?.include
1141
- ? mergeIncludeWithAccessControl(
1142
- args.include,
1143
- accessControlledInclude,
1144
- listConfig.fields,
1145
- config,
1146
- listName,
1147
- )
1148
- : toPrismaInclude(accessControlledInclude)
1139
+ include = mergeIncludeWithAccessControl(
1140
+ args.include,
1141
+ accessControlledInclude,
1142
+ listConfig.fields,
1143
+ config,
1144
+ listName,
1145
+ )
1146
+ } else {
1147
+ // A bare read (no caller `include`) fetches each row's own columns only,
1148
+ // matching Prisma's semantics for the same call (ADR-0024). Relations
1149
+ // are fetched only when a caller names them. This also means no related
1150
+ // list's operation-level `query` access is evaluated on a bare read.
1151
+ include = undefined
1149
1152
  }
1150
1153
 
1151
1154
  // Virtual fields have no database column. Whichever path produced
@@ -1412,7 +1415,16 @@ function createGet<TPrisma extends PrismaClientLike>(
1412
1415
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1413
1416
  createFn: any,
1414
1417
  ) {
1415
- return async () => {
1418
+ return async (args?: {
1419
+ include?: Record<string, unknown>
1420
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1421
+ query?: any
1422
+ // `select` is not honoured — accepted only so the no-op can be made visible.
1423
+ select?: Record<string, unknown>
1424
+ }) => {
1425
+ // `select` is a visible no-op: warn, then proceed with include/query narrowing.
1426
+ warnIfSelectIgnored(args, listName, 'get')
1427
+
1416
1428
  // First try to find the existing record
1417
1429
  // Access Prisma model dynamically - required because model names are generated at runtime
1418
1430
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1437,24 +1449,54 @@ function createGet<TPrisma extends PrismaClientLike>(
1437
1449
  }
1438
1450
  }
1439
1451
 
1440
- // Build include with access control filters
1441
- const accessControlledInclude = await buildIncludeWithAccessControl(
1442
- listConfig.fields,
1443
- {
1444
- session: context.session,
1445
- context,
1446
- },
1447
- config,
1448
- 0,
1449
- // Seed the cycle guard with the root list so a relationship cycle back
1450
- // to it (self-referential or longer) stops re-descending.
1451
- [listName],
1452
- )
1452
+ // When a query fragment is provided, build the include from the fragment
1453
+ // instead of the access-controlled include. Access control still runs via
1454
+ // filterReadableFields; the fragment then narrows to only the requested fields.
1455
+ const fragment = isFragment(args?.query) ? args.query : null
1456
+ let include: Record<string, unknown> | undefined
1457
+
1458
+ if (fragment) {
1459
+ include = buildInclude(fragment._fields) ?? undefined
1460
+ } else if (context._isSudo) {
1461
+ // Sudo bypasses access control entirely the caller's include is trusted
1462
+ // and used as-is; no per-relation filtering.
1463
+ include = args?.include
1464
+ } else if (args?.include) {
1465
+ // Caller named relations to fetch — build the access-controlled include
1466
+ // and MERGE (not replace) it with the caller's, exactly like the other
1467
+ // read ops (#566/#830).
1468
+ const accessControlledInclude = await buildIncludeWithAccessControl(
1469
+ listConfig.fields,
1470
+ {
1471
+ session: context.session,
1472
+ context,
1473
+ },
1474
+ config,
1475
+ 0,
1476
+ // Seed the cycle guard with the root list so a relationship cycle back
1477
+ // to it (self-referential or longer) stops re-descending.
1478
+ [listName],
1479
+ )
1480
+ include = mergeIncludeWithAccessControl(
1481
+ args.include,
1482
+ accessControlledInclude,
1483
+ listConfig.fields,
1484
+ config,
1485
+ listName,
1486
+ )
1487
+ } else {
1488
+ // A bare read (no caller `include`) fetches the row's own columns only,
1489
+ // matching Prisma's semantics for the same call (ADR-0024).
1490
+ include = undefined
1491
+ }
1492
+
1493
+ // Virtual fields have no database column and must never reach Prisma (#628).
1494
+ include = stripVirtualFieldsFromInclude(include, listConfig.fields, config)
1453
1495
 
1454
1496
  // Try to find the record
1455
1497
  const item = await model.findFirst({
1456
1498
  where,
1457
- include: toPrismaInclude(accessControlledInclude),
1499
+ include,
1458
1500
  })
1459
1501
 
1460
1502
  // If record exists, return it
@@ -1471,6 +1513,10 @@ function createGet<TPrisma extends PrismaClientLike>(
1471
1513
  0,
1472
1514
  listName,
1473
1515
  )
1516
+ // When a fragment is provided, pick only the requested fields from the result
1517
+ if (fragment) {
1518
+ return pickFields(filtered, fragment._fields)
1519
+ }
1474
1520
  return filtered
1475
1521
  }
1476
1522