24 lines
1.1 KiB
SQL
24 lines
1.1 KiB
SQL
-- +goose Up
|
|||
|
|
-- Per-member access overlay set by the company owner.
|
||
|
|
--
|
||
|
|
-- Sparse JSONB map of dashboard feature key -> false. Absent key means "inherit"
|
||
|
|
-- (allowed, still subject to the plan). The overlay is purely restrictive: effective
|
||
|
|
-- access = plan features ∩ global gates ∩ member overlay, so a member can never be
|
||
|
|
-- granted more than the company's plan allows and no privilege escalation is possible.
|
||
|
|
--
|
||
|
|
-- The company owner (companies.owner_user_id) is never restricted — the owner is the
|
||
|
|
-- one who edits these — so their row's overlay is ignored at resolve time.
|
||
|
|
|
||
|
|
ALTER TABLE memberships
|
||
|
|
ADD COLUMN IF NOT EXISTS permissions JSONB NOT NULL DEFAULT '{}'::jsonb;
|
||
|
|
|
||
|
|
-- Partial index: only restricted members carry a non-empty overlay, and the common
|
||
|
|
-- read is "does this member have any restriction at all".
|
||
|
|
CREATE INDEX IF NOT EXISTS memberships_restricted_idx
|
||
|
|
ON memberships (company_id, user_id)
|
||
|
|
WHERE permissions <> '{}'::jsonb;
|
||
|
|
|
||
|
|
-- +goose Down
|
||
|
|
DROP INDEX IF EXISTS memberships_restricted_idx;
|
||
|
|
ALTER TABLE memberships DROP COLUMN IF EXISTS permissions;
|