mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:01:09 +02:00
feat(spaces): add spaces pg schema — credentials + module_permissions
Groundwork for server-side Space extensions that must NOT live in Dexie:
- spaces.credentials — per-space OAuth tokens, API keys, SMTP
configs. Access tokens are stored
encrypted at rest with the service KEK.
- spaces.module_permissions — role × module read/write/admin overrides
on top of the SPACE_MODULE_ALLOWLIST
defaults.
Both tables FK to auth.organizations with ON DELETE CASCADE so deleting
a space drops its credentials and permission overrides automatically.
RLS is intentionally deferred — enabling it now would lock out services
that don't yet pass space context. A follow-up migration turns it on
after mana-api speaks the Spaces protocol end-to-end.
To apply locally: bun run db:push in services/mana-auth, or psql -f
sql/004_spaces.sql against the mana_platform DB.
No runtime code reads these tables yet — they're the scaffolding that
Task-8 (mana-sync) and the eventual social-relay/clubs modules will
consume.
Plan: docs/plans/spaces-foundation.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
da1bb2d6e9
commit
698ffe797c
3 changed files with 167 additions and 0 deletions
70
services/mana-auth/sql/004_spaces.sql
Normal file
70
services/mana-auth/sql/004_spaces.sql
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
-- Migration 004: Spaces schema
|
||||
--
|
||||
-- Adds the `spaces` schema with two server-side tables that extend Better
|
||||
-- Auth organizations for our multi-tenancy model. See
|
||||
-- docs/plans/spaces-foundation.md for the full RFC, and the Drizzle
|
||||
-- definitions at src/db/schema/spaces.ts.
|
||||
--
|
||||
-- Why a separate schema:
|
||||
-- - Keeps auth tables focused on identity, not domain extensions
|
||||
-- - Lets us grant narrower RLS policies per schema
|
||||
-- - Mirrors the pgSchema-per-concern pattern used across mana_platform
|
||||
--
|
||||
-- Idempotent: re-running on a partially-migrated DB is safe.
|
||||
|
||||
-- ─── Schema ──────────────────────────────────────────────────────
|
||||
CREATE SCHEMA IF NOT EXISTS spaces;
|
||||
|
||||
-- ─── credentials ────────────────────────────────────────────────
|
||||
-- Per-space external credentials: OAuth tokens, API keys, SMTP configs.
|
||||
-- NEVER stored client-side — these are server-held secrets, wrapped with
|
||||
-- the service-wide KEK (same mechanism as auth.encryption_vaults).
|
||||
CREATE TABLE IF NOT EXISTS spaces.credentials (
|
||||
space_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
access_token_encrypted TEXT NOT NULL,
|
||||
refresh_token_encrypted TEXT,
|
||||
expires_at TIMESTAMPTZ,
|
||||
scopes TEXT[],
|
||||
provider_account_id TEXT,
|
||||
metadata_json TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (space_id, provider),
|
||||
CONSTRAINT space_credentials_space_fk
|
||||
FOREIGN KEY (space_id) REFERENCES auth.organizations (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS space_credentials_space_idx
|
||||
ON spaces.credentials (space_id);
|
||||
|
||||
-- ─── module_permissions ─────────────────────────────────────────
|
||||
-- Role × module permission matrix. If no row exists for a given
|
||||
-- (space, role, module) tuple, the default is derived from SPACE_MODULE_ALLOWLIST
|
||||
-- plus role-tier fallback (owner > admin > member). Rows here are
|
||||
-- explicit overrides — typically written when a space owner customises
|
||||
-- the default permissions for a custom role.
|
||||
CREATE TABLE IF NOT EXISTS spaces.module_permissions (
|
||||
space_id TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
module_id TEXT NOT NULL,
|
||||
can_read BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
can_write BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
can_admin BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (space_id, role, module_id),
|
||||
CONSTRAINT space_module_permissions_space_fk
|
||||
FOREIGN KEY (space_id) REFERENCES auth.organizations (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS space_module_permissions_space_module_idx
|
||||
ON spaces.module_permissions (space_id, module_id);
|
||||
|
||||
-- ─── RLS ─────────────────────────────────────────────────────────
|
||||
-- Defer enabling RLS until the rest of the app is scope-aware. Turning
|
||||
-- it on now would lock out services that don't yet pass the space
|
||||
-- context. Re-enable in a follow-up migration once mana-api speaks the
|
||||
-- Spaces protocol end-to-end.
|
||||
--
|
||||
-- ALTER TABLE spaces.credentials ENABLE ROW LEVEL SECURITY;
|
||||
-- ALTER TABLE spaces.module_permissions ENABLE ROW LEVEL SECURITY;
|
||||
Loading…
Add table
Add a link
Reference in a new issue