feat(device-core): add project ownership schema
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
begin;
|
||||
|
||||
create table if not exists device_owner_scopes (
|
||||
id uuid primary key,
|
||||
scope_kind text not null
|
||||
check (scope_kind in ('company', 'personal')),
|
||||
owner_ref text not null
|
||||
check (length(btrim(owner_ref)) between 3 and 256),
|
||||
display_name text not null
|
||||
check (length(btrim(display_name)) between 1 and 160),
|
||||
lifecycle_state text not null default 'active'
|
||||
check (lifecycle_state in ('active', 'suspended', 'retired')),
|
||||
created_by_ref text not null
|
||||
check (length(btrim(created_by_ref)) between 3 and 256),
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
unique (scope_kind, owner_ref)
|
||||
);
|
||||
|
||||
create table if not exists device_projects (
|
||||
id uuid primary key,
|
||||
owner_scope_id uuid not null references device_owner_scopes(id),
|
||||
project_key text not null
|
||||
check (project_key ~ '^[a-z][a-z0-9-]{1,62}$'),
|
||||
name text not null
|
||||
check (length(btrim(name)) between 1 and 160),
|
||||
description text,
|
||||
lifecycle_state text not null default 'active'
|
||||
check (lifecycle_state in ('active', 'suspended', 'archived')),
|
||||
created_by_ref text not null
|
||||
check (length(btrim(created_by_ref)) between 3 and 256),
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
unique (owner_scope_id, project_key)
|
||||
);
|
||||
|
||||
create index if not exists device_projects_owner_scope_idx
|
||||
on device_projects (owner_scope_id, lifecycle_state, updated_at desc);
|
||||
|
||||
alter table device_instances
|
||||
add column if not exists project_id uuid references device_projects(id);
|
||||
|
||||
create unique index if not exists device_instances_id_project_idx
|
||||
on device_instances (id, project_id);
|
||||
|
||||
create table if not exists device_collections (
|
||||
id uuid primary key,
|
||||
project_id uuid not null references device_projects(id),
|
||||
collection_key text not null
|
||||
check (collection_key ~ '^[a-z][a-z0-9-]{1,62}$'),
|
||||
name text not null
|
||||
check (length(btrim(name)) between 1 and 160),
|
||||
description text,
|
||||
lifecycle_state text not null default 'active'
|
||||
check (lifecycle_state in ('active', 'archived')),
|
||||
created_by_ref text not null
|
||||
check (length(btrim(created_by_ref)) between 3 and 256),
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
unique (project_id, collection_key),
|
||||
unique (id, project_id)
|
||||
);
|
||||
|
||||
create index if not exists device_collections_project_idx
|
||||
on device_collections (project_id, lifecycle_state, updated_at desc);
|
||||
|
||||
create table if not exists device_collection_members (
|
||||
collection_id uuid not null,
|
||||
device_id uuid not null,
|
||||
project_id uuid not null references device_projects(id),
|
||||
added_by_ref text not null
|
||||
check (length(btrim(added_by_ref)) between 3 and 256),
|
||||
added_at timestamptz not null default now(),
|
||||
primary key (collection_id, device_id),
|
||||
foreign key (collection_id, project_id)
|
||||
references device_collections(id, project_id),
|
||||
foreign key (device_id, project_id)
|
||||
references device_instances(id, project_id)
|
||||
);
|
||||
|
||||
create index if not exists device_collection_members_device_idx
|
||||
on device_collection_members (device_id, collection_id);
|
||||
|
||||
create table if not exists device_project_grants (
|
||||
id uuid primary key,
|
||||
project_id uuid not null references device_projects(id),
|
||||
principal_kind text not null
|
||||
check (principal_kind in ('user', 'group')),
|
||||
principal_ref text not null
|
||||
check (length(btrim(principal_ref)) between 3 and 256),
|
||||
project_role text not null
|
||||
check (project_role in ('viewer', 'operator', 'engineer', 'admin', 'owner')),
|
||||
capability_allow text[] not null default '{}',
|
||||
capability_deny text[] not null default '{}',
|
||||
lifecycle_state text not null default 'active'
|
||||
check (lifecycle_state in ('active', 'revoked')),
|
||||
created_by_ref text not null
|
||||
check (length(btrim(created_by_ref)) between 3 and 256),
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
unique (project_id, principal_kind, principal_ref),
|
||||
check (not (capability_allow && capability_deny))
|
||||
);
|
||||
|
||||
create index if not exists device_project_grants_principal_idx
|
||||
on device_project_grants (
|
||||
principal_kind,
|
||||
principal_ref,
|
||||
lifecycle_state,
|
||||
project_id
|
||||
);
|
||||
|
||||
commit;
|
||||
Reference in New Issue
Block a user