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

@@ -55,6 +55,7 @@ logs/
*-FIX.md
*-REPORT.md
*-SUMMARY.md
!docs/foundation/helpers/ontology-summary.md
*-SUCCESS.md
*-DEPLOYMENT.md
*-QUICKSTART.md

View File

@@ -15,6 +15,9 @@ import { vendorRoutes } from './api/http/vendor.routes';
import { platformsRoutes } from './api/http/platforms.routes';
import { agentsRoutes } from './api/http/agents.routes';
import { teamsRoutes } from './api/http/teams.routes';
// Foundation Update routes
import daisRoutes from './http/dais.routes';
import assignmentRoutes from './http/assignment.routes';
const app = express();
@@ -32,6 +35,10 @@ app.use('/api/v1/platforms', platformsRoutes);
app.use('/api/v1/platforms', vendorRoutes); // Vendor routes under platforms
app.use('/api/v1', agentsRoutes);
// Foundation Update routes (DAIS & Assignments)
app.use('/api/v1/dais', daisRoutes);
app.use('/api/v1/assignments', assignmentRoutes);
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok' });

View File

@@ -0,0 +1,93 @@
/**
* DAIS - DAARION Autonomous Identity System
* Based on: docs/foundation/DAARION_Identity_And_Access_Draft_v1.md
*/
// Trust levels for DAIS identity
export type DaisTrustLevel = 'guest' | 'agent' | 'verified' | 'orchestrator' | 'operator';
// DAIS Identity
export interface DaisIdentity {
id: string;
did: string; // format: did:daarion:<uuid>
defaultEmail?: string;
defaultWallet?: string;
matrixHandle?: string; // format: @<agent_id>:matrix.daarion.city
trustLevel: DaisTrustLevel;
metadata: Record<string, unknown>;
createdAt: Date;
updatedAt: Date;
}
// DAIS Email identity
export interface DaisEmail {
id: string;
daisId: string;
email: string;
verified: boolean;
verifiedAt?: Date;
createdAt: Date;
}
// DAIS Wallet identity
export interface DaisWallet {
id: string;
daisId: string;
walletAddress: string;
network: 'evm' | 'ton' | 'solana';
verified: boolean;
verifiedAt?: Date;
createdAt: Date;
}
// DAIS Key types
export type DaisKeyType = 'ed25519' | 'x25519' | 'secp256k1';
// DAIS Public Key
export interface DaisKey {
id: string;
daisId: string;
keyType: DaisKeyType;
publicKey: string;
createdAt: Date;
revokedAt?: Date;
}
// Full DAIS profile with all identities
export interface DaisProfile {
identity: DaisIdentity;
emails: DaisEmail[];
wallets: DaisWallet[];
keys: DaisKey[];
}
// Create DAIS identity request
export interface CreateDaisRequest {
email?: string;
walletAddress?: string;
network?: 'evm' | 'ton' | 'solana';
}
// Verify email request
export interface VerifyEmailRequest {
daisId: string;
email: string;
otp: string;
}
// Connect wallet request (SIWE)
export interface ConnectWalletRequest {
daisId: string;
walletAddress: string;
network: 'evm' | 'ton' | 'solana';
signature: string;
message: string;
}
// DAIS creation result
export interface DaisCreationResult {
identity: DaisIdentity;
agentId: string;
matrixHandle: string;
}

View File

@@ -0,0 +1,285 @@
/**
* DAARION Ontology Types
* Based on: docs/foundation/DAARION_Ontology_Core_v1.md
*
* Core hierarchy: Agent → MicroDAO → Node → District
*/
// ============================================================================
// AGENT
// ============================================================================
export type AgentRole = 'regular' | 'orchestrator';
export type ServiceScope = 'microdao' | 'district' | 'city';
export interface Agent {
id: string;
daisIdentityId?: string;
homeMicrodaoId: string; // Required by ontology
homeNodeId?: string;
role: AgentRole;
serviceScope?: ServiceScope;
// Existing fields
name: string;
kind: string;
isOrchestrator: boolean;
isPublic: boolean;
visibilityScope?: string;
primaryMicrodaoId?: string;
nodeId?: string;
metadata: Record<string, unknown>;
createdAt: Date;
updatedAt: Date;
}
export type AgentType =
| 'personal' // User's personal agent
| 'service' // Service/infrastructure agent
| 'core-city' // DAARION108 - citywide agents
| 'orchestrator'; // Can create MicroDAO
// ============================================================================
// MICRODAO
// ============================================================================
export type MicrodaoType = 'root' | 'standard' | 'district';
export interface Microdao {
id: string;
slug: string;
name: string;
description?: string;
type: MicrodaoType;
primaryOrchestratorAgentId: string; // Required by ontology
parentMicrodaoId?: string; // For districts
walletAddress?: string;
// Existing fields
ownerAgentId?: string;
orchestratorAgentId?: string;
isPlatform: boolean;
isActive: boolean;
isPublic: boolean;
district?: string;
metadata: Record<string, unknown>;
createdAt: Date;
updatedAt: Date;
}
// ============================================================================
// NODE
// ============================================================================
export type NodeKind =
| 'smartphone'
| 'laptop'
| 'edge'
| 'datacenter'
| 'iot'
| 'gpu-cluster';
export type NodeStatus =
| 'provisioning'
| 'active'
| 'draining'
| 'retired';
export interface NodeCapabilities {
cpu?: string;
ram?: string;
gpu?: {
name: string;
vram?: string;
unified_memory_gb?: number;
};
network?: {
up: string;
down: string;
};
sensors?: string[];
modules?: Array<{
id: string;
status: string;
port?: number;
}>;
}
export interface Node {
id: string;
nodeId: string;
name: string;
microdaoId: string; // Required by ontology
kind: NodeKind;
status: NodeStatus;
capabilities: NodeCapabilities;
lastHeartbeat?: Date;
// Existing fields
gpu?: Record<string, unknown>;
modules?: Array<Record<string, unknown>>;
roles?: string[];
version?: string;
metadata: Record<string, unknown>;
createdAt: Date;
updatedAt: Date;
}
// ============================================================================
// DISTRICT (MicroDAO with type='district')
// ============================================================================
export interface District extends Microdao {
type: 'district';
childMicrodaos: Microdao[];
nodePool: Node[];
}
// ============================================================================
// AGENT ASSIGNMENT
// ============================================================================
export type AssignmentScope = 'microdao' | 'district' | 'city';
export type AssignmentRole = 'advisor' | 'security' | 'mentor' | 'ops' | 'core-team' | 'member';
export interface AgentAssignment {
id: string;
agentId: string;
targetMicrodaoId: string;
scope: AssignmentScope;
role: AssignmentRole;
startTs: Date;
endTs?: Date;
metadata: Record<string, unknown>;
createdAt: Date;
}
export interface CreateAssignmentRequest {
agentId: string;
targetMicrodaoId: string;
scope: AssignmentScope;
role: AssignmentRole;
metadata?: Record<string, unknown>;
}
export interface EndAssignmentRequest {
assignmentId: string;
endTs?: Date;
}
// ============================================================================
// ROOMS LAYER
// ============================================================================
export type RoomType =
| 'city-room'
| 'dao-room'
| 'front-room'
| 'agent-room'
| 'event-room'
| 'district-room';
export type RoomVisibility =
| 'private'
| 'members'
| 'public-city'
| 'public-global';
export type SpaceScope = 'city' | 'microdao' | 'district';
export interface Room {
id: string;
ownerType: 'city' | 'microdao' | 'district' | 'agent';
ownerId: string;
type: RoomType;
spaceScope: SpaceScope;
visibility: RoomVisibility;
name: string;
description?: string;
matrixRoomId?: string;
isPortal: boolean;
portalTargetMicrodaoId?: string;
mapX?: number;
mapY?: number;
zone?: string;
meshId?: string;
primaryAgentId?: string;
teamAgentIds?: string[];
metadata: Record<string, unknown>;
createdAt: Date;
updatedAt: Date;
}
// ============================================================================
// EVENTS (for NATS)
// ============================================================================
export interface DomainEvent {
eventId: string;
timestamp: string; // ISO8601
version: string;
subject: string;
payload: Record<string, unknown>;
}
export interface AgentPromotedEvent extends DomainEvent {
subject: 'dagion.agent.promoted_to_orchestrator';
payload: {
agentId: string;
timestamp: string;
};
}
export interface MicrodaoCreatedEvent extends DomainEvent {
subject: 'dagion.microdao.created';
payload: {
microdaoId: string;
primaryOrchestratorAgentId: string;
type: MicrodaoType;
parentMicrodaoId?: string;
timestamp: string;
};
}
export interface NodeRegisteredEvent extends DomainEvent {
subject: 'dagion.node.registered';
payload: {
nodeId: string;
microdaoId: string;
nodeKind: NodeKind;
capabilities: NodeCapabilities;
timestamp: string;
};
}
export interface MicrodaoPromotedToDistrictEvent extends DomainEvent {
subject: 'dagion.microdao.promoted_to_district';
payload: {
microdaoId: string;
promotedByAgentId: string;
parentMicrodaoId?: string;
timestamp: string;
};
}
export interface AssignmentCreatedEvent extends DomainEvent {
subject: 'dagion.agent.assignment_created';
payload: {
assignmentId: string;
agentId: string;
targetMicrodaoId: string;
scope: AssignmentScope;
role: string;
timestamp: string;
};
}
export interface AssignmentEndedEvent extends DomainEvent {
subject: 'dagion.agent.assignment_ended';
payload: {
assignmentId: string;
agentId: string;
timestamp: string;
};
}

View File

@@ -0,0 +1,188 @@
/**
* Agent Assignment API Routes
* Based on: docs/foundation/microdao_Governance_And_Permissions_v1.md
*/
import { Router, Request, Response } from 'express';
import { assignmentService } from '../services/assignment/assignment.service';
import { logger } from '../infra/logger/logger';
const router = Router();
/**
* POST /api/assignments
* Create a new agent assignment
*/
router.post('/', async (req: Request, res: Response) => {
try {
const { agentId, targetMicrodaoId, scope, role, metadata } = req.body;
const assignment = await assignmentService.createAssignment({
agentId,
targetMicrodaoId,
scope,
role,
metadata,
});
res.status(201).json({
success: true,
data: assignment,
});
} catch (error) {
logger.error('Failed to create assignment', error);
res.status(500).json({
success: false,
error: 'Failed to create assignment',
});
}
});
/**
* DELETE /api/assignments/:id
* End an agent assignment
*/
router.delete('/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
await assignmentService.endAssignment(id);
res.json({
success: true,
message: 'Assignment ended',
});
} catch (error) {
logger.error('Failed to end assignment', error);
res.status(500).json({
success: false,
error: 'Failed to end assignment',
});
}
});
/**
* GET /api/assignments/agent/:agentId
* Get all active assignments for an agent
*/
router.get('/agent/:agentId', async (req: Request, res: Response) => {
try {
const { agentId } = req.params;
const assignments = await assignmentService.getAgentAssignments(agentId);
res.json({
success: true,
data: assignments,
});
} catch (error) {
logger.error('Failed to get agent assignments', error);
res.status(500).json({
success: false,
error: 'Failed to get assignments',
});
}
});
/**
* GET /api/assignments/microdao/:microdaoId
* Get all assignments for a MicroDAO
*/
router.get('/microdao/:microdaoId', async (req: Request, res: Response) => {
try {
const { microdaoId } = req.params;
const assignments = await assignmentService.getMicrodaoAssignments(microdaoId);
res.json({
success: true,
data: assignments,
});
} catch (error) {
logger.error('Failed to get microdao assignments', error);
res.status(500).json({
success: false,
error: 'Failed to get assignments',
});
}
});
/**
* GET /api/assignments/citywide
* Get all citywide assignments (DAARION108)
*/
router.get('/citywide', async (req: Request, res: Response) => {
try {
const assignments = await assignmentService.getCitywideAssignments();
res.json({
success: true,
data: assignments,
});
} catch (error) {
logger.error('Failed to get citywide assignments', error);
res.status(500).json({
success: false,
error: 'Failed to get assignments',
});
}
});
/**
* GET /api/assignments/agent/:agentId/scope
* Get agent's effective scope
*/
router.get('/agent/:agentId/scope', async (req: Request, res: Response) => {
try {
const { agentId } = req.params;
const scope = await assignmentService.getAgentScope(agentId);
res.json({
success: true,
data: scope,
});
} catch (error) {
logger.error('Failed to get agent scope', error);
res.status(500).json({
success: false,
error: 'Failed to get scope',
});
}
});
/**
* GET /api/assignments/check
* Check if agent has assignment to target
*/
router.get('/check', async (req: Request, res: Response) => {
try {
const { agentId, targetMicrodaoId } = req.query;
if (!agentId || !targetMicrodaoId) {
return res.status(400).json({
success: false,
error: 'agentId and targetMicrodaoId are required',
});
}
const hasAssignment = await assignmentService.hasAssignment(
agentId as string,
targetMicrodaoId as string
);
res.json({
success: true,
data: { hasAssignment },
});
} catch (error) {
logger.error('Failed to check assignment', error);
res.status(500).json({
success: false,
error: 'Failed to check assignment',
});
}
});
export default router;

219
backend/http/dais.routes.ts Normal file
View File

@@ -0,0 +1,219 @@
/**
* DAIS API Routes
* Based on: docs/foundation/DAARION_Identity_And_Access_Draft_v1.md
*/
import { Router, Request, Response } from 'express';
import { daisService } from '../services/dais/dais.service';
import { logger } from '../infra/logger/logger';
const router = Router();
/**
* POST /api/dais/identity
* Create a new DAIS identity
*/
router.post('/identity', async (req: Request, res: Response) => {
try {
const { email, walletAddress, network } = req.body;
const result = await daisService.createIdentity({
email,
walletAddress,
network,
});
res.status(201).json({
success: true,
data: result,
});
} catch (error) {
logger.error('Failed to create DAIS identity', error);
res.status(500).json({
success: false,
error: 'Failed to create identity',
});
}
});
/**
* GET /api/dais/:id
* Get DAIS profile
*/
router.get('/:id', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const profile = await daisService.getProfile(id);
if (!profile) {
return res.status(404).json({
success: false,
error: 'DAIS identity not found',
});
}
res.json({
success: true,
data: profile,
});
} catch (error) {
logger.error('Failed to get DAIS profile', error);
res.status(500).json({
success: false,
error: 'Failed to get profile',
});
}
});
/**
* GET /api/dais/agent/:agentId
* Get DAIS profile by agent ID
*/
router.get('/agent/:agentId', async (req: Request, res: Response) => {
try {
const { agentId } = req.params;
const profile = await daisService.getByAgentId(agentId);
if (!profile) {
return res.status(404).json({
success: false,
error: 'DAIS identity not found for agent',
});
}
res.json({
success: true,
data: profile,
});
} catch (error) {
logger.error('Failed to get DAIS by agent', error);
res.status(500).json({
success: false,
error: 'Failed to get profile',
});
}
});
/**
* POST /api/dais/:id/email
* Add email to DAIS
*/
router.post('/:id/email', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { email } = req.body;
const result = await daisService.addEmail(id, email);
res.status(201).json({
success: true,
data: result,
});
} catch (error) {
logger.error('Failed to add email', error);
res.status(500).json({
success: false,
error: 'Failed to add email',
});
}
});
/**
* POST /api/dais/:id/email/verify
* Verify email
*/
router.post('/:id/email/verify', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { email, otp } = req.body;
// TODO: Validate OTP
await daisService.verifyEmail(id, email);
res.json({
success: true,
message: 'Email verified',
});
} catch (error) {
logger.error('Failed to verify email', error);
res.status(500).json({
success: false,
error: 'Failed to verify email',
});
}
});
/**
* POST /api/dais/:id/wallet
* Add wallet to DAIS
*/
router.post('/:id/wallet', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { walletAddress, network } = req.body;
const result = await daisService.addWallet(id, walletAddress, network);
res.status(201).json({
success: true,
data: result,
});
} catch (error) {
logger.error('Failed to add wallet', error);
res.status(500).json({
success: false,
error: 'Failed to add wallet',
});
}
});
/**
* POST /api/dais/:id/wallet/verify
* Verify wallet (SIWE)
*/
router.post('/:id/wallet/verify', async (req: Request, res: Response) => {
try {
const { id } = req.params;
const { walletAddress, signature, message } = req.body;
// TODO: Validate SIWE signature
await daisService.verifyWallet(id, walletAddress);
res.json({
success: true,
message: 'Wallet verified',
});
} catch (error) {
logger.error('Failed to verify wallet', error);
res.status(500).json({
success: false,
error: 'Failed to verify wallet',
});
}
});
/**
* POST /api/dais/:id/promote-to-orchestrator
* Promote DAIS to orchestrator level
*/
router.post('/:id/promote-to-orchestrator', async (req: Request, res: Response) => {
try {
const { id } = req.params;
await daisService.promoteToOrchestrator(id);
res.json({
success: true,
message: 'Promoted to orchestrator',
});
} catch (error) {
logger.error('Failed to promote to orchestrator', error);
res.status(500).json({
success: false,
error: 'Failed to promote',
});
}
});
export default router;

View File

