Eigentum an Mandantendaten
Klärt Eigentum jeder SaaS-Datenkategorie und erzwingt Beziehungen ohne stillen Wechsel über Arbeitsbereichsgrenzen.
tenant-model-data-ownership
Teammitglieder mit diesem Skill
Wann ist der Skill hilfreich?
Nutze ihn bei gemeinsamen Datenbanken oder Trennung von Benutzeridentität, Abrechnungskonten und operativen Arbeitsbereichsdaten.
Wobei hilft er dir?
- Trennt globale, persönliche, abrechnungsbezogene und operative Arbeitsbereichsdaten.
- Wählt eine zu tatsächlichen Anforderungen passende Isolationstopologie.
- Erzwingt begrenzte Beziehungen durch Constraints und Zeilenschutz.
Das könntest du fragen
Modelliere Mehrfachmitgliedschaften ohne Vermischung von Abrechnungs- und Betriebsdatenverantwortung. Lass eine Person zwei unterschiedlich abgerechneten Arbeitsbereichen beitreten. Definiere Eigentum an Identität, Rechnungen und Projekten samt Schutz vor vermischten Beziehungen.
Ausführliche Dokumentation
Hier findest du die ursprüngliche Anleitung, Beispiele und Prüfschritte des Skills in ihrer Originalsprache.
Weniger anzeigen
Tenant Model & Data Ownership
When to Use
Use when designing schemas, repositories, or domain models for multi-tenant SaaS applications (organizations, workspaces, teams, projects, and tenant-scoped resources).
Four-Tier Data Ownership Taxonomy
Never leave a table or entity's ownership ambiguous. Classify every record into one of four explicit scopes:
- System / Global Data: Shared reference data (
plans,currencies,feature_definitions,system_migrations)—never writable by tenant requests. - User / Personal Identity Data: Account-level identity (
users,user_sessions,passkeys,mfa_devices,personal_notifications)—owned byuser_idacross all workspaces the user belongs to. - Organization / Billing Account Data: Top-level customer entity (
organizations,billing_subscriptions,invoices,sso_domains). - Workspace / Tenant-Scoped Operational Data: Projects, tasks, documents, files, webhooks, API keys, and audit events—strictly owned by a single
workspace_id/tenant_id.
Never mix a user's personal integration credentials or settings with workspace-owned credentials.
Database Isolation Topologies & Defense in Depth
1. Pool, Schema, or Silo Selection
Match the physical isolation model to the project's architecture and compliance needs:
- Shared Database, Shared Schema (Pool Model): Every tenant-scoped table carries a
NOT NULLtenant_id(workspace_id) column. Most common and operationally simple, but requires strict query scoping and relational constraints. - Shared Database, Separate Schema / Separate Database (Bridge / Silo Model): Used only when contractually or architecturally required. Never silently migrate a shared-schema app into a multi-DB architecture without an explicit architectural decision.
2. Composite Foreign Keys to Prevent Cross-Tenant Graph Corruption
Relying solely on project_id REFERENCES projects(id) allows a bug in tasks insertion to attach tenant_id = A to a project_id owned by tenant_id = B!
- In relational databases (PostgreSQL, MySQL, SQLite), expose
(tenant_id, id)as aUNIQUEor compositePRIMARY KEYon parent tables and enforce Composite Foreign Keys on child tables:CREATE TABLE projects ( id UUID NOT NULL, tenant_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, name TEXT NOT NULL, PRIMARY KEY (tenant_id, id) ); CREATE TABLE tasks ( id UUID NOT NULL, tenant_id UUID NOT NULL, project_id UUID NOT NULL, title TEXT NOT NULL, PRIMARY KEY (tenant_id, id), FOREIGN KEY (tenant_id, project_id) REFERENCES projects (tenant_id, id) ON DELETE CASCADE ); - Place
tenant_idas the leading column in composite B-tree indexes ((tenant_id, status, created_at)) so tenant queries and uniqueness checks (UNIQUE (tenant_id, slug)) scan only a single tenant's slice.
3. PostgreSQL Row-Level Security (RLS) & SET LOCAL Pooling Safety
When PostgreSQL RLS is used as defense-in-depth alongside application query filters:
- Enable both
ALTER TABLE ... ENABLE ROW LEVEL SECURITY;andALTER TABLE ... FORCE ROW LEVEL SECURITY;(withoutFORCE, the table owner role bypasses RLS completely!). - Enforce both
USING(reads/updates/deletes) andWITH CHECK(inserts/updates) policies againstcurrent_setting('app.current_tenant_id', true). - Connection Pool Rule: Never run session-level
SET app.current_tenant_id = ...on a pooled connection—when returned to the pool, the next request inherits the previous tenant! Always bind the setting inside an explicit transaction usingSET LOCALorSELECT set_config('app.current_tenant_id', $1, true).
Enthaltene Dateien 1
SKILL.md
