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:
Apple
2025-11-29 15:24:38 -08:00
parent deeaf26b0b
commit 7b91c8e83c
43 changed files with 5733 additions and 47 deletions

View 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;