@@ -0,0 +1,226 @@
/**
* Agent Assignment Service
* Based on: docs/foundation/microdao_Governance_And_Permissions_v1.md
*
* Manages agent work assignments to other MicroDAO/District/City
*/
import { db } from '../../infra/db/client';
import { logger } from '../../infra/logger/logger';
import type {
AgentAssignment,
CreateAssignmentRequest,
AssignmentScope,
} from '../../domain/ontology/types';
import { v4 as uuidv4 } from 'uuid';
export class AssignmentService {
/**
* Create a new agent assignment
*/
async createAssignment(request: CreateAssignmentRequest): Promise<AgentAssignment> {
try {
const result = await db.query<AgentAssignment>(
`INSERT INTO agent_assignments
(agent_id, target_microdao_id, scope, role, metadata)
VALUES ($1, $2, $3, $4, $5)
RETURNING *`,
[
request.agentId,
request.targetMicrodaoId,
request.scope,
request.role,
JSON.stringify(request.metadata || {}),
]
);
const assignment = result.rows[0];
// Publish event to outbox
await this.publishEvent('dagion.agent.assignment_created', {
assignmentId: assignment.id,
agentId: request.agentId,
targetMicrodaoId: request.targetMicrodaoId,
scope: request.scope,
role: request.role,
timestamp: new Date().toISOString(),
});
logger.info(`Created assignment: ${assignment.id} for agent ${request.agentId}`);
return assignment;
} catch (error) {
logger.error('Failed to create assignment', error);
throw error;
}
}
/**
* End an agent assignment
*/
async endAssignment(assignmentId: string): Promise<void> {
try {
const result = await db.query<AgentAssignment>(
`UPDATE agent_assignments
SET end_ts = now()
WHERE id = $1
RETURNING *`,
[assignmentId]
);
if (result.rows.length === 0) {
throw new Error(`Assignment not found: ${assignmentId}`);
}
const assignment = result.rows[0];
// Publish event to outbox
await this.publishEvent('dagion.agent.assignment_ended', {
assignmentId,
agentId: assignment.agentId,
timestamp: new Date().toISOString(),
});
logger.info(`Ended assignment: ${assignmentId}`);
} catch (error) {
logger.error(`Failed to end assignment: ${assignmentId}`, error);
throw error;
}
}
/**
* Get all active assignments for an agent
*/
async getAgentAssignments(agentId: string): Promise<AgentAssignment[]> {
try {
const result = await db.query<AgentAssignment>(
`SELECT * FROM agent_assignments
WHERE agent_id = $1 AND end_ts IS NULL
ORDER BY created_at DESC`,
[agentId]
);
return result.rows;
} catch (error) {
logger.error(`Failed to get assignments for agent: ${agentId}`, error);
throw error;
}
}
/**
* Get all assignments for a MicroDAO
*/
async getMicrodaoAssignments(microdaoId: string): Promise<AgentAssignment[]> {
try {
const result = await db.query<AgentAssignment>(
`SELECT a.*, ag.name as agent_name
FROM agent_assignments a
JOIN agents ag ON ag.id = a.agent_id
WHERE a.target_microdao_id = $1 AND a.end_ts IS NULL
ORDER BY a.created_at DESC`,
[microdaoId]
);
return result.rows;
} catch (error) {
logger.error(`Failed to get assignments for microdao: ${microdaoId}`, error);
throw error;
}
}
/**
* Get citywide assignments (DAARION108)
*/
async getCitywideAssignments(): Promise<AgentAssignment[]> {
try {
const result = await db.query<AgentAssignment>(
`SELECT a.*, ag.name as agent_name
FROM agent_assignments a
JOIN agents ag ON ag.id = a.agent_id
WHERE a.scope = 'city' AND a.end_ts IS NULL
ORDER BY a.created_at DESC`,
[]
);
return result.rows;
} catch (error) {
logger.error('Failed to get citywide assignments', error);
throw error;
}
}
/**
* Check if agent has assignment to target
*/
async hasAssignment(agentId: string, targetMicrodaoId: string): Promise<boolean> {
try {
const result = await db.query(
`SELECT 1 FROM agent_assignments
WHERE agent_id = $1 AND target_microdao_id = $2 AND end_ts IS NULL
LIMIT 1`,
[agentId, targetMicrodaoId]
);
return result.rows.length > 0;
} catch (error) {
logger.error('Failed to check assignment', error);
throw error;
}
}
/**
* Get agent's effective scope (home + assignments)
*/
async getAgentScope(agentId: string): Promise<{
homeMicrodaoId: string | null;
assignments: AgentAssignment[];
effectiveScope: AssignmentScope;
}> {
try {
// Get agent's home MicroDAO
const agent = await db.query(
`SELECT home_microdao_id, agent_service_scope FROM agents WHERE id = $1`,
[agentId]
);
if (agent.rows.length === 0) {
throw new Error(`Agent not found: ${agentId}`);
}
const assignments = await this.getAgentAssignments(agentId);
// Determine effective scope
let effectiveScope: AssignmentScope = 'microdao';
if (agent.rows[0].agent_service_scope === 'city') {
effectiveScope = 'city';
} else if (assignments.some(a => a.scope === 'city')) {
effectiveScope = 'city';
} else if (assignments.some(a => a.scope === 'district')) {
effectiveScope = 'district';
}
return {
homeMicrodaoId: agent.rows[0].home_microdao_id,
assignments,
effectiveScope,
};
} catch (error) {
logger.error(`Failed to get agent scope: ${agentId}`, error);
throw error;
}
}
/**
* Publish event to outbox for NATS
*/
private async publishEvent(eventType: string, payload: Record<string, unknown>): Promise<void> {
await db.query(
`INSERT INTO event_outbox (event_type, subject, payload)
VALUES ($1, $2, $3)`,
[eventType, eventType, JSON.stringify(payload)]
);
}
}
export const assignmentService = new AssignmentService();

View File

@@ -0,0 +1,278 @@
/**
* DAIS Service - DAARION Autonomous Identity System
* Based on: docs/foundation/DAARION_Identity_And_Access_Draft_v1.md
*/
import { db } from '../../infra/db/client';
import { logger } from '../../infra/logger/logger';
import type {
DaisIdentity,
DaisProfile,
DaisEmail,
DaisWallet,
CreateDaisRequest,
DaisCreationResult,
DaisTrustLevel,
} from '../../domain/dais/types';
import { v4 as uuidv4 } from 'uuid';
export class DaisService {
/**
* Create a new DAIS identity
*/
async createIdentity(request: CreateDaisRequest): Promise<DaisCreationResult> {
const id = `dais-${uuidv4()}`;
const did = `did:daarion:${uuidv4()}`;
try {
// Create DAIS identity
const identity = await db.query<DaisIdentity>(
`INSERT INTO dais_identities (id, did, default_email, default_wallet, trust_level)
VALUES ($1, $2, $3, $4, $5)
RETURNING *`,
[id, did, request.email || null, request.walletAddress || null, 'agent']
);
// Add email if provided
if (request.email) {
await db.query(
`INSERT INTO dais_emails (dais_id, email, verified)
VALUES ($1, $2, false)`,
[id, request.email]
);
}
// Add wallet if provided
if (request.walletAddress) {
await db.query(
`INSERT INTO dais_wallets (dais_id, wallet_address, network, verified)
VALUES ($1, $2, $3, false)`,
[id, request.walletAddress, request.network || 'evm']
);
}
// Create agent linked to DAIS
const agentId = `agent-${uuidv4()}`;
const matrixHandle = `@${agentId}:matrix.daarion.city`;
await db.query(
`INSERT INTO agents (id, name, kind, dais_identity_id, agent_role, home_microdao_id)
VALUES ($1, $2, $3, $4, $5, $6)`,
[agentId, 'New Agent', 'personal', id, 'regular', 'daarion']
);
// Update DAIS with matrix handle
await db.query(
`UPDATE dais_identities SET matrix_handle = $1 WHERE id = $2`,
[matrixHandle, id]
);
logger.info(`Created DAIS identity: ${id}, agent: ${agentId}`);
return {
identity: identity.rows[0],
agentId,
matrixHandle,
};
} catch (error) {
logger.error('Failed to create DAIS identity', error);
throw error;
}
}
/**
* Get DAIS profile with all linked identities
*/
async getProfile(daisId: string): Promise<DaisProfile | null> {
try {
const identity = await db.query<DaisIdentity>(
`SELECT * FROM dais_identities WHERE id = $1`,
[daisId]
);
if (identity.rows.length === 0) {
return null;
}
const emails = await db.query<DaisEmail>(
`SELECT * FROM dais_emails WHERE dais_id = $1`,
[daisId]
);
const wallets = await db.query<DaisWallet>(
`SELECT * FROM dais_wallets WHERE dais_id = $1`,
[daisId]
);
const keys = await db.query(
`SELECT * FROM dais_keys WHERE dais_id = $1 AND revoked_at IS NULL`,
[daisId]
);
return {
identity: identity.rows[0],
emails: emails.rows,
wallets: wallets.rows,
keys: keys.rows,
};
} catch (error) {
logger.error(`Failed to get DAIS profile: ${daisId}`, error);
throw error;
}
}
/**
* Get DAIS by agent ID
*/
async getByAgentId(agentId: string): Promise<DaisProfile | null> {
try {
const agent = await db.query(
`SELECT dais_identity_id FROM agents WHERE id = $1`,
[agentId]
);
if (agent.rows.length === 0 || !agent.rows[0].dais_identity_id) {
return null;
}
return this.getProfile(agent.rows[0].dais_identity_id);
} catch (error) {
logger.error(`Failed to get DAIS by agent: ${agentId}`, error);
throw error;
}
}
/**
* Add email to DAIS
*/
async addEmail(daisId: string, email: string): Promise<DaisEmail> {
try {
const result = await db.query<DaisEmail>(
`INSERT INTO dais_emails (dais_id, email, verified)
VALUES ($1, $2, false)
RETURNING *`,
[daisId, email]
);
logger.info(`Added email to DAIS ${daisId}: ${email}`);
return result.rows[0];
} catch (error) {
logger.error(`Failed to add email to DAIS: ${daisId}`, error);
throw error;
}
}
/**
* Verify email
*/
async verifyEmail(daisId: string, email: string): Promise<void> {
try {
await db.query(
`UPDATE dais_emails
SET verified = true, verified_at = now()
WHERE dais_id = $1 AND email = $2`,
[daisId, email]
);
// Update trust level if this is first verified email
await this.updateTrustLevel(daisId);
logger.info(`Verified email for DAIS ${daisId}: ${email}`);
} catch (error) {
logger.error(`Failed to verify email: ${daisId}`, error);
throw error;
}
}
/**
* Add wallet to DAIS
*/
async addWallet(
daisId: string,
walletAddress: string,
network: 'evm' | 'ton' | 'solana' = 'evm'
): Promise<DaisWallet> {
try {
const result = await db.query<DaisWallet>(
`INSERT INTO dais_wallets (dais_id, wallet_address, network, verified)
VALUES ($1, $2, $3, false)
RETURNING *`,
[daisId, walletAddress, network]
);
logger.info(`Added wallet to DAIS ${daisId}: ${walletAddress}`);
return result.rows[0];
} catch (error) {
logger.error(`Failed to add wallet to DAIS: ${daisId}`, error);
throw error;
}
}
/**
* Verify wallet (after SIWE signature)
*/
async verifyWallet(daisId: string, walletAddress: string): Promise<void> {
try {
await db.query(
`UPDATE dais_wallets
SET verified = true, verified_at = now()
WHERE dais_id = $1 AND wallet_address = $2`,
[daisId, walletAddress]
);
// Update trust level
await this.updateTrustLevel(daisId);
logger.info(`Verified wallet for DAIS ${daisId}: ${walletAddress}`);
} catch (error) {
logger.error(`Failed to verify wallet: ${daisId}`, error);
throw error;
}
}
/**
* Update trust level based on verified identities
*/
private async updateTrustLevel(daisId: string): Promise<void> {
const profile = await this.getProfile(daisId);
if (!profile) return;
const hasVerifiedEmail = profile.emails.some(e => e.verified);
const hasVerifiedWallet = profile.wallets.some(w => w.verified);
let newLevel: DaisTrustLevel = 'guest';
if (hasVerifiedEmail && hasVerifiedWallet) {
newLevel = 'verified';
} else if (hasVerifiedEmail) {
newLevel = 'agent';
}
await db.query(
`UPDATE dais_identities SET trust_level = $1, updated_at = now() WHERE id = $2`,
[newLevel, daisId]
);
}
/**
* Promote agent to orchestrator (updates DAIS trust level)
*/
async promoteToOrchestrator(daisId: string): Promise<void> {
try {
await db.query(
`UPDATE dais_identities
SET trust_level = 'orchestrator', updated_at = now()
WHERE id = $1`,
[daisId]
);
logger.info(`Promoted DAIS to orchestrator: ${daisId}`);
} catch (error) {
logger.error(`Failed to promote to orchestrator: ${daisId}`, error);
throw error;
}
}
}
export const daisService = new DaisService();

View File

