You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Decision] analytics: a cube's refreshKey has nothing to key on — build the cache for every and retire sql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637
Ruled: 5890724395 · letter C — refreshKey retired whole (every and sql), no cache built; this card is the retirement card · 2026-09-29T12:59Z
This card carries the refreshKey half of #20282; #20282 keeps format and granularities (stage 2, PR #20635) and the descriptions (stage 3).
Filed by the domain:spec execution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20282 stage-2 report 5889706157 (open question 1), with the seat's answer 5889752648. The dispatch ordered refreshKey measured only. ⛔ Not a claim.
One-line problem
An analytics cube can declare how often its results refresh (refreshKey: { every: '1 hour' }), and the showcase app does. Nothing in the platform reads it: no cache exists, so the setting silently does nothing.
Background and evidence (measured by the stage-2 dev at tree 958251b6ac)
refreshKey is declared on analytics_cube (packages/spec/src/data/analytics.zod.ts, every and sql, both optional strings). Both liveness rows are dead.
Readers: 0.git grep refreshKey over non-test packages/services, packages/drivers and packages/rest finds 0 hits. Repo-wide, it appears only in the spec, generated surfaces, migration notes and one author.
Nothing to key on.service-analytics references no job, cache or scheduler service. Its one cache is request-scoped (dimension-labels.ts#withLabelFetchCache). A scheduler exists (service-job), and analytics does not use it.
History. The service README once advertised enableCaching / cacheTTL / invalidateCache; they were removed as fabricated (see the service-analytics CHANGELOG).
refreshKey.sql has no safe seam. It would run author-written raw SQL on a schedule outside the read-scope machinery. Every other cube sql is treated as an object name.
ADR-0049 (enforce-or-remove) states the same rule for security properties. refreshKey.sql is security-adjacent: it is raw SQL that would run outside read scope.
Protocol statement: this is not a request to change the protocol. It asks which enforcement the declared keys get, or whether they leave.
Premises, each with a re-check
Readers are still 0: git grep -n refreshKey origin/main -- 'packages/services' 'packages/drivers' 'packages/rest' ':!*.test.ts'.
service-analytics still uses no cache or job service: git grep -n -E "ICacheService|IJobService|cache\.|jobs?\." origin/main -- packages/services/service-analytics/src ':!*.test.ts'.
Options (what each does, and what a customer would notice)
What it does
What a customer notices
A
Build every as a result cache in its own L card, sequenced after #20282's stage 3. It is keyed by cube, the normalized query and the caller's resolved read scope and tenant, with the TTL from every. Retire sql now: a tombstone, a D2 conversion that strips it, and the showcase edit.
Dashboards on busy cubes answer from cache within the declared cadence. An author who wrote sql gets a loud refusal with a migration note.
B
Keep both keys as authored intent: the rows stay dead with this census, and nothing is built until a deployment pulls.
Nothing changes. A declared refresh cadence keeps doing nothing, silently.
C
Retire refreshKey whole (every and sql): tombstones, a D2 strip and the showcase edit. This reverses triage's ENFORCE.
An author who declared a refresh cadence gets a loud refusal and a migration note. There is no caching, and none is promised.
A in business terms: the platform promises the cadence the author wrote, as Cube.dev's refreshKey does for its caches. The half that cannot be made safe is removed.
B in business terms: a settings screen with a switch wired to nothing.
C in business terms: take the switch off the screen until there is a machine behind it.
A: build every in its own L card after stage 3, and retire sql now.
Self-check: 只看①选 A;②③④ 是否翻转:否(②④ 只把 every 的建设推到第 3 阶段之后、单独成卡,不改字母)。
Fallback: C, if you weigh startup focus above the ENFORCE ruling for this family. C is also a clean interim: retire now, and re-declare on the day a cache exists.
Confidence gap: this seat cannot see customer projects outside this repository. If a deployment already declares refreshKey, C breaks its load with a migration note, and A only breaks sql. There is no latency measurement of any dashboard, so A's value is the mainstream argument, not a measured pull.
Ruled: 5890724395 · letter C — refreshKey retired whole (every and sql), no cache built; this card is the retirement card · 2026-09-29T12:59Z
This card carries the
refreshKeyhalf of #20282; #20282 keepsformatandgranularities(stage 2, PR #20635) and the descriptions (stage 3).Filed by the
domain:specexecution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20282 stage-2 report5889706157(open question 1), with the seat's answer5889752648. The dispatch orderedrefreshKeymeasured only. ⛔ Not a claim.One-line problem
An analytics cube can declare how often its results refresh (
refreshKey: { every: '1 hour' }), and the showcase app does. Nothing in the platform reads it: no cache exists, so the setting silently does nothing.Background and evidence (measured by the stage-2 dev at tree
958251b6ac)refreshKeyis declared onanalytics_cube(packages/spec/src/data/analytics.zod.ts,everyandsql, both optional strings). Both liveness rows aredead.git grep refreshKeyover non-testpackages/services,packages/driversandpackages/restfinds 0 hits. Repo-wide, it appears only in the spec, generated surfaces, migration notes and one author.examples/app-showcase/src/data/analytics/showcase.cube.ts:87declaresevery: '1 hour'.service-analyticsreferences no job, cache or scheduler service. Its one cache is request-scoped (dimension-labels.ts#withLabelFetchCache). A scheduler exists (service-job), and analytics does not use it.enableCaching/cacheTTL/invalidateCache; they were removed as fabricated (see theservice-analyticsCHANGELOG).refreshKey.sqlhas no safe seam. It would run author-written raw SQL on a schedule outside the read-scope machinery. Every other cubesqlis treated as an object name.Governing text
Seam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900 (5727134555), the maintainer's criterion: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役,而不是看仓里有没有人读」.public,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 (5859510828) applied it to this family: ENFORCE.refreshKey.sqlis security-adjacent: it is raw SQL that would run outside read scope.Premises, each with a re-check
git grep -n refreshKey origin/main -- 'packages/services' 'packages/drivers' 'packages/rest' ':!*.test.ts'.service-analyticsstill uses no cache or job service:git grep -n -E "ICacheService|IJobService|cache\.|jobs?\." origin/main -- packages/services/service-analytics/src ':!*.test.ts'.Options (what each does, and what a customer would notice)
everyas a result cache in its own L card, sequenced after #20282's stage 3. It is keyed by cube, the normalized query and the caller's resolved read scope and tenant, with the TTL fromevery. Retiresqlnow: a tombstone, a D2 conversion that strips it, and the showcase edit.sqlgets a loud refusal with a migration note.deadwith this census, and nothing is built until a deployment pulls.refreshKeywhole (everyandsql): tombstones, a D2 strip and the showcase edit. This reverses triage's ENFORCE.refreshKeydoes for its caches. The half that cannot be made safe is removed.四轴分析(业务立场)
every: '1 hour'),无任何部署报告看板慢。过去宣传过的分析缓存是虚构后被删除的。维护者判据只问主流有没有:Cube.dev 有refreshKey,所以分诊判 ENFORCE。sql探针没有安全执行接缝,长远看应删。every兑现、让sql响亮拒绝;C 让两者都响亮拒绝;B 保留陷阱。os-decision-facets
every兑现、sql删除),特例减少;B 保留一个声明未兑现的特例;C 删除声明,契约最小。sql);B 让 AI 继续照 showcase 写无效键。Prior rulings read:
refreshKeyin docs/adr + docs/NORTH-STAR.md + AGENTS.md → 0 hits; ADR-0049 (enforce-or-remove, security properties); thread: analytics: an authored cube'spublic,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 (triage5859510828, pitfall note5869426939, stage-2 report5889706157, seat answer5889752648), ruling A′ ④ on [Decision] Route declared≠enforced work by the SEAM, not the layer — aSeam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900 (5727134555)Recommendation
A: build
everyin its own L card after stage 3, and retiresqlnow.every的建设推到第 3 阶段之后、单独成卡,不改字母)。refreshKey, C breaks its load with a migration note, and A only breakssql. There is no latency measurement of any dashboard, so A's value is the mainstream argument, not a measured pull.After the ruling
everycache, sequenced after analytics: an authored cube'spublic,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282's stage 3 and marked for its own design review, and a small spec card that retiressql.every's describe states "not read yet" until the cache lands.deadwith this census re-verified, and this card closesnot_plannedwith the ruling cited.Related: #20282 (the family card), PR #20635 (stage 2), #18900 (ruling A′).
Generated by Claude Code