Tenant Isolation
Per-school tenant isolation: one school’s data is never another school’s
The toolchain runs each school as its own tenant. Isolation is a property of the data layer, not a filter a route applies after reading. A record from one school is never visible to another school.
Isolation at the data layer, not the route
Each school is a tenant leaf. A read scoped to one school returns only that school’s roster, galleries, orders, and exports — enforced at the data layer before any application route sees the result. It is not a WHERE clause a route could omit; the isolation fires first. One school’s portraits, roster, and order history are never visible on another school’s surface.
The roster is the tenant spine
Because every module keys off the roster, tenant isolation follows the roster automatically. A gallery, an order, and a pro-lab export all resolve to a roster record that belongs to exactly one school tenant. There is no shared portrait pool across schools and no cross-school directory. The roster scopes the whole toolchain.
The school owns its data
A school owns its roster, its consent records, its galleries, and its order history. The toolchain reads the roster on import and reflects roster changes on the next import cycle; the authoritative roster stays in the school’s own system. If a school leaves, its records go with it. The toolchain is the operating software, not the owner of the school’s record.
Free to run — no contract, no per-seat fee
Running the toolchain carries no contract and no per-seat fee. A school operates the roster import, the consent gate, the galleries, the derived products, and the pro-lab output without a license charge. Pricing and checkout are not on this page; the order rails’ live payment step is honest-off. The software a school runs its program on is free to run.