# Instructors and Academies are Organizations

The repository's architectural decision, rationale and consequences.

# Instructors and Academies are Organizations

**Status:** accepted · **Date:** 2026-11-13 · **Related:** [ADR-0003](0003-organizations-are-the-tenant.md), [ADR-0009](0009-row-level-security.md)

**Enforcement:** `[test]` `instructor.procedures.test.ts` (another Organization gets NOT_FOUND/CONFLICT, a non-Member FORBIDDEN) · `[test]` `packages/db/src/rls-catalog.test.ts` and `db:verify-rls`.

The template's tenant is the Organization, and every User gets a personal Organization at sign-up. BJJ Travel has two sides: an Instructor (one person) and an Academy (an owner plus staff).

## Decision [#decision]

- **Travel Role** is chosen once per Organization (`travel_role`): `instructor` or `academy` (US-01). The Instructor's personal Organization holds `instructor_profile`, `travel_window`, `visit` and `consent_record`; an Academy is an Organization with Members (S5).
- The network (S2) lives there too: `contact`, `introduction` (insert-only, no UPDATE grant) and `intro_request` (UPDATE only on `status`, `answered_at`). A Contact has no email or phone column (RN08).
- All Instructor tables use `pgTable.withRLS` + `tenantPolicy`; history tables (`visit`, `consent_record`) get no UPDATE grant.
- Cross-side reads (an Academy sees published windows; an Instructor sees registered Academies) are deliberate tenant crossings through `asSystem(db, reason, fn)`, each with its own `SystemReason`, and return only what the visibility rules allow.

