Context
offplan.online — multi-tenant B2B2C SaaS где один платежник (Client) может оперировать несколькими типами Organisations (Studio / Agency / Developer), и где гостевые Organisations (приглашённые без платной подписки) видят только то что им явно открыто. Phase 1.3 (Tenancy & Permission Model) — foundational: блокирует Phase 1.4 / 1.7 / 1.10 / 1.11.
Архитектура должна закрывать:
- Кто платит (Client → Organisation tier подписка).
- Кто работает с контентом (Organisation team — 5 ролей).
- Кто видит публичный контент (Buyer + anonymous viewers через scoped URLs).
- Cross-Organisation collaboration (Studio → Developer как guest, или reverse).
- Internal/External Sales Agent split (employee vs agency-affiliated).
Все эти решения зафиксированы в Foundational §1 (Entities) + §2 (Onboarding) + §4 (Access) launch-plan-stage-1.html. ADR 0009 — codification single-source-of-truth для tech team + future ADR cross-references.
Decision
Tenancy model = Client-Organisation hybrid с 5 Partner ролями + Operator + Buyer.
Entity model (Foundational §1)
- Client — billing-payer, owns 1+ Organisations. Один email = одна Client identity (workspace switcher pattern для multi-Org users).
- Organisation — operational unit, multi-select type (Studio / Agency / Developer). Все content (projects / units / etc) scope'ится к Organisation. Одна Organisation = одна subscription tier (per ADR 0008).
- Buyer — end-customer, passwordless per-presentation magic link (no dashboard, tokenised URL only). См. ADR 0012 для buyer presentation flow.
- Operator — OPL master role (
staff.offplan.online), отдельный auth surface, не описывается в данном ADR (Phase 1.4 Operator Dashboard).
5 Partner roles (Foundational §2 + CONV-22)
Внутри Organisation team:
- Owner — billing, member management, full operational control. 1 per Organisation, transferable (per ADR 0003).
- Admin — member management + full operational. 0+ per Organisation.
- Sales Manager —
Content Editor + stock allocation + buyer flow(объединённая operational роль per CONV-22). Не управляет членами + не видит billing. - Content Editor — full content control, no stock allocation, no buyer flow. Sees all units regardless of allocation (content access ≠ sales access — separate concern).
- Sales Agent — reads + reserves units assigned to him/her per S·1 (см. ADR 0010). Two operational variants (CONV-24): Internal SA (Organisation employee, sees all Org units) + External SA (agency-affiliated, sees only assigned). Variant derived через
organisation_idlink на Sales Agent's home Org.
Hybrid login surfaces (Foundational §2 + CONV-21)
- Per-Organisation branded
{slug}.offplan.online/login— Owner + team default. - Central fallback
app.offplan.online/login— для users которые не помнят subdomain. - Single auth backend, session cookie scope
*.offplan.online, 30d (per ADR 0005). - Auth methods: Google + email/password (per ADR 0005). Microsoft + Custom SSO — Tier 3 Stage 2 (per ADR 0005 v3).
Auth-scoped views (CONV-21)
Один URL {slug}.offplan.online/projects/{project-slug} рендерит разный контент в зависимости от viewer state:
- Anonymous → Public Visibility preset (Foundational §5).
- Authed Organisation team member → full content фильтрованный по S·1 stock allocation (per ADR 0010).
- Buyer с tokenised URL → unit-aware buyer view (per ADR 0012 + Phase 1.11).
Login entry surface — иконка top-right на каждой странице sales-app (Phase 1.10.0).
Scoped URL routing (Foundational §2)
- Subdomain = Organisation identity:
{slug}.offplan.online(default), Tier 2+ custom domain (per ADR 0011 + Phase 1.7.10). - Project slug = within-Org identity:
/projects/{project-slug}. - Buyer token URL = ephemeral magic link с unit context:
/p/{opaque_token}(Phase 1.11). - Reserved subdomain blacklist —
staff/app/api/admin/www/ etc (Phase 1.4.2).
Cross-entity invitations (Foundational §4)
- Forward (Developer → Studio): Developer invite Studio Organisation as guest (Studio видит только присланные content, не свой). Studio = Free Guest tier (per ADR 0008).
- Reverse (Studio → Developer): Studio приглашает Developer как Free Guest, conversion path к own paid tier при self-onboarding (Phase 1.2 Onboarding flow).
- Token mechanics: opaque token + 7d expiry + single-use (Phase 1.3.7).
- Email mismatch: invite email ≠ account email → error message Stage 1 (no auto-link).
Permission scoping (Foundational §4)
Three orthogonal axes:
- Role permissions (RBAC matrix per Foundational §4.2) — что роль может делать (CRUD on entities).
- Stock allocation (S·1 per ADR 0010) — какие юниты role видит/может продать.
- Visibility presets (Public Visibility per Foundational §5) — что anonymous / public видит на subdomain.
Three axes are independent: role allows action → allocation allows resource → visibility preset shows to anonymous.
Alternatives Considered
- Monolithic tenancy (one Org type) — rejected. Client + Organisation split позволяет multi-Org Clients (e.g., agency operating under multiple brand identities); Organisation type multi-select handles studios that also act as agencies.
- Shared-org model (no tenant boundary) — rejected. Anti-pattern для off-plan property where multi-developer + multi-agency content must isolate at Organisation level (legal + commercial requirements).
- Pure RBAC (role-only, no scoping) — rejected. RBAC alone не решает «Sales Agent X видит units assigned, не others» — нужен resource-level scope (S·1) поверх RBAC.
- Pure ABAC (attribute-based) — rejected as primary mechanism. ABAC более expressive, но overkill для Stage 1 + harder для tech team to implement and audit. RBAC + scoping сейчас + ABAC layer добавляется в Stage 2 если custom workflows понадобятся.
Consequences
- Phase 1.3.1-1.3.12 могут стартовать без дальнейшего sub-plan input — все 12 numbered tasks реализуют ratified architecture в этом ADR.
- Sub-plan
plans/permission-and-tenancy-model.md(currently stub) — обогащает ADR 0009 tech-level details: DB schema, RBAC implementation matrix, exact API contracts. Sub-plan ratification отдельной/planсессией. - DB schema impact:
clients/organisations/organisation_memberships(with role enum) /buyer_tokens/invitations(with type forward|reverse) /referralstables. - Audit log requirements: per ADR 0004 retention, all role/membership/invitation events logged.
- Cross-references:
- ADR 0010 (Stock allocation) — uses Sales Agent role + Internal/External split here.
- ADR 0008 (Tier model) — uses Organisation entity для tier subscription scoping.
- ADR 0005 (Auth methods) — applies к 5 Partner roles (Buyer uses magic link, Operator separate auth surface).
- ADR 0012 (Real-time sync) — uses Buyer entity + tokenised URL для presentation.
Revisit trigger
- Custom roles demand from 3+ studios — RBAC matrix becomes ABAC layer in Stage 2.
- Cross-Org workflow required (e.g., Studio + Agency joint sales team) — re-evaluate Cross-entity invitations as full federation.
- Buyer dashboard demand — re-evaluate Buyer entity from passwordless tokenised к full account model.