Specul de arhitectura cere Platform Kernel INAINTEA modulelor de domeniu. Modulele A1/A2 au fost construite peste un kernel caruia ii lipseau exact piesele astea. Le adaug acum, aditiv, fara sa rup ce merge. - workspaces: tenant != workspace. Workspace-ul e contextul de lucru DIN tenant. Backfill: fiecare tenant existent primeste workspace implicit, altfel SessionGuard i-ar respinge toate requesturile. - memberships.workspace_id + valid_from/valid_until: rol per workspace si acces delegat cu expirare (contabil pana la o data). SessionGuard respinge membership expirat si membership legat de alt workspace. - ExecutionContext inlocuieste sesiunea subtire (userId+tenantId+role): requestId, correlationId, workspaceId, membershipId, roles, permissions, purpose, timezone, source. Tipul vechi ramane exportat sub acelasi nume, ca sa nu ating ~15 module de domeniu doar pentru o redenumire. - GET /v1/navigation: menu registry mutat in backend. Filtreaza pe rol, tip de workspace, permisiuni si feature flags; intoarce doar itemii autorizati. Ramane UX, nu securitate -- fiecare endpoint verifica din nou. - event envelope: workspace_id, occurred_at, actor_id, aggregate_type, causation_id, classification, provenance - audit envelope: workspace_id, actor_type, purpose, changed_fields, before/after hash, session_id
167 lines
6.9 KiB
TypeScript
167 lines
6.9 KiB
TypeScript
import type { MembershipRole } from '../auth/execution-context';
|
|
|
|
/**
|
|
* MENU REGISTRY -- sursa de adevar pentru Main Navigator, in BACKEND (spec §5).
|
|
* Frontend-ul nu mai decide ce vede userul; primeste doar itemii autorizati de
|
|
* la /v1/navigation. Cea din ceo-web ramane doar ca fallback offline.
|
|
*
|
|
* releaseStage = CAND e planificat (A0..A4). status = daca exista ACUM in cod.
|
|
*/
|
|
export type ReleaseStage = 'A0' | 'A1' | 'A2' | 'A3' | 'A4';
|
|
export type MenuStatus = 'ready' | 'planned';
|
|
export type WorkspaceType = 'personal' | 'family' | 'business' | 'community' | 'project';
|
|
|
|
export interface MenuItem {
|
|
id: string;
|
|
label: string;
|
|
route: string;
|
|
icon: string;
|
|
parentId?: string;
|
|
order: number;
|
|
requiredPermissions: string[];
|
|
allowedWorkspaceTypes: WorkspaceType[];
|
|
allowedRoles?: MembershipRole[];
|
|
featureFlag?: string;
|
|
releaseStage: ReleaseStage;
|
|
status: MenuStatus;
|
|
isEnabled: boolean;
|
|
/** Ce lipseste ca sa devina 'ready'. Afisat in UI pe pagina neconstruita. */
|
|
missing?: string;
|
|
}
|
|
|
|
const ALL: WorkspaceType[] = ['personal', 'family', 'business', 'community', 'project'];
|
|
const B = '/dashboard';
|
|
|
|
/** Sectiunile (parinti). Copiii le refera prin parentId. */
|
|
export const MENU_SECTIONS: MenuItem[] = [
|
|
s('command-center', 'Command Center', 'command', 1, 'A1', ALL),
|
|
s('life-os', 'Life OS', 'life', 2, 'A3', ['personal', 'family']),
|
|
s('business-os', 'Business OS', 'business', 3, 'A1', ['business', 'project']),
|
|
s('documents', 'Documents & Evidence', 'documents', 4, 'A2', ALL),
|
|
s('intelligence', 'Intelligence', 'intelligence', 5, 'A2', ALL),
|
|
s('decisions', 'Decisions & Opportunities', 'decisions', 6, 'A3', ALL),
|
|
s('relationships', 'Relationships & Community', 'relationships', 7, 'A3', ALL),
|
|
s('trust', 'Trust & Reputation', 'trust', 8, 'A4', ALL),
|
|
s('ai', 'AI & Automations', 'ai', 9, 'A2', ALL),
|
|
s('reports', 'Reports', 'reports', 10, 'A2', ALL),
|
|
s('data-intelligence', 'Data Intelligence', 'data', 11, 'A2', ALL, ['owner', 'admin']),
|
|
s('integrations', 'Integrations & Devices', 'integrations', 12, 'A3', ALL, ['owner', 'admin']),
|
|
s('privacy', 'Privacy, Security & Audit', 'privacy', 13, 'A2', ALL),
|
|
s('settings', 'Settings & Administration', 'settings', 14, 'A1', ALL),
|
|
];
|
|
|
|
function s(
|
|
id: string,
|
|
label: string,
|
|
icon: string,
|
|
order: number,
|
|
releaseStage: ReleaseStage,
|
|
allowedWorkspaceTypes: WorkspaceType[],
|
|
allowedRoles?: MembershipRole[],
|
|
): MenuItem {
|
|
return {
|
|
id,
|
|
label,
|
|
route: '',
|
|
icon,
|
|
order,
|
|
requiredPermissions: [],
|
|
allowedWorkspaceTypes,
|
|
allowedRoles,
|
|
releaseStage,
|
|
status: 'planned',
|
|
isEnabled: true,
|
|
};
|
|
}
|
|
|
|
function item(
|
|
id: string,
|
|
parentId: string,
|
|
label: string,
|
|
route: string,
|
|
order: number,
|
|
releaseStage: ReleaseStage,
|
|
status: MenuStatus,
|
|
requiredPermissions: string[],
|
|
extra: Partial<MenuItem> = {},
|
|
): MenuItem {
|
|
return {
|
|
id,
|
|
parentId,
|
|
label,
|
|
route,
|
|
icon: '',
|
|
order,
|
|
requiredPermissions,
|
|
allowedWorkspaceTypes: ALL,
|
|
releaseStage,
|
|
status,
|
|
isEnabled: true,
|
|
...extra,
|
|
};
|
|
}
|
|
|
|
export const MENU_ITEMS: MenuItem[] = [
|
|
// 01 Command Center
|
|
item('cc-overview', 'command-center', 'Executive Overview', B, 1, 'A1', 'ready', ['navigation:read']),
|
|
item('cc-briefing', 'command-center', 'Daily Briefing', `${B}/briefing`, 2, 'A1', 'ready', ['briefing:read']),
|
|
item('cc-priorities', 'command-center', 'Priorities', `${B}/priorities`, 3, 'A2', 'planned', ['briefing:read'], {
|
|
missing: 'Priority Rules Engine determinist; AI doar explica scorul, nu il stabileste.',
|
|
}),
|
|
item('cc-alerts', 'command-center', 'Alerts & Deadlines', `${B}/alerts`, 4, 'A2', 'planned', ['briefing:read'], {
|
|
missing: 'Obiect comun Deadline alimentat din contracte, facturi, documente si aplicatii.',
|
|
}),
|
|
item('cc-approvals', 'command-center', 'Approval Center', `${B}/approvals`, 5, 'A2', 'planned', ['*'], {
|
|
missing: 'Coada de aprobare pentru clasele R3-R5. AI Gateway le blocheaza deja pana exista.',
|
|
}),
|
|
item('cc-activity', 'command-center', 'Activity Timeline', `${B}/activity`, 6, 'A2', 'planned', ['*'], {
|
|
missing: 'Vizualizare peste outbox_events + audit_log, care se populeaza deja.',
|
|
}),
|
|
item('cc-review', 'command-center', 'Daily / Weekly Review', `${B}/review`, 7, 'A2', 'planned', ['briefing:read'], {
|
|
missing: 'Job programat saptamanal + snapshot de review.',
|
|
}),
|
|
|
|
// 03 Business OS (itemii construiti)
|
|
item('bo-organizations', 'business-os', 'Organizations', `${B}/organizations`, 2, 'A1', 'ready', ['organization:read']),
|
|
item('bo-tasks', 'business-os', 'Tasks & Operations', `${B}/tasks`, 6, 'A1', 'ready', ['task:read']),
|
|
item('bo-transactions', 'business-os', 'Transactions', `${B}/transactions`, 8, 'A2', 'planned', ['*'], {
|
|
missing: 'Tabela transactions exista (cu evidence_status); lipsesc /v1/transactions si state machine-ul.',
|
|
}),
|
|
item('bo-accountant', 'business-os', 'Accountant Pack', `${B}/accountant-pack`, 13, 'A2', 'planned', ['*'], {
|
|
missing: 'Export pe perioada + verificare evidence gaps + partajare limitata in timp.',
|
|
}),
|
|
|
|
// 05 Intelligence (itemii construiti)
|
|
item('int-companies', 'intelligence', 'Company Intelligence', `${B}/companies`, 3, 'A2', 'ready', ['intelligence:search']),
|
|
item('int-segments', 'intelligence', 'Saved Segments', `${B}/segments`, 6, 'A2', 'ready', ['segment:read']),
|
|
item('int-research', 'intelligence', 'Research Briefs', `${B}/research`, 7, 'A2', 'ready', ['research_brief:read']),
|
|
item('int-memory', 'intelligence', 'Memory & Knowledge', `${B}/memory`, 11, 'A4', 'planned', ['*'], {
|
|
missing: 'memory-graph (Apache AGE) ruleaza pe server, neconectat la ceo-api.',
|
|
}),
|
|
|
|
// 09 AI & Automations
|
|
item('ai-assistant', 'ai', 'AI Executive Assistant', `${B}/assistant`, 1, 'A2', 'planned', ['*'], {
|
|
missing: 'AI Gateway exista si Hermes ruleaza izolat, dar ceo-api nu expune inca server MCP cu uneltele CEO OS.',
|
|
}),
|
|
item('ai-costs', 'ai', 'Costs & Usage', `${B}/ai/costs`, 9, 'A2', 'planned', ['*'], {
|
|
missing: 'Costurile reale se salveaza deja per cerere in ai_requests.cost_usd; lipseste agregarea.',
|
|
}),
|
|
|
|
// 11 Data Intelligence (doar owner/admin, mostenit de la sectiune)
|
|
item('di-overview', 'data-intelligence', 'Data Overview', `${B}/data`, 1, 'A2', 'planned', ['*'], {
|
|
missing: 'Platforma de date e functionala (Apollo/ClickHouse); lipseste UI-ul de administrare.',
|
|
}),
|
|
|
|
// 13 Privacy
|
|
item('pr-audit', 'privacy', 'Audit Log', `${B}/privacy/audit`, 6, 'A2', 'planned', ['*'], {
|
|
missing: 'audit_log se populeaza la fiecare operatiune materiala; lipseste UI-ul de consultare.',
|
|
}),
|
|
|
|
// 14 Settings
|
|
item('set-workspaces', 'settings', 'Workspaces', `${B}/settings/workspaces`, 3, 'A1', 'planned', ['*'], {
|
|
missing: 'Workspaces exista acum in backend; lipseste UI-ul de administrare si creare.',
|
|
}),
|
|
item('set-members', 'settings', 'Members', `${B}/members`, 4, 'A1', 'ready', ['*'], {
|
|
allowedRoles: ['owner', 'admin'],
|
|
}),
|
|
];
|