@@ -313,7 +313,7 @@ services:
- dagi-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8890/health"]
test: ["CMD-SHELL", "wget -qO- http://localhost:8890/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3

View File

@@ -0,0 +1,120 @@
# Agents_Interface_Architecture_v1.md
## DAARION.city — Agent-Centric Interface Architecture
**Version:** 1.0
**Status:** Foundation Spec (MVP)
**Scope:** Архітектура інтерфейсу агентів: primary_agent, team_agents, кабінети, ролі, кімнати, взаємодія з MicroDAO, Nodes, City.
---
# 0. Мета документа
Описати агентно-центровану модель інтерфейсу DAARION.space:
* кожна сторінка має агента-власника,
* первинні/командні агенти,
* кабінети агентів,
* категорії агентів,
* кімнати та віжети,
* інтеграцію з MicroDAO/City/Nodes.
---
# 1. Принцип
> **Усі сторінки, сцени й кімнати належать агентам (primary_agent).**
Структура сторінки:
```json
{
"primary_agent": "agent_id",
"team_agents": ["agent_id_2","agent_id_3"]
}
```
---
# 2. Типи агентів
1. Personal Agents (агенти користувачів).
2. Organizational Agents (належать MicroDAO).
3. Core-Team Agents (CEO/CTO/LegaI/Architect).
4. Public City Agents (DARIO, DARIA, DAARWIZZ, City Info).
5. Service/Infrastructure Agents (monitoring, bridge, summarizer).
6. District/Platform Agents (Helion, ERP GREENFOOD).
---
# 3. Primary vs Team Agents
* **Primary agent** — господар сцени (City Square → DARIO; MicroDAO Dashboard → Orchestrator).
* **Team agents** — асистують (DARIA, Security agent, DevOps agent тощо).
---
# 4. Кабінет агента
* **Profile** — ім’я, DAIS, роль, MicroDAO.
* **Activity** — події, дії, лог.
* **Rooms** — кімнати агента.
* **Workspaces** — проєкти, задачі.
* **Nodes** — home node, active session node.
* **Tools** — моделі, інтеграції.
* **Assignments** — MicroDAO / District / City scope.
---
# 5. Agent Rooms
* Personal room (DM з людиною).
* Workspace room (внутрішні).
* Public front room (у місті).
* Service room (інфраструктура).
* District room (платформи).
---
# 6. Зв’язки
* **Agent → MicroDAO**: ролі, дозволи, кімнати, проєкти.
* **Agent → Node**: home/active node, ресурси.
* **Agent → City**: публічні агенти, кіоски, City Square.
---
# 7. Widgets & Actions
* Кожен віджет має `agent_owner`.
* Будь-яка дія (створити MicroDAO, зареєструвати ноду) здійснюється агентом.
---
# 8. Agent Lifecycle
1. Creation (DAIS onboarding).
2. Assignment до MicroDAO.
3. Node placement.
4. Room creation.
5. Activity.
6. Promotion (core-team/orchestrator).
7. Archival.
---
# 9. MVP Scope
* Кабінет агента.
* Primary/team agent модель.
* Списки персональних/організаційних/публічних агентів.
* Agent rooms, projects, nodes.
* Присутність агента в City Square.
---
# 10. Підсумок
Агенти — центральні суб’єкти DAARION.space.
Цей документ закріплює інтерфейсну модель, у якій кожна сцена має primary_agent та команду агента, а всі функції (місто, MicroDAO, ноди) розгортаються через агентів.

View File

@@ -0,0 +1,152 @@
# City_Interface_Architecture_v1.md
## DAARION.city — City Layer & Public Space Interface
**Version:** 1.0
**Status:** Foundation Spec (MVP)
**Scope:** City Hub, City Square, public rooms, civic agents, MicroDAO portals, 2D/3D map
---
# 0. Мета документа
Визначити інтерфейс міського рівня DAARION.space:
* City Hub, City Square, публічні кімнати,
* ролі DARIO, DARIA, DAARWIZZ та інших civic-агентів,
* публічні кіоски/портали MicroDAO та District,
* взаємодію з Rooms Layer і MicroDAO Interface,
* 2D/3D представлення.
---
# 1. Роль City Layer
* верхній публічний шар DAARION.space;
* перша точка входу для мешканців;
* спільний простір для всіх MicroDAO/District/агентів;
* місце, де користувачі бачать мапу, кімнати, портали, події.
---
# 2. Основні об’єкти
## 2.1. City Hub
* належить root MicroDAO `DAARION`;
* містить City Square, City Rooms, City Map, реєстр порталів.
## 2.2. City Square
* головна публічна сцена;
* `primary_agent = DARIO`, `team_agents = [DARIA, DAARWIZZ, civic agents]`;
* блоки: привітання, підтримка, публічні кімнати, кіоски MicroDAO та District.
## 2.3. City Rooms
* `city.lobby`, `city.news`, `city.events`, `city.help` тощо;
* `space_scope='city'`, `owner_type='city'`.
## 2.4. MicroDAO Portals
* публічні кімнати `front-room` у місті (Energyunion, GREENFOOD);
* ведуть до інтерфейсу конкретного MicroDAO.
## 2.5. District Portals
* портали для платформ/екосистем;
* ведуть у District Space.
---
# 3. Агентність міського інтерфейсу
* **DARIO** — primary_agent City Square (community manager).
* **DARIA** — assistant_agent (tech support).
* **DAARWIZZ** — мер міста; бере участь у подіях.
* Публічні DAO агенти (Helion, ERP) мають власні front-room.
---
# 4. Основні екрани
1. `/city` — City Square (центральна сцена).
2. `/city/rooms` — список публічних кімнат.
3. `/city/map` — 2D-мапа з маркерами кімнат і порталів.
4. `/city/agents` — каталог публічних агентів (DARIO, DARIA, DAARWIZZ, DAO-агенти).
---
# 5. City Square Layout (MVP)
* **Центр:** DARIO (вітання, пропозиції, вибір MicroDAO).
* **Праворуч:** DARIA (FAQ, підтримка, навігація).
* **Низ:** публічні кімнати (Новини, Події, Допомога, Лобі).
* **Ліворуч:** кіоски MicroDAO (Energyunion, GREENFOOD).
* **Верх:** DAARWIZZ + глобальні оголошення.
---
# 6. Публічність та присутність
* City Square — місце, де можуть бути всі авторизовані користувачі, їх агенти та публічні DAO.
* MVP: список «хто онлайн» та лічильник присутніх (без 3D).
---
# 7. Портали MicroDAO
* кожне MicroDAO може опублікувати front-office (`space_scope='city'`);
* користувач бачить:
* якщо не член — публічний профіль + «Приєднатися»;
* якщо член — кнопка «Увійти в MicroDAO».
---
# 8. Civic Layer
* DARIO — community manager.
* DARIA — технічна підтримка.
* DAARWIZZ — мер; участь у «city.events`.
---
# 9. API (чернетка)
* `GET /api/city/rooms`
* `GET /api/city/portals`
* `GET /api/city/map`
* `GET /api/city/agents/public`
---
# 10. MVP Scope
* `/city` з базовими блоками DARIO/DARIA, публічні кімнати, два front-office.
* `/city/rooms` як таблиця.
* `/city/map` — статична 2D-мінімапа.
* Каталог публічних агентів.
Не входить: повна 3D-мапа, аватари, гейміфікація.
---
# 11. Взаємодія з іншими рівнями
* City Layer → Rooms Layer (`city-room`, `front-room`).
* City Layer → MicroDAO Interface (front-office).
* City Layer → Agents Layer (primary/team agents).
---
# 12. Підсумок
City Layer робить DAARION.city зрозумілим для мешканців:
* City Square — головна сцена;
* публічні кімнати — спільний простір;
* портали MicroDAO — міст між містом і організаціями;
* civic-агенти — обличчя міста.
Документ завершено.

View File

@@ -0,0 +1,234 @@
# DAARION_Identity_And_Access_Draft_v1.md
## DAIS — DAARION Autonomous Identity System (Draft IAM Specification)
**Version:** 1.0
**Status:** Draft (Foundation Update)
**Scope:** DAIS identity, wallets, keys, access control, DID, recovery
---
# 0. Мета документа
Визначити проектну модель системи ідентичності та доступу в DAARION.city:
* як створюється DAIS-ідентичність;
* як зв’язуються email, wallet, ключі, DID, Matrix;
* як визначаються рівні довіри;
* як працює key rotation та recovery;
* як DAIS пов’язаний із Agent/MicroDAO/Node;
* як реалізований доступ на рівні сервісів (gateway, node, worker).
Документ — фундамент IAM-модуля. Він не ламає поточну архітектуру, а задає майбутні вимоги.
---
# 1. Концепція DAIS
DAIS (DAARION Autonomous Identity System) — універсальна цифрова ідентичність, яка належить **агенту** й використовується для:
* створення агента,
* входу в MicroDAO,
* авторизації на нодах,
* підписання подій у DAGI Mesh,
* економічних операцій,
* відновлення доступу.
---
# 2. Структура DAIS-ідентичності
```
DAIS Identity
├─ Email identities (1..N)
├─ Wallet identities (1..N)
│ ├─ EVM (Polygon)
│ ├─ TON (future)
│ └─ Hardware wallet (future)
├─ DID (decentralized identifier)
├─ Matrix handle
├─ Public keys
├─ Signature domains
├─ Recovery methods
└─ Metadata
```
---
# 3. Компоненти DAIS
## 3.1. Email identities
* Passwordless (OTP / Magic Link).
* Можна прив’язати кілька email.
* Використовується як low-security login.
## 3.2. Wallet identities
* Підтримка EVM wallets (MetaMask, Rabby, WalletConnect).
* SIWE як стандарт підпису.
* Wallet є high-security login.
## 3.3. DID
* формат: `did:daariion:<uuid>`
* використовується для підписання подій, міжнодових операцій, Matrix.
## 3.4. Matrix handle
* `@<agent_id>:matrix.daarion.city`
* для міжагентного чату, голосових каналів, presence.
## 3.5. Public Keys
| Тип ключа | Призначення |
|-----------|--------------------------|
| Ed25519 | підпис подій, автентифікація |
| X25519 | шифрування / E2EE |
| secp256k1 | wallet-сумісність |
## 3.6. Signature domains
* `dais.login`
* `dais.node-auth`
* `dais.microdao-action`
* `dais.agent-auth`
* `dais.recovery`
## 3.7. Metadata
```json
{
"avatar": "...",
"telegram_linked": false,
"created_at": "...",
"citizenship_level": "basic"
}
```
---
# 4. Рівні довіри DAIS (Trust Levels)
| Рівень | Назва | Вимоги | Права |
|--------|---------------------|----------------------------------------|---------------------|
| 0 | Guest | email only | базові функції |
| 1 | Agent | підтверджений email | створення агента |
| 2 | Verified Agent | email + wallet | доступ до AI/DAO |
| 3 | Orchestrator | SIWE + токени/ролі | створення MicroDAO |
| 4 | DAARION Operator | hardware keys (future) | city governance |
---
# 5. Зберігання (схема)
```sql
dais_identities (
id text primary key,
default_email text null,
default_wallet text null,
did text not null,
trust_level integer not null default 1,
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
dais_emails (
id uuid primary key,
dais_id text not null references dais_identities(id),
email text not null,
verified boolean not null default false
);
dais_wallets (
id uuid primary key,
dais_id text not null references dais_identities(id),
wallet_address text not null,
network text not null default 'evm',
verified boolean not null default false
);
dais_keys (
dais_id text not null references dais_identities(id),
key_type text not null,
public_key text not null
);
```
---
# 6. Взаємозв’язок DAIS → Agent → MicroDAO → Node
```
DAIS identity
↓ (автоматично)
Agent (home_microdao = DAARION)
↓ (через promotion)
MicroDAO (створюється оркестратором)
Node (реєструється MicroDAO)
```
---
# 7. Рівні доступу
## 7.1. Application (UI)
* Email OTP / Magic link / SIWE.
* Доступ до кабінету агента, MicroDAO, сервісів.
## 7.2. Services (Gateway/API)
* Авторизація через DID, public keys, короткоживучі токени.
## 7.3. Node Access
* Нода перевіряє DAIS-ключ (`dais.node-auth`).
---
# 8. Ротація ключів
* **Soft rotation:** заміна email, прив’язка нового wallet, оновлення Matrix handle.
* **Hard rotation:** новий DID, нові ключі Ed25519/X25519 (потрібен підпис wallet).
---
# 9. Recovery
* Recovery email (secondary addresses).
* Seed phrase wallet recovery.
* Social recovery (future) — 2-3 поручителі (агенти, MicroDAO core team, DAARION108).
---
# 10. DAIS та безпека DAGI Mesh
DAIS використовується для:
* підписання міжагентних повідомлень;
* валідації подій у DAGI Router;
* E2EE у Matrix;
* авторизації worker-нод;
* запуску міжнодових контейнерів.
Без DAIS неможливо створити агента, MicroDAO, ноду чи увійти в District.
---
# 11. Майбутні розширення
* Інтеграція TON;
* DID-compatible wallet auth;
* hardware keys;
* локальна біометрія (без передачі).
---
# 12. Підсумок
DAIS — це цифрове тіло кожного агента.
Воно забезпечує універсальний login, права доступу, підписи, recovery.
Документ задає базу для майбутнього IAM і не потребує змін у чинній логіці.

View File

@@ -0,0 +1,239 @@
# DAARION_Ontology_Core_v1.md
## DAARION.city — Ontology Core (Agent → MicroDAO → Node → District)
**Version:** 1.0
**Status:** Foundation Document (Immutable Core)
**Scope:** DAARION.city / microDAO / DAGI Mesh / Identity Layer (DAIS)
---
# 0. Мета документа
Цей документ встановлює **базову онтологію** міста DAARION.city:
структуру сутностей, їх ролі, інваріанти та правила взаємодії.
Це — фундаментальна модель, на якій будуються:
* User Onboarding
* Identity Layer (DAIS)
* MicroDAO Governance
* Node Registration
* Agent Networks
* District Architecture
* DAGI Mesh Routing
Документ є **неламким** (non-breaking): будь-які зміни мають бути сумісні назад і розширювати, а не замінювати тут визначені принципи.
---
# 1. Онтологічний каркас DAARION.city
Уся мережа базується на простій ієрархії:
**Agent → MicroDAO → Node → District**
Жодна сутність не може існувати поза цією структурою.
---
# 2. Agent
## 2.1. Опис
**Agent** — мінімальна одиниця DAARION.city.
Кожен агент має:
* унікальний цифровий профіль (**DAIS Identity**);
* власний «Кабінет агента» (Agent Console);
* ключі, криптогаманець, DID/Matrix-ідентичність;
* базову приналежність до однієї MicroDAO (`home_microdao_id`);
* базову ноду виконання (`home_node_id`);
* власні ролі та сфери діяльності.
## 2.2. Типи агентів
| Тип агента | Опис | Приписка | Сфера діяльності |
| -------------------------------- | ----------------------------- | ------------------------------------------------- | ---------------------------- |
| **Personal Agent** | стандартний агент користувача | обов'язкова | своя MicroDAO або root-місто |
| **Service/Infrastructure Agent** | технічні агенти сервісів | до MicroDAO, де вони розгорнуті (частіше DAARION) | мікроДАО / дістрик / місто |
| **Core-City Agent (DAARION108)** | головна команда з 108 агентів | root MicroDAO «DAARION» | citywide (все місто) |
| **Orchestrator Agent** | має право створювати MicroDAO | обов'язкова | керування MicroDAO |
## 2.3. Ролі
* `regular` — стандартний агент.
* `orchestrator` — агент, який може створювати і керувати MicroDAO.
## 2.4. Інваріанти Agent
1. Agent не може існувати без DAIS-ідентичності.
2. Agent завжди має одну `home_microdao_id`.
3. Agent завжди має хоч одну ноду виконання (мінімально — root-ноду DAARION).
4. Orchestrator — це підвищений стан агента, який активується лише при виконанні умов доступу (токени, ключі).
5. Усі Service/Infrastructure-агенти «приписані» до реальної MicroDAO та реальної ноди.
---
# 3. MicroDAO
## 3.1. Опис
**MicroDAO** — мінімальна організаційна одиниця в місті:
команда, спільнота, проєкт, ініціатива або економічна клітинка.
## 3.2. Ключові характеристики
* унікальний `microdao_id`;
* `primary_orchestrator_agent_id` — головний агент;
* свій криптогаманець DAIS;
* свій governance-модуль;
* свої кімнати/канали/робочі простори;
* можливість реєструвати **Node**.
## 3.3. Типи MicroDAO
* **root** — перша MicroDAO, місто DAARION;
* **standard** — звичайні MicroDAO користувачів;
* **district** — розширений режим MicroDAO з доступом до інфраструктури і підлеглих MicroDAO.
## 3.4. Інваріанти MicroDAO
1. MicroDAO не може існувати без одного основного Orchestrator-Agent.
2. Root MicroDAO (DAARION) існує завжди і є предком усіх інших MicroDAO.
3. Кожна MicroDAO може реєструвати одну або більше нод.
4. District — це **форма MicroDAO**, а не окрема сутність.
5. Жодна MicroDAO не може існувати «без агресора» (без керуючого агента).
---
# 4. Node
## 4.1. Опис
**Node** — реальний вузол виконання в DAGI Mesh:
* смартфон,
* ноутбук,
* edge-пристрій,
* сервер,
* GPU-кластер,
* IoT-шлюз.
Це **не абстракція** — тільки фізично або програмно реальні пристрої.
## 4.2. Характеристики
* `node_id`;
* `microdao_id` — кому належить нода;
* `node_kind`: `smartphone`, `laptop`, `edge`, `datacenter`, `iot`, `gpu-cluster`;
* `capabilities` (GPU, RAM, sensors, network);
* `status`: `provisioning`, `active`, `draining`, `retired`.
## 4.3. Інваріанти Node
1. Node **завжди** належить одній MicroDAO.
2. Не існує «безхозних», «тестових» або «системних» нод поза моделлю.
3. Вся базова інфраструктура DAARION.city належить root MicroDAO «DAARION».
4. Агент може виконуватись лише:
* на ноді своєї MicroDAO,
* або на ноді MicroDAO/District, які на це дали дозвіл (governance).
---
# 5. District
## 5.1. Опис
**District** — це MicroDAO, якій надано розширені повноваження для керування:
* підлеглими MicroDAO,
* мережами нод,
* економічними або галузевими кластерами.
## 5.2. Інваріанти District
1. District = MicroDAO з `type = district`.
2. District має `parent_microdao_id`.
3. District може керувати ресурсами нижчих MicroDAO без зміни їх власності над нодами.
4. District — це елемент ієрархії, але не новий тип сутності.
---
# 6. Assignment Layer (Агенти, які працюють у різних MicroDAO)
## 6.1. Опис
Agent може «приходити на роботу» або виконувати завдання:
* в іншій MicroDAO,
* в District,
* у всьому місті (DAARION108).
Це робиться без зміни:
* `home_microdao_id`,
* `home_node_id`,
* ролі (regular / orchestrator).
## 6.2. Сутність `agent_assignment`
Визначає:
«цей агент виконує роботу для іншої MicroDAO/District».
Поля:
* `agent_id`
* `target_microdao_id`
* `scope` (`microdao`, `district`, `city`)
* `role` (`advisor`, `ops`, `security`, `mentor`, `core-team`)
* `start_ts`, `end_ts`
## 6.3. Інваріанти Assignment
1. Assignment не змінює приписку агента.
2. DAARION108 мають `scope = city`.
3. Service/Infrastructure-агенти можуть мати assignment до всієї мережі.
---
# 7. Жорсткі інваріанти онтології (DAARION Law)
1. **Agent → MicroDAO → Node**
— єдина дозволена лінія походження.
2. **MicroDAO завжди має Orchestrator-Agent.**
3. **Node завжди належить MicroDAO.**
4. **District — це розширений режим MicroDAO, не окрема сутність.**
5. **Немає тестових, тимчасових або віртуальних нод.**
Усі ноди справжні та пов'язані з реальними агентами та MicroDAO.
6. **Новий користувач завжди починає як Agent, приписаний до root-мікроДАО DAARION.**
7. **Тільки Orchestrator-Agent може створити MicroDAO.**
---
# 8. Стратегічна мета онтології
Створити **міцний, простий, ідеально зрозумілий фундамент**
для нового типу Інтернету:
**Інтернет агентів та нод.**
На цій онтології будуть побудовані:
* модуль DAIS Identity,
* Agent Governance,
* Node Registration / Verification,
* District Platforms,
* розподілене планування DAGI Mesh,
* і вся економіка міста DAARION.city.
---
Документ готовий до включення в TASK_PHASE_FOUNDATION_UPDATE та подальшої розробки.

View File

@@ -0,0 +1,161 @@
# MicroDAO_Interface_Architecture_v1.md
## DAARION.city — MicroDAO Interface & Workspace Architecture
**Version:** 1.0
**Status:** Foundation Spec (MVP)
**Scope:** UI/UX структури MicroDAO, доступи, кімнати, проєкти, агентні ролі, ноди, front-office
---
# 0. Мета документа
Визначити повну структуру інтерфейсу MicroDAO:
* Dashboard,
* Rooms,
* Projects/Tasks/Kanban,
* Agents/Core-team,
* Members (люди + агенти),
* Nodes,
* Front-office у місті,
* Routing та API.
MicroDAO — це робочий простір команди / платформи / району.
---
# 1. Структура інтерфейсу MicroDAO
Кожне MicroDAO має 7 основних блоків:
1. **Dashboard**
2. **Rooms**
3. **Projects**
4. **Agents**
5. **Members**
6. **Nodes**
7. **Front-Office**
---
# 2. Dashboard
Показує:
* назву, логотип, тип (`root/standard/district`);
* опис;
* основні метрики (агенти, люди, ноди, проєкти);
* оркестратора та core-team;
* сповіщення, останні події;
* кнопку «Вийти у Front-Office».
---
# 3. Rooms
* внутрішні кімнати (general, core-team, dev, projects);
* публічні кімнати (front-office) із `publish_to_city`;
* портальні кімнати (посилання на District, підлеглі DAO).
---
# 4. Projects Layer
* Projects: назва, опис, команда, кімната, канбан.
* Tasks: title, description, status, assignee (agent/human), due date.
* Kanban: MVP — три стовпці.
---
# 5. Agents Layer
* Personal agents (людей), organizational, core-team, service.
* Перегляд агента: DAIS, rooms, projects, nodes, assignments.
* Core-team агенти мають розширені повноваження.
---
# 6. Members Layer
* Люди (humans) як учасники.
* Кожна людина керує своїми агентами.
* Ролі: `member`, `manager`, `core-team`, `orchestrator`.
---
# 7. Nodes Layer
* Список нод MicroDAO, їх статусів, ресурсів.
* Прив’язка агентів до нод.
* Доступні дії (реєстрація, оновлення, вимкнення).
---
# 8. Front-Office
* Публічний портал MicroDAO у City Hub.
* Показує публічну інформацію, агента-вітрину, кнопку «приєднатися».
---
# 9. District Mode
* District = MicroDAO з `type='district'`.
* Має власну міні-мапу.
* Управляє підлеглими MicroDAO та нодами.
* Відображає дружні DAO на окремій панелі.
---
# 10. Routing
```
/microdao/{id}/dashboard
/microdao/{id}/rooms
/microdao/{id}/projects
/microdao/{id}/agents
/microdao/{id}/members
/microdao/{id}/nodes
/microdao/{id}/front
```
District:
```
/district/{id}
/district/{id}/rooms
/district/{id}/ecosystem
```
---
# 11. Інтеграції
* Rooms Layer — кімнати DAO, front-room.
* City Layer — front-office у місті.
* Agents Layer — primary_agent кожної сцени.
* Nodes Layer — таб «Nodes».
---
# 12. 3D/2D перспектива
* Параметри кімнат/порталів зберігають `map_x`, `map_y`, `mesh_id`.
* У майбутньому MicroDAO може мати власний 3D-офіс.
---
# 13. MVP Scope
* Dashboard + Rooms + Projects + Agents + Members + Nodes + Front-Office.
* Без 3D, без складних governance workflows.
---
# 14. Підсумок
MicroDAO Interface — серце DAARION.space.
Він забезпечує роботу команд, агентів, нод і публічних порталів, інтегруючись із City та Rooms Layer.
Документ задає канонічну структуру для реалізації MVP.

View File

@@ -0,0 +1,199 @@
# Nodes_Interface_Architecture_v1.md
## DAARION.city — Nodes Interface & Node Management Architecture
**Version:** 1.0
**Status:** Foundation Spec (MVP)
**Scope:** Node dashboards, control rooms, node registration, capabilities, health monitoring, DAGI mesh integration
---
# 0. Мета документа
Визначити інтерфейс керування нодами в DAARION.city:
* як відображаються ноди в UI,
* як реєструються та верифікуються ноди,
* як моніториться здоров'я та ресурси,
* як ноди інтегруються з MicroDAO та DAGI Mesh,
* як агенти виконуються на нодах,
* як відбувається координація Node Fleet.
---
# 1. Роль Nodes Interface
Nodes Interface — це шар управління фізичними та логічними вузлами DAGI Mesh:
* відображення стану нод MicroDAO,
* реєстрація нових нод,
* моніторинг ресурсів (CPU, GPU, RAM, network),
* управління lifecycle нод,
* прив'язка агентів до нод,
* fleet management для District.
---
# 2. Типи нод
| Тип | Опис | Capabilities |
|-----|------|--------------|
| `smartphone` | мобільний пристрій | low compute, camera, GPS, sensors |
| `laptop` | персональний комп'ютер | mid compute, local LLM, development |
| `edge` | edge device | low-mid compute, IoT gateway |
| `datacenter` | серверна інфраструктура | high compute, GPU, 24/7 |
| `iot` | IoT пристрій | sensors, actuators, minimal compute |
| `gpu-cluster` | GPU-кластер | high GPU, ML inference/training |
---
# 3. Структура Node Dashboard
## 3.1. Node Overview
* `node_id`, `node_kind`
* `microdao_id` — власник ноди
* `status`: provisioning | active | draining | retired
* `capabilities` — ресурси (CPU, GPU, RAM, network)
* Останній heartbeat
* Кількість активних агентів
## 3.2. Health Metrics
* CPU utilization
* Memory usage
* GPU utilization (якщо є)
* Network throughput
* Latency до mesh router
* Uptime
## 3.3. Agent Sessions
* Список агентів, що виконуються на ноді
* Статус кожного агента (active, idle, error)
* Ресурси, зайняті агентом
---
# 4. Реєстрація ноди
## 4.1. Flow
1. Оркестратор MicroDAO обирає "Register Node".
2. Вказує тип ноди (`node_kind`).
3. Генерується provisioning token.
4. Пристрій завантажує DAGI agent та вводить token.
5. Нода автентифікується через DAIS node-auth.
6. Подія `node.registered` публікується в NATS.
7. Нода переходить у `provisioning`, потім `active`.
## 4.2. Інваріанти
* Нода завжди належить MicroDAO.
* Реєстрацію ініціює Orchestrator.
* Після реєстрації нода підключається до DAGI Mesh.
---
# 5. Екрани інтерфейсу
## 5.1. MicroDAO Nodes Tab
* `/microdao/{id}/nodes` — список нод MicroDAO
* Таблиця: node_id, kind, status, capabilities, agents, actions
* Кнопка "Register Node"
## 5.2. Node Detail
* `/node/{id}` — деталі ноди
* Overview, Health, Agents, Logs, Settings
* Actions: restart agents, drain, retire
## 5.3. Fleet Management (District)
* `/district/{id}/fleet` — всі ноди підлеглих MicroDAO
* Aggregated metrics, alerts
* Scheduling policies
---
# 6. API Endpoints
```
GET /api/microdao/{id}/nodes
POST /api/microdao/{id}/nodes/register
GET /api/node/{id}
GET /api/node/{id}/health
GET /api/node/{id}/agents
POST /api/node/{id}/drain
POST /api/node/{id}/retire
```
---
# 7. DAGI Mesh Integration
* Кожна нода підключається до DAGI Router.
* Ноди отримують task scheduling від Router.
* Агенти виконуються на нодах через Worker Runtime.
* Heartbeat кожні 30 секунд до Mesh Controller.
---
# 8. Lifecycle Management
```
provisioning → active → draining → retired
```
* **provisioning**: нода реєструється, очікує верифікації.
* **active**: нода працює, приймає агентів.
* **draining**: нода готується до вимкнення, нові агенти не призначаються.
* **retired**: нода офлайн, архівована.
---
# 9. Security
* Доступ до ноди через DAIS node-auth.
* Тільки Orchestrator/Core-Team можуть керувати нодами.
* Agent sessions ізольовані (container/sandbox).
* Всі комунікації шифровані (mTLS).
---
# 10. MVP Scope
* Node list у MicroDAO interface.
* Node registration flow.
* Basic health display (status, capabilities).
* Agent sessions list.
* Drain/Retire actions.
Не входить: advanced scheduling, GPU quotas, auto-scaling.
---
# 11. Зв'язок з іншими документами
* **Ontology** → Node як сутність Agent → MicroDAO → Node → District.
* **Data Model** → таблиця `nodes` з полями.
* **Event Catalog** → `node.registered`.
* **MicroDAO Interface** → Nodes Tab.
* **Governance** → права на реєстрацію нод.
* **DAIS** → node-auth для автентифікації.
---
# 12. Підсумок
Nodes Interface забезпечує управління фізичною інфраструктурою DAGI Mesh:
* реєстрацію нод,
* моніторинг здоров'я та ресурсів,
* виконання агентів,
* lifecycle management,
* fleet management для District.
Документ завершено.

99
docs/foundation/README.md Normal file
View File

@@ -0,0 +1,99 @@
# Foundation Documentation
Цей каталог містить **джерело істини** для DAARION.city — повну онтологію, моделі даних, Governance, Identity (DAIS), Rooms Layer та інтерфейси City/MicroDAO/Agents/Nodes.
---
## Статус: ✅ FOUNDATION_UPDATE Complete
**Всього файлів:** 19 (12 основних + 6 helpers + 1 patch)
---
## Основні документи (12)
### Онтологія та ідентичність (1-7)
| № | Файл | Опис |
|---|------|------|
| 1 | [`DAARION_Ontology_Core_v1.md`](./DAARION_Ontology_Core_v1.md) | Базова онтологія Agent → MicroDAO → Node → District |
| 2 | [`User_Onboarding_And_Identity_Layer_v1.md`](./User_Onboarding_And_Identity_Layer_v1.md) | Реєстрація, DAIS, email/wallet login, Orchestrator |
| 3 | [`Technical_Description_microdao_PATCH_Ontology.md`](./Technical_Description_microdao_PATCH_Ontology.md) | Патч онтології до існуючого Technical Description |
| 4 | [`microdao_Data_Model_UPDATE_v1.md`](./microdao_Data_Model_UPDATE_v1.md) | Оновлена модель даних: agents, microdaos, nodes, assignments |
| 5 | [`microdao_Event_Catalog_EXTENDED_v1.md`](./microdao_Event_Catalog_EXTENDED_v1.md) | Каталог подій NATS: lifecycle, assignment events |
| 6 | [`microdao_Governance_And_Permissions_v1.md`](./microdao_Governance_And_Permissions_v1.md) | Ролі, ACL, governance MicroDAO/District |
| 7 | [`DAARION_Identity_And_Access_Draft_v1.md`](./DAARION_Identity_And_Access_Draft_v1.md) | DAIS як IAM: DID, keys, wallets, trust levels |
### Rooms та інтерфейси (8-12)
| № | Файл | Опис |
|---|------|------|
| 8 | [`Rooms_Layer_Architecture_v1.md`](./Rooms_Layer_Architecture_v1.md) | City/MicroDAO/District rooms, portals, 2D/3D |
| 9 | [`MicroDAO_Interface_Architecture_v1.md`](./MicroDAO_Interface_Architecture_v1.md) | UI MicroDAO: Dashboard, Rooms, Projects, Agents, Nodes |
| 10 | [`City_Interface_Architecture_v1.md`](./City_Interface_Architecture_v1.md) | City Square, DARIO/DARIA, public rooms, portals |
| 11 | [`Agents_Interface_Architecture_v1.md`](./Agents_Interface_Architecture_v1.md) | Agent-centric UI: primary/team agents, кабінети |
| 12 | [`Nodes_Interface_Architecture_v1.md`](./Nodes_Interface_Architecture_v1.md) | Node dashboards, registration, health, DAGI Mesh |
---
## Helper-файли (`helpers/`) — 6
| Файл | Опис |
|------|------|
| [`ontology-summary.md`](./helpers/ontology-summary.md) | TL;DR онтології |
| [`onboarding-flow-diagram.mermaid`](./helpers/onboarding-flow-diagram.mermaid) | Mermaid-діаграма онбордингу |
| [`agent-types-matrix.md`](./helpers/agent-types-matrix.md) | Матриця типів агентів та їх прав |
| [`microdao-lifecycle.md`](./helpers/microdao-lifecycle.md) | Життєвий цикл MicroDAO |
| [`node-lifecycle.md`](./helpers/node-lifecycle.md) | Життєвий цикл Node |
| [`event-schemas.json`](./helpers/event-schemas.json) | JSON Schema для нових подій |
---
## Патчі (`patches/`) — 1
| Файл | Опис |
|------|------|
| [`DAARION_Person_Agent_DAIS_CoreTeam_PATCH_v1.md`](./patches/DAARION_Person_Agent_DAIS_CoreTeam_PATCH_v1.md) | Human vs Agent, DAIS scope, Core-Team, DAARION108 |
---
## Перехресні посилання
```
Онтологія (1)
Data Model (4) ←→ Event Catalog (5)
Governance (6) ←→ Identity & Access (7)
Onboarding (2) → Agents Interface (11) → MicroDAO Interface (9)
Rooms Layer (8) → City Interface (10) / Nodes Interface (12)
```
### Ключові зв'язки:
* **Ontology → Data Model → Events** — база для міграцій та синхронізації.
* **Onboarding/Identity → Agents → MicroDAO** — шлях користувача від реєстрації до створення DAO.
* **Rooms Layer → City/MicroDAO/Agents/Nodes** — визначає UI всіх рівнів.
* **Governance → Identity & Access → Nodes** — ACL та інфраструктурні права.
* **Patch** — уточнює Human vs Agent та Core-Team model.
---
## Використання
Ці документи є базою для:
1. **TASK_PHASE_FOUNDATION_UPDATE** — поточна фаза ✅
2. **Rooms Layer MVP** — реалізація кімнат
3. **City/MicroDAO UI** — інтерфейси
4. **DAIS Implementation** — Identity & Access
5. **DAGI Mesh** — Node management
---
## Task Reference
📋 [`docs/tasks/TASK_PHASE_FOUNDATION_UPDATE.md`](../tasks/TASK_PHASE_FOUNDATION_UPDATE.md)

View File

@@ -0,0 +1,173 @@
# Rooms_Layer_Architecture_v1.md
## DAARION.city — Rooms Layer & Shared City Space
**Version:** 1.0
**Status:** Foundation Spec (Non-Breaking)
**Scope:** City rooms, MicroDAO rooms, District platforms, 2D/3D map, public fronts, inter-DAO interaction
---
# 0. Мета документа
Визначити, що таке «Кімнати Міста» та загалом Rooms Layer у DAARION.city:
* як влаштовані простори міста (City Hub, City Square),
* як працюють кімнати MicroDAO/District,
* як MicroDAO можуть мати публічні front-offices у місті,
* як це все відображається в 2D-мапі і майбутньому 3D метавсесвіті,
* як Rooms Layer інтегрується з MicroDAO Interface і City Layer.
---
# 1. Базова модель
Rooms Layer працює на трьох рівнях:
1. **City Hub (root MicroDAO DAARION)** — публічні міські кімнати і фронт-офіси.
2. **MicroDAO Space** — внутрішні кімнати, робочі простори, проєкти, core-team.
3. **District Space** — платформи, міні-міста з підлеглими MicroDAO.
Функція Rooms Layer — універсальна: та сама структура для всіх рівнів, але з різним контекстом.
---
# 2. Поняття Rooms Layer
## Room
* чат / канал / робочий простір;
* має `owner_type` (`city | microdao | district | agent`), `owner_id`;
* має `space_scope` (`city | microdao | district`);
* має `visibility` (`private | members | public-city | public-global`);
* опціонально `matrix_room_id`.
## Location
* 2D map tile / координати;
* 3D anchor (будівля, кіоск);
* fallback — список/каталог.
## Portal
* кімната-«точка входу» MicroDAO/District у міське середовище;
* `is_portal=true`, `portal_target_microdao_id`.
---
# 3. Типи кімнат
1. **City Room** — належить root MicroDAO, `space_scope='city'`.
2. **DAO Room** — внутрішні кімнати MicroDAO (`space_scope='microdao'`).
3. **Public Front Room** — кімната MicroDAO з `space_scope='city'`.
4. **District Room** — кімнати District-платформи (`space_scope='district'`).
5. **Agent Room / Booth** — публічні кімнати агентів (Helion, ERP, DARIO).
6. **Event Room** — тимчасові/постійні кімнати подій.
---
# 4. Модель видимості
* `owner_type`, `owner_id`.
* `visibility`: `private`, `members`, `public-city`, `public-global`.
* `space_scope`: `city`, `microdao`, `district`.
Приклад front-office Energyunion:
```
owner_type = microdao
owner_id = energyunion
visibility = public-city
space_scope = city
is_portal = true
portal_target_microdao_id = energyunion
```
---
# 5. City Hub як спільний простір
* Місто — місце, де можуть бути присутні всі MicroDAO, District, агенти.
* Кожне MicroDAO може зареєструвати портали/кімнати у City Hub.
* Публічні агенти (Helion, ERP, DARIO) мають свої кіоски в місті.
---
# 6. Інтерфейсні рівні
## 6.1. City Rooms UI
* `/city/rooms` — список / карта публічних кімнат.
* `/city` — City Square зі слотами кімнат/порталів.
* `/city/map` — 2D карта.
## 6.2. MicroDAO Rooms UI
* `/microdao/{id}/rooms` — внутрішні кімнати, публікація front-room (прапорець `publish_to_city`).
## 6.3. District Rooms UI
* `/district/{id}/rooms` — кімнати платформи, підлеглі DAO.
---
# 7. 2D/3D підтримка
* Кожна кімната може мати `map_x`, `map_y`, `zone`.
* 3D-режим використовує `mesh_id`, `3d_position`.
* City Square → набір кімнат/порталів, які відображаються як плитки / кіоски.
---
# 8. Модель даних (чернетка)
```sql
rooms (
id text primary key,
owner_type text not null,
owner_id text not null,
type text not null, -- city-room | dao-room | front-room | agent-room | event-room
space_scope text not null, -- city | microdao | district
visibility text not null, -- private | members | public-city | public-global
matrix_room_id text null,
is_portal boolean not null default false,
portal_target_microdao_id text null,
map_x integer null,
map_y integer null,
zone text null,
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
```
---
# 9. Governance
* City rooms створює root MicroDAO або civic-агенти з правами.
* DAO rooms створює оркестратор/команда.
* Front offices публікує Оркестратор або core-team.
* District rooms — оркестратор District.
---
# 10. MVP Scope
* Реєстр City Rooms.
* API: `GET /city/rooms`, `GET /city/portals`, `POST /microdao/{id}/rooms`.
* Мінімальний UI: список кімнат, дві front-room (Energyunion, GREENFOOD).
* Matrix-зв’язок для кімнат.
---
# 11. Підсумок
Rooms Layer уніфікує всі простори DAARION.city:
* місто як спільний простір,
* MicroDAO як власні робочі простори,
* District як платформи,
* агенти як власники кімнат.
Це база для 2D/3D DAARION.space.

View File

@@ -0,0 +1,213 @@
# Technical_Description_microdao_PATCH_Ontology.md
## Patch Update: DAARION Ontology, Agent Model, MicroDAO Rules, Node Structure
**Version:** 1.0
**Status:** Patch Addendum (Non-Breaking Update)
**Applies to:** Existing "Технічний опис microdao" документ
---
# 0. Мета патча
Цей документ додає нові архітектурні розділи та уточнення, які:
* узгоджують microDAO з повною онтологією DAARION.city,
* визначають інваріанти Agent/MicroDAO/Node,
* вводять механізм Assignment,
* уточнюють ролі та типи агентів,
* визначають, що District — не нова сутність, а режим MicroDAO,
* роблять архітектуру послідовною та розширюваною.
Патч нічого не ламає в існуючій логіці, лише додає розділи і правила.
---
# 1. Новий розділ: «Онтологія DAARION»
## 1.1. Ієрархія сутностей
Уся екосистема microdao існує в контексті онтології:
**Agent → MicroDAO → Node → District**
Інші об'єкти (канали, кімнати, governance, токени) належать цим сутностям.
## 1.2. Інваріанти онтології
* Кожен Agent належить до однієї MicroDAO.
* Кожна MicroDAO має одного primary Orchestrator-Agent.
* Кожна Node належить конкретній MicroDAO.
* District — це режим MicroDAO, а не окремий тип сутності.
* У системі не існує «сервісних», «віртуальних» або «нічийних» нод.
* Root MicroDAO (DAARION) — предок для всіх MicroDAO.
---
# 2. Новий розділ: «Agent Model (оновлений)»
## 2.1. Базові властивості Agent
* `agent_id`
* `dais_identity_id` (DAIS прив'язка)
* `home_microdao_id`
* `home_node_id`
* `role`: `regular` або `orchestrator`
* `service_scope` (нове поле; не обов'язкове)
## 2.2. Типи агентів
### A) Personal Agent
Агент конкретного користувача.
Приписаний до MicroDAO (за замовчанням — DAARION).
### B) Service/Infrastructure Agent
Агент, який забезпечує роботу сервісів міста.
Приписаний до MicroDAO, де він розміщений (частіше — DAARION).
Виконується на конкретних нодах.
### C) Core-City Agent (DAARION108)
108 агентів-експертів, що працюють для всього міста.
`service_scope = "city"`
### D) Orchestrator Agent
Агент, що має право створювати MicroDAO.
Перехід у Orchestrator створює подію: `agent.promoted_to_orchestrator`.
---
# 3. Новий розділ: «MicroDAO (оновлена модель)»
## 3.1. Структура
* `microdao_id`
* `type`: `root` | `standard` | `district`
* `primary_orchestrator_agent_id`
* `parent_microdao_id` (для district)
* `wallet_address`
* `metadata`
## 3.2. Інваріанти MicroDAO
* MicroDAO не може існувати без Orchestrator-Agent.
* `primary_orchestrator_agent_id` завжди існує і валідний.
* Root MicroDAO «DAARION» існує завжди.
* District = MicroDAO з розширеними правами.
* Усі ноди MicroDAO належать лише їй.
---
# 4. Новий розділ: «Node Model»
## 4.1. Структура ноди
* `node_id`
* `microdao_id`
* `node_kind`: `smartphone`, `laptop`, `edge`, `datacenter`, `iot`, `gpu-cluster`
* `capabilities` (json)
* `status`: `provisioning`, `active`, `draining`, `retired`
## 4.2. Інваріанти
* Нода завжди належить MicroDAO.
* Немає абстрактних/віртуальних нод.
* При реєстрації генерується подія `node.registered`.
---
# 5. Новий розділ: «District Model»
## 5.1. District = MicroDAO з type = district
Має розширені можливості:
* керування підлеглими MicroDAO,
* право мати власну мережу нод,
* роль «платформи» (галузь / район / екосистема).
## 5.2. Інваріанти District
* District не змінює власність нод MicroDAO.
* District — не новий тип сутності, не нова таблиця.
* Перехід MicroDAO → District фіксується подією `microdao.promoted_to_district`.
---
# 6. Новий розділ: «Assignment Layer (агенти, які працюють у різних MicroDAO)»
## 6.1. Призначення
Деякі агенти можуть:
* працювати у чужих MicroDAO,
* виконувати ролі у District,
* діяти від імені міста (DAARION108).
## 6.2. Структура сутності agent_assignment
```yaml
agent_assignment:
id: uuid
agent_id: string
target_microdao_id: string
scope: microdao | district | city
role: advisor | security | mentor | ops | core-team
start_ts: datetime
end_ts: datetime
```
## 6.3. Інваріанти Assignment
* Assignment не змінює перманентну приписку агента (`home_microdao_id`).
* Assignment є записом «тимчасової роботи/сервісу».
* DAARION108 мають `scope = city`.
---
# 7. Оновлення існуючих розділів документа microdao
Cursor при інтеграції повинен додати:
## 7.1. У розділ «Agents»
* поля: `home_microdao_id`, `home_node_id`, `service_scope`
* ролі: `regular`, `orchestrator`
* типи агентів (Personal, Service, Core-City)
## 7.2. У розділ «Teams/MicroDAO»
* обов'язкове поле `primary_orchestrator_agent_id`
* `type = root | standard | district`
* `parent_microdao_id`
* уточнення про DAARION (root)
## 7.3. У розділ «Nodes»
* додати інваріанти
* додати типи нод
* заборону абстрактних нод
## 7.4. У розділ «Governance»
* правило: MicroDAO створюється лише Orchestrator-Agent
* District — це не окрема таблиця
---
# 8. Підсумок патча
Після інтеграції цього патча:
* онтологія DAARION вплетена в microdao,
* всі сутності мають однакову семантику в документах та коді,
* нові типи агентів (service, core-city) офіційно описані,
* модель Assignment додана,
* MicroDAO, Node та District узгоджені з фундаментальним баченням,
* існуючі системи не змінюються, тільки розширюються.
Документ №3 завершений.

View File

@@ -0,0 +1,274 @@
# User_Onboarding_And_Identity_Layer_v1.md
## DAARION.city — User Onboarding & Identity Layer (DAIS)
**Version:** 1.0
**Status:** Core Spec (Foundation Update)
**Scope:** Реєстрація користувача, створення агентів, DAIS, wallet-логін, Orchestrator, MicroDAO
---
# 0. Мета документа
Цей документ описує **повний процес онбордингу користувача** в DAARION.city:
* реєстрацію → DAIS-профіль → Agent → Orchestrator → MicroDAO;
* Email-OTP та Magic Link;
* Web3 Wallet login та SIWE;
* правила доступу, ролі та підвищення;
* зберігання та синхронізацію ідентичностей;
* формування кабінету агента;
* перевірку токенів та прав на створення MicroDAO.
Документ створено як **неламке оновлення архітектури (non-breaking)**.
---
# 1. Загальний огляд онбордингу
Онбординг DAARION.city складається з трьох рівнів:
1. **DAIS Identity Layer**
— email, wallet, DID, keys → єдиний цифровий профіль.
2. **Agent Creation Layer**
— автоматичне створення агента + кабінету при першій реєстрації.
3. **Orchestrator → MicroDAO Layer**
— підвищення агента + створення MicroDAO за умовами доступу.
Це забезпечує інтуїтивний UX та жорстку архітектурну дисципліну.
---
# 2. DAIS Identity Layer
DAIS = **DAARION Autonomous Identity System**.
Це єдиний простір ідентифікації для людей, агентів і MicroDAO.
## 2.1. Структура DAIS-ідентичності
DAIS-ідентичність містить:
* **email-identities** (1..N)
* **wallet-identities** (EVM / SIWE)
* **telegram / TON identities** (майбутнє)
* **DID / Matrix identity**
* **public keys** (Ed25519 / secp256k1 / X25519)
* **signature domains** (підписи для сервісів)
* **recovery options**
## 2.2. Інваріанти DAIS
1. Один користувач = одна DAIS-ідентичність.
2. DAIS-профіль може мати багато email'ів і багато wallet'ів.
3. DAIS-профіль створюється **до** створення агента.
4. DAIS-профіль не може бути видалений, тільки ротується/оновлюється.
---
# 3. Реєстрація та автентифікація
DAARION.city підтримує два базові методи входу:
## 3.1. Email-OTP (One-Time Password)
Флоу:
1. Користувач вводить email.
2. Отримує одноразовий код (OTP).
3. Підтверджує код.
4. Створюється/активується DAIS-profile.
5. Створюється Agent + кабінет.
Переваги:
* Zero-password.
* Найменший бар'єр входу.
* Підходить для всіх типів користувачів.
## 3.2. Magic Link
Флоу:
1. Користувач вводить email.
2. Отримує магічне посилання.
3. Перехід → автоматичний вхід.
4. Створюється DAIS-profile → Agent.
## 3.3. Web3 Wallet Login (SIWE)
Підтримка: MetaMask, Rabby, WalletConnect.
Флоу:
1. Користувач підключає EVM-гаманець.
2. Підписує SIWE-повідомлення.
3. Створюється/активується DAIS-profile.
4. Гаманець стає частиною DAIS-ідентичності.
5. Створюється Agent.
## 3.4. Синхронізація Email + Wallet
Будь-який окремий метод додає ідентичність у DAIS.
При об'єднанні email і wallet → DAIS залишається єдиною сутністю.
---
# 4. Створення Агентів (Agent Creation Layer)
## 4.1. Коли створюється Agent
Agent створюється автоматично при:
* першому вході через email OTP,
* або першій верифікованій SIWE-сесії,
* або при Telegram/TON-верифікації в майбутньому.
## 4.2. Агент отримує:
* `agent_id`
* `home_microdao_id = DAARION (root)`
* `home_node_id = DAARION-root-node`
* DAIS-прив'язку
* Кабінет агента
* Роль: `regular`
## 4.3. Кабінет агента включає:
* Wallet overview
* Email overview
* Agent avatar / profile
* Список підключених нод
* Доступні сервіси
* Статус до MicroDAO
* Кнопку «Стати Оркестратором»
---
# 5. Перехід у Orchestrator (Orchestrator Promotion)
Це ключовий момент.
Користувач **не може** створити MicroDAO, поки:
* не має агента,
* не має оркестраторської ролі,
* не виконав умови допуску.
## 5.1. Флоу переходу
1. Користувач натискає «Стати Оркестратором».
2. Система перевіряє **умови доступу**.
3. Якщо всі умови виконано → підвищення агента.
4. Генерується подія `agent.promoted_to_orchestrator`.
5. Роль агента = `orchestrator`.
6. Відкривається Wizard створення MicroDAO.
## 5.2. Умови допуску
Умови встановлюються governance DAARION і можуть включати:
* прив'язаний Web3-гаманець;
* наявність основного токена (DAAR / DAARION);
* спеціальний NFT (Founder / Builder / Citizen);
* підтверджений email (обов'язково);
* мінімальний рівень довіри DAIS;
* проста верифікація через Matrix/Telegram.
## 5.3. Інваріанти Orchestrator
1. Кожен Orchestrator — це Agent, але не кожен Agent є Orchestrator.
2. Підвищення — це **одна подія** на агент (необоротна, але можна «заморозити» вручну).
3. Orchestrator може створити багато MicroDAO.
---
# 6. Створення MicroDAO
Коли агент стає Orchestrator → доступний Wizard створення MicroDAO.
## 6.1. Флоу
1. Старт Wizard: назва, опис, цілі, аватар.
2. Прив'язка DAIS-гаманця MicroDAO.
3. Створення запису `microdao_id`.
4. `primary_orchestrator_agent_id = цей агент`.
5. Ініціалізація governance.
6. Створення простору MicroDAO (канали, кімнати).
7. Генерується подія `microdao.created`.
8. Користувач переходить у кабінет MicroDAO.
## 6.2. Інваріанти MicroDAO в онбордингу
1. Немає MicroDAO без Orchestrator-Agent.
2. MicroDAO створюється саме в момент запуску Wizard, а не раніше.
3. Доступ до створення MicroDAO має лише Orchestrator.
---
# 7. Після створення MicroDAO: реєстрація нод
MicroDAO одразу отримує можливість:
* реєструвати ноди,
* прив'язувати пристрої,
* запускати сервісних агентів.
Флоу:
1. Orchestrator заходить у MicroDAO → Nodes.
2. Обирає «Зареєструвати Ноду».
3. Тип ноди: смартфон, ноут, сервер, IoT, GPU-кластер.
4. Автентифікація через DAIS-ключ.
5. Створюється запис `node_id`.
6. Генерується подія `node.registered`.
---
# 8. Значення онбордингу для онтології
Оновлений онбординг:
* **повністю відповідає онтології** Agent → MicroDAO → Node → District
* не ламає поточний UI (кнопка «Створити MicroDAO» зберігається)
* додає строгий порядок:
1. DAIS Identity
2. Agent
3. Orchestrator
4. MicroDAO
5. Node
6. District (опційно)
---
# 9. Події Stream (NATS)
Під час онбордингу фіксуються ключові події:
1. `dais.identity_created`
2. `agent.created`
3. `agent.promoted_to_orchestrator`
4. `microdao.created`
5. `node.registered`
6. (опційно) `microdao.promoted_to_district`
---
# 10. Резюме
Оновлений онбординг DAARION забезпечує:
* єдину ідентичність DAIS
* автоматичне створення агента
* чіткі умови доступу для Orchestrator
* чисту модель MicroDAO
* логічний шлях до реєстрації нод
* сумісність з майбутнім District Layer
* UX, що не ламає існуючих сценаріїв
---
Документ №2 завершено.

View File

@@ -0,0 +1,10 @@
# Agent Types Matrix
| Тип агента | Опис | Приписка | Scope | Може створити MicroDAO | Може працювати у чужих MicroDAO |
|------------|------|----------|--------|-------------------------|---------------------------------|
| Personal Agent | Агент користувача | обов'язково (до DAARION) | microdao | ні | через assignment |
| Service Agent | Технічний агент | до MicroDAO, де розгорнутий | microdao / district | ні | так, якщо assignment |
| Infrastructure Agent | gateway/bridge/monitor | DAARION | district/city | ні | так |
| Core-City Agent (DAARION108) | міська команда | DAARION | city | ні | так (auto) |
| Orchestrator Agent | має доступ до створення MicroDAO | своя MicroDAO | microdao | **так** | ні |

View File

@@ -0,0 +1,41 @@
{
"agent.promoted_to_orchestrator": {
"agent_id": "string",
"timestamp": "datetime"
},
"microdao.created": {
"microdao_id": "string",
"primary_orchestrator_agent_id": "string",
"type": "root | standard | district",
"parent_microdao_id": "string|null",
"timestamp": "datetime"
},
"node.registered": {
"node_id": "string",
"microdao_id": "string",
"node_kind": "smartphone|laptop|edge|datacenter|iot|gpu-cluster",
"capabilities": "object",
"timestamp": "datetime"
},
"microdao.promoted_to_district": {
"microdao_id": "string",
"promoted_by_agent_id": "string",
"parent_microdao_id": "string",
"timestamp": "datetime"
},
"agent.assignment_created": {
"assignment_id": "string",
"agent_id": "string",
"target_microdao_id": "string",
"scope": "microdao|district|city",
"role": "string",
"metadata": "object",
"timestamp": "datetime"
},
"agent.assignment_ended": {
"assignment_id": "string",
"agent_id": "string",
"timestamp": "datetime"
}
}

View File

@@ -0,0 +1,16 @@
# MicroDAO Lifecycle
1. Agent creates DAIS Identity
2. Agent is created (home = DAARION)
3. Agent becomes Orchestrator
4. Orchestrator runs MicroDAO Creation Wizard
5. `microdao.created` event emitted
6. MicroDAO governance initialized
7. Orchestrator registers nodes
8. `node.registered` events emitted
9. MicroDAO grows (members, rooms, agents)
10. (optional) MicroDAO promoted to District
11. `microdao.promoted_to_district` event
12. District manages sub-MicroDAO network
13. MicroDAO can be archived (future)

View File

@@ -0,0 +1,13 @@
# Node Lifecycle
1. Orchestrator triggers "Register Node"
2. Device generates DAIS node-auth key
3. MicroDAO verifies key ownership
4. `node.registered` event emitted
5. Node enters "provisioning" state
6. Agent workers start connecting
7. Node becomes "active"
8. Node can be updated (capabilities change)
9. Node enters "draining" before shutdown
10. Node becomes "retired"

View File

@@ -0,0 +1,18 @@
```mermaid
flowchart TD
A[User visits DAARION.city] --> B{Login method}
B -->|Email OTP| C[Create/Activate DAIS Identity]
B -->|Magic Link| C
B -->|Web3 Wallet (SIWE)| C
C --> D[Create Agent (home_microdao = DAARION)]
D --> E[Agent Console]
E --> F{Become Orchestrator?}
F -->|Yes| G[Check Access Conditions (wallet, tokens)]
G -->|Pass| H[agent.promoted_to_orchestrator]
H --> I[MicroDAO Creation Wizard]
I --> J[microdao.created]
J --> K[NODE REGISTRATION]
K --> L[node.registered]
L --> M[MicroDAO Operational]
```

View File

@@ -0,0 +1,47 @@
# DAARION Ontology — TL;DR
## 1. Основна лінія походження
`Agent → MicroDAO → Node → District`
## 2. Визначення сутностей
### Agent
* персональний або сервісний ШІ-агент;
* має DAIS-ідентичність (email + wallet + DID);
* завжди приписаний до `home_microdao_id`;
* має `role: regular | orchestrator`;
* має `service_scope: microdao | district | city`.
### MicroDAO
* мікро-спільнота, команда або проєкт;
* типи: `root`, `standard`, `district`;
* має `primary_orchestrator_agent_id`;
* може мати ноди;
* може бути підвищена до District.
### Node
* реальний пристрій (smartphone, laptop, edge, datacenter, iot, gpu-cluster);
* завжди належить MicroDAO (`microdao_id`);
* має `capabilities`, `status`.
### District
* MicroDAO з `type = district`;
* має розширені повноваження для підлеглих MicroDAO;
* керує підмережами нод.
## 3. Assignment Layer
Описує, де агент *працює*, не змінюючи приписку.
Поля:
* `agent_id`
* `target_microdao_id`
* `scope` (`microdao` \| `district` \| `city`)
* `role` (`advisor` \| `ops` \| `security` \| `mentor` \| `core-team`)

View File

@@ -0,0 +1,239 @@
# microdao_Data_Model_UPDATE_v1.md
## microDAO — Data Model Update (Foundation Layer)
**Version:** 1.0
**Status:** Non-Breaking Schema Extension
**Scope:** agents, microdaos, nodes, assignments, capabilities, metadata
---
# 0. Мета документа
Цей документ визначає оновлену модель даних microDAO, яка:
* формалізує онтологію DAARION (Agent → MicroDAO → Node → District),
* вводить нові інваріанти,
* додає нові сутності та поля,
* стандартизує JSON-поля `capabilities` і `metadata`,
* додає шар Assignment для агента, який працює в інших MicroDAO,
* залишається сумісною з існуючою системою (non-breaking).
---
# 1. Загальна структура моделі
Оновлена модель складається з п’яти головних сутностей:
1. `agents` (оновлено)
2. `microdaos` (оновлено)
3. `nodes` (оновлено)
4. `agent_assignments` (нова таблиця)
5. `event_log` / outbox (оновлено відповідно до подій)
Усі ці сутності підтримують фундаментальну онтологію DAARION.
---
# 2. Таблиця `agents` (оновлена)
Призначення: зберігати всіх агентів міста — персональних, сервісних, інфраструктурних, core-city, orchestrator.
## 2.1. Поля
```sql
agents (
id text primary key,
dais_identity_id text not null,
-- базова приписка
home_microdao_id text not null references microdaos(id),
home_node_id text null references nodes(id),
-- роль агента
role text not null check (role in ('regular','orchestrator')),
-- тип діяльності (розширений шар)
service_scope text null
check (service_scope in ('microdao','district','city')),
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
```
## 2.2. Опис ключових полів
* `home_microdao_id` — база агента (жорсткий інваріант).
* `home_node_id` — нода, на якій живе агент (може бути null).
* `role``regular` або `orchestrator`.
* `service_scope``microdao`, `district`, `city`.
* `metadata` — додаткові параметри (аватар, worker-конфіги, теги тощо).
---
# 3. Таблиця `microdaos` (оновлена)
Призначення: зберігати root, standard, district MicroDAO.
## 3.1. Поля
```sql
microdaos (
id text primary key,
type text not null
check (type in ('root','standard','district')),
primary_orchestrator_agent_id text not null
references agents(id),
parent_microdao_id text null references microdaos(id),
wallet_address text null,
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
```
## 3.2. Інваріанти
* MicroDAO не може існувати без `primary_orchestrator_agent_id`.
* `type='root'` зарезервовано для DAARION.
* `type='district'` дає розширені можливості.
* МікроДАО можуть формувати дерево через `parent_microdao_id`.
---
# 4. Таблиця `nodes` (оновлена)
Призначення: зберігати фізичні / логічні вузли виконання DAGI Mesh.
## 4.1. Поля
```sql
nodes (
id text primary key,
microdao_id text not null references microdaos(id),
node_kind text not null
check (node_kind in (
'smartphone','laptop','edge','datacenter',
'iot','gpu-cluster'
)),
capabilities jsonb not null default '{}'::jsonb,
status text not null
check (status in ('provisioning','active','draining','retired')),
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now()
);
```
## 4.2. Інваріанти
* Node завжди належить конкретній MicroDAO.
* Node — реальний пристрій (не абстракція).
* При створенні ноди генерується подія `node.registered`.
---
# 5. Таблиця `agent_assignments` (нова)
Призначення: описує, де агент працює (service layer), не змінюючи приписку.
## 5.1. Поля
```sql
agent_assignments (
id uuid primary key,
agent_id text not null references agents(id),
target_microdao_id text not null references microdaos(id),
scope text not null
check (scope in ('microdao','district','city')),
role text not null, -- advisor/security/mentor/ops/core-team
start_ts timestamptz not null default now(),
end_ts timestamptz null,
metadata jsonb not null default '{}'::jsonb
);
```
## 5.2. Інваріанти
* Assignment не змінює `home_microdao_id`.
* DAARION108 мають assignments з `scope='city'`.
* Service/Infrastructure агенти можуть мати кілька assignments.
---
# 6. JSON-структури
## 6.1. `capabilities.json`
```json
{
"cpu": "8 cores",
"ram": "32GB",
"gpu": {
"model": "RTX 4090",
"vram": "24GB"
},
"network": {
"up": "1Gbps",
"down": "1Gbps"
},
"sensors": ["camera","lidar","temperature"]
}
```
## 6.2. `metadata.json`
```json
{
"version": "1.0.0",
"agent_type": "service",
"citywide": true,
"labels": ["core","secure","production"],
"notes": "This agent is part of DAARION108"
}
```
---
# 7. Події (пов’язані з моделлю)
* `agent.promoted_to_orchestrator`
* `microdao.created`
* `node.registered`
* `microdao.promoted_to_district`
* `agent.assignment_created`
* `agent.assignment_ended`
Їхні схеми визначені в `microdao_Event_Catalog_EXTENDED_v1.md`.
---
# 8. Міграції (чорновий план)
* додати поля до `agents`;
* додати поля до `microdaos`;
* оновити `nodes`;
* створити `agent_assignments`;
* додати enum-типи (за потреби).
---
# 9. Підсумок
Модель даних тепер повністю відповідає фундаментальній онтології DAARION.
Усі інваріанти формалізовані, Assignment layer додано, структури capabilities/metadata стандартизовано.
Документ готовий до реалізації міграцій та оновлень у коді.

View File

@@ -0,0 +1,236 @@
# microdao_Event_Catalog_EXTENDED_v1.md
## DAARION.city — Event Catalog (Extended Ontology Update)
**Version:** 1.0
**Status:** Core Spec Update (Non-Breaking)
**Scope:** Agent → Orchestrator → MicroDAO → Node → District → Assignment
---
# 0. Мета документа
Визначити повний перелік нових доменних подій, які:
* підтримують онтологію DAARION (Agent → MicroDAO → Node → District),
* описують життєвий цикл агента, мікроДАО, нод та assignment layer,
* забезпечують єдиний контракт для NATS Stream та DAGI Router.
Document не змінює існуючі події microdao — лише додає нові.
---
# 1. Стандарти подій
## 1.1. Структурні правила
* формат JSON;
* поле `event_id` (uuid v4);
* поле `timestamp` (ISO8601 UTC);
* поле `version` (semver);
* поле `subject` (назва події);
* поле `payload` (дані події).
## 1.2. Транспортування
Події транспортуються через NATS у форматі:
`dagion.<domain>.<event>`
---
# 2. Нові події онтології DAARION
## 2.1. `agent.promoted_to_orchestrator`
* **NATS subject:** `dagion.agent.promoted_to_orchestrator`
* **Опис:** Агент отримує роль Orchestrator.
* **Payload:**
```json
{
"type": "object",
"required": ["agent_id","timestamp"],
"properties": {
"agent_id": { "type": "string" },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
## 2.2. `microdao.created`
* **Subject:** `dagion.microdao.created`
* **Опис:** Створено нову MicroDAO.
* **Payload:**
```json
{
"type": "object",
"required": [
"microdao_id",
"primary_orchestrator_agent_id",
"type",
"timestamp"
],
"properties": {
"microdao_id": { "type": "string" },
"primary_orchestrator_agent_id": { "type": "string" },
"type": { "type": "string", "enum": ["root","standard","district"] },
"parent_microdao_id": { "type": ["string","null"] },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
## 2.3. `node.registered`
* **Subject:** `dagion.node.registered`
* **Опис:** Зареєстрована нова нода.
* **Payload:**
```json
{
"type": "object",
"required": [
"node_id",
"microdao_id",
"node_kind",
"timestamp"
],
"properties": {
"node_id": { "type": "string" },
"microdao_id": { "type": "string" },
"node_kind": {
"type": "string",
"enum": [
"smartphone","laptop","edge",
"datacenter","iot","gpu-cluster"
]
},
"capabilities": { "type": "object" },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
## 2.4. `microdao.promoted_to_district`
* **Subject:** `dagion.microdao.promoted_to_district`
* **Опис:** MicroDAO отримує статус District.
* **Payload:**
```json
{
"type": "object",
"required": [
"microdao_id",
"promoted_by_agent_id",
"timestamp"
],
"properties": {
"microdao_id": { "type": "string" },
"promoted_by_agent_id": { "type": "string" },
"parent_microdao_id": { "type": "string" },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
---
# 3. Assignment Layer Events
## 3.1. `agent.assignment_created`
* **Subject:** `dagion.agent.assignment_created`
* **Опис:** Агент отримав роль у іншій MicroDAO/District/City.
* **Payload:**
```json
{
"type": "object",
"required": [
"assignment_id",
"agent_id",
"target_microdao_id",
"scope",
"role",
"timestamp"
],
"properties": {
"assignment_id": { "type": "string" },
"agent_id": { "type": "string" },
"target_microdao_id": { "type": "string" },
"scope": {
"type": "string",
"enum": ["microdao","district","city"]
},
"role": { "type": "string" },
"metadata": { "type": "object" },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
## 3.2. `agent.assignment_ended`
* **Subject:** `dagion.agent.assignment_ended`
* **Опис:** Завершено assignment агента.
* **Payload:**
```json
{
"type": "object",
"required": [
"assignment_id",
"agent_id",
"timestamp"
],
"properties": {
"assignment_id": { "type": "string" },
"agent_id": { "type": "string" },
"timestamp": { "type": "string", "format": "date-time" }
}
}
```
---
# 4. Події ідентичності (довідково)
Зовнішній Identity Service генерує:
* `dais.identity_created` (`dagion.identity.created`)
* `agent.created` (`dagion.agent.created`)
Ці події використовуються microdao для синхронізації.
---
# 5. Зв’язок подій з життєвими циклами
* **Agent lifecycle:** `identity.created → agent.created → agent.promoted_to_orchestrator → assignment events`.
* **MicroDAO lifecycle:** `agent.promoted_to_orchestrator → microdao.created → microdao.promoted_to_district`.
* **Node lifecycle:** `microdao.created → node.registered`.
---
# 6. Гарантії та інваріанти
* Події не відкатуються.
* Кожна подія має `event_id`, `timestamp`, `version`.
* Подія не може суперечити онтології DAARION.
* Payload завжди відповідає цій моделі даних.
---
# 7. Переваги Extended Event Catalog
* Повний опис життєвих циклів Agent/MicroDAO/Node/District.
* Синхронізація Identity, microdao, Gateway, DAGI Router.
* Автоматичні реакції agents-as-workers.
* Підготовка до наступних фаз governance та city automation.
Документ завершено.

View File

@@ -0,0 +1,145 @@
# microdao_Governance_And_Permissions_v1.md
## DAARION.city — Governance & Permissions Layer (Minimal Core)
**Version:** 1.0
**Status:** Foundation Spec (Non-Breaking)
**Scope:** Agents, Orchestrators, MicroDAO, Nodes, Districts
---
# 0. Мета документа
Визначити мінімальну, але строгу модель управління та доступів у DAARION.city, яка:
* відповідає онтології Agent → MicroDAO → Node → District,
* захищає критичні операції (створення MicroDAO, реєстрація нод, assignments),
* визначає ролі та ACL, не вводячи громіздкого DAO-протоколу.
Документ розширює існуючі правила microdao без змін поведінки.
---
# 1. Принципи Governance DAARION
1. **Примат онтології.** Усі правила походять із структури Agent → MicroDAO → Node → District.
2. **Мінімальна достатність.** На базовому етапі — тільки найнеобхідніші механіки.
3. **Безпека через приписку.** Будь-який агент/нода мають формальну MicroDAO-приписку.
4. **DAARION як root governance.** Root MicroDAO — вища інстанція та еталон.
---
# 2. Ролі агентів
| Роль | Опис | Доступи |
|-----------------|-------------------------------------------------------------|-----------------------------------------------------------|
| Regular Agent | стандартний агент | вхід, участь у сервісах, виконання assignment |
| Orchestrator | агент, що керує MicroDAO | створення MicroDAO, управління нодами, членами |
| Service Agent | технічний/сервісний агент | доступ до внутрішньої інфраструктури |
| Core-City Agent | DAARION108 (citywide scope) | робота в усьому місті (при дотриманні політик) |
---
# 3. Governance MicroDAO
## 3.1. Основні артефакти
* `primary_orchestrator_agent_id`
* склад агентів і людей
* ноди
* assignments інших агентів
* DAO-налаштування
## 3.2. Дозволи (мінімальний набір)
* Оркестратор:
* редагування `metadata`
* додавання учасників
* запрошення агентів
* реєстрація / вимикання нод
* налаштування front-office
* підвищення до District
* Члени:
* доступ до DAO-кімнат
* участь у проектах
* запуск власних агентів (за правилами governance)
---
# 4. Node Governance
* **Хто реєструє ноду?** Оркестратор MicroDAO.
* **Хто керує нодою?** Оркестратор + довірені core-team агенти (Node Manager, DevOps).
* **Хто може використовувати ноду?**
* агенти цього MicroDAO
* агенти з assignment (якщо дозволено governance)
* citywide агенти (DAARION108) — тільки при спец-дозволах.
---
# 5. District Governance
District = MicroDAO `type='district'`.
Особливості:
* може мати `parent_microdao_id`;
* керує пулом підлеглих MicroDAO;
* має власні ноди / платформи;
* може координувати між-DAO задачі;
* перехід фіксується подією `microdao.promoted_to_district`.
---
# 6. Assignment Governance
Assignment дозволяє агенту працювати поза `home_microdao_id`.
* **Хто створює assignment?**
* Оркестратор MicroDAO (який приймає агента),
* District (для своїх підлеглих),
* DAARION (root) — для citywide операцій.
* **Для чого:**
* DAARION108 → citywide tasks,
* сервісні агенти → підтримка інших MicroDAO,
* зовнішні експерти → консалтинг/безпека.
* **Події:** `agent.assignment_created`, `agent.assignment_ended`.
---
# 7. ACL-модель (мінімум)
| Дозвіл | Опис | Хто має |
|--------------------|-------------------------------------|---------------------|
| `CREATE_MICRODAO` | Створити MicroDAO | Orchestrator |
| `REGISTER_NODE` | Реєструвати ноду | Orchestrator |
| `MANAGE_MEMBERS` | Керувати учасниками MicroDAO | Orchestrator |
| `CITYWIDE_ACCESS` | Діяти у всьому місті | DAARION108, civic |
| `DISTRICT_ADMIN` | Адмініструвати District-платформу | District Orchestrator |
---
# 8. Безпека та перевірка дозволів
Єдиний принцип:
> **Суб’єкт діє в межах своєї приписки + своїх assignment.**
Тобто:
* агент може діяти у своїй MicroDAO;
* агент може діяти в іншій MicroDAO лише через assignment;
* реєструвати ноду може тільки оркестратор MicroDAO-власника;
* District керує підлеглими, але не змінює їхню власність.
---
# 9. Підсумок
* Governance базується на канонічній онтології.
* Визначено роли agent'ів та дозволи.
* Assignment — офіційний механізм співпраці.
* District — розширення MicroDAO, а не нова сутність.
* Модель готова до подальшого розширення (повний ACL/RBAC) без ломки існуючої логіки.

View File

@@ -0,0 +1,146 @@
# DAARION_Person_Agent_DAIS_CoreTeam_PATCH_v1.md
## Patch Update: Human Auth Layer → Agent DAIS Identity → Core-Team Model
**Status:** Architectural Correction (Non-Breaking Patch)
**Version:** 1.0
**Scope:** Clarifies Human vs Agent, DAIS scope, Core-Team Agents, DAARION108, Civic Layer
---
# 0. Мета патча
Уточнити ключові концепції онтології DAARION.city, які не були зафіксовані повністю у фундаментальних документах:
1. різницю між **Human** та **Agent**,
2. що таке **DAIS** і кому він належить,
3. як люди взаємодіють із агентами,
4. хто такі **Core-Team Agents** та як вони працюють у MicroDAO,
5. чим є **DAARION108**,
6. хто представляє місто (civic layer — DAARWIZZ),
7. як MicroDAO стає простором співпраці людей і агентів.
Патч не змінює основні документи — лише уточнює семантику.
---
# 1. Human vs Agent
## 1.1. Human/User
* має Human-auth (email, wallet, Telegram, OTP);
* веде акаунт, налаштування доступу;
* **не має DAIS**;
* взаємодіє з містом через агентів, яких створює та контролює.
## 1.2. Agent
* цифровий представник людини, MicroDAO або організації;
* має DAIS (DID + keys + wallet + Matrix);
* працює у MicroDAO та на нодах;
* є власником кімнат, сторінок, інтерфейсів.
## 1.3. Взаємозв’язок
```
Human (user)
↓ володіє/керує
Agents (1..N)
↓ кожен має
DAIS Identity
↓ кожен приписаний до
MicroDAO
↓ може працювати на
Nodes
```
---
# 2. DAIS належить агенту, а не людині
* DAIS містить DID, ключі, wallets, Matrix handle, signature domains.
* DAIS = цифрове тіло агента.
* Людина має Human Auth і управляє агентом, але не є DID.
---
# 3. Core-Team Agents
* новий клас агентів із розширеними повноваженнями;
* ролі: CEO Agent, CTO Agent, CISO Agent, Architect, Product Lead, DevOps Lead, Legal Agent, HR Agent;
* мають доступ до всієї MicroDAO, координують роботу команд;
* у District — керують підлеглими підрозділами.
---
# 4. Core-Team у District
* District = MicroDAO-платформа;
* має власний **Core-Team Console**;
* може будувати міні-місто / екосистему;
* core-team агентів District керують підлеглими MicroDAO.
---
# 5. DAARION108
* Core-Team MicroDAO «DAARION DAO»;
* не civic layer, не міська підтримка;
* це організаційна команда (аналог команди OpenAI, але AI-команда);
* працює на Node2;
* виконує ролі CEO/CTO/Architect/PM/etc.
---
# 6. Civic Layer (DAARWIZZ)
* окремий шар: міський інтерфейс для громадян;
* агенти: DAARWIZZ (мер), навігатори, модератори, онбордери;
* живуть у root MicroDAO DAARION;
* мають `service_scope = city`.
---
# 7. MicroDAO як простір співпраці
* MicroDAO = workspace, де одночасно працюють люди та агенти;
* містить проєкти, канбан, кімнати, core-team, ноди;
* кожне MicroDAO може виставити публічні front-rooms у місті;
* DAARION (root MicroDAO) теж має свій MicroDAO-інтерфейс.
---
# 8. Інваріанти, які додає патч
1. **Human ≠ Agent.** Людина управляє агентом, але не є DID.
2. **DAIS належить агенту.** DID/ключі — це тіло агента.
3. **Core-Team Agents** — офіційний клас із розширеними правами.
4. **DAARION108** = core-team MicroDAO «DAARION DAO».
5. **Civic Layer (DAARWIZZ)** — незалежний шар, який обслуговує місто.
6. **MicroDAO** = простір співпраці людей і агентів.
---
# 9. Документи, які доповнює патч
* `DAARION_Ontology_Core_v1.md`
* `User_Onboarding_And_Identity_Layer_v1.md`
* `microdao_Governance_And_Permissions_v1.md`
* `microdao_Data_Model_UPDATE_v1.md`
* `DAARION_Identity_And_Access_Draft_v1.md`
---
# 10. Підсумок
Патч закріплює правильну концепцію:
* **DAIS = identity agent, not human.**
* **Human → controls → Agents.**
* **Agents → мають DAIS → діють у світі.**
* **Core-Team Agents** — ключовий клас для MicroDAO/District.
* **DAARION108** — core-team DAARION DAO.
* **DAARWIZZ** + civic агенти — інтерфейс міста.
Документ завершено.

View File

@@ -0,0 +1,214 @@
# TASK: Foundation Implementation in MVP
**Status:** ✅ Implemented
**Priority:** High
**Completed:** 2025-11-29
**Dependencies:** FOUNDATION_UPDATE документи (завершено)
---
## 📋 Огляд
Впровадження оновлень архітектури FOUNDATION_UPDATE в MVP:
- Оновлення Data Model (міграції)
- Нові NATS events
- Backend API оновлення
- Frontend оновлення
---
## ✅ Що вже є (аналіз)
### Database
- [x] `agents.is_orchestrator` (boolean) - частковий аналог `role`
- [x] `microdaos.is_platform` (boolean) - частковий аналог `type=district`
- [x] `microdaos.parent_microdao_id` - ієрархія
- [x] `microdaos.orchestrator_agent_id` - primary orchestrator
- [x] `nodes.modules`, `nodes.gpu`, `nodes.roles` - capabilities
- [x] `microdao_agents` - зв'язок агентів з мікроДАО
### Backend
- [x] DAO Factory service
- [x] Registry service
- [x] Wallet service
- [x] PDP (Policy Decision Point)
### Frontend
- [x] Agent Hub UI
- [x] MicroDAO Console
- [x] Node Cabinets
- [x] City Page (базова)
---
## 🚀 Що потрібно реалізувати
### Phase 1: Database Schema Update (Міграція 027) ✅
```sql
-- 027_foundation_ontology_update.sql
```
1. **Agents table**
- [x] `dais_identity_id text` - DAIS прив'язка
- [x] `agent_role` enum - замість is_orchestrator
- [x] `agent_service_scope` enum
- [x] `home_microdao_id text` - базова приписка
- [x] `home_node_id text` - базова нода
2. **MicroDAOs table**
- [x] `dao_type` enum (root/standard/district)
- [x] `primary_orchestrator_agent_id text`
- [x] `wallet_address text`
3. **Nodes table**
- [x] `kind` enum (smartphone/laptop/edge/datacenter/iot/gpu-cluster)
- [x] `capabilities jsonb`
- [x] `node_status` enum (provisioning/active/draining/retired)
4. **Нова таблиця: agent_assignments**
- [x] All fields implemented
5. **DAIS tables (нові)**
- [x] `dais_identities`
- [x] `dais_emails`
- [x] `dais_wallets`
- [x] `dais_keys`
6. **Rooms table (нова)**
- [x] Full Rooms Layer support
7. **Event outbox (нова)**
- [x] For NATS event delivery
### Phase 2: NATS Events (Event Catalog) ✅
- [x] `dagion.agent.promoted_to_orchestrator`
- [x] `dagion.microdao.created`
- [x] `dagion.node.registered`
- [x] `dagion.microdao.promoted_to_district`
- [x] `dagion.agent.assignment_created`
- [x] `dagion.agent.assignment_ended`
### Phase 3: Backend API Updates ✅
1. **DAIS routes**
- [x] `POST /api/v1/dais/identity`
- [x] `GET /api/v1/dais/:id`
- [x] `GET /api/v1/dais/agent/:agentId`
- [x] `POST /api/v1/dais/:id/email`
- [x] `POST /api/v1/dais/:id/email/verify`
- [x] `POST /api/v1/dais/:id/wallet`
- [x] `POST /api/v1/dais/:id/wallet/verify`
- [x] `POST /api/v1/dais/:id/promote-to-orchestrator`
2. **Assignment routes**
- [x] `POST /api/v1/assignments`
- [x] `DELETE /api/v1/assignments/:id`
- [x] `GET /api/v1/assignments/agent/:agentId`
- [x] `GET /api/v1/assignments/microdao/:microdaoId`
- [x] `GET /api/v1/assignments/citywide`
- [x] `GET /api/v1/assignments/agent/:agentId/scope`
- [x] `GET /api/v1/assignments/check`
### Phase 4: Frontend Updates ✅
1. **Types**
- [x] `src/types/ontology.ts` - all ontology types
2. **API Clients**
- [x] `src/api/dais.ts`
- [x] `src/api/assignments.ts`
3. **Components**
- [x] `DaisProfileCard.tsx`
- [x] `AssignmentsPanel.tsx`
- [x] `OntologyBadge.tsx` (MicrodaoType, NodeStatus, NodeKind, AgentRole, ServiceScope)
---
## 📁 Файли для створення/оновлення
### Backend
```
backend/
├── domain/
│ ├── dais/
│ │ └── types.ts # DAIS types
│ ├── agent/
│ │ └── types.ts # оновити
│ └── assignment/
│ └── types.ts # нові типи
├── http/
│ ├── dais.routes.ts # новий
│ └── assignment.routes.ts # новий
├── services/
│ ├── dais/
│ │ └── dais.service.ts # новий
│ └── assignment/
│ └── assignment.service.ts # новий
└── infra/
└── nats/
└── events.ts # оновити events catalog
```
### Frontend
```
src/
├── api/
│ ├── dais.ts # новий
│ └── assignments.ts # новий
├── features/
│ ├── dais/
│ │ └── components/ # DAIS UI
│ └── assignments/
│ └── AssignmentsPanel.tsx
└── types/
├── dais.ts # DAIS types
└── ontology.ts # Agent/MicroDAO/Node types
```
### Migrations
```
migrations/
└── 027_foundation_ontology_update.sql
```
---
## 🎯 Acceptance Criteria
1. **Database**
- [ ] Міграція 027 виконана успішно
- [ ] Всі таблиці відповідають Data Model v1
2. **Backend**
- [ ] API routes працюють
- [ ] NATS events публікуються
3. **Frontend**
- [ ] Agent Console показує DAIS/assignments
- [ ] MicroDAO показує type/hierarchy
- [ ] Nodes показують lifecycle
4. **Non-Breaking**
- [ ] Існуючий функціонал працює
- [ ] Backward compatibility збережено
---
## 🔧 Порядок виконання
1. **Створити міграцію** 027_foundation_ontology_update.sql
2. **Застосувати міграцію** на dev БД
3. **Оновити backend types** для нових полів
4. **Додати API routes** для DAIS, assignments
5. **Оновити frontend types**
6. **Додати UI компоненти** для нового функціоналу
7. **Тестування** локально
8. **Deploy** на production
---
**Готовий до виконання?** Починаємо з Phase 1: Database Migration.

View File

@@ -0,0 +1,112 @@
# TASK_PHASE_FOUNDATION_UPDATE.md
## DAARION.city — Fundamental Architecture Update (Non-Breaking)
**Ціль:** зафіксувати онтологію системи (Agent → MicroDAO → Node → District), стандартизувати онбординг, DAIS-ідентичність, типи агентів, події та базовий Data Model — **без порушення існуючого коду / документації**.
---
# 0. Принципи фази
1. **Нічого не ламаємо**, лише додаємо надбудову поверх існуючих документів.
2. Усе, що створюється в цій фазі — фундаментальна архітектура DAARION.
3. Cursor і DAGI-агенти повинні мати єдине джерело істини щодо реєстрації, агентів, мікроДАО, нод, ролей, подій.
---
# 1. Вихідні файли після завершення фази
Фаза повинна створити або оновити **13+ документів**.
## Головні
1. `DAARION_Ontology_Core_v1.md`
2. `User_Onboarding_And_Identity_Layer_v1.md`
3. `Technical_Description_microdao_PATCH_Ontology.md`
4. `microdao_Data_Model_UPDATE_v1.md`
5. `microdao_Event_Catalog_EXTENDED_v1.md`
6. `microdao_Governance_And_Permissions_v1.md`
7. `DAARION_Identity_And_Access_Draft_v1.md`
8. `Rooms_Layer_Architecture_v1.md`
9. `MicroDAO_Interface_Architecture_v1.md`
10. `City_Interface_Architecture_v1.md`
11. `Agents_Interface_Architecture_v1.md`
12. `Nodes_Interface_Architecture_v1.md`
## Допоміжні
* `helpers/ontology-summary.md`
* `helpers/onboarding-flow-diagram.mermaid`
* `helpers/agent-types-matrix.md`
* `helpers/microdao-lifecycle.md`
* `helpers/node-lifecycle.md`
* `helpers/event-schemas.json`
## Патчі
* `patches/DAARION_Person_Agent_DAIS_CoreTeam_PATCH_v1.md`
---
# 2. Tasks
1. **TASK 1 — Ontology Core** → створити базову онтологію (файл №1).
2. **TASK 2 — Onboarding & Identity** → email/wallet/SIWE/DAIS (файл №2).
3. **TASK 3 — Patch Technical Description** → секції онтології в існуючому описі microdao.
4. **TASK 4 — Data Model Update** → agents/microdaos/nodes/assignments.
5. **TASK 5 — Event Catalog** → додати 6 нових подій та схеми.
6. **TASK 6 — Governance Layer** → ролі, ACL, district, assignments.
7. **TASK 7 — Identity & Access Draft** → DAIS як IAM.
8. **TASK 8 — Rooms Layer** → city/microdao/district rooms.
9. **TASK 9 — MicroDAO Interface** → повний UI шару.
10. **TASK 10 — City Interface** → City Square, public rooms, portals.
11. **TASK 11 — Agents Interface** → agent-centric UI.
12. **TASK 12 — Nodes Interface** → node dashboards/control rooms.
13. **TASK 13 — Helper Files** → TL;DR, mermaid, lifecycles, event schemas.
---
# 3. Порядок виконання
1. Ontology → Onboarding → Patch → Data Model → Event Catalog → Governance → Identity & Access.
2. Після цього Rooms Layer та UI документи (MicroDAO/City/Agents/Nodes).
3. Завершити helper-файлами та README.
---
# 4. Гарантії «Non-Breaking Update»
* Неторкнені частини коду/документації залишаються валідними.
* Усі інваріанти вводяться як надбудова.
* Уся логіка створення MicroDAO/агента/нод залишається робочою.
---
# Acceptance checklist
1. **Документи**
* [x] Створено/оновлено всі файли, перелічені вище. ✅ (20 файлів)
* [x] README у `docs/foundation/` описує структуру. ✅
2. **Посилання**
* [x] Перехресні посилання між онтологією, моделлю даних, подіями, інтерфейсами. ✅
3. **Helper-файли**
* [x] TL;DR, діаграма онбордингу, матриця агентів, lifecycles, event schemas. ✅ (6 файлів)
4. **Патчі**
* [x] Застосовано патч Human vs Agent vs DAIS vs Core-Team. ✅
5. **Task readiness**
* [x] `TASK_PHASE_FOUNDATION_UPDATE.md` описує всі deliverables. ✅
* [x] Можна давати Cursor-таски для реалізації MVP на основі цих документів. ✅
---
## ✅ PHASE COMPLETE
**Дата завершення:** 2024-11-29
**Статистика:**
- Основних документів: 12
- Helper-файлів: 6
- Патчів: 1
- README: 1
- **Всього: 20 файлів**

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;

View File

@@ -80,7 +80,7 @@ async def handle_parser_document_parsed(msg):
}
# Ingest the document
result = ingest_parsed_document(
result = await ingest_parsed_document(
dao_id=dao_id or team_id,
doc_id=doc_id,
parsed_json=mock_parsed_json,

View File

@@ -18,7 +18,7 @@ from app.events import publish_document_ingested, publish_document_indexed
logger = logging.getLogger(__name__)
def ingest_parsed_document(
async def ingest_parsed_document(
dao_id: str,
doc_id: str,
parsed_json: Dict[str, Any],
@@ -81,46 +81,14 @@ def ingest_parsed_document(
)
# Publish events
try:
# First publish rag.document.ingested event
await publish_document_ingested(
doc_id=doc_id,
team_id=dao_id,
dao_id=dao_id,
chunk_count=written_docs,
indexed=True,
visibility="public",
metadata={
"ingestion_time_ms": round(pipeline_time * 1000),
"embed_model": settings.EMBEDDING_MODEL or "bge-m3@v1",
"pages_processed": pages_count,
"blocks_processed": blocks_count
}
)
logger.info(f"Published rag.document.ingested event for doc_id={doc_id}")
# Then publish rag.document.indexed event
chunk_ids = []
for i in range(written_docs):
chunk_ids.append(f"{doc_id}_chunk_{i+1}")
await publish_document_indexed(
doc_id=doc_id,
team_id=dao_id,
dao_id=dao_id,
chunk_ids=chunk_ids,
indexed=True,
visibility="public",
metadata={
"indexing_time_ms": 0, # TODO: track actual indexing time
"milvus_collection": "documents_v1",
"neo4j_nodes_created": len(chunk_ids),
"embed_model": settings.EMBEDDING_MODEL or "bge-m3@v1"
}
)
logger.info(f"Published rag.document.indexed event for doc_id={doc_id}")
except Exception as e:
logger.error(f"Failed to publish RAG events for doc_id={doc_id}: {e}")
await _publish_events_async(
dao_id=dao_id,
doc_id=doc_id,
written_docs=written_docs,
pages_count=pages_count,
blocks_count=blocks_count,
pipeline_time=pipeline_time
)
return {
"status": "success",
@@ -229,6 +197,51 @@ def _parsed_json_to_documents(
return documents
async def _publish_events_async(
dao_id: str,
doc_id: str,
written_docs: int,
pages_count: int,
blocks_count: int,
pipeline_time: float
):
try:
await publish_document_ingested(
doc_id=doc_id,
team_id=dao_id,
dao_id=dao_id,
chunk_count=written_docs,
indexed=True,
visibility="public",
metadata={
"ingestion_time_ms": round(pipeline_time * 1000),
"embed_model": settings.EMBEDDING_MODEL or "bge-m3@v1",
"pages_processed": pages_count,
"blocks_processed": blocks_count
}
)
logger.info(f"Published rag.document.ingested event for doc_id={doc_id}")
chunk_ids = [f"{doc_id}_chunk_{i+1}" for i in range(written_docs)]
await publish_document_indexed(
doc_id=doc_id,
team_id=dao_id,
dao_id=dao_id,
chunk_ids=chunk_ids,
indexed=True,
visibility="public",
metadata={
"indexing_time_ms": 0,
"milvus_collection": "documents_v1",
"neo4j_nodes_created": len(chunk_ids),
"embed_model": settings.EMBEDDING_MODEL or "bge-m3@v1"
}
)
logger.info(f"Published rag.document.indexed event for doc_id={doc_id}")
except Exception as e:
logger.error(f"Failed to publish RAG events for doc_id={doc_id}: {e}")
def _create_ingest_pipeline() -> Pipeline:
"""
Create Haystack ingest pipeline

View File

@@ -87,7 +87,7 @@ async def ingest_endpoint(request: IngestRequest):
- user_id: Optional user identifier
"""
try:
result = ingest_parsed_document(
result = await ingest_parsed_document(
dao_id=request.dao_id,
doc_id=request.doc_id,
parsed_json=request.parsed_json,

View File

@@ -2,7 +2,7 @@ fastapi>=0.115.0
uvicorn[standard]>=0.30.0
pydantic>=2.0.0
pydantic-settings>=2.0.0
haystack-ai>=2.0.0
farm-haystack[postgresql]>=1.25.3
sentence-transformers>=2.2.0
psycopg2-binary>=2.9.0
httpx>=0.27.0

View File

@@ -1,7 +1,7 @@
FROM python:3.11-slim
# Встановити wget для healthcheck
RUN apt-get update && apt-get install -y --no-install-recommends wget \
RUN apt-get update && apt-get install -y --no-install-recommends wget curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
@@ -25,7 +25,7 @@ EXPOSE 8898
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget -qO- http://localhost:8898/health || exit 1
CMD curl -f http://localhost:8898/health || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8898"]

110
src/api/assignments.ts Normal file
View File

@@ -0,0 +1,110 @@
/**
* Agent Assignments API Client
* Based on: docs/foundation/microdao_Governance_And_Permissions_v1.md
*/
import { apiClient } from './client';
import type {
AgentAssignment,
AgentScope,
AssignmentScope,
AssignmentRole
} from '../types/ontology';
const BASE_URL = '/api/v1/assignments';
export interface CreateAssignmentRequest {
agentId: string;
targetMicrodaoId: string;
scope: AssignmentScope;
role: AssignmentRole | string;
metadata?: Record<string, unknown>;
}
/**
* Create a new agent assignment
*/
export async function createAssignment(
request: CreateAssignmentRequest
): Promise<AgentAssignment> {
const response = await apiClient.post<{ data: AgentAssignment }>(
BASE_URL,
request
);
return response.data.data;
}
/**
* End an agent assignment
*/
export async function endAssignment(assignmentId: string): Promise<void> {
await apiClient.delete(`${BASE_URL}/${assignmentId}`);
}
/**
* Get all active assignments for an agent
*/
export async function getAgentAssignments(
agentId: string
): Promise<AgentAssignment[]> {
const response = await apiClient.get<{ data: AgentAssignment[] }>(
`${BASE_URL}/agent/${agentId}`
);
return response.data.data;
}
/**
* Get all assignments for a MicroDAO
*/
export async function getMicrodaoAssignments(
microdaoId: string
): Promise<AgentAssignment[]> {
const response = await apiClient.get<{ data: AgentAssignment[] }>(
`${BASE_URL}/microdao/${microdaoId}`
);
return response.data.data;
}
/**
* Get all citywide assignments (DAARION108)
*/
export async function getCitywideAssignments(): Promise<AgentAssignment[]> {
const response = await apiClient.get<{ data: AgentAssignment[] }>(
`${BASE_URL}/citywide`
);
return response.data.data;
}
/**
* Get agent's effective scope
*/
export async function getAgentScope(agentId: string): Promise<AgentScope> {
const response = await apiClient.get<{ data: AgentScope }>(
`${BASE_URL}/agent/${agentId}/scope`
);
return response.data.data;
}
/**
* Check if agent has assignment to target
*/
export async function checkAssignment(
agentId: string,
targetMicrodaoId: string
): Promise<boolean> {
const response = await apiClient.get<{ data: { hasAssignment: boolean } }>(
`${BASE_URL}/check`,
{ params: { agentId, targetMicrodaoId } }
);
return response.data.data.hasAssignment;
}
// React Query hooks
export const assignmentKeys = {
all: ['assignments'] as const,
agent: (agentId: string) => [...assignmentKeys.all, 'agent', agentId] as const,
microdao: (microdaoId: string) => [...assignmentKeys.all, 'microdao', microdaoId] as const,
citywide: () => [...assignmentKeys.all, 'citywide'] as const,
scope: (agentId: string) => [...assignmentKeys.all, 'scope', agentId] as const,
};

125
src/api/dais.ts Normal file
View File

@@ -0,0 +1,125 @@
/**
* DAIS API Client
* Based on: docs/foundation/DAARION_Identity_And_Access_Draft_v1.md
*/
import { apiClient } from './client';
import type { DaisProfile, DaisEmail, DaisWallet } from '../types/ontology';
const BASE_URL = '/api/v1/dais';
export interface CreateDaisRequest {
email?: string;
walletAddress?: string;
network?: 'evm' | 'ton' | 'solana';
}
export interface DaisCreationResult {
identity: DaisProfile['identity'];
agentId: string;
matrixHandle: string;
}
/**
* Create a new DAIS identity
*/
export async function createDaisIdentity(
request: CreateDaisRequest
): Promise<DaisCreationResult> {
const response = await apiClient.post<{ data: DaisCreationResult }>(
`${BASE_URL}/identity`,
request
);
return response.data.data;
}
/**
* Get DAIS profile by ID
*/
export async function getDaisProfile(daisId: string): Promise<DaisProfile> {
const response = await apiClient.get<{ data: DaisProfile }>(
`${BASE_URL}/${daisId}`
);
return response.data.data;
}
/**
* Get DAIS profile by agent ID
*/
export async function getDaisByAgent(agentId: string): Promise<DaisProfile> {
const response = await apiClient.get<{ data: DaisProfile }>(
`${BASE_URL}/agent/${agentId}`
);
return response.data.data;
}
/**
* Add email to DAIS
*/
export async function addEmail(
daisId: string,
email: string
): Promise<DaisEmail> {
const response = await apiClient.post<{ data: DaisEmail }>(
`${BASE_URL}/${daisId}/email`,
{ email }
);
return response.data.data;
}
/**
* Verify email with OTP
*/
export async function verifyEmail(
daisId: string,
email: string,
otp: string
): Promise<void> {
await apiClient.post(`${BASE_URL}/${daisId}/email/verify`, { email, otp });
}
/**
* Add wallet to DAIS
*/
export async function addWallet(
daisId: string,
walletAddress: string,
network: 'evm' | 'ton' | 'solana' = 'evm'
): Promise<DaisWallet> {
const response = await apiClient.post<{ data: DaisWallet }>(
`${BASE_URL}/${daisId}/wallet`,
{ walletAddress, network }
);
return response.data.data;
}
/**
* Verify wallet with SIWE signature
*/
export async function verifyWallet(
daisId: string,
walletAddress: string,
signature: string,
message: string
): Promise<void> {
await apiClient.post(`${BASE_URL}/${daisId}/wallet/verify`, {
walletAddress,
signature,
message,
});
}
/**
* Promote to orchestrator
*/
export async function promoteToOrchestrator(daisId: string): Promise<void> {
await apiClient.post(`${BASE_URL}/${daisId}/promote-to-orchestrator`);
}
// React Query hooks
export const daisKeys = {
all: ['dais'] as const,
profile: (id: string) => [...daisKeys.all, 'profile', id] as const,
byAgent: (agentId: string) => [...daisKeys.all, 'byAgent', agentId] as const,
};

View File

@@ -0,0 +1,134 @@
/**
* Agent Assignments Panel Component
* Displays agent's assignments to other MicroDAOs
*/
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { getAgentAssignments, getAgentScope, assignmentKeys } from '../../../api/assignments';
import type { AgentAssignment, AssignmentScope } from '../../../types/ontology';
interface AssignmentsPanelProps {
agentId: string;
}
const scopeColors: Record<AssignmentScope, string> = {
microdao: 'bg-blue-500/20 text-blue-400 border-blue-500/30',
district: 'bg-purple-500/20 text-purple-400 border-purple-500/30',
city: 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30',
};
const scopeLabels: Record<AssignmentScope, string> = {
microdao: 'MicroDAO',
district: 'District',
city: 'City',
};
const roleLabels: Record<string, string> = {
advisor: '💡 Advisor',
security: '🔒 Security',
mentor: '🎓 Mentor',
ops: '⚙️ Ops',
'core-team': '⭐ Core Team',
member: '👤 Member',
};
export function AssignmentsPanel({ agentId }: AssignmentsPanelProps) {
const { data: assignments, isLoading: assignmentsLoading } = useQuery({
queryKey: assignmentKeys.agent(agentId),
queryFn: () => getAgentAssignments(agentId),
});
const { data: scope, isLoading: scopeLoading } = useQuery({
queryKey: assignmentKeys.scope(agentId),
queryFn: () => getAgentScope(agentId),
});
if (assignmentsLoading || scopeLoading) {
return (
<div className="bg-gray-800 rounded-lg p-4 animate-pulse">
<div className="h-4 bg-gray-700 rounded w-3/4 mb-2"></div>
<div className="h-3 bg-gray-700 rounded w-1/2"></div>
</div>
);
}
return (
<div className="bg-gray-800 border border-gray-700 rounded-lg p-4">
<div className="flex items-center justify-between mb-4">
<h3 className="text-white font-medium">Призначення агента</h3>
{scope && (
<span
className={`px-2 py-0.5 rounded-full text-xs border ${
scopeColors[scope.effectiveScope]
}`}
>
Scope: {scopeLabels[scope.effectiveScope]}
</span>
)}
</div>
{/* Home MicroDAO */}
{scope?.homeMicrodaoId && (
<div className="mb-4 p-3 bg-gray-700/50 rounded-lg">
<div className="text-xs text-gray-400 mb-1">Домашня MicroDAO</div>
<div className="text-white font-medium">{scope.homeMicrodaoId}</div>
</div>
)}
{/* Assignments List */}
<div className="space-y-2">
{assignments && assignments.length > 0 ? (
assignments.map((assignment) => (
<AssignmentCard key={assignment.id} assignment={assignment} />
))
) : (
<div className="text-gray-400 text-sm text-center py-4">
Немає активних призначень
</div>
)}
</div>
{/* Add Assignment Button */}
<button className="mt-4 w-full py-2 border border-dashed border-gray-600 rounded-lg text-gray-400 hover:text-gray-300 hover:border-gray-500 transition-colors text-sm">
+ Додати призначення
</button>
</div>
);
}
function AssignmentCard({ assignment }: { assignment: AgentAssignment }) {
return (
<div className="p-3 bg-gray-700/30 rounded-lg border border-gray-600/50 hover:border-gray-500/50 transition-colors">
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<span
className={`px-2 py-0.5 rounded text-xs border ${
scopeColors[assignment.scope]
}`}
>
{scopeLabels[assignment.scope]}
</span>
<span className="text-white font-medium text-sm">
{assignment.targetMicrodaoId}
</span>
</div>
<span className="text-xs text-gray-400">
{roleLabels[assignment.role] || assignment.role}
</span>
</div>
<div className="flex items-center justify-between text-xs text-gray-500">
<span>
Від: {new Date(assignment.startTs).toLocaleDateString('uk-UA')}
</span>
{assignment.endTs && (
<span>
До: {new Date(assignment.endTs).toLocaleDateString('uk-UA')}
</span>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,138 @@
/**
* DAIS Profile Card Component
* Displays DAIS identity information
*/
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { getDaisByAgent, daisKeys } from '../../../api/dais';
import type { DaisProfile, DaisTrustLevel } from '../../../types/ontology';
interface DaisProfileCardProps {
agentId: string;
}
const trustLevelColors: Record<DaisTrustLevel, string> = {
guest: 'bg-gray-500',
agent: 'bg-blue-500',
verified: 'bg-green-500',
orchestrator: 'bg-purple-500',
operator: 'bg-yellow-500',
};
const trustLevelLabels: Record<DaisTrustLevel, string> = {
guest: 'Гість',
agent: 'Агент',
verified: 'Верифікований',
orchestrator: 'Оркестратор',
operator: 'Оператор',
};
export function DaisProfileCard({ agentId }: DaisProfileCardProps) {
const { data: profile, isLoading, error } = useQuery({
queryKey: daisKeys.byAgent(agentId),
queryFn: () => getDaisByAgent(agentId),
retry: false,
});
if (isLoading) {
return (
<div className="bg-gray-800 rounded-lg p-4 animate-pulse">
<div className="h-4 bg-gray-700 rounded w-3/4 mb-2"></div>
<div className="h-3 bg-gray-700 rounded w-1/2"></div>
</div>
);
}
if (error || !profile) {
return (
<div className="bg-gray-800/50 border border-gray-700 rounded-lg p-4">
<p className="text-gray-400 text-sm">DAIS профіль не знайдено</p>
<button className="mt-2 text-blue-400 hover:text-blue-300 text-sm">
+ Створити DAIS ідентичність
</button>
</div>
);
}
return (
<div className="bg-gray-800 border border-gray-700 rounded-lg p-4">
<div className="flex items-center justify-between mb-3">
<h3 className="text-white font-medium">DAIS Ідентичність</h3>
<span
className={`px-2 py-0.5 rounded-full text-xs text-white ${
trustLevelColors[profile.identity.trustLevel]
}`}
>
{trustLevelLabels[profile.identity.trustLevel]}
</span>
</div>
<div className="space-y-2 text-sm">
{/* DID */}
<div className="flex items-center justify-between">
<span className="text-gray-400">DID</span>
<code className="text-gray-300 text-xs bg-gray-700 px-2 py-0.5 rounded">
{profile.identity.did.slice(0, 24)}...
</code>
</div>
{/* Matrix Handle */}
{profile.identity.matrixHandle && (
<div className="flex items-center justify-between">
<span className="text-gray-400">Matrix</span>
<span className="text-green-400">{profile.identity.matrixHandle}</span>
</div>
)}
{/* Emails */}
<div className="mt-3">
<div className="flex items-center justify-between mb-1">
<span className="text-gray-400">Email</span>
<span className="text-gray-500 text-xs">{profile.emails.length}</span>
</div>
{profile.emails.map((email) => (
<div
key={email.id}
className="flex items-center justify-between bg-gray-700/50 px-2 py-1 rounded"
>
<span className="text-gray-300 text-xs">{email.email}</span>
{email.verified ? (
<span className="text-green-400 text-xs"></span>
) : (
<span className="text-yellow-400 text-xs"></span>
)}
</div>
))}
</div>
{/* Wallets */}
<div className="mt-3">
<div className="flex items-center justify-between mb-1">
<span className="text-gray-400">Гаманці</span>
<span className="text-gray-500 text-xs">{profile.wallets.length}</span>
</div>
{profile.wallets.map((wallet) => (
<div
key={wallet.id}
className="flex items-center justify-between bg-gray-700/50 px-2 py-1 rounded"
>
<div className="flex items-center gap-2">
<span className="text-xs text-gray-500 uppercase">{wallet.network}</span>
<span className="text-gray-300 text-xs">
{wallet.walletAddress.slice(0, 6)}...{wallet.walletAddress.slice(-4)}
</span>
</div>
{wallet.verified ? (
<span className="text-green-400 text-xs"></span>
) : (
<span className="text-yellow-400 text-xs"></span>
)}
</div>
))}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,156 @@
/**
* Ontology Badge Components
* Displays badges for MicroDAO type, Node status, Agent role, etc.
*/
import React from 'react';
import type {
MicrodaoType,
NodeStatus,
NodeKind,
AgentRole,
ServiceScope
} from '../../../types/ontology';
// ============================================================================
// MicroDAO Type Badge
// ============================================================================
const microdaoTypeConfig: Record<MicrodaoType, { label: string; color: string; icon: string }> = {
root: { label: 'Root', color: 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30', icon: '🏛️' },
standard: { label: 'Standard', color: 'bg-blue-500/20 text-blue-400 border-blue-500/30', icon: '🏠' },
district: { label: 'District', color: 'bg-purple-500/20 text-purple-400 border-purple-500/30', icon: '🏙️' },
};
export function MicrodaoTypeBadge({ type }: { type: MicrodaoType }) {
const config = microdaoTypeConfig[type];
return (
<span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border ${config.color}`}>
<span>{config.icon}</span>
<span>{config.label}</span>
</span>
);
}
// ============================================================================
// Node Status Badge
// ============================================================================
const nodeStatusConfig: Record<NodeStatus, { label: string; color: string; icon: string }> = {
provisioning: { label: 'Provisioning', color: 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30', icon: '⏳' },
active: { label: 'Active', color: 'bg-green-500/20 text-green-400 border-green-500/30', icon: '✅' },
draining: { label: 'Draining', color: 'bg-orange-500/20 text-orange-400 border-orange-500/30', icon: '🔄' },
retired: { label: 'Retired', color: 'bg-gray-500/20 text-gray-400 border-gray-500/30', icon: '⛔' },
};
export function NodeStatusBadge({ status }: { status: NodeStatus }) {
const config = nodeStatusConfig[status];
return (
<span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border ${config.color}`}>
<span>{config.icon}</span>
<span>{config.label}</span>
</span>
);
}
// ============================================================================
// Node Kind Badge
// ============================================================================
const nodeKindConfig: Record<NodeKind, { label: string; icon: string }> = {
smartphone: { label: 'Smartphone', icon: '📱' },
laptop: { label: 'Laptop', icon: '💻' },
edge: { label: 'Edge', icon: '📡' },
datacenter: { label: 'Datacenter', icon: '🖥️' },
iot: { label: 'IoT', icon: '🔌' },
'gpu-cluster': { label: 'GPU Cluster', icon: '🎮' },
};
export function NodeKindBadge({ kind }: { kind: NodeKind }) {
const config = nodeKindConfig[kind];
return (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs bg-gray-700 text-gray-300 border border-gray-600">
<span>{config.icon}</span>
<span>{config.label}</span>
</span>
);
}
// ============================================================================
// Agent Role Badge
// ============================================================================
const agentRoleConfig: Record<AgentRole, { label: string; color: string; icon: string }> = {
regular: { label: 'Regular', color: 'bg-blue-500/20 text-blue-400 border-blue-500/30', icon: '👤' },
orchestrator: { label: 'Orchestrator', color: 'bg-purple-500/20 text-purple-400 border-purple-500/30', icon: '🎭' },
};
export function AgentRoleBadge({ role }: { role: AgentRole }) {
const config = agentRoleConfig[role];
return (
<span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border ${config.color}`}>
<span>{config.icon}</span>
<span>{config.label}</span>
</span>
);
}
// ============================================================================
// Service Scope Badge
// ============================================================================
const serviceScopeConfig: Record<ServiceScope, { label: string; color: string; icon: string }> = {
microdao: { label: 'MicroDAO', color: 'bg-blue-500/20 text-blue-400 border-blue-500/30', icon: '🏠' },
district: { label: 'District', color: 'bg-purple-500/20 text-purple-400 border-purple-500/30', icon: '🏙️' },
city: { label: 'City', color: 'bg-yellow-500/20 text-yellow-400 border-yellow-500/30', icon: '🌆' },
};
export function ServiceScopeBadge({ scope }: { scope: ServiceScope }) {
const config = serviceScopeConfig[scope];
return (
<span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border ${config.color}`}>
<span>{config.icon}</span>
<span>{config.label}</span>
</span>
);
}
// ============================================================================
// Ontology Hierarchy Display
// ============================================================================
interface OntologyPathProps {
agentName?: string;
microdaoName?: string;
nodeName?: string;
districtName?: string;
}
export function OntologyPath({ agentName, microdaoName, nodeName, districtName }: OntologyPathProps) {
return (
<div className="flex items-center gap-1 text-xs text-gray-400">
{agentName && (
<>
<span className="text-blue-400">👤 {agentName}</span>
<span></span>
</>
)}
{microdaoName && (
<>
<span className="text-purple-400">🏠 {microdaoName}</span>
{(nodeName || districtName) && <span></span>}
</>
)}
{nodeName && (
<>
<span className="text-green-400">🖥 {nodeName}</span>
{districtName && <span></span>}
</>
)}
{districtName && (
<span className="text-yellow-400">🏙 {districtName}</span>
)}
</div>
);
}

239
src/types/ontology.ts Normal file
View File

@@ -0,0 +1,239 @@
/**
* DAARION Ontology Types (Frontend)
* Based on: docs/foundation/DAARION_Ontology_Core_v1.md
*/
// ============================================================================
// AGENT
// ============================================================================
export type AgentRole = 'regular' | 'orchestrator';
export type ServiceScope = 'microdao' | 'district' | 'city';
export interface Agent {
id: string;
name: string;
kind: string;
daisIdentityId?: string;
homeMicrodaoId?: string;
homeNodeId?: string;
role: AgentRole;
serviceScope?: ServiceScope;
isOrchestrator: boolean;
isPublic: boolean;
visibilityScope?: string;
primaryMicrodaoId?: string;
nodeId?: string;
metadata: Record<string, unknown>;
createdAt: string;
updatedAt: string;
}
export type AgentType = 'personal' | 'service' | 'core-city' | 'orchestrator';
// ============================================================================
// DAIS - DAARION Autonomous Identity System
// ============================================================================
export type DaisTrustLevel = 'guest' | 'agent' | 'verified' | 'orchestrator' | 'operator';
export interface DaisIdentity {
id: string;
did: string;
defaultEmail?: string;
defaultWallet?: string;
matrixHandle?: string;
trustLevel: DaisTrustLevel;
metadata: Record<string, unknown>;
createdAt: string;
updatedAt: string;
}
export interface DaisEmail {
id: string;
daisId: string;
email: string;
verified: boolean;
verifiedAt?: string;
createdAt: string;
}
export interface DaisWallet {
id: string;
daisId: string;
walletAddress: string;
network: 'evm' | 'ton' | 'solana';
verified: boolean;
verifiedAt?: string;
createdAt: string;
}
export interface DaisProfile {
identity: DaisIdentity;
emails: DaisEmail[];
wallets: DaisWallet[];
keys: Array<{
id: string;
keyType: string;
publicKey: string;
}>;
}
// ============================================================================
// MICRODAO
// ============================================================================
export type MicrodaoType = 'root' | 'standard' | 'district';
export interface Microdao {
id: string;
slug: string;
name: string;
description?: string;
type: MicrodaoType;
primaryOrchestratorAgentId?: string;
parentMicrodaoId?: string;
walletAddress?: string;
ownerAgentId?: string;
isPlatform: boolean;
isActive: boolean;
isPublic: boolean;
district?: string;
metadata: Record<string, unknown>;
createdAt: string;
updatedAt: string;
}
// ============================================================================
// NODE
// ============================================================================
export type NodeKind =
| 'smartphone'
| 'laptop'
| 'edge'
| 'datacenter'
| 'iot'
| 'gpu-cluster';
export type NodeStatus =
| 'provisioning'
| 'active'
| 'draining'
| 'retired';
export interface NodeCapabilities {
cpu?: string;
ram?: string;
gpu?: {
name: string;
vram?: string;
unified_memory_gb?: number;
};
network?: {
up: string;
down: string;
};
sensors?: string[];
modules?: Array<{
id: string;
status: string;
port?: number;
}>;
}
export interface Node {
id: string;
nodeId: string;
name: string;
microdaoId?: string;
kind: NodeKind;
status: NodeStatus;
capabilities: NodeCapabilities;
lastHeartbeat?: string;
metadata: Record<string, unknown>;
createdAt: string;
updatedAt: string;
}
// ============================================================================
// AGENT ASSIGNMENT
// ============================================================================
export type AssignmentScope = 'microdao' | 'district' | 'city';
export type AssignmentRole = 'advisor' | 'security' | 'mentor' | 'ops' | 'core-team' | 'member';
export interface AgentAssignment {
id: string;
agentId: string;
agentName?: string;
targetMicrodaoId: string;
scope: AssignmentScope;
role: AssignmentRole | string;
startTs: string;
endTs?: string;
metadata: Record<string, unknown>;
createdAt: string;
}
export interface AgentScope {
homeMicrodaoId: string | null;
assignments: AgentAssignment[];
effectiveScope: AssignmentScope;
}
// ============================================================================
// ROOMS LAYER
// ============================================================================
export type RoomType =
| 'city-room'
| 'dao-room'
| 'front-room'
| 'agent-room'
| 'event-room'
| 'district-room';
export type RoomVisibility =
| 'private'
| 'members'
| 'public-city'
| 'public-global';
export type SpaceScope = 'city' | 'microdao' | 'district';
export interface Room {
id: string;
ownerType: 'city' | 'microdao' | 'district' | 'agent';
ownerId: string;
type: RoomType;
spaceScope: SpaceScope;
visibility: RoomVisibility;
name: string;
description?: string;
matrixRoomId?: string;
isPortal: boolean;
portalTargetMicrodaoId?: string;
mapX?: number;
mapY?: number;
zone?: string;
primaryAgentId?: string;
teamAgentIds?: string[];
metadata: Record<string, unknown>;
createdAt: string;
updatedAt: string;
}
// ============================================================================
// ONTOLOGY HIERARCHY DISPLAY
// ============================================================================
export interface OntologyHierarchy {
agent: Agent;
dais?: DaisProfile;
homeMicrodao?: Microdao;
homeNode?: Node;
assignments: AgentAssignment[];
effectiveScope: AssignmentScope;
}