Overview
The applications schema manages resources (applications, VMs, servers), user access permissions, and integration with cloud providers and hypervisors.
Tables
resources
Core resource/application definitions.
CREATE TABLE public.resources (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
organization_id UUID NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
resource_type public.resource_type NOT NULL,
ip_address TEXT,
connection_method TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Columns
Resource unique identifier (auto-generated)
Organization that owns this resource
Resource name (e.g., “Production Database”, “Finance App”)
Connection method: guacamole, tsplus, rdp, ssh, direct, web
Resource-specific configuration and connection details
Resource creation timestamp
Resource Types
CREATE TYPE public.resource_type AS ENUM (
'windows_vm',
'linux_vm',
'rdp',
'ssh',
'guacamole_session',
'tsplus_html5',
'tailscale_node',
'web_app',
'direct',
'custom'
);
Guacamole Resource:
{
"pomerium_url": "https://access.company.com",
"guacamole_connection_id": "connection-123",
"protocol": "rdp",
"port": 3389
}
TSPlus Resource:
{
"tsplus_url": "https://rdp.company.com",
"tsplus_user": "DOMAIN\\username",
"target_host": "10.0.1.50",
"domain": "COMPANY"
}
Web Application:
{
"external_url": "https://app.company.com",
"icon_url": "https://app.company.com/icon.png",
"supports_sso": true
}
SSH Resource:
{
"pomerium_url": "https://access.company.com",
"ssh_connection_id": "ssh-prod-01",
"port": 22,
"username": "ubuntu"
}
Indexes
CREATE INDEX idx_resources_organization_id ON public.resources(organization_id);
user_resource_access
User access permissions to resources.
CREATE TABLE public.user_resource_access (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
resource_id UUID NOT NULL REFERENCES public.resources(id) ON DELETE CASCADE,
status public.access_status DEFAULT 'pending',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
activated_at TIMESTAMP WITH TIME ZONE,
revoked_at TIMESTAMP WITH TIME ZONE,
UNIQUE(user_id, resource_id)
);
Columns
Access grant unique identifier
status
access_status
default:"pending"
Access status: pending, active, revoked
Access grant creation timestamp
When access was activated
Access Status Enum
CREATE TYPE public.access_status AS ENUM (
'pending', -- Access requested but not yet approved
'active', -- Access granted and active
'revoked' -- Access revoked
);
Indexes
CREATE INDEX idx_user_resource_access_user_id ON public.user_resource_access(user_id);
CREATE INDEX idx_user_resource_access_resource_id ON public.user_resource_access(resource_id);
resource_permissions
Drag-and-drop access control for resources.
CREATE TABLE public.resource_permissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
resource_id UUID NOT NULL REFERENCES public.resources(id) ON DELETE CASCADE,
subject_type TEXT NOT NULL,
subject_id UUID NOT NULL,
permission_level TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(resource_id, subject_type, subject_id)
);
Columns
Resource this permission applies to
Subject type: user, role, group
ID of user, role, or group
Permission level: read, write, admin
Permission creation timestamp
Permission Levels
| Level | Description |
|---|
read | Can view and access resource |
write | Can modify resource settings |
admin | Full control including permissions |
cloud_providers
Cloud provider integrations (AWS, Azure, GCP, etc.).
CREATE TABLE public.cloud_providers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
provider_type TEXT NOT NULL,
api_endpoint TEXT,
credentials JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
Columns
Provider configuration ID
Organization this provider belongs to
Provider name (e.g., “AWS Production”)
Provider type: aws, azure, gcp, digitalocean, linode
API endpoint URL (for custom/private cloud)
Encrypted provider credentials
Configuration creation timestamp
AWS:
{
"access_key_id": "AKIA...",
"secret_access_key": "encrypted-secret",
"region": "us-east-1"
}
Azure:
{
"tenant_id": "tenant-uuid",
"client_id": "client-uuid",
"client_secret": "encrypted-secret",
"subscription_id": "sub-uuid"
}
GCP:
{
"project_id": "my-project",
"private_key": "encrypted-key",
"client_email": "[email protected]"
}
hypervisors
Hypervisor integrations (Proxmox, VMware, etc.).
CREATE TABLE public.hypervisors (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
hypervisor_type TEXT NOT NULL,
api_endpoint TEXT NOT NULL,
credentials JSONB,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT now()
);
Columns
Hypervisor configuration ID
Organization this hypervisor belongs to
Hypervisor name (e.g., “Proxmox Cluster 1”)
Type: proxmox, vmware, hyperv, kvm, xen
Encrypted hypervisor credentials
Configuration creation timestamp
Proxmox:
{
"username": "root@pam",
"password": "encrypted-password",
"realm": "pam",
"verify_ssl": false
}
VMware:
{
"username": "[email protected]",
"password": "encrypted-password",
"datacenter": "Datacenter1"
}
ldap_configurations
LDAP/Active Directory integration settings.
CREATE TABLE public.ldap_configurations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
server_url TEXT NOT NULL,
bind_dn TEXT,
base_dn TEXT NOT NULL,
credentials JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
Columns
Organization this config belongs to
LDAP server URL (e.g., ldap://dc.company.com:389)
Bind DN for authentication
Base DN for searches (e.g., DC=company,DC=com)
Configuration creation timestamp
authentik_configurations
Authentik SSO integration settings.
CREATE TABLE public.authentik_configurations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id UUID NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
name TEXT NOT NULL,
api_endpoint TEXT NOT NULL,
api_token TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
Columns
Authentik configuration ID
Organization this config belongs to
Authentik API endpoint URL
Configuration creation timestamp
Example Queries
Create Resource
INSERT INTO resources (
organization_id,
name,
resource_type,
connection_method,
metadata
) VALUES (
'org-uuid',
'Customer Portal',
'web_app',
'direct',
'{
"external_url": "https://portal.company.com",
"icon_url": "https://portal.company.com/icon.png",
"supports_sso": true
}'::jsonb
)
RETURNING *;
Grant Access
INSERT INTO user_resource_access (
user_id,
resource_id,
status,
activated_at
) VALUES (
'user-uuid',
'resource-uuid',
'active',
now()
)
ON CONFLICT (user_id, resource_id)
DO UPDATE SET
status = 'active',
activated_at = now();
Get User’s Resources
SELECT
r.id,
r.name,
r.resource_type,
r.connection_method,
r.metadata,
ura.status,
ura.activated_at
FROM resources r
JOIN user_resource_access ura ON ura.resource_id = r.id
WHERE ura.user_id = 'user-uuid'
AND ura.status = 'active'
ORDER BY r.name;
Get Resource Access List
SELECT
p.id as user_id,
p.full_name,
p.role,
ura.status,
ura.activated_at,
ura.revoked_at
FROM user_resource_access ura
JOIN profiles p ON p.id = ura.user_id
WHERE ura.resource_id = 'resource-uuid'
ORDER BY ura.status, p.full_name;
Row Level Security
resources
-- Users can view resources in their organization
CREATE POLICY "Users can view resources in their organization"
ON public.resources FOR SELECT
USING (
organization_id IN (
SELECT organization_id FROM public.profiles WHERE id = auth.uid()
)
OR EXISTS (
SELECT 1 FROM public.profiles
WHERE profiles.id = auth.uid()
AND profiles.role = 'global_admin'
)
);
-- Org admins can manage resources
CREATE POLICY "Org admins can manage resources in their org"
ON public.resources FOR ALL
USING (
organization_id IN (
SELECT organization_id FROM public.profiles
WHERE id = auth.uid()
AND role IN ('org_admin', 'global_admin')
)
);
user_resource_access
-- Users can view their own access
CREATE POLICY "Users can view their own access"
ON public.user_resource_access FOR SELECT
USING (user_id = auth.uid());
-- Admins can view all access in their org
CREATE POLICY "Admins can view all access in their org"
ON public.user_resource_access FOR SELECT
USING (
EXISTS (
SELECT 1 FROM public.profiles p1
JOIN public.profiles p2 ON p1.organization_id = p2.organization_id
WHERE p1.id = auth.uid()
AND p2.id = user_resource_access.user_id
AND p1.role IN ('org_admin', 'support', 'global_admin')
)
);
-- Admins can manage access
CREATE POLICY "Admins can manage access in their org"
ON public.user_resource_access FOR ALL
USING (
EXISTS (
SELECT 1 FROM public.profiles p1
JOIN public.profiles p2 ON p1.organization_id = p2.organization_id
WHERE p1.id = auth.uid()
AND p2.id = user_resource_access.user_id
AND p1.role IN ('org_admin', 'global_admin')
)
);
Credential Tables
-- Only admins can view cloud providers
CREATE POLICY "Only admins can view cloud providers"
ON public.cloud_providers FOR SELECT
USING (
organization_id = public.get_user_org_id(auth.uid())
AND public.get_user_role(auth.uid()) IN ('org_admin', 'global_admin')
);
-- Similar policies for hypervisors, LDAP, Authentik configs
/functions/v1/session-launcher - Launch resource sessions
organizations - Resource ownership
profiles - User access
groups - Group-based access
audit_logs - Resource access audit trail