| 1 | # 🤖 Tenancy: what one instance is, and what that buys |
| 2 | |
| 3 | The first decision for any CARLOS app, before trust model, shape, hosting |
| 4 | or identity (decisions.md). Every other benefit on carlosframework.com |
| 5 | follows from it: isolation, hibernation, residency, erasure, taking the |
| 6 | data home. Settle it on day one and write it down as a **tenancy |
| 7 | declaration** (§6). Changing it later is a data migration across every |
| 8 | instance, not an edit. |
| 9 | |
| 10 | Status as of 2026-10-18. Carloku serves platform v0.28.0; rastrillo is |
| 11 | v0.28.0. Where a piece below is designed but not shipped, it says so. |
| 12 | |
| 13 | ## 1. The boundary: what is one instance? |
| 14 | |
| 15 | **The instance boundary is the app's choice** (the family doctrine). No |
| 16 | unit is the default. The gallery at carlosframework.com/apps runs all of |
| 17 | these, and all of them are correct for their app: |
| 18 | |
| 19 | | One instance is… | Person : instance | Apps that do it | |
| 20 | |---|---|---| |
| 21 | | a person | 1 : 1 | Kass (a training log; a coach is a *member* of the client's instance), Slopbox (one account), Dineraya (a buyer) | |
| 22 | | a conversation or space | 1 : N | Eleven (one chat) | |
| 23 | | a mailbox | 1 : 1 | Keymail | |
| 24 | | a team | N : 1 | Oficina (one per team, per app: docs, sheets), Correomona, an internal finance ledger | |
| 25 | | a customer organisation | N : 1 | Tito (one per organiser account, plus a sandbox instance each), Dineraya (a merchant), Jelly (designed: one per signup) | |
| 26 | | a community | N : N | Woodstar (a relay: founder plus invited members) | |
| 27 | | a repository | N : N | amadan (one per repo; the hub holds only names and membership) | |
| 28 | | a connection | 1 : 1 | a payments app with one instance per bank connection | |
| 29 | | the whole app | N : 1 | Movement (one sign-up list); a rastrillo app out of the box | |
| 30 | | nothing: no user data | none | static sites (carlosframework.com, carloku.com) | |
| 31 | |
| 32 | Most products run **more than one pattern**: a central app plus per-unit |
| 33 | instances (Tito, amadan, Oficina, Slopbox, Eleven), or one |
| 34 | binary in several roles (Dineraya: buyer, merchant, and one shared |
| 35 | dispatcher). |
| 36 | |
| 37 | **Choosing the unit.** Ask, in order: |
| 38 | |
| 39 | 1. **Whose data is it?** The unit is the smallest group that owns data |
| 40 | together and would be harmed if it leaked to the next group. |
| 41 | 2. **What should fail together?** A panic or a runaway query takes down |
| 42 | one instance. Choose the unit whose outage you can explain to one |
| 43 | customer. |
| 44 | 3. **Who leaves together?** A unit's data is its own database and its |
| 45 | own objects, so exporting it is copying them and erasing it is a |
| 46 | bounded list (the platform keeps a deleted instance's data until you |
| 47 | remove it). Pick the unit a customer would ask to |
| 48 | export, delete or move to their own boxes. |
| 49 | 4. **What crosses units?** Sharing is **membership**, never copying: a |
| 50 | person joins someone else's instance (a coach in a client's log, a |
| 51 | member in a team). If a feature needs to *query* across units |
| 52 | (reporting, search across all customers), the unit is too small or |
| 53 | that feature belongs in its own app. A central app answers "what |
| 54 | might I have access to", never "may I have this". A view across |
| 55 | tenants (a vendor's dashboard, a person's search over their own |
| 56 | spaces) has its own pattern: §2 "Seeing across tenants". |
| 57 | 5. **Does it idle?** Instances that sit idle hibernate and cost nothing. |
| 58 | Small units that are used in bursts get the most from this. |
| 59 | |
| 60 | **The anti-pattern: tenancy by `WHERE` clause.** One instance, a |
| 61 | `tenant_id` column, every customer in one file. It gives up isolation, |
| 62 | per-unit erasure, per-unit residency and per-unit hibernation at once, |
| 63 | and one missed `WHERE` exposes everyone. On CARLOS, isolation is a |
| 64 | process and a file. Use one shared instance only when the whole app |
| 65 | really is one unit (one team, one list). |
| 66 | |
| 67 | ## 2. How people reach their instance |
| 68 | |
| 69 | Four recommended models, from the user-models design (approved |
| 70 | 2026-09-28). They are recommendations, not rules: if none fits, choose |
| 71 | your own and record why. |
| 72 | |
| 73 | | | Model | You sign in to… | Recommended when | Runs it today | |
| 74 | |---|---|---|---|---| |
| 75 | | A | **One instance, in-app accounts** | the app itself | one team, one household, one list, a personal tool | the internal finance ledger, Movement, the rastrillo default | |
| 76 | | B | **Simple home** | *your* instance | each person or team owns a space that stands alone | Oficina, Kass (in-process), the bank-connection app | |
| 77 | | C | **Hub** | a whole product | people belong to several spaces and move between them all day | Tito (subdomains and a proxy), amadan (path routes) | |
| 78 | | D | **Blind home** | your instances, server-blind | end-to-end encrypted apps where the centre must hold nothing readable | Eleven's home, Slopbox's home; `rastrillo/vault` is the client | |
| 79 | |
| 80 | - **A** is the least machinery: rastrillo `auth` or `password`, owner |
| 81 | scoping, and `idear` for roles and invitations. Its cost is that one |
| 82 | instance's blast radius is everyone in it, and it never grows into a |
| 83 | product with many independent customers. |
| 84 | - **B** is a small central app where you sign in, see your instances, |
| 85 | add one, and open one. Each instance has its own hostname and its own |
| 86 | sessions, and still accepts ordinary sign-in on its own origin, so it |
| 87 | works if the home is down. The home hands you in with a signed, |
| 88 | single-use assertion (rastrillo `assertion`, issuer the home, audience |
| 89 | the instance), posted in a form, never in a URL. Smallest leak profile |
| 90 | of the recommended models: the home knows who signed up and which |
| 91 | instances they own, nothing inside any of them. Cost: no shared chrome; |
| 92 | moving between spaces goes through the home. |
| 93 | - **C** puts the product on one domain and each tenant under a path |
| 94 | (`example.com/acme`) via the platform's path routes. One origin, one |
| 95 | session, one switcher; every tenant still its own process and file. |
| 96 | Costs: one origin is one browser security boundary, so use C only when |
| 97 | every tenant runs the app's own code (a product whose tenants publish |
| 98 | raw HTML their customers wrote needs B's per-tenant hostnames). The |
| 99 | hub's session-signing key is the product's crown jewel. **Today a path |
| 100 | target must live on the same box as the hostname**, so a path-routed |
| 101 | product is one box big. |
| 102 | How it fits together: the tenant receives `/acme/...` unchanged, so the |
| 103 | tenant app serves everything (routes, assets, redirects, form actions) |
| 104 | under its base path, and its own direct hostname redirects to the |
| 105 | product path. Because hub and tenants share one origin, there is one |
| 106 | session: the hub mints a short-lived signed cookie (15 minutes, with a |
| 107 | per-user epoch so "sign out everywhere" works), and tenants hold the |
| 108 | hub's public key (`carlos env set`) and verify it on every request, |
| 109 | never minting their own. Ordinary per-tenant rastrillo sessions do not |
| 110 | work under model C: every tenant would set the same cookie name on the |
| 111 | same origin and sign the others out. The hub delivers roster changes to the |
| 112 | instance first, with a signed request, then records its directory |
| 113 | copy. |
| 114 | - **D** is B's shape for server-blind apps: the home holds credential |
| 115 | public keys and one sealed blob per person and can read neither. |
| 116 | |
| 117 | **Central apps are stateless** (ruled 2026-09-27, a foundational CARLOS |
| 118 | principle). A home, hub, directory or sign-in service keeps no database: |
| 119 | its records are objects in its own store (`carlos store create`), created |
| 120 | with `If-None-Match: *` and updated with `If-Match`, at keys it can |
| 121 | compute (`users/<uid>.json`, `tenants/<slug>.json`). Nothing to |
| 122 | replicate, restore or migrate, and it moves between boxes with nothing |
| 123 | to copy. Anything relational (reporting, search) belongs in an instance. |
| 124 | |
| 125 | **Safety invariants, whichever model:** |
| 126 | |
| 127 | 1. The provisioning credential (`carlos services create --role instance |
| 128 | --app <tenant-app>`) lives on the central app, never on the tenant app. |
| 129 | It is app-wide today: it can also delete any sibling instance. Publish |
| 130 | that as a leak until the platform ships a create-only role. The same |
| 131 | goes for any `instance`-role token (`CARLOS_INSTANCE_TOKEN`): never put |
| 132 | one in the tenant app's secrets, whatever the convenience. |
| 133 | 2. An instance decides access from its own roster. A signature proves |
| 134 | who, never what. |
| 135 | 3. Handoff tokens never ride in URLs, and the receiver enforces single |
| 136 | use. |
| 137 | 4. Model C only where every tenant runs the app's own code. |
| 138 | 5. Every model publishes its leak profile (§3). |
| 139 | |
| 140 | **What is real today, and what is not** (2026-10-15): |
| 141 | |
| 142 | | Piece | State | |
| 143 | |---|---| |
| 144 | | Instances API, `instance` service role, path routes, `assertion`, `vault`, `idear`, stores | Shipped. Use them. platform.md "Provisioning instances from your own app" | |
| 145 | | Create-only, quota-bounded provisioning role | Not built (platform #185). Use the `instance` role and name the leak | |
| 146 | | Path targets on another box | Not built (platform #186). Model C is one box big | |
| 147 | | rastrillo `objrec`, stateless auth store, signed-cookie sessions, `provision`, base-path serving, `rastrillo new --model home\|hub` | Not released (`objrec` is on a branch). Hand-build on the patterns above, and don't claim the framework does it | |
| 148 | |
| 149 | ### Seeing across tenants |
| 150 | |
| 151 | A vendor wants totals across every customer; a person wants to search |
| 152 | every space they belong to. Tito runs both with one rule: **the centre |
| 153 | reports only what it owns or witnesses. It never opens a tenant's |
| 154 | database.** Four ways data legitimately crosses the boundary, in order of |
| 155 | preference: |
| 156 | |
| 157 | 1. **Witnessed facts.** Make the number a fact the vendor owns (a fee, a |
| 158 | charge, usage) and record it where the vendor already sits on the |
| 159 | path: the proxy, payment egress, mail egress, a payment provider's |
| 160 | webhook. Tito's staff console gets collections, request timings and |
| 161 | capacity this way, from facts its router, payment relay and the |
| 162 | payment provider saw for themselves. Fees *owed* are partly computed |
| 163 | from facts instances report, which is step 2. |
| 164 | 2. **Pushed facts through an outbox.** Where only the instance knows, it |
| 165 | writes a fixed-shape record (a fee accrual, a ticket count) to an |
| 166 | outbox table in the same transaction as the work, and a sender |
| 167 | delivers it to the central side, retrying until accepted. The |
| 168 | instance is usually asleep, so send at the end of the request that did |
| 169 | the work, and let anything undelivered go on the next wake or a daily |
| 170 | `carlos schedule` tick (a tighter schedule keeps the instance awake, |
| 171 | and that is billed). Retries mean duplicates, so each record carries a |
| 172 | stable id; the receiver dedupes on it in the same transaction as the |
| 173 | ledger write, acknowledges only after commit, and refuses a different |
| 174 | payload under an id it already holds (Tito does all four for fees). The record's |
| 175 | shape is declared residue, published like any other. The receiver |
| 176 | files each record under the instance that sent it, so **an instance |
| 177 | can only speak for itself**. Short self-descriptions (name, region, |
| 178 | counts) can also ride on responses the centre already proxies. |
| 179 | 3. **Browser fan-out for a person's own view.** A search or switcher |
| 180 | across someone's spaces asks each instance they are a member of, |
| 181 | from the browser. Every instance answers as it would any other request |
| 182 | from that person: membership, then their role's capabilities and any |
| 183 | narrower scope (Tito filters by the events and series a member may |
| 184 | see), so a result list never shows what the person could not open. No |
| 185 | central copy; nothing widens the set beyond real memberships. Tito |
| 186 | does this on one origin (model C), where the one session already |
| 187 | reaches every tenant. Across per-tenant hostnames (model B) each |
| 188 | request needs that origin's own session, so there it is usually a |
| 189 | link per space instead. Every request can wake a sleeping instance, |
| 190 | so Tito answers typing from a cache the browser built from each |
| 191 | instance's own answers (refreshed when that account's digest changes), |
| 192 | and asks the instances live only when the person asks for more |
| 193 | results, at most four at a time. |
| 194 | 4. **One tenant at a time, with consent.** Support access is granted from |
| 195 | inside the tenant (in Tito, by a member, never above their own role, |
| 196 | and capped at admin), time-limited, and logged before the first read, |
| 197 | failing closed if the log write fails. Never aggregation. |
| 198 | |
| 199 | **Where the vendor's records live.** Not in the router, hub or home. A |
| 200 | **back office app** with its own instance and database holds the |
| 201 | vendor's ledger, partners and statements, receives the outbox, takes |
| 202 | signed identity like any tenant instance, and asks the central app for |
| 203 | anything else through a narrow API (list accounts, create one). Tito's |
| 204 | console holds these in its router today; its proposed split moves them |
| 205 | into a back office app of this shape. |
| 206 | |
| 207 | **Not allowed:** a central app or reporting job opening tenant databases |
| 208 | (`carlos db pull` across every instance is a backup of everyone, not a |
| 209 | report); copying tenant content (buyers, messages, documents) into a |
| 210 | central store; a `tenant_id` warehouse. |
| 211 | |
| 212 | **The sender problem (2026-10-16).** Step 2 is only as good as the |
| 213 | receiver's knowledge of which instance sent a record. It must derive |
| 214 | that from a credential bound to the sending instance and verified by the |
| 215 | receiver, never from a name the sender supplies, and never from the |
| 216 | app-wide `instance` token, which every holder can present for any |
| 217 | sibling. Tito today trusts box-local sockets plus a header the instance |
| 218 | sets, so a compromised instance could report as a sibling. The family has |
| 219 | no ready-made per-instance sender credential on Carloku: platform tokens |
| 220 | are app-wide (#155, not built), and even scoped platform tokens would |
| 221 | not by themselves authenticate an instance to *your* receiver. Until a |
| 222 | pattern exists, cross-check pushed facts against what you witnessed |
| 223 | where you can (a fee against the provider's webhook), keep pushed |
| 224 | records to facts a lying instance gains little from, and name the gap as |
| 225 | a leak. |
| 226 | |
| 227 | ## 3. What the host can see: the trust class |
| 228 | |
| 229 | Tenancy says where the walls are; the trust class says what a host can |
| 230 | read inside them. Pick a class per **workload**, not per product: an |
| 231 | end-to-end encrypted app with an automation sidecar is two answers (Eleven |
| 232 | and Kass: instance A2, agent sidecar C). Classes order S ≤ A < B < C; the |
| 233 | A variants are flavours, not grades. |
| 234 | |
| 235 | | Class | The host holds | Examples | |
| 236 | |---|---|---| |
| 237 | | **S** stateless | no user data at all | static sites; a central app holding only public keys can be S plus declared residue (Dineraya's dispatcher) | |
| 238 | | **A1** host-blind | ciphertext; only transport shape leaks (who connects when, sizes, timing) | Slopbox (padded blobs, encrypted names) | |
| 239 | | **A2** host-blind, declared residue | ciphertext plus a published list of plaintext metadata | Keymail (routing headers), Kass (log timestamps), Eleven (thread membership), Dineraya buyer | |
| 240 | | **A/pub** public by design | A, plus surfaces that are public on purpose, listed one by one | Woodstar (public posts; DMs and blobs sealed) | |
| 241 | | **B** sealed single-tenant | sealed at rest (parked DB, replica, blobs); the live instance holds a key while awake because unattended work needs plaintext | an internal finance ledger, one instance per team (the defining example); Dineraya merchant | |
| 242 | | **C** host-sighted | plaintext at rest, chosen and written down: support visibility, SQL over personal data, payments | Tito (the defining example) | |
| 243 | |
| 244 | Several apps have not published a class letter yet (amadan's is |
| 245 | unresolved; Oficina, Movement and Correomona describe their |
| 246 | posture in words, without a letter). Don't assign one on their behalf. |
| 247 | |
| 248 | **The test is the CARLOS one: publish the database and see what leaks.** |
| 249 | A leaks its declared residue and nothing more; B's cold copy leaks |
| 250 | nothing; C leaks the data, and said so up front. Enforce it in CI: push a |
| 251 | marker through the app, then grep the raw SQLite bytes and bucket objects |
| 252 | for it. An undeclared plaintext surface is a class violation whatever the |
| 253 | intent. decisions.md §1 has each app's recorded reasoning. |
| 254 | |
| 255 | **Placement follows the class (designed, not yet enforced).** Hosts are |
| 256 | tiered by who controls the box: 0 the operator, 1 a named counterparty |
| 257 | under a data-processing agreement, 2 a stranger. S and A run anywhere, B |
| 258 | never on tier 2, C only on tier 0 or where the agreement names the data. |
| 259 | As of 2026-10-15 the platform does not record or enforce trust classes, |
| 260 | so declare the class in your README and AGENTS.md now; don't tell users |
| 261 | the platform enforces it. |
| 262 | |
| 263 | **Two more axes, independent of the class:** a **licence class** (L1 |
| 264 | libre, L2 source-available commercial, L3 open with a hosted offering, L4 |
| 265 | closed hosted-only, L5 closed hosted and on-prem: Tito, Jelly) and three |
| 266 | **remix flags** (forkable, agent-driveable through typed tools, |
| 267 | agent-rebuildable from a published skill). An L5 app can be class A; an |
| 268 | L1 app can be class C. |
| 269 | |
| 270 | ## 4. What the choice buys |
| 271 | |
| 272 | The benefits on carlosframework.com, each with the mechanism behind it |
| 273 | and what it depends on. State a benefit only with its mechanism, and only |
| 274 | the ones your tenancy actually earns. |
| 275 | |
| 276 | | Benefit | Mechanism | Depends on | State on Carloku, 2026-10-15 | |
| 277 | |---|---|---|---| |
| 278 | | **Isolated data per tenant** | each unit is its own process, SQLite file and socket; instances get CPU and IO limits and no loopback or private-network access | a boundary smaller than "the whole app" | live | |
| 279 | | **Blast radius of one** | a panic or runaway query kills one process; the next request restarts it | same | live | |
| 280 | | **A security claim you can falsify** | publish the database and see what leaks; the residue is declared | a declared class plus the CI grep test | yours to write | |
| 281 | | **Multiple trust classes** | one product, a class per workload (instance, sidecar, central app) | splitting workloads that need plaintext from those that don't | declare now; placement enforcement not built | |
| 282 | | **Encryption encouraged** | sealed content (A), sealed at rest (B), keys in browsers | the class you pick | rastrillo `crypto`, `vault`, `webauthn` are primitives; app-level E2EE is hand-built | |
| 283 | | **Continuous security monitoring** | `carlos errors`, `carlos availability`, edge analytics, opt-in virus scanning of stores | nothing | live | |
| 284 | | **Cost/performance efficiency** | idle instances hibernate to the bucket and cost nothing; the fleet is sized to concurrent use, not headcount | units that idle (smaller units idle more) | live | |
| 285 | | **Wake in under 500 ms** | a request for a sleeping instance is held while it wakes | same | live | |
| 286 | | **Replicated from the first byte** | every database streams to object storage; every wake is a restore | an instance with a database (central apps keep records in the store instead) | live | |
| 287 | | **Export and erasure per tenant** | a tenant's data is its own database and its own objects, never rows mixed with others, so export is copying them and erasure is a bounded list | the unit matching who leaves together | export live (`carlos db pull`); erasure is a procedure you write: `instances delete` deliberately keeps the parked database, replica and store objects, so name each and how it goes | |
| 288 | | **Residency per app or per instance** | an instance only wakes on a host in its region | per-unit instances, so each customer can be pinned | released, switched off on Carloku | |
| 289 | | **Self-hostable, first class** | one binary, a bucket and DNS; same binary hosted, on a customer's boxes (`carlos fleets`), or on a self-run platform | nothing; licence class decides what customers may do | live | |
| 290 | | **One codebase, every deployment** (vendors) | one instance per customer means on-prem is a fleet you administer, not a fork | per-customer instances | customer fleets live; Tito self-hosts in three regions | |
| 291 | | **API- and agent-driveable** | actions opt in as tools that reach the same handler a form does | rastrillo `tools` (manifest-generated) | in rastrillo; no app has published tools yet | |
| 292 | |
| 293 | What a tenancy choice **costs** belongs in the same declaration: |
| 294 | cross-unit queries are hard by design; a stateless centre makes writes |
| 295 | dearer than a SQLite row; model C is one box big today; class A or B |
| 296 | makes recovery and search product surface; class C puts confidentiality |
| 297 | on operator policy and authorization, not mathematics. |
| 298 | |
| 299 | ## 5. Worked choices |
| 300 | |
| 301 | Short, to show the reasoning. Each still needs its own declaration. |
| 302 | |
| 303 | - **A bookkeeping ledger per small business, synced nightly with the |
| 304 | bank.** One instance per business; model B (a stateless home lists the |
| 305 | business's ledgers). Class B: sealed at rest, the live instance holds |
| 306 | the key for the unattended sync, and the README says a live-host |
| 307 | compromise reads data. Nightly work is `carlos schedule`, so the |
| 308 | instance sleeps the rest of the day. |
| 309 | - **A forge where people belong to several organisations.** One instance |
| 310 | per repository (amadan) or per organisation; model C, a stateless hub |
| 311 | with path routes and one session. Trust is per content tier: public and |
| 312 | private repos are server-readable (C), end-to-end encrypted repos are A. |
| 313 | Rendered markdown is the app's own code, so C's one-origin rule holds; |
| 314 | raw user-hosted HTML (pages) needs its own hostnames. One box big until |
| 315 | cross-box path targets ship. |
| 316 | - **A support desk sold to companies, whose agents read customer email; |
| 317 | big customers want on-prem.** One instance per customer company. Class |
| 318 | C, argued from support load, repaid with origin splits (credentials on |
| 319 | one origin, customer-authored mail rendered on another). Licence L5 if |
| 320 | closed. On-prem is a customer fleet or a self-hosted platform following |
| 321 | your release channel: the same binary, not a fork. |
| 322 | - **Team chat.** One instance per conversation or team; model D, a blind |
| 323 | home. Class A2 with the residue listed (membership, timestamps). |
| 324 | - **A product site.** No instance at all: `carlos deploy --kind static`. |
| 325 | Class S. |
| 326 | |
| 327 | ## 6. The tenancy declaration |
| 328 | |
| 329 | Write this into AGENTS.md (and the README's trade-offs) before code. It |
| 330 | is the answer an agent planning a CARLOS app gives first. |
| 331 | |
| 332 | ``` |
| 333 | Tenancy declaration: <app>, <date>, <who decided> |
| 334 | One instance is: <the unit> (person : instance = 1:1 | N:1 | 1:N | N:N) |
| 335 | Why this unit: <whose data; what fails together; who leaves together> |
| 336 | Reached through: model A | B | C | D, or <own model, and why> |
| 337 | Central app: none | home | hub; stateless, records in its store |
| 338 | Workloads and class: instance = <S|A1|A2|A/pub|B|C>; sidecar = <…>; central = <…> |
| 339 | Declared residue: <every plaintext surface, one per line> |
| 340 | Keys live: <browsers | instance memory while awake | n/a> |
| 341 | Hosting: Carloku | customer fleets | self-hosted platform |
| 342 | Licence class: L1–L5, or "not published yet" |
| 343 | Benefits claimed: <each with its mechanism, from §4> |
| 344 | Costs accepted: <each, plainly> |
| 345 | Waiting on: <unshipped platform or rastrillo pieces relied on, by name> |
| 346 | ``` |
| 347 | |
| 348 | ## Common mistakes |
| 349 | |
| 350 | | Mistake | Reality | |
| 351 | |---|---| |
| 352 | | A Carloku account per customer | Accounts are the app author's tenancy on the platform. Customers are instances of your app. | |
| 353 | | A `tenant_id` column in one shared instance | Gives up isolation, erasure, residency and hibernation per tenant. Make the tenant an instance. | |
| 354 | | A stateful home or hub with its own SQLite | Central apps are stateless; records are objects in the store. | |
| 355 | | The provisioning credential on the tenant app | Every instance would hold a token that can delete its siblings. It lives on the central app only. | |
| 356 | | Trusting the hub's membership list for access | The instance's own roster decides. The hub's copy is a directory. | |
| 357 | | One class for the whole product | Class is per workload. A sidecar or central app that sees plaintext gets its own letter. | |
| 358 | | Claiming the platform enforces your class or residency | Neither is enforced on Carloku as of 2026-10-15. Declare; don't overclaim. | |
| 359 | | Copying data between instances to share it | Sharing is membership. Data never crosses a boundary. | |
| 360 | | A reporting job that opens every tenant's database | The centre reports what it owns or witnesses; instances push fixed-shape facts through an outbox; a person's cross-space view fans out in the browser — §2 "Seeing across tenants". | |
| 361 | |