# Framework vs Application Ownership This document defines **ownership boundaries** between the framework and application code. These boundaries are intentional and non-negotiable: they exist to preserve upgradeability, predictability, and developer sanity under stress. Ownership answers a simple question: > **Who is allowed to change this, and under what rules?** The framework draws a hard line between *framework‑owned* and *application‑owned* concerns, while still encouraging extension through explicit, visible mechanisms. --- ## Core Principle The framework is not a library of suggestions. It is a **runtime with invariants**. Application code: * **uses** the framework * **extends** it through defined seams * **never mutates or overrides its invariants** Framework code: * guarantees stable behavior * owns critical lifecycle and security concerns * must remain internally consistent across versions Breaking this boundary creates systems that work *until they don’t*, usually during upgrades or emergencies. --- ## Database Ownership ### Framework‑Owned Tables Certain database tables are **owned and managed exclusively by the framework**. Examples (illustrative, not exhaustive): * authentication primitives * session or token state * internal capability/permission metadata * migration bookkeeping * framework feature flags or invariants #### Rules Application code **must not**: * modify schema * add columns * delete rows * update rows directly * rely on undocumented columns or behaviors Application code **may**: * read via documented framework APIs * reference stable identifiers explicitly exposed by the framework Think of these tables as **private internal state** — even though they live in your database. > If the framework needs you to interact with this data, it will expose an API for it. #### Rationale These tables: * encode security or correctness invariants * may change structure across framework versions * must remain globally coherent Treating them as app‑owned data tightly couples your app to framework internals and blocks safe upgrades. --- ### Application‑Owned Tables All domain data belongs to the application. Examples: * users (as domain actors, not auth primitives) * posts, orders, comments, invoices * business‑specific joins and projections * denormalized or performance‑oriented tables #### Rules Application code: * owns schema design * owns migrations * owns constraints and indexes * may evolve these tables freely The framework: * never mutates application tables implicitly * interacts only through explicit queries or contracts #### Integration Pattern Where framework concepts must relate to app data: * use **foreign keys to framework‑exposed identifiers**, or * introduce **explicit join tables** owned by the application No hidden coupling, no magic backfills. --- ## Code Ownership ### Framework‑Owned Code Some classes, constants, and modules are **framework‑owned**. These include: * core request/response abstractions * auth and user primitives * capability/permission evaluation logic * lifecycle hooks * low‑level utilities relied on by the framework itself #### Rules Application code **must not**: * modify framework source * monkey‑patch or override internals * rely on undocumented behavior * change constant values or internal defaults Framework code is treated as **read‑only** from the app’s perspective. --- ### Extension Is Encouraged (But Explicit) Ownership does **not** mean rigidity. The framework is designed to be extended via **intentional seams**, such as: * subclassing * composition * adapters * delegation * configuration objects * explicit registration APIs #### Preferred Patterns * **Subclass when behavior is stable and conceptual** * **Compose when behavior is contextual or optional** * **Delegate when authority should remain with the framework** What matters is that extension is: * visible in code * locally understandable * reversible No spooky action at a distance. --- ## What the App Owns Completely The application fully owns: * domain models and data shapes * SQL queries and result parsing * business rules * authorization policy *inputs* (not the engine) * rendering decisions * feature flags specific to the app * performance trade‑offs The framework does not attempt to infer intent from your domain. --- ## What the Framework Guarantees In return for respecting ownership boundaries, the framework guarantees: * stable semantics across versions * forward‑only migrations for its own tables * explicit deprecations * no silent behavior changes * identical runtime behavior in dev and prod The framework may evolve internally — **but never by reaching into your app’s data or code**. --- ## A Useful Mental Model * Framework‑owned things are **constitutional law** * Application‑owned things are **legislation** You can write any laws you want — but you don’t amend the constitution inline. If you need a new power, the framework should expose it deliberately. --- ## Summary * Ownership is about **who is allowed to change what** * Framework‑owned tables and code are read‑only to the app * Application‑owned tables and code are sovereign * Extension is encouraged, mutation is not * Explicit seams beat clever hacks Respecting these boundaries keeps systems boring — and boring systems survive stress.