Files
website/server/db
wtclaude 225663d62e feat(teams): core schema for Teams, membership, sync state and moderation
The six core tables Team core is built on (docs/website/TEAMS.md §2.1, §2.5,
§2.5.1, §2.9), plus the §2.10 account-deletion decisions expressed as foreign
keys rather than left to whatever the defaults happened to be.

Every table is core-internal (§10.3): a module populates them through the team
provider and must never read or write one directly. They carry no <moduleId>_
prefix, correctly -- MODULE_API.md §2.6's prefix rule binds modules, and these
are core's.

team_forum_grants lands in this phase rather than in phase 4, so the four-path
resolver is written once and its non-contamination tests are real. Nothing
writes it yet; the grant/revoke flow, the per-Team cap and the leader UI are
phase 4's.

Two departures from the SQL as TEAMS.md sketched it, both recorded in the file:

  - team_forum_grants.user_id is nullable with ON DELETE SET NULL, following
    §2.10 (the audit trail of who granted whom must survive the account) rather
    than §2.5's CASCADE.

  - its uniqueness marker is derived from revoked_at alone, with user_id moved
    into the unique KEY. §2.5's `active_user AS (IF(revoked_at IS NULL, user_id,
    NULL))` cannot coexist with the line above: MariaDB refuses ON DELETE SET
    NULL on a foreign key whose column is a base column of a STORED generated
    column (error 1901). The semantics are identical -- at most one active grant
    per (team, user), unlimited revoked rows.

Verified by running ensureSchema() against MariaDB 11: all six tables create,
both generated columns materialise, and every foreign key's delete rule matches
§2.10's table. The uniqueness encoding was checked directly -- a second active
grant for the same (team, user) is rejected 1062 while revoked rows accumulate
freely.

Refs docs/website/TEAMS.md Part 12 phase 2

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-17 14:40:26 -05:00
..