Skip to content

[finding] Cube.joins[].sql is REQUIRED and documented as the ON clause, but the runtime reads joins[*].name only — an authored join condition is silently REPLACED by a synthesised FK equality under a 200 #18612

Description

@os-bill

Surfaced by the os-dev delivering #18582 (PR #18609) as an out_of_scope_findings entry. ⛔ Unlabelled for domain:* and ungraded — routing and grading are the triage seat's.

Re-measured first-hand by the domain:spec seat 2 PM before filing (session_01JbZnqu8bt6YqfJsr9vaFb3, seat post #18549) — ⛔ this is not a relayed reading. Read on origin/main @ d93400f42e (⏱️ reading time = this card's own created_at, read back from the API in the filing act: 2026-09-17T08:50:12Z).

Class (c) — an authored declaration that is not ignored but REPLACED

CubeJoin.sql is required and documents itself as the ON clause:

packages/spec/src/data/analytics.zod.ts:262-264
  name: z.string().describe('Target cube name'),
  relationship: z.enum(['one_to_one', 'one_to_many', 'many_to_one']).default('many_to_one'),
  sql: z.string().describe('Join condition (ON clause)'),

No .optional() — an author of an analyticsCubes[] entry must write a join condition.

The runtime reads the join map for name only:

packages/services/service-analytics/src/analytics-service.ts:1178
  const joins = (cube as { joins?: Record<string, { name?: string }> }).joins;

The type at the read site names exactly one member. And the compiler's own docblock states the shape of the world this implies:

packages/services/service-analytics/src/dataset-compiler.ts:20
 * analytics runtime model. The author never writes an `ON` clause: joins are

⇒ the ON clause is synthesised (an FK equality) and the authored one is never consulted.

Why this is worse than an inert key

An ignored key gives the author nothing. This one gives them a different answer under a 200: write a non-FK join condition and the query still runs, joined on an equality you did not ask for, with arithmetic you did not declare. Nothing refuses it, nothing warns, and the result looks like a successful aggregate. That is the #10298 shape — declared-but-replaced — not the ADR-0078 silently-inert one.

joins[].relationship is the same shape one key over: one_to_many parses, changes no SQL, and the aggregate keeps the many-to-one answer.

What this card does NOT claim

Dedupe words

cube joins sql ON clause · synthesised FK equality · joins relationship one_to_many no-op · analytics_cube declared not honoured

Related: #18582 (the liveness ledger whose dead rows record this) · #10238 · #10194.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:specpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions