Skip to content

Commit 0edca88

Browse files
committed
fix(service-analytics): runtime strings state each decision in words instead of a tracker number (stage 8)
The read-scope compiler's undefined-comparand and non-boolean-flag refusals, the native-SQL cross-field backstop and the two /analytics/sql echo refusals no longer cite tracker numbers; each states the decision in words. The doc-authoring prose-id ledger is recomputed with --census-ledger and is now empty. Text only. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1ca1eb0 commit 0edca88

5 files changed

Lines changed: 32 additions & 30 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/service-analytics': patch
3+
---
4+
5+
The read-scope comparand refusals, the native-SQL cross-field backstop and the two display-SQL echo refusals no longer cite tracker numbers; each one states the decision behind it in words
6+
7+
Clause-②: no
8+
9+
Some strings the analytics service shows to operators and callers pointed at an issue-tracker number for the reason behind them. The number goes; where the sentence did not already say what was decided, it now does.
10+
11+
- The read-scope compiler's undefined-comparand refusal says an undefined comparand is refused rather than read as null, on the SQL drivers and on this door alike. Its refusal of a non-boolean `$null`, `$exists` or `$empty` comparand says a non-boolean comparand for any of the three is refused rather than coerced, on every driver and on this door alike. Both still say they fail closed, and that the producer to fix is whoever built the read scope, never the caller of the query.
12+
- The native-SQL strategy's cross-field backstop and the `/analytics/sql` echo's refusal of a field-reference comparison say the engine path's driver enforces the cross-field rules (declared same-table columns only, never the tenant-isolation column, one comparison class) with metadata it owns, so those rules are enforced in one place, next to the metadata they read.
13+
- That echo refusal and the echo's unmapped-operator refusal say the echo renders every predicate the query runs with, or refuses.
14+
15+
Text only: no status, error code, field, route or control flow moves. A client or log filter that matches the old text (for example a tracker-number suffix) needs the new spelling.

‎packages/services/service-analytics/src/read-scope-sql.ts‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,8 +1682,9 @@ function undefinedComparandError(field: string, path: string): Error {
16821682
`predicate was meant ({ "${field}": null } or { "${field}": { "$null": true } }), or omit the key ` +
16831683
`when the value is genuinely absent. The producer to fix is whoever BUILT this read scope — an ` +
16841684
`admin-authored sharing rule / permission set, its CEL lowering, or the in-process code that ` +
1685-
`assembled the FilterCondition — never the caller of this query, who cannot author it (#6050 ` +
1686-
`ruling B, pushed down to this compiler by #6125).`,
1685+
`assembled the FilterCondition — never the caller of this query, who cannot author it. An ` +
1686+
`undefined comparand is refused rather than read as null, on the SQL drivers and on this door ` +
1687+
`alike.`,
16871688
);
16881689
}
16891690

@@ -1870,7 +1871,8 @@ function nonBooleanFlagComparandError(op: string, field: string, path: string):
18701871
`not a string, a number, null or undefined. The producer to fix is whoever BUILT this read ` +
18711872
`scope — an admin-authored sharing rule / permission set, its CEL lowering, or the in-process ` +
18721873
`code (a getReadScope option) that assembled the FilterCondition — never the caller of this ` +
1873-
`query, who cannot author it (#5347 / #5369, pushed down to this compiler by #6387).`,
1874+
`query, who cannot author it. A non-boolean comparand for any of the three is refused rather ` +
1875+
`than coerced, on every driver and on this door alike.`,
18741876
);
18751877
}
18761878

‎packages/services/service-analytics/src/strategies/native-sql-strategy.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,9 +1034,11 @@ export class NativeSQLStrategy implements AnalyticsStrategy {
10341034
`[native-sql-strategy] ${hit.source} carries a field reference ` +
10351035
`{ "$field": "${hit.ref}" } under "${hit.op}" on "${hit.field}", which this strategy does not ` +
10361036
`compile into a column-to-column comparison — it would BIND the reference object as the ` +
1037-
`comparison's value and answer a wrong row set silently (#7598). \`canHandle\` declines such a ` +
1037+
`comparison's value and answer a wrong row set silently. \`canHandle\` declines such a ` +
10381038
`query so it routes to the ObjectQL/engine path, whose driver compiles it and enforces the ` +
1039-
`#5222 rulings with metadata it owns; reaching this throw means the decline and this emitter ` +
1039+
`cross-field rules (declared same-table columns only, never the tenant-isolation column, one ` +
1040+
`comparison class) with metadata it owns, so those rules are enforced in one place, next to ` +
1041+
`the metadata they read; reaching this throw means the decline and this emitter ` +
10401042
`stopped agreeing, which is our bug and must never degrade to a silent answer.`,
10411043
);
10421044
}

‎packages/services/service-analytics/src/strategies/objectql-strategy.ts‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,11 +462,14 @@ export class ObjectQLStrategy implements AnalyticsStrategy {
462462
`{ "$field": "${crossField.ref}" } under "${crossField.op}" on "${crossField.field}". ` +
463463
`The query itself is SERVED — \`NativeSQLStrategy.canHandle\` declines a cross-field ` +
464464
`comparison so it routes to the ObjectQL engine path, where driver-sql compiles it into a ` +
465-
`column-to-column predicate written TOTAL across NULLs and enforces the #5222 rulings ` +
466-
`(#7598, maintainer ruling 2026-08-12). This renderer has no faithful rendering of that ` +
465+
`column-to-column predicate written TOTAL across NULLs and enforces the cross-field rules ` +
466+
`(declared same-table columns only, never the tenant-isolation column, one comparison class) ` +
467+
`with metadata it owns, so those rules are enforced in one place, next to the metadata they ` +
468+
`read. This renderer has no faithful rendering of that ` +
467469
`predicate: what it can emit is a comparison against the reference object as a bound VALUE, ` +
468470
`which reproduces none of the rows the query returns. Refusing rather than half-rendering — ` +
469-
`an echo that contradicts execution is worse than no echo (#3601 / #3602 / #3650). Run the ` +
471+
`an echo that contradicts execution is worse than no echo, so the echo renders every ` +
472+
`predicate the query runs with, or refuses. Run the ` +
470473
`query itself (/analytics/query) to get its rows.`,
471474
);
472475
}
@@ -1478,7 +1481,7 @@ export class ObjectQLStrategy implements AnalyticsStrategy {
14781481
`filter-normalizer.ts refuses anything it cannot map — so this means a new ` +
14791482
`operator reached the normalizer without an arm here. Add one rather than ` +
14801483
`dropping the predicate: an echo without it describes a WIDER query than the ` +
1481-
`one that ran (#5333).`,
1484+
`one that ran, and the echo renders every predicate the query runs with, or refuses.`,
14821485
);
14831486
}
14841487
params.push(values[0]);
Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1 @@
1-
{
2-
"packages/services/service-analytics/src/read-scope-sql.ts": {
3-
"#5347": 1,
4-
"#5369": 1,
5-
"#6050": 1,
6-
"#6125": 1,
7-
"#6387": 1
8-
},
9-
"packages/services/service-analytics/src/strategies/native-sql-strategy.ts": {
10-
"#5222": 1,
11-
"#7598": 1
12-
},
13-
"packages/services/service-analytics/src/strategies/objectql-strategy.ts": {
14-
"#3601": 1,
15-
"#3602": 1,
16-
"#3650": 1,
17-
"#5222": 1,
18-
"#5333": 1,
19-
"#7598": 1
20-
}
21-
}
1+
{}

0 commit comments

Comments
 (0)