|
63 | 63 | "verifiedAt": "2026-09-30", |
64 | 64 | "evidence": "packages/services/service-analytics/src/strategies/native-sql-strategy.ts#resolveMeasureSql — `measure.sql` is the column the aggregate is applied to (`'*'` the COUNT(*) form), and `qualifyAndRegisterJoin(measure.sql, …)` is what lowers a dotted reference into a LEFT JOIN chain; packages/services/service-analytics/src/strategies/objectql-strategy.ts#resolveFieldName reads `measure.sql.replace(/^\\$/, '')` as the aggregate field for the `engine.aggregate` path; packages/services/service-analytics/src/analytics-service.ts#fieldsOfColumnSql resolves it to the field(s) the analytics door's field-level read gate judges.", |
65 | 65 | "producer": "packages/cli/src/commands/serve.ts#CAPABILITY_PROVIDERS — the `analytics` entry declares `configKey: 'analyticsCubes'` and the capability resolver threads it into the plugin (`const cubes = (config as any).analyticsCubes ?? (config as any).cubes ?? []; arg = { cubes }`); packages/services/service-analytics/src/analytics-service.ts#registerAll (`if (config.cubes) this.cubeRegistry.registerAll(config.cubes)`) is where the authored array becomes the registry every consumer below resolves through. Without this thread an authored cube reaches no reader at all — the `seed.env` shape (#4837).", |
66 | | - "note": "REQUIRED. NARROWED 2026-09-30 (#20943, maintainer ruling D; ADR-0021 zero raw expressions, ADR-0049 enforce-or-remove): the value is a COLUMN REFERENCE — a bare identifier, a dotted identifier path (relationship hops, then the column), or `'*'` on a `count` measure — and any SQL expression is refused at parse with a prescription naming the ADR-0021 dataset form (a measure-scoped `filter`, `derived: { op, of }`). The admitted pattern is the one `IDENTIFIER_PATH` (native-sql-strategy.ts) and the read gate already use to tell a column path from an expression (#4157), so every admitted value resolves to a field the gate can judge. Still LIVE: the key itself is unchanged and read at the three sites above. The runtime's expression branches (verbatim emit on the raw-SQL path, the gate's stand-down) remain for a cube that reaches the service without meeting the parse; their deletion is the services-lane follow-up. The D3 entry is `cube-member-sql-expression-retired`; there is no D2 conversion, because an expression has no mechanical rewrite into a dataset." |
| 66 | + "note": "REQUIRED. NARROWED 2026-09-30 (#20943, maintainer ruling D; ADR-0021 zero raw expressions, ADR-0049 enforce-or-remove): the value is a COLUMN REFERENCE — a bare identifier, a dotted identifier path (relationship hops, then the column), or `'*'`, which the schema admits on any measure (the count-only boundary is #21000's) — and any SQL expression is refused at parse with a prescription naming the ADR-0021 dataset form (a measure-scoped `filter`, `derived: { op, of }`). The admitted pattern is the one `IDENTIFIER_PATH` (native-sql-strategy.ts) and the read gate already use to tell a column path from an expression (#4157), so every admitted value other than `'*'` (which reads no field value) resolves to a field the gate can judge. Still LIVE: the key itself is unchanged and read at the three sites above. The runtime's expression branches (verbatim emit on the raw-SQL path, the gate's stand-down) remain for a cube that reaches the service without meeting the parse; their deletion is the services-lane follow-up. The D3 entry is `cube-member-sql-expression-retired`; there is no D2 conversion, because an expression has no mechanical rewrite into a dataset." |
67 | 67 | }, |
68 | 68 | "format": { |
69 | 69 | "status": "live", |
|
107 | 107 | "verifiedAt": "2026-09-30", |
108 | 108 | "evidence": "packages/services/service-analytics/src/strategies/native-sql-strategy.ts#resolveDimensionSql — `dim.sql` is the GROUP BY / SELECT column, and `qualifyAndRegisterJoin(dim.sql, …)` lowers a dotted path into the LEFT JOIN chain; packages/services/service-analytics/src/strategies/objectql-strategy.ts#resolveFieldName reads `dim.sql.replace(/^\\$/, '')` as the group-by field for the `engine.aggregate` path; packages/services/service-analytics/src/analytics-service.ts#fieldsOfColumnSql resolves it to the field(s) the analytics door's field-level read gate judges.", |
109 | 109 | "producer": "packages/cli/src/commands/serve.ts#CAPABILITY_PROVIDERS — the `analytics` entry declares `configKey: 'analyticsCubes'` and the capability resolver threads it into the plugin (`const cubes = (config as any).analyticsCubes ?? (config as any).cubes ?? []; arg = { cubes }`); packages/services/service-analytics/src/analytics-service.ts#registerAll (`if (config.cubes) this.cubeRegistry.registerAll(config.cubes)`) is where the authored array becomes the registry every consumer below resolves through. Without this thread an authored cube reaches no reader at all — the `seed.env` shape (#4837).", |
110 | | - "note": "REQUIRED. NARROWED 2026-09-30 with `measures.sql` (#20943, maintainer ruling D): a bare identifier or a dotted identifier path; a SQL expression — a CASE bucket included — and `'*'` are refused at parse. A bucket computed over a column's values has no expression form in the cube or the dataset layer; the prescription sends it to a field of the object that a dimension names. Still LIVE, at the sites above." |
| 110 | + "note": "REQUIRED. NARROWED 2026-09-30 with `measures.sql` (#20943, maintainer ruling D): a bare identifier or a dotted identifier path, and `'*'`, which the schema admits on a dimension too (the accept set ruling D's execution parameters name for both members; it never made a working query, and narrowing it is #21000's); a SQL expression — a CASE bucket included — is refused at parse. A bucket computed over a column's values has no expression form in the cube or the dataset layer; the prescription sends it to a field of the object that a dimension names. Still LIVE, at the sites above." |
111 | 111 | }, |
112 | 112 | "granularities": { |
113 | 113 | "status": "live", |
|
0 commit comments