From 109f099a4c9226c4fb02df8b0ad2101eb0c3a439 Mon Sep 17 00:00:00 2001 From: Mike Kell Date: Fri, 11 Jul 2025 20:45:34 -0400 Subject: [PATCH] Updated directory structure. Initial authnication design and database initialization files. --- auth/supabase/init.sql | 196 ++++++++++++++++++++++++++ db/schema.sql | 0 docs/README.md | 0 infra/architecture.md | 36 +++++ monitoring/README.md | 0 reports/complycore_report_template.md | 0 6 files changed, 232 insertions(+) create mode 100644 auth/supabase/init.sql create mode 100644 db/schema.sql create mode 100644 docs/README.md create mode 100644 infra/architecture.md create mode 100644 monitoring/README.md create mode 100644 reports/complycore_report_template.md diff --git a/auth/supabase/init.sql b/auth/supabase/init.sql new file mode 100644 index 0000000..4b718a3 --- /dev/null +++ b/auth/supabase/init.sql @@ -0,0 +1,196 @@ +-- =============================== +-- ComplyCore Supabase IAM + RLS Init +-- Includes: +-- - Tenants +-- - Users +-- - Service Accounts (NPEs) +-- - Audit Logs +-- =============================== + +-- 1. Define user roles +CREATE TYPE user_role AS ENUM ('client_user', 'client_admin', 'reviewer', 'superadmin'); + +-- 2. Define authentication scopes for service accounts +CREATE TYPE api_scope AS ENUM ('upload', 'evaluate', 'read_reports', 'manage_projects'); + +-- 3. Tenants table +CREATE TABLE tenants ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + dba_name TEXT, + cage_code TEXT, + sam_uid TEXT, + duns_number TEXT, + naics_codes TEXT[], + address_line1 TEXT, + address_line2 TEXT, + city TEXT, + state_province TEXT, + postal_code TEXT, + country TEXT DEFAULT 'USA', + primary_contact_name TEXT, + primary_contact_email TEXT, + primary_contact_phone TEXT, + cmmc_target_level TEXT DEFAULT 'Level 2', + sponsoring_agency TEXT, + compliance_status TEXT DEFAULT 'pending', + notes TEXT, + created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc', now()) +); + +-- 4. Users table (linked to auth.users) +CREATE TABLE users ( + id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, + tenant_id UUID NOT NULL REFERENCES tenants(id), + role user_role NOT NULL DEFAULT 'client_user', + + -- Identity + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + job_title TEXT, + department TEXT, + + -- Contact + email TEXT NOT NULL UNIQUE, + phone_office TEXT, + phone_mobile TEXT, + address_line1 TEXT, + address_line2 TEXT, + city TEXT, + state_province TEXT, + postal_code TEXT, + country TEXT DEFAULT 'USA', + + -- Flags + is_service_account BOOLEAN DEFAULT false, + mfa_enabled BOOLEAN DEFAULT false, + + -- System + last_login_at TIMESTAMP WITH TIME ZONE, + notes TEXT, + created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc', now()) +); + +-- 5. Service Accounts (API Clients) +CREATE TABLE api_clients ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES tenants(id), + name TEXT NOT NULL, + client_id TEXT NOT NULL UNIQUE, + client_secret TEXT NOT NULL, + scopes api_scope[] NOT NULL, + enabled BOOLEAN DEFAULT true, + created_by UUID REFERENCES users(id), + description TEXT, + last_used_at TIMESTAMP WITH TIME ZONE, + created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc', now()) +); + +-- 6. Evaluation results table +CREATE TABLE evaluations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + tenant_id UUID NOT NULL REFERENCES tenants(id), + project_id UUID NOT NULL, + control_id TEXT NOT NULL, + status TEXT CHECK (status IN ('implemented', 'partial', 'missing')), + notes TEXT, + created_by UUID REFERENCES users(id), + created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc', now()) +); + +-- 7. Audit log +CREATE TABLE auth_audit_log ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + actor_id UUID, -- user or service account + tenant_id UUID NOT NULL REFERENCES tenants(id), + action TEXT NOT NULL, + target_table TEXT, + target_id UUID, + ip_address TEXT, + user_agent TEXT, + result TEXT CHECK (result IN ('success', 'fail')) DEFAULT 'success', + timestamp TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc', now()) +); + +-- ======================================= +-- Session Context Claims +-- ======================================= + +CREATE OR REPLACE FUNCTION set_claim_context() +RETURNS void +LANGUAGE plpgsql +SECURITY DEFINER +AS $$ +DECLARE + v_role TEXT; + v_tenant UUID; +BEGIN + SELECT role, tenant_id INTO v_role, v_tenant + FROM public.users + WHERE id = auth.uid(); + + -- Set session-scoped variables + PERFORM set_config('request.jwt.claim.role', v_role, true); + PERFORM set_config('request.jwt.claim.tenant_id', v_tenant::text, true); +END; +$$; + +-- ======================================= +-- Row-Level Security (RLS) Policies +-- ======================================= + +-- Enable RLS +ALTER TABLE users ENABLE ROW LEVEL SECURITY; +ALTER TABLE evaluations ENABLE ROW LEVEL SECURITY; +ALTER TABLE api_clients ENABLE ROW LEVEL SECURITY; +ALTER TABLE auth_audit_log ENABLE ROW LEVEL SECURITY; + +-- Users: only see own row +CREATE POLICY "Self-access only" + ON users + USING (id = auth.uid()); + +-- Evaluations: Tenant isolation for client roles +CREATE POLICY "Tenant isolation" + ON evaluations + FOR ALL + USING ( + (current_setting('request.jwt.claim.role', true) IN ('client_user', 'client_admin')) + AND tenant_id = current_setting('request.jwt.claim.tenant_id', true)::uuid + ); + +-- Evaluations: Reviewer read-only access +CREATE POLICY "Reviewer read access" + ON evaluations + FOR SELECT + USING ( + current_setting('request.jwt.claim.role', true) = 'reviewer' + ); + +-- Evaluations: Superadmin full access +CREATE POLICY "Superadmin full access" + ON evaluations + FOR ALL + USING ( + current_setting('request.jwt.claim.role', true) = 'superadmin' + ) + WITH CHECK ( + current_setting('request.jwt.claim.role', true) = 'superadmin' + ); + +-- Service Accounts: Restrict to own tenant + enabled +CREATE POLICY "API client isolation" + ON api_clients + FOR ALL + USING ( + tenant_id = current_setting('request.jwt.claim.tenant_id', true)::uuid + AND enabled = true + ); + +-- Audit Log: tenant-scoped visibility +CREATE POLICY "Audit tenant visibility" + ON auth_audit_log + FOR SELECT + USING ( + tenant_id = current_setting('request.jwt.claim.tenant_id', true)::uuid + ); diff --git a/db/schema.sql b/db/schema.sql new file mode 100644 index 0000000..e69de29 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..e69de29 diff --git a/infra/architecture.md b/infra/architecture.md new file mode 100644 index 0000000..ad41600 --- /dev/null +++ b/infra/architecture.md @@ -0,0 +1,36 @@ +```mermaid +graph TD + subgraph Clients + A1[Client Browser] --> F1[ComplyCore Web Portal] + end + + subgraph "Frontend (Flutter Web / Next.js)" + F1 -->|Login| IAM[Identity & Access Management] + F1 -->|Upload Docs| U1[Secure File Upload] + F1 -->|Start Eval| A1_n8n[n8n Workflow Trigger] + F1 -->|View Results| R1[Report Viewer] + end + + subgraph "Backend (Core Platform Services)" + IAM --> DB[(PostgreSQL w/ RLS)] + U1 --> Storage[MinIO or Nextcloud] + A1_n8n --> EvalAPI[FastAPI Evaluation Engine] + EvalAPI --> DB + EvalAPI --> Storage + EvalAPI --> ReportGen[Markdown/PDF Generator] + ReportGen --> R1 + ReportGen --> PDFOut[PDF Report Files] + end + + subgraph "DevOps (Secure Infrastructure)" + Logging[Wazuh / Prometheus / Loki] + IAM --> Logging + EvalAPI --> Logging + Storage --> Logging + end + + subgraph External + Admin[Reviewer / Auditor Portal] + Admin --> F1 + end +``` diff --git a/monitoring/README.md b/monitoring/README.md new file mode 100644 index 0000000..e69de29 diff --git a/reports/complycore_report_template.md b/reports/complycore_report_template.md new file mode 100644 index 0000000..e69de29