Skip to content

Commit bd79104

Browse files
committed
refactor(runtime): callData decides the system bypass once, for the addressed object and the relation targets
One read of the execution context's system flag, so the system-context census row for callData's exposure bypass keeps describing one decision. Claude-Session: https://claude.ai/code/session_01ADzJtzYTLUfgrRZHxkagkX Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9e9aa0b commit bd79104

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

‎packages/runtime/src/action-execution.ts‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ const RELATION_CONDITION_TARGET_OPERATION = DATA_ACTION_TO_API_OPERATION[RELATIO
216216
* `callData` must not give two answers depending on whether the deployment
217217
* registered the protocol slot (the #5138 rule this file already keeps).
218218
*
219-
* Callers skip it for a system context, exactly as they skip the addressed
220-
* gate: these flags govern API exposure, not the engine's own reads. A schema
219+
* `callData` skips it for a system context on the one decision that skips the
220+
* addressed gate: these flags govern API exposure, not the engine's own reads. A schema
221221
* that cannot be resolved finds no condition (the filtered object) or serves
222222
* (a target), the gate's own fail-open.
223223
*/
@@ -287,7 +287,11 @@ export async function callData(deps: ActionExecutionDeps,
287287
// Honour the object's `apiEnabled` / `apiMethods` declarations for
288288
// external traffic. System/internal contexts bypass — these flags
289289
// govern API *exposure*, not internal engine self-writes.
290-
if (!executionContext?.isSystem && params?.object) {
290+
// [#22823] Decided ONCE, here: the same bypass covers each nested-relation
291+
// condition's target, asked below on the two arms that hand the engine a
292+
// caller's `where` ({@link refuseUnservedRelationTargets}).
293+
const exposureGated = !executionContext?.isSystem;
294+
if (exposureGated && params?.object) {
291295
let def: any;
292296
try {
293297
const meta = await deps.resolveService(requestContext, 'metadata', scopeId);
@@ -491,7 +495,7 @@ export async function callData(deps: ActionExecutionDeps,
491495
// [#22823] …and each nested-relation condition's TARGET, before the
492496
// engine reads it — the protocol path asks the same of the same
493497
// sites (`refuseUnservedRelationTarget`).
494-
if (!executionContext?.isSystem) {
498+
if (exposureGated) {
495499
await refuseUnservedRelationTargets(deps, requestContext, ql, params.object, bag.where, scopeId);
496500
}
497501
let all = await ql.find(params.object, findOpts(bag));
@@ -525,7 +529,7 @@ export async function callData(deps: ActionExecutionDeps,
525529
// is asked before the engine aggregates, as the query fallback asks
526530
// it (the engine lowers relation conditions in `where` only, never
527531
// in an aggregation's own `filter`).
528-
if (!executionContext?.isSystem) {
532+
if (exposureGated) {
529533
await refuseUnservedRelationTargets(deps, requestContext, engine, params.object, params.where, scopeId);
530534
}
531535
const rows = await engine.aggregate(

0 commit comments

Comments
 (0)