| 1 | --- |
| 2 | name: building-carlos-apps |
| 3 | description: Use when building or designing an app on the CARLOS architecture (Cost-efficient, Available, Replicated, Lightweight, Open, Secure) or with rastrillo (the CARLOS web framework), bringing an existing app onto it, deciding what one instance is (per person, team, customer, repo, or one shared instance; a signup that creates instances; a home or hub; reporting across tenants; SaaS customers who want on-prem), choosing a trust class (S, A1, A2, A/pub, B, C), or weighing the family's other open choices (app shape, hosting, identity). For the zero-decisions happy path to a first live app, use getting-started instead. |
| 4 | --- |
| 5 | |
| 6 | # π€ Building CARLOS apps |
| 7 | |
| 8 | ## Overview |
| 9 | |
| 10 | CARLOS is an application architecture: **one static Go binary, one |
| 11 | fully-isolated instance per tenant (own process, own SQLite file, own unix |
| 12 | socket), many instances on one small box behind a small router**, with |
| 13 | every database continuously replicated to object storage and idle |
| 14 | instances hibernating to it. What a tenant *is* (a person, a team, a |
| 15 | customer company, a repository, a chat, or the whole app) is the app's |
| 16 | first decision. |
| 17 | Everything below is distilled from the prompt histories, repo instruction |
| 18 | files and code of the apps it was extracted from. The house style is to |
| 19 | state rules as laws, date and attribute decisions, and make rules |
| 20 | mechanical rather than remembered. |
| 21 | |
| 22 | ## When to use |
| 23 | |
| 24 | - Starting a new product that should join the family, especially when it |
| 25 | needs real decisions: tenancy, trust class, app shape, hosting, identity. |
| 26 | - Working out what one instance of an app should be, how people reach it, |
| 27 | what the host can see, and which CARLOS benefits that earns. |
| 28 | - Porting an existing app onto the model (Tito's path β see "Adopting"). |
| 29 | - Any question of the form "what would a CARLOS app do here?" β stack, |
| 30 | hosting, testing, deploys, process, and the trade-offs between the |
| 31 | family's sanctioned options. |
| 32 | |
| 33 | Not for: contributing to one of the existing apps (read that repo's |
| 34 | AGENTS.md instead β it always wins over this skill). And for "just get me |
| 35 | a first app live, decide everything for me", use the sibling skill |
| 36 | **carlos:getting-started** β it is this skill with every decision |
| 37 | pre-answered with the defaults (one instance, class C declared, server |
| 38 | shape, Carloku). |
| 39 | |
| 40 | ## Start here: tenancy, then trust |
| 41 | |
| 42 | Before stack, screens or deploys, answer three questions and write the |
| 43 | answers down as a **tenancy declaration** in AGENTS.md. Everything else |
| 44 | in this skill, and every benefit on carlosframework.com, hangs off them. |
| 45 | |
| 46 | 1. **What is one instance?** A person (Kass), a chat (Eleven), a mailbox |
| 47 | (Keymail), a team (Oficina, an internal finance ledger), a customer company (Tito), a |
| 48 | community (Woodstar), a repository (amadan), a bank connection, |
| 49 | the whole app (Movement), or nothing at all (a static site). The |
| 50 | boundary is the app's choice; there is no default. Choose the smallest |
| 51 | unit that owns data together, fails together and leaves together. |
| 52 | Sharing is membership in someone's instance, never a copy. Never |
| 53 | tenancy by a `tenant_id` column in one shared file. Totals across |
| 54 | tenants come from facts the centre owns or witnesses and fixed-shape |
| 55 | records instances push, never from opening tenant databases. |
| 56 | 2. **How do people reach it?** One instance with in-app accounts, a |
| 57 | simple home that lists your instances, a hub that puts every tenant |
| 58 | under one domain, or a blind home for end-to-end encrypted apps. |
| 59 | Central apps are stateless: records in object storage, no database. |
| 60 | 3. **What can the host see?** A trust class per workload: S (no user |
| 61 | data), A1/A2/A-pub (host-blind, with declared residue or public |
| 62 | surfaces), B (sealed at rest, readable while awake), C (plaintext, |
| 63 | chosen and written down). |
| 64 | |
| 65 | Then name the benefits the design earns, each with its mechanism (isolated |
| 66 | data per tenant, blast radius of one, hibernation, per-tenant export and |
| 67 | erasure, residency once switched on, a falsifiable security claim, self-hosting from the same |
| 68 | binary), and the costs it accepts. **[references/tenancy.md](references/tenancy.md)** |
| 69 | has the gallery's real choices, the four user models, the classes, the |
| 70 | benefits table with what is live today, worked examples, and the |
| 71 | declaration template. Read it first. |
| 72 | |
| 73 | ## Where this sits now (2026-10-15) |
| 74 | |
| 75 | The family's conventions have progressively become running infrastructure. |
| 76 | Read this skill alongside three facts: |
| 77 | |
| 78 | - **The platform** (`carlosframework/platform`) is live and complete |
| 79 | enough that a member ships, promotes, configures, watches logs, attaches |
| 80 | domains, and rolls back entirely through the `carlos` CLI with zero |
| 81 | infrastructure access. Routing, TLS, replication, hibernation, restarts, |
| 82 | and config delivery are the platform's job now β and since late August |
| 83 | so are **canaries** (`carlos canary`), **timetables** |
| 84 | (`carlos schedule`), **errors and analytics** counted at the edge with |
| 85 | no SDK, a **password gate** in front of a hostname, **feature flags**, |
| 86 | and **latency DNS steering** β and since September, **server-held |
| 87 | credentials** (`carlos services`) so a signup flow can create a |
| 88 | customer's instance itself, **path routes** so one hostname can serve |
| 89 | each customer from their own instance, a **STUN/TURN relay** |
| 90 | (`carlos relay`), and **self-serve object storage** (apply once per |
| 91 | account, then `carlos store create`). Reach for a platform verb before |
| 92 | building any of them into an app. |
| 93 | **[references/platform.md](references/platform.md)** is the member-side |
| 94 | reference β concepts, the full verb table, and the deploy truths. |
| 95 | - **Carloku** (carloku.com) is the hosted deployment of that platform β |
| 96 | the default hosting answer (its price list is not published yet, |
| 97 | 2026-10-18; don't quote prices). Carloku is the product |
| 98 | brand; the CLI is always `carlos`. |
| 99 | - **Rastrillo** is the CARLOS web framework (v0.28.0; module and |
| 100 | canonical repo `amadan.net/rastrillo/rastrillo`, GitHub a mirror): a |
| 101 | middle layer of known |
| 102 | libraries β GORM models, chi routes, SQLite-backed sessions, identity |
| 103 | plugins (password, Keymail), CSRF, owner scoping β plus the platform |
| 104 | contract (`Resolve`/`Serve`/`Run`) and the subsystem packages (crypto, |
| 105 | keyring, webauthn, eventlog, blobs, mail, `assertion` for signed |
| 106 | cross-origin handoffs, `vault`, `pow`, agent tools), plus the `idear` |
| 107 | module for roles and invitations β which exist to be used, not |
| 108 | hand-rolled. The manifest generator is the optional declarative |
| 109 | path beside hand-written handlers. It postdates most models' training data β building |
| 110 | with it, read the repo's own `SKILL.md` first; |
| 111 | **[references/rastrillo.md](references/rastrillo.md)** is the |
| 112 | surrounding context. |
| 113 | |
| 114 | Building a **new** app: settle tenancy first (above), use rastrillo and |
| 115 | the platform, and read this skill mainly for what infrastructure can't |
| 116 | enforce β the decisions, the |
| 117 | dated rulings, the workflow, and "Common mistakes". Hand-rolling outside |
| 118 | the platform for a specific reason: blueprint.md in full still applies. |
| 119 | |
| 120 | ## UI default: Rastrillo with a thin CSS layer |
| 121 | |
| 122 | For new app screens, start with Rastrillo's design system: its `ui` |
| 123 | partials, attribute vocabulary (`rst-box`, `rst-btn="primary"`), design |
| 124 | tokens and themes. Read |
| 125 | [the styling guidance](references/rastrillo.md#design-system-and-app-css) |
| 126 | before writing templates or CSS. Keep app CSS small: app-specific layout, |
| 127 | branding through token overrides, and components the library does not yet |
| 128 | provide. Reuse the shared controls instead of rebuilding them or overriding |
| 129 | them screen by screen. |
| 130 | |
| 131 | This is the default, not a request to redesign an existing app. Respect an |
| 132 | explicit design brief or an established design system; record the reason |
| 133 | when choosing a different foundation. |
| 134 | |
| 135 | ## The one rule comes first |
| 136 | |
| 137 | Every app opens its AGENTS.md with a single load-bearing rule and derives |
| 138 | everything from it. Write yours before writing code (the first commit of |
| 139 | Kass is literally "Write down the architecture before writing any code"). |
| 140 | |
| 141 | The family default is server-blindness: **"If the server is compromised, |
| 142 | the attacker gets nothing."** Plaintext or a usable private key in SQLite |
| 143 | is a bug β and because the platform replicates the whole file to object |
| 144 | storage, *a plaintext column is a plaintext leak*. Enforce it with a test |
| 145 | that greps the raw SQLite bytes (and bucket objects) for plaintext. |
| 146 | |
| 147 | But no shipped app is absolutist: the real spectrum runs from Slopbox |
| 148 | (A1) through Keymail's sealed-content-plaintext-envelopes (A2) and |
| 149 | Woodstar's split-by-content-class (A2 + A/pub) to an internal finance ledger's sealed |
| 150 | single-tenant (B) and Tito's deliberate server trust (C), and the |
| 151 | discipline that makes any position legitimate is the same β **choose on |
| 152 | day one, name every leak, publish the list**. The whole axis, with each app's recorded |
| 153 | reasoning and a decision guide, is |
| 154 | **[references/decisions.md](references/decisions.md)** β read it before |
| 155 | settling a new app's trust model, app shape, hosting, or identity story. |
| 156 | |
| 157 | ## Guiding principles |
| 158 | |
| 159 | 1. **Intent before code.** AGENTS.md is written first and is binding. Design |
| 160 | docs precede big builds; the doc's decisions are taken β if one proves |
| 161 | wrong, stop and flag it in the PR rather than redesigning. |
| 162 | 2. **Decisions are dated, attributed, and settled.** "Paul's call, |
| 163 | 2026-07-26" next to every ruling, rejected alternatives recorded beside |
| 164 | it, under a heading like "Settled decisions (don't relitigate casually)". |
| 165 | 3. **Built to outlive AI.** Human legibility beats AI convenience. Never add |
| 166 | machinery only an LLM can drive; operational knowledge lives in scripts |
| 167 | and docs in the repo, never solely in prompts or agent memory. "No LLM |
| 168 | cookbooks": ops run through a command, never reconstructed from prose β |
| 169 | a script drifts loudly, a document drifts silently. |
| 170 | 4. **Rules are mechanical, not remembered.** The module-size cap is a test. |
| 171 | Contrast ratios are computed from the token file by a test. A guard a |
| 172 | shell step can satisfy is a guard a shell step can be wrong about β put |
| 173 | guards inside the test binary. Generated configs are marked GENERATED |
| 174 | and regenerated on a timer, never hand-edited. |
| 175 | 5. **Blast radius is the unit of design.** One process + one DB per account: |
| 176 | a panic takes down one person. The corollary cuts both ways: strict |
| 177 | validation belongs where its blast radius is one request, not one fleet |
| 178 | (a shared package that panics at init once 502'd every process at once). |
| 179 | 6. **Defer until earned, with the trigger written down.** Keep a |
| 180 | "Deliberately not built yet" section. And ship a thing *off* rather |
| 181 | than untested when the only real proof needs infrastructure you don't |
| 182 | have yet. |
| 183 | 7. **Don't diverge gratuitously from the family.** Shared shape is what |
| 184 | makes components extractable; a local improvement to shared code is a |
| 185 | debt to upstream, noted as such. |
| 186 | 8. **Honesty over polish.** Publish trade-offs plainly ("Honest trade-offs |
| 187 | β read before trusting it"), never overclaim maturity, and don't let |
| 188 | the UI lie: an uncertain state is a sentence, never a fabricated number, |
| 189 | and a claim about a person ("you earned your rest") has to be true. |
| 190 | 9. **Every deviation from the one rule is enumerated**, justified, and |
| 191 | published β never hidden. |
| 192 | |
| 193 | ## The eleven factors |
| 194 | |
| 195 | CARLOS is the architecture; the values under it are **the eleven factors** |
| 196 | ([11factor.org](https://11factor.org) is the canonical text β link to it, |
| 197 | don't copy it). Sibling repos cite factors **by number**, so know the names: |
| 198 | |
| 199 | I. Trust no one Β· II. Let kids play Β· III. Encrypt everything Β· |
| 200 | IV. Great design is for everyone Β· V. Intent is the system Β· |
| 201 | VI. Built by humanity, owned by humanity Β· VII. Self-hosting is a right Β· |
| 202 | VIII. Many small things Β· IX. Inefficient builds efficient Β· |
| 203 | X. Humans come first Β· XI. Centralised infrastructure is glue. |
| 204 | |
| 205 | The ones the family invokes operationally: |
| 206 | |
| 207 | - **III β Encrypt everything** β the one rule: server-blind by default; |
| 208 | deviations are legitimate under the deviation rule, not violations. |
| 209 | - **V β Intent is the system** β AGENTS.md and design docs before code; |
| 210 | "the code should have to argue with something." |
| 211 | - **VI β Built by humanity, owned by humanity** β open source; private |
| 212 | until it works is allowed, but "factor VI is not optional, only |
| 213 | deferred." |
| 214 | - **VII β Self-hosting is a right** β self-hosting is first-class, never a |
| 215 | degraded tier; hosted convenience (Carloku) is the product, never the |
| 216 | software. |
| 217 | - **VIII β Many small things** β instance-per-account, scale by adding |
| 218 | instances, not replicas of one. |
| 219 | - **X β Humans come first** β AI is "a guest with a name tag": opt-in, |
| 220 | never required, always disclosed (π€ marking), and every path works with |
| 221 | the AI switched off. The strongest form is Kass's: the AI is an ordinary |
| 222 | member whose code never runs inside the server process, and whose |
| 223 | conclusions land as proposals into human review, never as direct writes. |
| 224 | |
| 225 | ## Quick reference β the shape |
| 226 | |
| 227 | | Concern | The CARLOS answer | |
| 228 | |---|---| |
| 229 | | Language | Go, one static binary, `CGO_ENABLED=0`, thin `main.go` dispatch | |
| 230 | | Dependencies | Stdlib first; "adding a dependency is a decision, not a default"; hand-roll small clients over SDKs; a scoped exception is dated and does not extend to its neighbours | |
| 231 | | Storage | `modernc.org/sqlite`, WAL, one DB per instance, additive-only migrations β automatic on rastrillo | |
| 232 | | Quantities | Integer cents, integer grams β "a float never touches an amount" | |
| 233 | | Frontend | Two shapes, chosen deliberately: `server` (server-rendered, zero-JS baseline β the default) or `client` (Woodstar's shape) β see decisions.md Β§2 | |
| 234 | | JS discipline | 300-line module cap enforced by test, ratchet-down only; VanJS (vendored) the one sanctioned reactive dependency | |
| 235 | | Routing, TLS, replication, hibernation, restarts | The platform's job β see platform.md; hand-rolled only off-platform (blueprint.md) | |
| 236 | | Periodic work | `carlos schedule` β a time and a path; each fire is a POST to a route the app already serves, over its own socket. Never cron, never a second worker. A schedule tighter than the idle window stops the instance hibernating, and that is billed β platform.md | |
| 237 | | Object storage | Once per account, `carlos store apply` and a deployment operator approves; then `carlos store create` declares a bucket and credentials arrive as env; `carlos store scan` is opt-in virus scanning, off by default. It reconciles β it counts the objects it has NOT looked at β so ask for both numbers. Server-blindness wins over it: a client-encrypted store gets no coverage claim, because nothing can read the bytes β platform.md | |
| 238 | | Errors and analytics | `carlos errors` needs no wiring and collects from day one (tagged log lines; edge-seen 5xx are `carlos availability`); `carlos analytics` counts at the edge with no JavaScript, no cookie, no stored IP, and is opt-in per app or account. Do not add a third-party analytics script to a CARLOS app β platform.md | |
| 239 | | Canaries | `carlos canary` β a branch-only channel and hostname, outside every pipeline, seven-day lease. Review there, never on localhost. Pass `--environment` if the app carries config, or every form submission on the canary host fails β platform.md | |
| 240 | | Config environments | `carlos env --environment` writes a named bundle; a route is bound to one via the instance record (`instances set-environment`), then `carlos restart --environment` cycles exactly what reads it β platform.md | |
| 241 | | Feature flags | `carlos features set` β the platform serves them, only the app interprets them, and they land on the instance's next poll with no restart β platform.md | |
| 242 | | Hostname-level password | `carlos gate` β one shared password at the edge in front of an app's hostnames, for a prototype or a private static site. A curtain over a hostname, never a substitute for the app's own accounts β platform.md | |
| 243 | | Outbound email | `carlos email enable` β the platform mints the sending identity, publishes DKIM/SPF/DMARC, delivers SMTP credentials as env; never run an MTA or hold a cloud mail key β platform.md | |
| 244 | | Scheduled work | `carlos schedule set` declares it; the app's part is a POST handler guarded by `carlos.Tick` β the instance is asleep, so never an in-process cron β platform.md | |
| 245 | | Tenancy | The app chooses what one instance is; the declaration (unit, user model, class per workload, residue, benefits, costs) goes in AGENTS.md before code β tenancy.md | |
| 246 | | A customer per instance | The signup app holds an `instance`-role credential (`carlos services create --role instance --app <tenant-app>`) and `POST`s `/api/cli/apps/<account>/<tenant-app>/instances` β customers are instances, never Carloku accounts. The credential is app-wide, so it lives on the signup app only β platform.md "Provisioning instances from your own app" | |
| 247 | | One hostname, many instances | Path routes: the first path segment of a claimed hostname points at another route in the same account, on the same box. One hostname is one origin β platform.md "One hostname, many instances" | |
| 248 | | Central apps (sign-in, directory, home) | Stateless: no SQLite of their own, records in object storage, so they run anywhere and lose nothing when moved | |
| 249 | | WebRTC | `carlos relay enable` β the platform's STUN/TURN, delivered as `CARLOS_RELAY`; never a third-party TURN service β platform.md | |
| 250 | | Hosting | Carloku hosted (default) / customer fleets / self-hosted platform β decisions.md Β§3 | |
| 251 | | Deploys | `carlos deploy`: ship + promote + watch `X-Carlos-Version` until live; verify against the thing you changed with the binary you built. A static site is the same one command β `--kind static --host <h> <dir>`, which declares the route too β platform.md | |
| 252 | | Activity descriptions | Pass a concise `--message` on supported mutations: say what changes and why. The console records the exact target separately. Agents supply the message even when prompts are disabled β platform.md | |
| 253 | | Identity | "Sign in with Keymail" / passkeys+PRF / magic link+TOTP by trust model β decisions.md Β§4 | |
| 254 | | Trust | A class per workload, S to C; server-blind by default; every softening named and grep-tested. Placement by class is designed, not enforced β tenancy.md Β§3, decisions.md Β§1 | |
| 255 | | UI stance | Hide the machinery: no hostnames, keys, or crypto vocabulary in the default flow β "no nerdspeak"; calm UI, red for danger only, no toasts | |
| 256 | | Process | Code on amadan by default (its agent house rules: `amadan agent skill -install`); worktree per session, branch, regular pushed commits; merge to main (`amadan branch merge`, optionally `-squash`) only when done, approved and CI green (CI green binds once the repo has CI β a new repo's first merges land on done + approved and add CI early); review on a deployed canary, never localhost | |
| 257 | | Authorship | π€/π¨ markers, `Co-Authored-By: Claude β¦` trailers, published prompt + carbon ledgers | |
| 258 | |
| 259 | ## Details |
| 260 | |
| 261 | - **[references/tenancy.md](references/tenancy.md)** β read first: what |
| 262 | one instance is, across every shape in the gallery; the four user |
| 263 | models (one instance, simple home, hub, blind home); stateless central |
| 264 | apps; the trust classes S to C; the benefits each choice earns, with |
| 265 | mechanism and what is live; and the tenancy declaration to write |
| 266 | before code. |
| 267 | - **[references/decisions.md](references/decisions.md)** β the four axes: |
| 268 | trust model, app shape, hosting, identity β each with the family's real |
| 269 | positions, recorded reasons, and a decision guide. |
| 270 | - **[references/platform.md](references/platform.md)** β the platform |
| 271 | member-side: concepts (accounts, releases, channels, instances, |
| 272 | hibernation, config bundles, canaries), the `carlos` CLI verb table, |
| 273 | deploying a static site, standing a canary beside production, scheduled |
| 274 | work (the tick contract, idempotency, one-shot timers, what a tight |
| 275 | schedule costs), errors and analytics, sending email (SMTP credentials, |
| 276 | DKIM/DMARC alignment, the credential-propagation trap), deploy truths, |
| 277 | self-hosting. |
| 278 | - **[references/rastrillo.md](references/rastrillo.md)** β building an |
| 279 | app with rastrillo: the middle-layer shape, where the authoritative |
| 280 | SKILL.md lives, the safety rules, and the declarative manifest path. |
| 281 | - **[references/blueprint.md](references/blueprint.md)** β the technical |
| 282 | blueprint the platform automated: the carlos core, storage rules, |
| 283 | crypto conventions, box setup. The reference for self-hosting outside |
| 284 | the platform and for understanding what it does on your behalf. |
| 285 | - **[references/process.md](references/process.md)** β working |
| 286 | conventions: repo docs, git/PR workflow, canaries, the test layers |
| 287 | (including the uidump pattern), `/end-session`, ledgers and |
| 288 | AI-authorship marking. |
| 289 | |
| 290 | ## Adopting CARLOS in an existing app (Tito's path) |
| 291 | |
| 292 | 1. Restate the model in your first commit and at the top of README and |
| 293 | AGENTS.md. |
| 294 | 2. Deploy onto the platform (hosted or self-hosted) rather than porting |
| 295 | the router/replication machinery β that is what it is for. Only when |
| 296 | the app must run somewhere the platform can't: take the core into |
| 297 | `internal/carlos`, kept close to blueprint.md's shape so it can be |
| 298 | swapped for the platform later. |
| 299 | 3. Adopt the conventions alongside (worktrees, PR playbook, canaries, |
| 300 | additive migrations, zero-JS-first). |
| 301 | 4. List every deferred component with its trigger; list every deliberate |
| 302 | departure with its reason. |
| 303 | 5. Fixes you make to shared-shape code are candidates to upstream β record |
| 304 | them. |
| 305 | |
| 306 | ## Common mistakes |
| 307 | |
| 308 | | Mistake | Reality | |
| 309 | |---|---| |
| 310 | | One shared instance with a `tenant_id` column for many customers | Isolation on CARLOS is a process and a file. A `WHERE` clause gives up per-tenant isolation, erasure, residency and hibernation, and one missed clause leaks everyone. Make the tenant an instance β tenancy.md | |
| 311 | | Starting to code before deciding what one instance is | The unit decides the user model, the trust class's blast radius and which benefits the app can claim. Retrofitting it is a migration across every instance. | |
| 312 | | Adding a framework/bundler "just for this screen" | The no-build-step rule is load-bearing (auditability, longevity). One more ES module, one concern. | |
| 313 | | Choosing the client shape because it feels modern | The client shape is for client-held keys, live channels, and server-blind state β and it must self-impose the discipline the server shape gets free (decisions.md Β§2). | |
| 314 | | Creating a Carloku account per customer, or signing up customers with a person's CLI login | Accounts are *your* tenancy on the platform; customers are instances of your app. A signup flow holds a service credential (`carlos services`) and calls the instances API β platform.md | |
| 315 | | Giving every tenant its own hostname because "the edge routes by Host only" | It no longer does: path routes split one claimed hostname by its first segment, within one account and one box β platform.md | |
| 316 | | Hand-rolling a router, certs, Litestream, or restart machinery | The platform's job. An app on the platform is a binary on a unix socket (`--socket`/`--db`; there is no `$PORT`). | |
| 317 | | Giving a static site an instance | It has no process to run. The edge serves it off the channel pointer, so `carlos deploy --kind static --host <h> <dir>` is the whole deploy β `instances enable`/`create` is the binary recipe, and following it here builds a route that succeeds at every step and can never wake. | |
| 318 | | Concluding you have no access because the console redirected you | A `curl` of the console 302s to a login page for everyone β a browser session is not what the CLI holds. `carlos auth whoami` is the only thing that answers the question, and it is the first command of any platform task. | |
| 319 | | Guessing a channel name from the ladder in `--help` | Channels belong to the app. A new app has exactly one (`edge`), and `canary β edge β beta β stable` is the frozen legacy ladder for apps that declare no pipeline. `carlos channels` lists this app's; `carlos pipeline` orders them. | |
| 320 | | Growing the biggest file/package | A new concern gets a new small module or package β never more growth of the biggest one. | |
| 321 | | Destructive migration "to clean up" | Migrations are additive-only. New code over an old DB must always be safe. Never delete data to update. | |
| 322 | | Trusting a backup that exists | "A backup you've never restored is a hope, not a backup." (Platform-run for platform apps; your job off-platform.) | |
| 323 | | Verifying a deploy with a 200 | An app-shell route 200s for any build ever shipped. Only `X-Carlos-Version` on the canonical host, after the watch, is proof β and minted alias hosts carry no version header by design. | |
| 324 | | Treating a promote as a deploy | Until the process cycles, the old binary serves. Platform-known units cycle automatically; hibernating tenants wake into the new build; a bespoke unit stays old until something restarts it. | |
| 325 | | Reviewing on localhost | Review happens on a deployed canary, always. Shared hosts only ever run merged main. | |
| 326 | | Skipping the post-deploy browser check | A JS syntax error takes the whole client down and only a real engine sees it (the keymail rule). | |
| 327 | | Treating a day-one absolute as unsatisfiable and quietly skipping it | A gate a brand-new project cannot meet is a gate not written for day one. Name the bootstrap case in the rule and make satisfying it early work β a rule agents learn to step around stops working everywhere. | |
| 328 | | Relitigating a settled decision in a drive-by | Settled decisions change with new facts, dated and attributed β not casually. | |
| 329 | | A retired stack left owning DNS or deploy paths | It can silently undo a cutover (a legacy apply once reverted a live A record). Move the records; delete the verb that can report success while changing nothing. | |
| 330 | |