## Documentation (20 files) - DAARION Ontology Core v1 (Agent → MicroDAO → Node → District) - User Onboarding & Identity Layer (DAIS) - Data Model UPDATE, Event Catalog, Governance & Permissions - Rooms Layer, City/MicroDAO/Agents/Nodes Interface Architecture - Helper files: ontology-summary, lifecycles, event-schemas ## Database Migration (027) - DAIS tables: dais_identities, dais_emails, dais_wallets, dais_keys - agent_assignments table for Assignment Layer - rooms table for Rooms Layer - event_outbox for NATS event delivery - New enums: agent_role, microdao_type, node_kind, node_status, etc. - Updated agents, microdaos, nodes tables with ontology fields ## Backend - DAIS service & routes (/api/v1/dais/*) - Assignment service & routes (/api/v1/assignments/*) - Domain types for DAIS and Ontology ## Frontend - Ontology types (Agent, MicroDAO, Node, DAIS, Assignments) - API clients for DAIS and Assignments - UI components: DaisProfileCard, AssignmentsPanel, OntologyBadge Non-breaking update - all existing functionality preserved.
374 lines
16 KiB
SQL
374 lines
16 KiB
SQL
-- Migration 027: Foundation Ontology Update
|
|
-- Purpose: Implement DAARION.city ontology (Agent → MicroDAO → Node → District)
|
|
-- Based on: docs/foundation/microdao_Data_Model_UPDATE_v1.md
|
|
-- Date: 2025-11-29
|
|
-- Status: Non-Breaking Update
|
|
|
|
-- ============================================================================
|
|
-- 0. ENUM TYPES
|
|
-- ============================================================================
|
|
|
|
-- Agent role enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'agent_role') THEN
|
|
CREATE TYPE agent_role AS ENUM ('regular', 'orchestrator');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Agent service scope enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'service_scope') THEN
|
|
CREATE TYPE service_scope AS ENUM ('microdao', 'district', 'city');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- MicroDAO type enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'microdao_type') THEN
|
|
CREATE TYPE microdao_type AS ENUM ('root', 'standard', 'district');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Node kind enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'node_kind') THEN
|
|
CREATE TYPE node_kind AS ENUM ('smartphone', 'laptop', 'edge', 'datacenter', 'iot', 'gpu-cluster');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Node status enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'node_status') THEN
|
|
CREATE TYPE node_status AS ENUM ('provisioning', 'active', 'draining', 'retired');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Assignment scope enum (same as service_scope but for assignments)
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'assignment_scope') THEN
|
|
CREATE TYPE assignment_scope AS ENUM ('microdao', 'district', 'city');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- DAIS trust level enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'dais_trust_level') THEN
|
|
CREATE TYPE dais_trust_level AS ENUM ('guest', 'agent', 'verified', 'orchestrator', 'operator');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- ============================================================================
|
|
-- 1. DAIS IDENTITY TABLES (DAIS = DAARION Autonomous Identity System)
|
|
-- ============================================================================
|
|
|
|
-- Main DAIS identity table
|
|
CREATE TABLE IF NOT EXISTS dais_identities (
|
|
id TEXT PRIMARY KEY,
|
|
did TEXT NOT NULL UNIQUE, -- format: did:daarion:<uuid>
|
|
default_email TEXT,
|
|
default_wallet TEXT,
|
|
matrix_handle TEXT, -- format: @<agent_id>:matrix.daarion.city
|
|
trust_level dais_trust_level NOT NULL DEFAULT 'agent',
|
|
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dais_identities_did ON dais_identities(did);
|
|
CREATE INDEX IF NOT EXISTS idx_dais_identities_trust ON dais_identities(trust_level);
|
|
|
|
-- DAIS email identities
|
|
CREATE TABLE IF NOT EXISTS dais_emails (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
dais_id TEXT NOT NULL REFERENCES dais_identities(id) ON DELETE CASCADE,
|
|
email TEXT NOT NULL,
|
|
verified BOOLEAN NOT NULL DEFAULT false,
|
|
verified_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(dais_id, email)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dais_emails_dais ON dais_emails(dais_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dais_emails_email ON dais_emails(email);
|
|
|
|
-- DAIS wallet identities
|
|
CREATE TABLE IF NOT EXISTS dais_wallets (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
dais_id TEXT NOT NULL REFERENCES dais_identities(id) ON DELETE CASCADE,
|
|
wallet_address TEXT NOT NULL,
|
|
network TEXT NOT NULL DEFAULT 'evm', -- evm, ton, solana
|
|
verified BOOLEAN NOT NULL DEFAULT false,
|
|
verified_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(dais_id, wallet_address)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dais_wallets_dais ON dais_wallets(dais_id);
|
|
CREATE INDEX IF NOT EXISTS idx_dais_wallets_address ON dais_wallets(wallet_address);
|
|
|
|
-- DAIS public keys
|
|
CREATE TABLE IF NOT EXISTS dais_keys (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
dais_id TEXT NOT NULL REFERENCES dais_identities(id) ON DELETE CASCADE,
|
|
key_type TEXT NOT NULL, -- ed25519, x25519, secp256k1
|
|
public_key TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
revoked_at TIMESTAMPTZ,
|
|
UNIQUE(dais_id, key_type, public_key)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_dais_keys_dais ON dais_keys(dais_id);
|
|
|
|
-- ============================================================================
|
|
-- 2. AGENTS TABLE UPDATE
|
|
-- ============================================================================
|
|
|
|
-- Add new ontology fields to agents
|
|
ALTER TABLE agents ADD COLUMN IF NOT EXISTS dais_identity_id TEXT REFERENCES dais_identities(id);
|
|
ALTER TABLE agents ADD COLUMN IF NOT EXISTS agent_role agent_role DEFAULT 'regular';
|
|
ALTER TABLE agents ADD COLUMN IF NOT EXISTS agent_service_scope service_scope;
|
|
ALTER TABLE agents ADD COLUMN IF NOT EXISTS home_microdao_id TEXT;
|
|
ALTER TABLE agents ADD COLUMN IF NOT EXISTS home_node_id TEXT;
|
|
|
|
-- Create indexes
|
|
CREATE INDEX IF NOT EXISTS idx_agents_dais ON agents(dais_identity_id);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_role ON agents(agent_role);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_service_scope ON agents(agent_service_scope);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_home_microdao ON agents(home_microdao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_agents_home_node ON agents(home_node_id);
|
|
|
|
-- Migrate existing is_orchestrator to agent_role
|
|
UPDATE agents
|
|
SET agent_role = 'orchestrator'::agent_role
|
|
WHERE is_orchestrator = true AND agent_role IS NULL;
|
|
|
|
UPDATE agents
|
|
SET agent_role = 'regular'::agent_role
|
|
WHERE is_orchestrator = false AND agent_role IS NULL;
|
|
|
|
-- Set default home_microdao_id for existing agents
|
|
UPDATE agents
|
|
SET home_microdao_id = primary_microdao_id
|
|
WHERE home_microdao_id IS NULL AND primary_microdao_id IS NOT NULL;
|
|
|
|
-- ============================================================================
|
|
-- 3. MICRODAOS TABLE UPDATE
|
|
-- ============================================================================
|
|
|
|
-- Add new ontology fields to microdaos
|
|
ALTER TABLE microdaos ADD COLUMN IF NOT EXISTS dao_type microdao_type DEFAULT 'standard';
|
|
ALTER TABLE microdaos ADD COLUMN IF NOT EXISTS primary_orchestrator_agent_id TEXT;
|
|
ALTER TABLE microdaos ADD COLUMN IF NOT EXISTS wallet_address TEXT;
|
|
|
|
-- Create indexes
|
|
CREATE INDEX IF NOT EXISTS idx_microdaos_type ON microdaos(dao_type);
|
|
CREATE INDEX IF NOT EXISTS idx_microdaos_primary_orchestrator ON microdaos(primary_orchestrator_agent_id);
|
|
|
|
-- Migrate existing is_platform to dao_type
|
|
UPDATE microdaos
|
|
SET dao_type = 'district'::microdao_type
|
|
WHERE is_platform = true AND dao_type IS NULL;
|
|
|
|
UPDATE microdaos
|
|
SET dao_type = 'standard'::microdao_type
|
|
WHERE is_platform = false AND dao_type IS NULL;
|
|
|
|
-- Set DAARION as root
|
|
UPDATE microdaos
|
|
SET dao_type = 'root'::microdao_type
|
|
WHERE slug = 'daarion';
|
|
|
|
-- Copy orchestrator_agent_id to primary_orchestrator_agent_id
|
|
UPDATE microdaos
|
|
SET primary_orchestrator_agent_id = orchestrator_agent_id
|
|
WHERE primary_orchestrator_agent_id IS NULL AND orchestrator_agent_id IS NOT NULL;
|
|
|
|
-- ============================================================================
|
|
-- 4. NODES TABLE UPDATE
|
|
-- ============================================================================
|
|
|
|
-- Add new ontology fields to nodes
|
|
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS kind node_kind DEFAULT 'datacenter';
|
|
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS node_status node_status DEFAULT 'active';
|
|
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS capabilities JSONB NOT NULL DEFAULT '{}'::jsonb;
|
|
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS microdao_id TEXT;
|
|
ALTER TABLE nodes ADD COLUMN IF NOT EXISTS last_heartbeat TIMESTAMPTZ;
|
|
|
|
-- Create indexes
|
|
CREATE INDEX IF NOT EXISTS idx_nodes_kind ON nodes(kind);
|
|
CREATE INDEX IF NOT EXISTS idx_nodes_status ON nodes(node_status);
|
|
CREATE INDEX IF NOT EXISTS idx_nodes_microdao ON nodes(microdao_id);
|
|
|
|
-- Migrate existing nodes
|
|
UPDATE nodes
|
|
SET kind = 'datacenter'::node_kind,
|
|
node_status = 'active'::node_status
|
|
WHERE kind IS NULL;
|
|
|
|
-- Build capabilities from existing gpu/modules columns
|
|
UPDATE nodes
|
|
SET capabilities = jsonb_build_object(
|
|
'gpu', COALESCE(gpu, '{}'::jsonb),
|
|
'modules', COALESCE(modules, '[]'::jsonb),
|
|
'roles', COALESCE(array_to_json(roles), '[]'::json)
|
|
)
|
|
WHERE capabilities = '{}'::jsonb;
|
|
|
|
-- Set DAARION as owner for existing nodes
|
|
UPDATE nodes
|
|
SET microdao_id = (SELECT id FROM microdaos WHERE slug = 'daarion' LIMIT 1)
|
|
WHERE microdao_id IS NULL;
|
|
|
|
-- ============================================================================
|
|
-- 5. AGENT ASSIGNMENTS TABLE (NEW)
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_assignments (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
target_microdao_id TEXT NOT NULL,
|
|
scope assignment_scope NOT NULL DEFAULT 'microdao',
|
|
role TEXT NOT NULL, -- advisor, security, mentor, ops, core-team
|
|
start_ts TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
end_ts TIMESTAMPTZ,
|
|
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(agent_id, target_microdao_id, role)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_assignments_agent ON agent_assignments(agent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_assignments_target ON agent_assignments(target_microdao_id);
|
|
CREATE INDEX IF NOT EXISTS idx_assignments_scope ON agent_assignments(scope);
|
|
CREATE INDEX IF NOT EXISTS idx_assignments_active ON agent_assignments(agent_id) WHERE end_ts IS NULL;
|
|
|
|
-- Migrate existing microdao_agents to assignments
|
|
INSERT INTO agent_assignments (agent_id, target_microdao_id, scope, role)
|
|
SELECT
|
|
agent_id,
|
|
microdao_id,
|
|
'microdao'::assignment_scope,
|
|
COALESCE(role, 'member')
|
|
FROM microdao_agents
|
|
ON CONFLICT (agent_id, target_microdao_id, role) DO NOTHING;
|
|
|
|
-- ============================================================================
|
|
-- 6. ROOMS TABLE (City/MicroDAO/District rooms)
|
|
-- ============================================================================
|
|
|
|
-- Room type enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'room_type') THEN
|
|
CREATE TYPE room_type AS ENUM ('city-room', 'dao-room', 'front-room', 'agent-room', 'event-room', 'district-room');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Room visibility enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'room_visibility') THEN
|
|
CREATE TYPE room_visibility AS ENUM ('private', 'members', 'public-city', 'public-global');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Space scope enum
|
|
DO $$ BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'space_scope') THEN
|
|
CREATE TYPE space_scope AS ENUM ('city', 'microdao', 'district');
|
|
END IF;
|
|
END $$;
|
|
|
|
-- Rooms table (foundation for Rooms Layer)
|
|
CREATE TABLE IF NOT EXISTS rooms (
|
|
id TEXT PRIMARY KEY,
|
|
owner_type TEXT NOT NULL, -- city, microdao, district, agent
|
|
owner_id TEXT NOT NULL,
|
|
type room_type NOT NULL DEFAULT 'dao-room',
|
|
space_scope space_scope NOT NULL DEFAULT 'microdao',
|
|
visibility room_visibility NOT NULL DEFAULT 'members',
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
matrix_room_id TEXT,
|
|
is_portal BOOLEAN NOT NULL DEFAULT false,
|
|
portal_target_microdao_id TEXT,
|
|
map_x INTEGER,
|
|
map_y INTEGER,
|
|
zone TEXT,
|
|
mesh_id TEXT, -- for 3D
|
|
primary_agent_id TEXT,
|
|
team_agent_ids TEXT[],
|
|
metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_rooms_owner ON rooms(owner_type, owner_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rooms_type ON rooms(type);
|
|
CREATE INDEX IF NOT EXISTS idx_rooms_scope ON rooms(space_scope);
|
|
CREATE INDEX IF NOT EXISTS idx_rooms_visibility ON rooms(visibility);
|
|
CREATE INDEX IF NOT EXISTS idx_rooms_portal ON rooms(is_portal) WHERE is_portal = true;
|
|
|
|
-- ============================================================================
|
|
-- 7. EVENT OUTBOX (for NATS events)
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS event_outbox (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
event_type TEXT NOT NULL, -- dagion.agent.promoted_to_orchestrator, etc.
|
|
subject TEXT NOT NULL, -- NATS subject
|
|
payload JSONB NOT NULL,
|
|
version TEXT NOT NULL DEFAULT '1.0',
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending, published, failed
|
|
retry_count INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
published_at TIMESTAMPTZ,
|
|
error_message TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_outbox_status ON event_outbox(status);
|
|
CREATE INDEX IF NOT EXISTS idx_outbox_type ON event_outbox(event_type);
|
|
CREATE INDEX IF NOT EXISTS idx_outbox_pending ON event_outbox(created_at) WHERE status = 'pending';
|
|
|
|
-- ============================================================================
|
|
-- 8. COMMENTS
|
|
-- ============================================================================
|
|
|
|
COMMENT ON TABLE dais_identities IS 'DAIS (DAARION Autonomous Identity System) - unified digital identity';
|
|
COMMENT ON TABLE dais_emails IS 'Email identities linked to DAIS';
|
|
COMMENT ON TABLE dais_wallets IS 'Wallet identities (EVM/TON) linked to DAIS';
|
|
COMMENT ON TABLE dais_keys IS 'Public keys for signing/encryption (Ed25519, X25519, secp256k1)';
|
|
COMMENT ON TABLE agent_assignments IS 'Agent work assignments to other MicroDAO/District/City';
|
|
COMMENT ON TABLE rooms IS 'Rooms Layer - city/microdao/district rooms and portals';
|
|
COMMENT ON TABLE event_outbox IS 'Outbox pattern for transactional NATS event delivery';
|
|
|
|
COMMENT ON COLUMN agents.agent_role IS 'Agent role: regular or orchestrator';
|
|
COMMENT ON COLUMN agents.agent_service_scope IS 'Service scope: microdao, district, or city';
|
|
COMMENT ON COLUMN agents.home_microdao_id IS 'Primary MicroDAO affiliation (ontology invariant)';
|
|
COMMENT ON COLUMN agents.home_node_id IS 'Primary node for agent execution';
|
|
|
|
COMMENT ON COLUMN microdaos.dao_type IS 'MicroDAO type: root (DAARION), standard, or district';
|
|
COMMENT ON COLUMN microdaos.primary_orchestrator_agent_id IS 'Main orchestrator agent for this MicroDAO';
|
|
|
|
COMMENT ON COLUMN nodes.kind IS 'Node hardware type: smartphone, laptop, edge, datacenter, iot, gpu-cluster';
|
|
COMMENT ON COLUMN nodes.node_status IS 'Lifecycle status: provisioning, active, draining, retired';
|
|
COMMENT ON COLUMN nodes.capabilities IS 'Node capabilities: CPU, GPU, RAM, network, sensors';
|
|
|
|
-- ============================================================================
|
|
-- 9. SEED DATA - City Rooms
|
|
-- ============================================================================
|
|
|
|
-- Create default city rooms
|
|
INSERT INTO rooms (id, owner_type, owner_id, type, space_scope, visibility, name, description, primary_agent_id)
|
|
VALUES
|
|
('city-lobby', 'city', 'daarion', 'city-room', 'city', 'public-city', 'City Lobby', 'Main entrance to DAARION.city', 'dario'),
|
|
('city-square', 'city', 'daarion', 'city-room', 'city', 'public-city', 'City Square', 'Central public space', 'dario'),
|
|
('city-news', 'city', 'daarion', 'city-room', 'city', 'public-city', 'City News', 'Latest news and announcements', 'daria'),
|
|
('city-help', 'city', 'daarion', 'city-room', 'city', 'public-city', 'City Help', 'Support and assistance', 'daria'),
|
|
('city-events', 'city', 'daarion', 'city-room', 'city', 'public-city', 'City Events', 'Events and activities', 'daarwizz')
|
|
ON CONFLICT (id) DO NOTHING;
|
|
|
|
-- ============================================================================
|
|
-- DONE
|
|
-- ============================================================================
|
|
|
|
SELECT 'Migration 027 completed: Foundation Ontology Update' as result;
|
|
|