Skip to main content

max / makenotwork

Refuse to start with two apps until the queries name one The config and the schema carry the product dimension now; the queries do not. About 169 statement sites still address versions, tier_state, gate_runs and the rest without naming a product. With one product configured that is correct, because every row is that product's. With two it is silent cross-product corruption: pom's promote would read MNW's tier state and advance it, and nothing would look wrong. So refuse rather than run wrong. The check is deleted by the commit that finishes the threading (GoingsOn sando b072577a); until then it is what makes a half-finished migration safe instead of a trap.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-06 23:35 UTC
Signed with PGP, not checked
Commit: 03ebaf6c30ae2633d9efdcbf7ebe8b99cace6db4
Parent: bd074e4
1 file changed, +23 insertions, -0 deletions
@@ -103,6 +103,29 @@
103 103 }),
104 104 );
105 105 }
106 + // TEMPORARY, and loud on purpose. The config and the schema carry the
107 + // product dimension; the queries do not yet — they address `versions`,
108 + // `tier_state`, `gate_runs` and the rest without naming an app. With one
109 + // product configured that is correct, because every row is that product's.
110 + // With two it is silent cross-product corruption: pom's promote would read
111 + // MNW's tier state and advance it.
112 + //
113 + // So refuse, rather than run wrong. This check is deleted by the commit that
114 + // finishes threading `app` through the queries, and until then it is what
115 + // makes a half-finished migration safe instead of a trap.
116 + anyhow::ensure!(
117 + apps.len() == 1,
118 + "{} apps configured ({}), but Sando's queries are still app-blind: they \
119 + address versions/tier_state/gate_runs without naming a product, so a \
120 + second app would read and advance the first one's state. Configure one \
121 + app until that threading lands (GoingsOn sando `{}`).",
122 + apps.len(),
123 + apps.keys()
124 + .map(ToString::to_string)
125 + .collect::<Vec<_>>()
126 + .join(", "),
127 + "b072577a",
128 + );
106 129 let apps = Arc::new(apps);
107 130 // The product a request that names none is about. First in declared order,
108 131 // which for a legacy config is the only one there is.