From 3106c2f21ab31f8bdee905043fa1e34d242dcb04 Mon Sep 17 00:00:00 2001 From: pallaoro Date: Thu, 9 Jul 2026 22:36:57 +0200 Subject: [PATCH] scalable: reused state inherits every behavior attached to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing 'don't optimize away the domain object' bullet warns against reuse that deletes the domain object. Add its mirror: reuse that silently inherits a hidden behavior. Repurposing an existing status/flag/enum/column (e.g. trialing to mean 'migration bridge') fires everything that already reads that value — webhooks, crons, entitlement gates, billing/credit grants, UI branches, cleanup jobs — not just the one property you wanted. Enumerate consumers up front (grep every reader) instead of discovering them reactively one bug at a time, and verify by diffing the whole system's response, not just the fields you predicted would change. --- commands/scalable.md | 1 + 1 file changed, 1 insertion(+) diff --git a/commands/scalable.md b/commands/scalable.md index 4456b15..41ca7a8 100644 --- a/commands/scalable.md +++ b/commands/scalable.md @@ -17,6 +17,7 @@ The governing question for the choice: **whatever is scalable, long term, and ca - **Do the cheapest decisive check yourself — don't defer it.** If one file (a `wrangler.jsonc`, an entrypoint, a config) would settle the load-bearing claim, open it. Ending your turn by asking the human to confirm what a file you could have read answers is the same deferral repeating one turn later. - **Look down the stack, not just sideways.** Before designing any new state — config keys, DB columns, env vars, endpoints, files — search the framework / platform / library you build on (and the rest of this repo) for a native primitive that already models this concern. The leanest correct option is frequently one that already exists one layer down; reinventing what the host exposes is the most common efficiency miss. Verify it against the dependency's actual source, not its docs alone. - **But don't optimize away the domain object.** "Reuse the primitive one layer down" is a virtue *until it deletes the thing the feature is actually about*. The trap: fusing a **property the feature requires** (email-binding, single-use, consent) with an **implementation that happens to carry it** (a Supabase magic link, an auth token, a signed URL) — once fused, reuse looks automatically correct, and you end up borrowing an *ephemeral auth artifact* to stand in for a *durable domain record*. Separate the two: name the property, then ask whether the primitive models the property or merely coincides with it today. An auth link is not an invitation; a cache key is not a job; a session is not an audit trail. When the feature needs a **lifecycle** — revoke, resend, expire independently, run several concurrently, record who accepted and when, ask consent before acting — that lifecycle *is* the domain object, and a first-class record (a row + a `requested → active / declined` status) is the correct construct, not gold-plating. Reuse that has no place to hang those states pushes the real cost into fragile edges (24h expiry, single-use collisions, "already registered", silent auto-accept). Adding well-chosen, durable state is sometimes the *efficient* move, not the wasteful one. +- **A reused state inherits every behavior already attached to it — enumerate them before you adopt it.** The bullet above warns against reuse that *deletes* the domain object; this is its mirror — reuse that silently *inherits* one. When the approach repurposes an existing status / flag / enum / column to mean something new (`trialing` to mean "currency-migration bridge", `pending` to mean "awaiting review", `archived` to mean "soft-deleted"), it doesn't just carry the one property you wanted — it fires *everything* that already reads that value: webhooks, cron jobs, entitlement gates, billing/credit grants, UI branches, cleanup sweeps. Before committing, **grep every consumer of that value** (`grep -rn 'trialing\|is_trial'` across every layer) and list what each one does with it; a behavior you never intended rides along for free. The tell that you skipped this: you validated the *one* behavior you wanted and discovered the others reactively — one bug (or one "wait, why did all of them get free credits?") at a time. The reused state's full behavior set is part of the decision, not a surprise you pay for after. And when you *do* adopt it, verify by diffing the **whole system's response** (side-effect tables, ledgers, related rows) before/after — not just the fields you predicted would change; the inherited behavior only shows up in the diff you didn't expect. **Define the three pillars for *this* decision — if they're not already clear.** Before judging, make each concrete for the case at hand: