feat(manager-core): add 0006 users_authz migration
Adds instance_role + reserved email/mfa_secret columns to admin_users, creates app_members for per-app role grants, and creates api_keys for bearer-token credentials. Schema snapshot re-blessed. Reserves invites and service_accounts shapes in a trailing comment block — both land in their own migrations when those flows ship. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,21 @@ table: admin_users
|
||||
created_at: timestamp with time zone NOT NULL default=now()
|
||||
updated_at: timestamp with time zone NOT NULL default=now()
|
||||
last_login_at: timestamp with time zone NULL
|
||||
instance_role: text NOT NULL default='owner'::text
|
||||
email: text NULL
|
||||
mfa_secret: text NULL
|
||||
|
||||
table: api_keys
|
||||
id: uuid NOT NULL default=gen_random_uuid()
|
||||
user_id: uuid NOT NULL
|
||||
hash: text NOT NULL
|
||||
prefix: text NOT NULL
|
||||
name: text NOT NULL
|
||||
scopes: ARRAY NOT NULL
|
||||
app_id: uuid NULL
|
||||
expires_at: timestamp with time zone NULL
|
||||
last_used_at: timestamp with time zone NULL
|
||||
created_at: timestamp with time zone NOT NULL default=now()
|
||||
|
||||
table: app_domains
|
||||
id: uuid NOT NULL default=gen_random_uuid()
|
||||
@@ -27,6 +42,12 @@ table: app_domains
|
||||
shape_key: text NOT NULL
|
||||
created_at: timestamp with time zone NOT NULL default=now()
|
||||
|
||||
table: app_members
|
||||
app_id: uuid NOT NULL
|
||||
user_id: uuid NOT NULL
|
||||
role: text NOT NULL
|
||||
created_at: timestamp with time zone NOT NULL default=now()
|
||||
|
||||
table: app_slug_history
|
||||
slug: text NOT NULL
|
||||
current_app_id: uuid NOT NULL
|
||||
@@ -88,14 +109,25 @@ indexes on admin_sessions:
|
||||
admin_sessions_user_idx: public.admin_sessions USING btree (user_id)
|
||||
|
||||
indexes on admin_users:
|
||||
admin_users_email_key: public.admin_users USING btree (email)
|
||||
admin_users_instance_role_idx: public.admin_users USING btree (instance_role)
|
||||
admin_users_pkey: public.admin_users USING btree (id)
|
||||
admin_users_username_key: public.admin_users USING btree (username)
|
||||
|
||||
indexes on api_keys:
|
||||
api_keys_pkey: public.api_keys USING btree (id)
|
||||
api_keys_prefix_idx: public.api_keys USING btree (prefix)
|
||||
api_keys_user_id_idx: public.api_keys USING btree (user_id)
|
||||
|
||||
indexes on app_domains:
|
||||
app_domains_app_id_idx: public.app_domains USING btree (app_id)
|
||||
app_domains_pkey: public.app_domains USING btree (id)
|
||||
app_domains_shape_key_key: public.app_domains USING btree (shape_key)
|
||||
|
||||
indexes on app_members:
|
||||
app_members_pkey: public.app_members USING btree (app_id, user_id)
|
||||
app_members_user_id_idx: public.app_members USING btree (user_id)
|
||||
|
||||
indexes on app_slug_history:
|
||||
app_slug_history_pkey: public.app_slug_history USING btree (slug)
|
||||
|
||||
@@ -127,15 +159,28 @@ constraints on admin_sessions:
|
||||
[PRIMARY KEY] admin_sessions_pkey: PRIMARY KEY (token_hash)
|
||||
|
||||
constraints on admin_users:
|
||||
[CHECK] admin_users_instance_role_check: CHECK ((instance_role = ANY (ARRAY['owner'::text, 'admin'::text, 'member'::text])))
|
||||
[PRIMARY KEY] admin_users_pkey: PRIMARY KEY (id)
|
||||
[UNIQUE] admin_users_email_key: UNIQUE (email)
|
||||
[UNIQUE] admin_users_username_key: UNIQUE (username)
|
||||
|
||||
constraints on api_keys:
|
||||
[FOREIGN KEY] api_keys_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
|
||||
[FOREIGN KEY] api_keys_user_id_fkey: FOREIGN KEY (user_id) REFERENCES admin_users(id) ON DELETE CASCADE
|
||||
[PRIMARY KEY] api_keys_pkey: PRIMARY KEY (id)
|
||||
|
||||
constraints on app_domains:
|
||||
[CHECK] app_domains_shape_check: CHECK ((shape = ANY (ARRAY['exact'::text, 'wildcard'::text, 'parameterized'::text])))
|
||||
[FOREIGN KEY] app_domains_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
|
||||
[PRIMARY KEY] app_domains_pkey: PRIMARY KEY (id)
|
||||
[UNIQUE] app_domains_shape_key_key: UNIQUE (shape_key)
|
||||
|
||||
constraints on app_members:
|
||||
[CHECK] app_members_role_check: CHECK ((role = ANY (ARRAY['app_admin'::text, 'editor'::text, 'viewer'::text])))
|
||||
[FOREIGN KEY] app_members_app_id_fkey: FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE
|
||||
[FOREIGN KEY] app_members_user_id_fkey: FOREIGN KEY (user_id) REFERENCES admin_users(id) ON DELETE CASCADE
|
||||
[PRIMARY KEY] app_members_pkey: PRIMARY KEY (app_id, user_id)
|
||||
|
||||
constraints on app_slug_history:
|
||||
[FOREIGN KEY] app_slug_history_current_app_id_fkey: FOREIGN KEY (current_app_id) REFERENCES apps(id) ON DELETE CASCADE
|
||||
[PRIMARY KEY] app_slug_history_pkey: PRIMARY KEY (slug)
|
||||
@@ -169,3 +214,4 @@ constraints on scripts:
|
||||
0003: routes
|
||||
0004: admin auth
|
||||
0005: apps
|
||||
0006: users authz
|
||||
|
||||
Reference in New Issue
Block a user