feat(foundation): FOUNDATION_UPDATE implementation
## 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.
This commit is contained in:
373
migrations/027_foundation_ontology_update.sql
Normal file
373
migrations/027_foundation_ontology_update.sql
Normal file
@@ -0,0 +1,373 @@
|
||||
-- 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;
|
||||
|
||||
Reference in New Issue
Block a user