feat(device-core): add project ownership schema

This commit is contained in:
Codex
2026-08-10 16:59:15 +03:00
parent bf0bc50abb
commit 336602c7ca
3 changed files with 184 additions and 5 deletions
@@ -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;