{ "$schema": "https://calm.finos.org/release/1.2/meta/calm.json", "metadata": [ { "vexa": { "purpose": "SSOT architecture model: module/service/contract inventory AND the runtime data plane (carriers, ownership, flows, egress boundary). gate:dataflow enforces model<->disk completeness, single-writer + render-only ownership, and a reality diff against code; gate:calm validates it against the FINOS meeting-intelligence pattern.", "principle": "P23 \u2014 one writer per data carrier; readers never re-derive a producer's data; the model covers every module/service/contract (no drift)." } } ], "nodes": [ { "unique-id": "meetings", "node-type": "system", "name": "meetings", "description": "capture \u2192 transcribe \u2192 record; owns the raw transcript", "metadata": [ { "path": "core/meetings" } ] }, { "unique-id": "agent", "node-type": "system", "name": "agent", "description": "the execution domain: a trigger becomes one governed agent turn over a workspace.v1 git repo; owns no transcript", "metadata": [ { "path": "core/agent" } ] }, { "unique-id": "gateway-system", "node-type": "system", "name": "gateway", "description": "the one public edge (api.v1, ws.v1)", "metadata": [ { "path": "core/gateway" } ] }, { "unique-id": "identity", "node-type": "system", "name": "identity", "description": "access + audit; owns the durable DB", "metadata": [ { "path": "core/identity" } ] }, { "unique-id": "runtime-system", "node-type": "system", "name": "runtime", "description": "workload spawn (bot/agent containers)", "metadata": [ { "path": "core/runtime" } ] }, { "unique-id": "deploy", "node-type": "system", "name": "deploy", "description": "deployment + execution-target registry", "metadata": [ { "path": "deploy" } ] }, { "unique-id": "service-authority-system", "node-type": "system", "name": "service authority", "description": "optional operator-owned admission and active-service authority; absent in stock OSS and never owns billing policy inside core" }, { "unique-id": "system-webhook-system", "node-type": "system", "name": "system webhook", "description": "optional operator-owned terminal-event consumer; absent in stock OSS and never selected from customer or meeting data" }, { "unique-id": "agent-api", "node-type": "service", "name": "agent-api", "description": "unit control-plane; dispatch -> runtime spawn; meeting copilot; private account research checkpoints and graph evidence receipts", "metadata": [ { "path": "core/agent/services/agent-api" }, { "path": "core/agent/control_plane" } ], "interfaces": [ { "unique-id": "agent-api-rest", "type": "api" } ] }, { "unique-id": "conformance", "node-type": "service", "name": "conformance", "description": "conformance \u2014 service in gateway", "metadata": [ { "path": "core/gateway/services/conformance" } ] }, { "unique-id": "gateway", "node-type": "service", "name": "gateway", "description": "edge: auth (scopes) + REST routing + WS fan-out", "metadata": [ { "path": "core/gateway/services/gateway" } ], "interfaces": [ { "unique-id": "gateway-rest", "type": "api" }, { "unique-id": "gateway-ws", "type": "websocket" } ] }, { "unique-id": "admin-api", "node-type": "service", "name": "admin-api", "description": "identity: token mint/validate, users, webhooks, and per-user calendar connections", "metadata": [ { "path": "core/identity/services/admin-api" } ], "interfaces": [ { "unique-id": "admin-api-rest", "type": "api" } ] }, { "unique-id": "bot", "node-type": "service", "name": "bot", "description": "spawned-per-meeting worker: join -> capture -> STT -> transcript.v1", "metadata": [ { "path": "core/meetings/services/bot" } ], "interfaces": [ { "unique-id": "bot-commands-sub", "type": "consumer" } ] }, { "unique-id": "transcription", "node-type": "service", "name": "transcription", "description": "transcription \u2014 STT service (faster-whisper / CTranslate2, OpenAI-compatible /v1/audio/transcriptions). The GPU workload, deployed separately from the main stack; the bot streams audio windows to it and receives segments. Does not write any redis carrier (the bot XADDs segments).", "metadata": [ { "path": "core/meetings/services/transcription" } ], "interfaces": [ { "unique-id": "stt-endpoint", "type": "api" } ] }, { "unique-id": "desktop", "node-type": "service", "name": "desktop", "description": "all-in-one dev host: bot+collector+gateway in one process", "metadata": [ { "path": "core/meetings/services/desktop" } ], "interfaces": [ { "unique-id": "desktop-rest", "type": "api" }, { "unique-id": "desktop-ingest-ws", "type": "websocket" } ] }, { "unique-id": "meeting-api", "node-type": "service", "name": "meeting-api", "description": "collector + bot-spawn + recordings + sessions + calendar import/autojoin (the hub); optionally asks an external service authority before spawn and at one-minute active boundaries", "metadata": [ { "path": "core/meetings/services/meeting-api" } ], "interfaces": [ { "unique-id": "meeting-api-rest", "type": "api" } ] }, { "unique-id": "service-authority", "node-type": "service", "name": "external service authority", "description": "optional operator-provided service-authority.v1 endpoint; decides only allow/deny and remains outside the self-hosted core", "interfaces": [ { "unique-id": "service-authority-rest", "type": "api" } ] }, { "unique-id": "system-webhook", "node-type": "service", "name": "operator terminal callback", "description": "optional operator-provided webhook.v1 endpoint for signed meeting.completed and bot.failed service facts", "interfaces": [ { "unique-id": "system-webhook-rest", "type": "api" } ] }, { "unique-id": "mcp", "node-type": "service", "name": "mcp", "description": "MCP tools + prompts over the public API (stateless FastAPI, /mcp mount)", "metadata": [ { "path": "core/gateway/services/mcp" } ], "interfaces": [ { "unique-id": "mcp-http", "type": "api" } ] }, { "unique-id": "buffer", "node-type": "module", "name": "buffer", "description": "buffer \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/buffer" } ] }, { "unique-id": "capture-codec", "node-type": "module", "name": "capture-codec", "description": "capture-codec \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/capture-codec" } ] }, { "unique-id": "gmeet-capture", "node-type": "module", "name": "gmeet-capture", "description": "gmeet-capture \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/gmeet-capture" } ] }, { "unique-id": "gmeet-pipeline", "node-type": "module", "name": "gmeet-pipeline", "description": "Shared channel-routed transcription for browser and native per-participant capture", "metadata": [ { "path": "core/meetings/modules/gmeet-pipeline" } ] }, { "unique-id": "jitsi-capture", "node-type": "module", "name": "jitsi-capture", "description": "jitsi-capture \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/jitsi-capture" } ] }, { "unique-id": "join", "node-type": "module", "name": "join", "description": "join \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/join" } ] }, { "unique-id": "mixed-capture-core", "node-type": "module", "name": "mixed-capture-core", "description": "mixed-capture-core \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/mixed-capture-core" } ] }, { "unique-id": "mixed-pipeline", "node-type": "module", "name": "mixed-pipeline", "description": "mixed-pipeline \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/mixed-pipeline" } ] }, { "unique-id": "no-image-backend", "node-type": "module", "name": "no-image-backend", "description": "no-image-backend \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/no-image-backend" } ] }, { "unique-id": "record-chunker", "node-type": "module", "name": "record-chunker", "description": "record-chunker \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/record-chunker" } ] }, { "unique-id": "recording", "node-type": "module", "name": "recording", "description": "recording \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/recording" } ] }, { "unique-id": "remote-browser", "node-type": "module", "name": "remote-browser", "description": "remote-browser \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/remote-browser" } ] }, { "unique-id": "teams-capture", "node-type": "module", "name": "teams-capture", "description": "teams-capture \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/teams-capture" } ] }, { "unique-id": "whisper", "node-type": "module", "name": "whisper", "description": "whisper \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/whisper" } ] }, { "unique-id": "zoom-capture", "node-type": "module", "name": "zoom-capture", "description": "zoom-capture \u2014 atomic module in meetings", "metadata": [ { "path": "core/meetings/modules/zoom-capture" } ] }, { "unique-id": "event.v1", "node-type": "contract", "name": "event.v1", "description": "event.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/event.v1", "domain": "agent" } ] }, { "unique-id": "invoke.v1", "node-type": "contract", "name": "invoke.v1", "description": "invoke.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/invoke.v1", "domain": "agent" } ] }, { "unique-id": "proactive-card.v1", "node-type": "contract", "name": "proactive-card.v1", "description": "proactive-card.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/proactive-card.v1", "domain": "agent" } ] }, { "unique-id": "blocks.v1", "node-type": "contract", "name": "blocks.v1", "description": "blocks.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/blocks.v1", "domain": "agent" } ] }, { "unique-id": "desktop.v1", "node-type": "contract", "name": "desktop.v1", "description": "desktop.v1 \u2014 the desktop read model: agent-api's DesktopSections (workspaces, presence, calls, placed agents and files) and the composed Desktop the terminal answers per request; nothing stored", "metadata": [ { "path": "core/agent/contracts/desktop.v1", "domain": "agent" } ] }, { "unique-id": "home-card.v1", "node-type": "contract", "name": "home-card.v1", "description": "home-card.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/home-card.v1", "domain": "agent" } ] }, { "unique-id": "home-customer.v1", "node-type": "contract", "name": "home-customer.v1", "description": "home-customer.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/home-customer.v1", "domain": "agent" } ] }, { "unique-id": "routine.v1", "node-type": "contract", "name": "routine.v1", "description": "routine.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/routine.v1", "domain": "agent" } ] }, { "unique-id": "task.v1", "node-type": "contract", "name": "task.v1", "description": "task.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/task.v1", "domain": "agent" } ] }, { "unique-id": "tool.v1", "node-type": "contract", "name": "tool.v1", "description": "tool.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/tool.v1", "domain": "agent" } ] }, { "unique-id": "models.v1", "node-type": "contract", "name": "models.v1", "description": "models.v1 \u2014 sealed/published contract (agent): the operator's model catalog (VEXA_MODEL_CATALOG) and the per-person list agent-api serves the terminal and the MCP", "metadata": [ { "path": "core/agent/contracts/models.v1", "domain": "agent" } ] }, { "unique-id": "unit.v1", "node-type": "contract", "name": "unit.v1", "description": "unit.v1 \u2014 sealed/published contract (agent)", "metadata": [ { "path": "core/agent/contracts/unit.v1", "domain": "agent" } ] }, { "unique-id": "workspace.v1", "node-type": "contract", "name": "workspace.v1", "description": "workspace.v1 \u2014 sealed/published contract (workspaces)", "metadata": [ { "path": "core/workspaces/contracts/workspace.v1", "domain": "workspaces" } ] }, { "unique-id": "api.v1", "node-type": "contract", "name": "api.v1", "description": "api.v1 \u2014 sealed/published contract (gateway)", "metadata": [ { "path": "core/gateway/contracts/api.v1", "domain": "gateway" } ] }, { "unique-id": "logevent.v1", "node-type": "contract", "name": "logevent.v1", "description": "logevent.v1 \u2014 sealed/published contract (gateway)", "metadata": [ { "path": "core/gateway/contracts/logevent.v1", "domain": "gateway" } ] }, { "unique-id": "gateway-identity.v1", "node-type": "contract", "name": "gateway-identity.v1", "description": "gateway-identity.v1 \u2014 sealed/published contract (gateway): the identity the edge resolved, signed onto every forward with the gateway's Ed25519 private key and verified with its public key by agent-api, meeting-api and the credential broker, none of which can sign", "metadata": [ { "path": "core/gateway/contracts/gateway-identity.v1", "domain": "gateway" } ] }, { "unique-id": "subject-ticket.v1", "node-type": "contract", "name": "subject-ticket.v1", "description": "subject-ticket.v1 \u2014 sealed contract (gateway): the producer-signed ticket that binds a flows call made for a person to that person's own event or grant. meeting-api (meetings), agent-api (agent), the flows mail intake (mail) and the gateway (its identity key) each sign with their own Ed25519 key; tickets ride a fact's refs (_tickets) through flows and reach the service door in X-Vexa-Subject-Ticket; the door holds only the public halves (VEXA_SUBJECT_TICKET_KEYS_DIR) and refuses a person-bound call without a ticket for that subject, class and meeting", "metadata": [ { "path": "core/gateway/contracts/subject-ticket.v1", "domain": "gateway" } ] }, { "unique-id": "ws.v1", "node-type": "contract", "name": "ws.v1", "description": "ws.v1 \u2014 sealed/published contract (gateway)", "metadata": [ { "path": "core/gateway/contracts/ws.v1", "domain": "gateway" } ] }, { "unique-id": "identity.v1", "node-type": "contract", "name": "identity.v1", "description": "identity.v1 \u2014 sealed/published contract (identity)", "metadata": [ { "path": "core/identity/contracts/identity.v1", "domain": "identity" } ] }, { "unique-id": "signin.v1", "node-type": "contract", "name": "signin.v1", "description": "signin.v1 \u2014 sealed contract (identity): sign-in admission, the admin claim and the claim-code check between the terminal's server and admin-api; its reason vocabularies are generated into both sides", "metadata": [ { "path": "core/identity/contracts/signin.v1", "domain": "identity" } ] }, { "unique-id": "acts.v1", "node-type": "contract", "name": "acts.v1", "description": "acts.v1 \u2014 sealed/published contract (meetings)", "metadata": [ { "path": "core/meetings/contracts/acts.v1", "domain": "meetings" } ] }, { "unique-id": "captured-signal.v1", "node-type": "contract", "name": "captured-signal.v1", "description": "captured-signal.v1 \u2014 sealed/published contract (meetings)", "metadata": [ { "path": "core/meetings/contracts/captured-signal.v1", "domain": "meetings" } ] }, { "unique-id": "flagged-issue.v1", "node-type": "contract", "name": "flagged-issue.v1", "description": "flagged-issue.v1 \u2014 sealed/published contract (meetings)", "metadata": [ { "path": "core/meetings/contracts/flagged-issue.v1", "domain": "meetings" } ] }, { "unique-id": "invocation.v1", "node-type": "contract", "name": "invocation.v1", "description": "invocation.v1 \u2014 sealed/published contract (meetings)", "metadata": [ { "path": "core/meetings/contracts/invocation.v1", "domain": "meetings" } ] }, { "unique-id": "lifecycle.v1", "node-type": "contract", "name": "lifecycle.v1", "description": "lifecycle.v1 \u2014 sealed/published bot status with producer-observed transition time (meetings)", "metadata": [ { "path": "core/meetings/contracts/lifecycle.v1", "domain": "meetings" } ] }, { "unique-id": "service-authority.v1", "node-type": "contract", "name": "service-authority.v1", "description": "service-authority.v1 \u2014 sealed opt-in admission and active-service decision contract without hosted billing data", "metadata": [ { "path": "core/meetings/contracts/service-authority.v1", "domain": "meetings" } ] }, { "unique-id": "session-profile.v1", "node-type": "contract", "name": "session-profile.v1", "description": "session-profile.v1 \u2014 sealed: what an authenticated bot's stored browser session may hold (the profile, with its size and count limits) and the write-back route and body; remote-browser and meeting-api each read a verbatim copy (gate:fact-parity session-profile-contract) (meetings)", "metadata": [ { "path": "core/meetings/contracts/session-profile.v1", "domain": "meetings" } ] }, { "unique-id": "transcription-language.v1", "node-type": "contract", "name": "transcription-language.v1", "description": "transcription-language.v1 \u2014 sealed: the language a meeting bot transcribes in (auto, forced, restricted to a list), its tiers (meeting, person, deployment) and their precedence, the setting a meeting runs with, and the live change PUT /bots/{platform}/{native_meeting_id}/config; meeting-api and identity read its goldens (meetings)", "metadata": [ { "path": "core/meetings/contracts/transcription-language.v1", "domain": "meetings" } ] }, { "unique-id": "transcript.v1", "node-type": "contract", "name": "transcript.v1", "description": "transcript.v1 \u2014 sealed/published contract (meetings)", "metadata": [ { "path": "core/meetings/contracts/transcript.v1", "domain": "meetings" } ] }, { "unique-id": "webhook.v1", "node-type": "contract", "name": "webhook.v1", "description": "webhook.v1 \u2014 sealed/published delivery including privacy-safe terminal service provenance (meetings)", "metadata": [ { "path": "core/meetings/contracts/webhook.v1", "domain": "meetings" } ] }, { "unique-id": "runtime.v1", "node-type": "contract", "name": "runtime.v1", "description": "runtime.v1 \u2014 sealed/published contract (runtime)", "metadata": [ { "path": "core/runtime/contracts/runtime.v1", "domain": "runtime" } ] }, { "unique-id": "schedule.v1", "node-type": "contract", "name": "schedule.v1", "description": "schedule.v1 \u2014 sealed/published contract (runtime)", "metadata": [ { "path": "core/runtime/contracts/schedule.v1", "domain": "runtime" } ] }, { "unique-id": "execution-targets.v1", "node-type": "contract", "name": "execution-targets.v1", "description": "execution-targets.v1 \u2014 sealed/published contract (deploy)", "metadata": [ { "path": "deploy/contracts/execution-targets.v1", "domain": "deploy" } ] }, { "unique-id": "config.v1", "node-type": "contract", "name": "config.v1", "description": "config.v1 \u2014 sealed/published contract (deploy): per-service deployment-config declaration (required-explicit / defaulted / capability tri-state + live probes), preflight + gate:config-contract (ADR-0026)", "metadata": [ { "path": "deploy/contracts/config.v1", "domain": "deploy" } ] }, { "unique-id": "outbound-url.v1", "node-type": "contract", "name": "outbound-url.v1", "description": "outbound-url.v1 \u2014 sealed/published contract (deploy): may a server fetch a URL somebody else supplied; the canonical ssrf.py vendored into every Python image that does, and the case table the Python and TypeScript guards are held to (ADR-0044)", "metadata": [ { "path": "deploy/contracts/outbound-url.v1", "domain": "deploy" } ] }, { "unique-id": "slim", "node-type": "webclient", "name": "slim", "description": "slim \u2014 client", "metadata": [ { "path": "clients/slim" } ] }, { "unique-id": "extension", "node-type": "webclient", "name": "extension", "description": "extension \u2014 client", "metadata": [ { "path": "clients/extension" } ] }, { "unique-id": "claude-plugin", "node-type": "webclient", "name": "claude-plugin", "description": "claude-plugin \u2014 client (Claude Code plugin: manifest, skills, hosted MCP config; no code)", "metadata": [ { "path": "clients/claude-plugin" } ] }, { "unique-id": "terminal", "node-type": "webclient", "name": "terminal", "description": "terminal \u2014 client", "metadata": [ { "path": "clients/terminal" } ], "controls": { "render-only": { "description": "A reader must not re-derive a producer's data. The terminal renders raw|processed; it must NOT contain a transcript-shaping transform (e.g. clustering).", "requirements": [ { "requirement-url": "calm/controls/render-only.requirement.json", "config": { "control-id": "vexa-p23-render-only", "name": "Render-only consumer", "description": "This consumer renders a producer's data and never re-derives it; gate:dataflow fails on a forbidden transform in its source.", "forbidden-symbols": [ "buildMeetingNotes" ] } } ] } } }, { "unique-id": "segments-stream", "node-type": "data-asset", "name": "transcription_segments (stream)", "description": "durable raw segment feed (transcript.v1); bot XADDs, collector XREADGROUPs Also written, never in a deployment, by the offline eval tools (core/meetings/eval/src/segment_bus.py signs its entries like a bot; core/agent/eval/replay/* bridges), which gate:dataflow does not scan.", "controls": { "ownership": { "description": "single writer", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "bot" ], "match": "transcription_segments", "op": "xadd" } } ] } }, "metadata": [ { "contract": "transcript.v1" }, { "stage": "raw" } ] }, { "unique-id": "tc-mutable", "node-type": "data-asset", "name": "tc:meeting:{id}:mutable (pubsub)", "description": "change-only transcript deltas the gateway + agent-api subscribe to", "controls": { "ownership": { "description": "shared \u2014 review (P23 prefers one writer)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "bot", "meeting-api" ], "match": "tc:meeting:.*:mutable", "op": "publish" } } ] } }, "metadata": [ { "contract": "transcript.v1" }, { "stage": "raw" } ] }, { "unique-id": "tc-stream", "node-type": "data-asset", "name": "tc:meeting:{id} (stream)", "description": "native per-meeting transcript stream the agent worker + terminal SSE read; the collector (meetings) is the single writer (P23) Also written, never in a deployment, by the offline eval replay bridges (core/agent/eval/replay/*), which gate:dataflow does not scan.", "controls": { "ownership": { "description": "single writer", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "tc:meeting:[^:]*$", "op": "xadd" } } ] } }, "metadata": [ { "contract": "transcript.v1" }, { "stage": "raw" } ] }, { "unique-id": "out-stream", "node-type": "data-asset", "name": "unit:{id}:out (stream)", "description": "worker output stream (agent activity / message deltas); agent-api relays as SSE", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-worker" ], "match": "unit:.*:out", "op": "xadd" } } ] } }, "metadata": [ { "contract": "proactive-card.v1" }, { "stage": "cards" } ] }, { "unique-id": "segments-table", "node-type": "database", "name": "transcription_segments (table)", "description": "persisted raw transcript rows", "controls": { "ownership": { "description": "single writer", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "transcription_segments", "op": "db-write" } } ] } }, "metadata": [ { "contract": "transcript.v1" }, { "stage": "raw" } ] }, { "unique-id": "terminal-app", "node-type": "module", "name": "terminal/app", "description": "Next.js routes + SSE proxy (terminal)", "metadata": [ { "path": "clients/terminal/src/app" } ] }, { "unique-id": "terminal-canvas", "node-type": "module", "name": "terminal/canvas", "description": "render engine: kit, runtime, useMeeting, notes (terminal)", "metadata": [ { "path": "clients/terminal/src/canvas" } ] }, { "unique-id": "terminal-contributions", "node-type": "module", "name": "terminal/contributions", "description": "contributed surfaces/commands (terminal)", "metadata": [ { "path": "clients/terminal/src/contributions" } ] }, { "unique-id": "terminal-data", "node-type": "module", "name": "terminal/data", "description": "HTTP data access (terminal): the fail-loud API client, secret redaction and the workspace API; imports only platform", "metadata": [ { "path": "clients/terminal/src/data" } ] }, { "unique-id": "terminal-platform", "node-type": "module", "name": "terminal/platform", "description": "the client substrate (terminal): DI, stores, commands, and the window-event and chat-turn vocabulary the surfaces share; imports no other terminal folder", "metadata": [ { "path": "clients/terminal/src/platform" } ] }, { "unique-id": "terminal-surfaces", "node-type": "module", "name": "terminal/surfaces", "description": "state stores + surfaces (meetingLive, chat, gatewayWS) (terminal)", "metadata": [ { "path": "clients/terminal/src/surfaces" } ] }, { "unique-id": "terminal-ui-kit", "node-type": "module", "name": "terminal/ui-kit", "description": "shared UI primitives (terminal)", "metadata": [ { "path": "clients/terminal/src/ui-kit" } ] }, { "unique-id": "terminal-workbench", "node-type": "module", "name": "terminal/workbench", "description": "dockview workbench shell (terminal)", "metadata": [ { "path": "clients/terminal/src/workbench" } ] }, { "unique-id": "terminal-minutes", "node-type": "module", "name": "terminal/minutes", "description": "the Minutes one-object shell \u2014 every room is a page + a conversation (replaces the workbench in minutes mode)", "metadata": [ { "path": "clients/terminal/src/minutes" } ] }, { "unique-id": "recording-blob", "node-type": "data-asset", "name": "recordings bucket (blob)", "description": "chunked meeting recordings: bot uploads chunks (record-chunker), meeting-api PUTs the stitched master", "controls": { "ownership": { "description": "two writers by design: bot=chunks, meeting-api=master", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "bot", "meeting-api" ] } } ] } }, "metadata": [ { "stage": "audio" } ] }, { "unique-id": "userdata-blob", "node-type": "data-asset", "name": "userdata bucket (blob)", "description": "authenticated-bot browser sessions (the session-profile.v1 subset): remote-browser's provisioning login uploads the signed-in session; the bot restores it before launch with a read-only key pair, and its rotated session comes back on clean teardown through meeting-api, which writes it", "controls": { "ownership": { "description": "two writers by design: remote-browser=provisioning upload, meeting-api=the authenticated bot's session write-back (session_profile); no bot holds a credential that writes it", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "remote-browser", "meeting-api" ] } } ] } }, "metadata": [ { "stage": "session" } ] }, { "unique-id": "runtime", "node-type": "service", "name": "runtime", "description": "runtime.v1 kernel: POST /workloads spawns containers (docker/k8s/process)", "interfaces": [ { "unique-id": "runtime-rest", "type": "api" } ], "metadata": [ { "path": "core/runtime/src" } ] }, { "unique-id": "model-proxy", "node-type": "service", "name": "model-proxy", "description": "the model-provider key proxy (H5/W1): the agent-api image run as `python -m control_plane.model_proxy` (port 8102). An agent worker's harness sends every model request \u2014 and its MCP toolbelt traffic \u2014 here with its turn's token; the proxy checks the token is live (not revoked, not expired), the model in the turn's scope and the turn under its request ceiling, swaps the token for the route's sealed credential (or reads the deployment's subscription file from its own mount), and streams the answer back. Holds no trust header and no key of its own; reachable only from agent workers", "metadata": [ { "path": "core/agent/control_plane/model_proxy.py" } ], "interfaces": [ { "unique-id": "model-proxy-rest", "type": "api" } ] }, { "unique-id": "model-routes", "node-type": "data-asset", "name": "mproxy:route:{id} + mproxy:unit-route:{unit} (redis keys)", "description": "a unit's model route as agent-api resolved it \u2014 endpoint, credential, the turn's models and output cap, the toolbelt URL and delegation token \u2014 AES-GCM sealed with VEXA_MODEL_PROXY_SECRET; the unit's pointer to it. No worker's Redis user can reach either", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "agent-api seals a cold spawn's route (control_plane/model_proxy.py Grants.put_route)", "writers": [ "agent-api" ], "match": "ROUTE_PREFIX", "op": "set" } } ] } } }, { "unique-id": "model-grants", "node-type": "data-asset", "name": "mproxy:grant:{sha256} + mproxy:count:{sha256} (redis keys)", "description": "one turn's token to the model proxy, by digest: its unit, route, expiry and request ceiling; the proxy counts the turn's model requests beside it and deletes both when the worker revokes the token at the end of its last run. No worker's Redis user can reach them", "controls": { "ownership": { "description": "shared writer (P23 review)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "agent-api mints a grant per delivered message; the proxy counts and revokes", "writers": [ "agent-api", "model-proxy" ], "match": "GRANT_PREFIX|COUNT_PREFIX", "op": "kv-write" } } ] } } }, { "unique-id": "llm-unreported-spend", "node-type": "data-asset", "name": "vexa:llm:unreported:{payer}:{unit} + its indexes (redis keys)", "description": "what the model proxy has relayed for a running turn and no worker has reported yet: each relayed call's provider usage, priced at the spend ledger's own table (llm_budget.cost_usd), per payer and unit, with a per-payer and a deployment index. The proxy checks ledger + this figure against the spend caps before every model request; agent-api's usage meter takes each reported amount off it and clears it when the turn completes (recording it when the turn reported nothing). Amounts and ids only; expires after two hours", "controls": { "ownership": { "description": "shared writer (P23 review)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "the model proxy adds each relayed call (llm_budget.add_unreported); agent-api's usage meter settles it against the worker's report (llm_budget.settle_unreported)", "writers": [ "agent-api", "model-proxy" ], "match": "UNREPORTED_PREFIX|_unreported_key|_unreported_index", "op": "kv-write" } } ] } } }, { "unique-id": "agent-worker", "node-type": "service", "name": "agent-worker", "description": "spawned isolated workspace-agent worker; selectable Claude Code or Codex app-server harness; one dispatch turn; every dispatch mounts the ordered [_global, active workspaces, _system] stack, fails closed without _global, and loads its authoritative entry context into the turn", "metadata": [ { "path": "core/agent/worker" } ] }, { "unique-id": "platform", "node-type": "system", "name": "platform", "description": "shared infra backing the services" }, { "unique-id": "redis", "node-type": "service", "name": "redis", "description": "stream + pub/sub broker for the live + durable transcript planes" }, { "unique-id": "postgres", "node-type": "database", "name": "postgres", "description": "durable relational store" }, { "unique-id": "object-store", "node-type": "service", "name": "object-store", "description": "S3-compatible object store for recordings and people's photos (person-photos/): the versitygw storage sidecar in Lite and Compose (plain files in a local volume); the chart's MinIO or the operator's S3 under Helm" }, { "unique-id": "livekit", "node-type": "service", "name": "livekit", "description": "Calls (#1783, ADR-0048 decision 6): the self-hosted LiveKit media server (Apache-2.0, unmodified upstream image pinned by digest), optional: compose profile `calls`, Helm `livekit.enabled`, not in Lite. meeting-api creates every room and its listener; agent-api mints participants' room tokens; browsers publish and subscribe media; the bot joins hidden and subscribe-only" }, { "unique-id": "bm-status", "node-type": "data-asset", "name": "bm:meeting:{id}:status (pubsub)", "description": "bot/meeting status pub/sub; gateway fans out", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "bm:meeting:.*:status", "op": "publish" } } ] } } }, { "unique-id": "u-meetings", "node-type": "data-asset", "name": "u:{user}:meetings (pubsub)", "description": "per-user meeting-status pub/sub; gateway auto-subscribes", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "u:.*:meetings", "op": "publish" } } ] } } }, { "unique-id": "bot-commands", "node-type": "data-asset", "name": "bot_commands:meeting:{id} (pubsub)", "description": "acts.v1 commands (leave/reconfigure/chat_send) to the bot", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "bot_commands:", "op": "publish" } } ] } } }, { "unique-id": "unit-in", "node-type": "data-asset", "name": "unit:{id}:in (stream)", "description": "a warm unit's input stream: agent-api is its only writer and signs every entry with the unit's own key (unit.v1 InputEntry); the worker runs only entries that verify, and agent-api's pending list shows only those", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "unit:.*:in", "op": "xadd" } } ] } }, "metadata": [ { "contract": "unit.v1" } ] }, { "unique-id": "va-chat", "node-type": "data-asset", "name": "va:meeting:{id}:chat (pubsub)", "description": "in-meeting chat as ws.v1 chat_message frames: the collector publishes each captured source:'chat' segment once it is stored; the gateway fans out", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ], "match": "va:meeting:.*:chat", "op": "publish" } } ] } }, "metadata": [ { "contract": "ws.v1" } ] }, { "unique-id": "identity-db", "node-type": "data-asset", "name": "identity (users/api_tokens/orgs)", "description": "users + scoped API tokens + orgs and explicit org memberships (MIGRATION-0008: one org per install; users.org_id is the account's home org)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "admin-api" ] } } ] } } }, { "unique-id": "dashboard", "node-type": "webclient", "name": "dashboard (deprecated)", "description": "dashboard \u2014 DEPRECATED 0.10 web client, shipped as an off-by-default compose/helm option while still load-bearing (#813): the multi-user UI hosted production runs against the 0.12 core via the gateway's hosted-compat surface. External pinned image (vexaai/dashboard), not built from this tree; versions on its own tag, never global.imageTag. Deprecation exit: deleted when the terminal covers the authenticated-session/browser-session flows.", "metadata": [ { "path": "deploy/compose", "external-image": "vexaai/dashboard" } ] }, { "unique-id": "flows", "node-type": "system", "name": "flows", "description": "the reaction engine; owns the reaction row and its effect receipts", "metadata": [ { "path": "core/flows" } ] }, { "unique-id": "flows-engine", "node-type": "module", "name": "flows-engine", "description": "the engine: stdlib-only at module scope \u2014 step implementations and flow definitions are values it receives, never imports", "metadata": [ { "path": "core/flows/src/flows" } ] }, { "unique-id": "flows-api", "node-type": "service", "name": "flows-api", "description": "the flows HTTP surface: fact ingress (/events), the flow registry and lifecycle, the reaction projection, the person-scoped timeline", "metadata": [ { "path": "core/flows/src/flows_integrations" } ], "interfaces": [ { "unique-id": "flows-http", "type": "api" } ] }, { "unique-id": "flows-worker", "node-type": "service", "name": "flows-worker", "description": "the one leased loop; a SKIP LOCKED poll over next_run_at is the only clock consumer \u2014 time is a column, not a scheduler", "metadata": [ { "path": "core/flows/src/flows_worker" } ] }, { "unique-id": "flows-defs", "node-type": "module", "name": "flows-defs", "description": "product behaviour as DATA: each flow is a typed event trigger plus an ordered list of step FUNCTIONS, one registration per version; in-flight reactions keep the version stamped at admission", "metadata": [ { "path": "core/flows/src/flows_defs" } ] }, { "unique-id": "flows-steps", "node-type": "module", "name": "flows-steps", "description": "the step implementations a flow names \u2014 one function per capability, registered by __name__; the real adapters call domain HTTP surfaces and sit OUTSIDE the engine's import graph, and fakes.py mirrors the same names so every fixture runs with zero domains attached", "metadata": [ { "path": "core/flows/src/flows_steps" } ] }, { "unique-id": "flows-schema", "node-type": "module", "name": "flows-schema", "description": "the schema source of truth: declarative SQLAlchemy models from which core/flows/schema.sql is generated (scripts/gen_schema.py, drift-tested); lives outside src/flows so the engine stays stdlib-pure at import", "metadata": [ { "path": "core/flows/src/flows_schema" } ] }, { "unique-id": "flows-sensors", "node-type": "module", "name": "flows-sensors", "description": "sensors turn the outside world into typed events with no model call (ADR-0050): one interface (SensorKind.tick(sensor, cursor) -> changes + next cursor) and one pool that keeps the needed sensors, ticks them under a lease, admits their changes through flows admission and reports their health; it reads providers only through the credential broker, which reads a person's calendar only under a live sensor grant that person issued (credential-broker.v1 /api/sensor-grants), and writes only the sensor table", "metadata": [ { "path": "core/flows/src/flows_sensors" } ] }, { "unique-id": "flows-timeline", "node-type": "module", "name": "flows-timeline", "description": "one person's day in order: the READ back over reactions and effect receipts along the time axis. It admits nothing, claims nothing and writes nothing \u2014 the read model for the timeline and queue surfaces", "metadata": [ { "path": "core/flows/src/flows_timeline" } ] }, { "unique-id": "flows-rows", "node-type": "data-asset", "name": "flows-rows", "description": "the reaction + effect_receipt tables (core/flows/schema.sql); a retry consults the receipt before touching the outside world again. TWO writers: flows-worker runs the steps and stamps the receipts, and flows-api admits facts (POST /events \u2192 admit() \u2192 INSERT INTO reaction) and registers flow versions (INSERT INTO flow_version) in its own process. The friction_occurrence table (the repeat counter behind POST /friction's dedup: one row per subject + tool + normalised reason + UTC hour) is written ONLY by flows-api's POST /friction (flows_integrations/friction_dedup.py) and read by flows-timeline's friction_for_subject" }, { "unique-id": "flows.v1", "node-type": "contract", "name": "flows.v1", "description": "flows.v1 \u2014 the carrier census (flows): one producing domain per event type, with the refs a consumer may rely on and the cardinality it may assume. Read by gate:config-contract (a publish-edge key's carriers must be registered here, owned by that service's domain), by gate:schema and by the flows suite. Unsealed by intent \u2014 see the contract's README", "metadata": [ { "path": "core/flows/contracts/flows.v1", "domain": "flows" } ] }, { "unique-id": "event.v2", "node-type": "contract", "name": "event.v2", "description": "event.v2 \u2014 the sealed fact envelope (PRD 0.13.4 D8, S5): the producer computes a fact's audience (next actor, requester, owner, members, workspace principals) and lifecycle fields only, signed with the producer's own Ed25519 key (each producer holds only its own; flows holds only their public keys) over the envelope, its expiry and the fact it rides on (event type, event id, refs); flows verifies it and admits a flow when its owner is the subject or in the audience", "metadata": [ { "path": "core/flows/contracts/event.v2", "domain": "flows" } ] }, { "unique-id": "flows-delivery", "node-type": "module", "name": "flows-delivery", "description": "the nudge delivery gate (PRD 0.13.4 S6, D15): decides whether a waiting card or room item is nudged outside the Inbox (seen suppresses, idle window, attention budget, working hours), composes template-only bodies and keeps delivery rows and receipts; off unless VEXA_FLOWS_NUDGES=1 and the flows_defs.nudges pack is loaded", "metadata": [ { "path": "core/flows/src/flows_delivery" } ] }, { "unique-id": "credentials-broker", "node-type": "service", "name": "credential-broker", "description": "Connections credential broker (credential-broker.v1, ADR-0040): verifies signed agent/human/git role assertions, owns connection metadata, audit and OAuth state, and uses stored credentials for the caller without returning them to the agent or human roles. Deployed with agent-api (compose, helm); not in Lite", "metadata": [ { "path": "core/agent/services/credential-broker" } ], "interfaces": [ { "unique-id": "credential-broker-rest", "type": "api" } ] }, { "unique-id": "credentials-vault", "node-type": "service", "name": "OpenBao (optional)", "description": "An OpenBao or Vault KV v2 mount the operator runs, selected with VEXA_CONNECTIONS_STORE=openbao; broker-only access. Not shipped by the chart or compose: without it the broker keeps credentials in credentials-store" }, { "unique-id": "credential-broker.v1", "node-type": "contract", "name": "credential-broker.v1", "description": "credential-broker.v1 \u2014 sealed/published contract (agent): the signed role assertion and every broker route body", "metadata": [ { "path": "core/agent/contracts/credential-broker.v1", "domain": "agent" } ] }, { "unique-id": "credentials-store", "node-type": "data-asset", "name": "broker state (metadata.sqlite, secrets.sqlite)", "description": "connection metadata, audit, OAuth state and (default backend) AES-256-GCM credential versions on the broker's own volume; ciphertext only, the key is a secret mounted beside it", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "credentials-broker" ] } } ] } } }, { "unique-id": "sdk-join.v1", "node-type": "contract", "name": "sdk-join.v1", "description": "Versioned joining worker IPC", "metadata": [ { "path": "core/meetings/contracts/sdk-join.v1", "domain": "meetings" } ] }, { "unique-id": "zoom-sdk-capture", "node-type": "module", "name": "zoom-sdk-capture", "description": "Native audio to shared capture contract; no meeting lifecycle", "metadata": [ { "path": "core/meetings/modules/zoom-sdk-capture" } ] }, { "unique-id": "sdk-capture.v1", "node-type": "contract", "name": "sdk-capture.v1", "description": "Native capture IPC", "metadata": [ { "path": "core/meetings/contracts/sdk-capture.v1", "domain": "meetings" } ] }, { "unique-id": "delegation.v1", "node-type": "contract", "name": "delegation.v1", "description": "delegation.v1 \u2014 sealed contract (identity): the per-dispatch vxd_ token agent-api mints for a worker and identity verifies at /internal/validate; one Python minter/verifier vendored byte for byte into both", "metadata": [ { "path": "core/identity/contracts/delegation.v1", "domain": "identity" } ] }, { "unique-id": "imports-status", "node-type": "data-asset", "name": "/.imports/{subject}/ (files)", "description": "a repository import's status records, one JSON file per import, written atomically under the workspace store but outside every workspace mount (control_plane/workspace_import.py); agent-api writes and reads them, no worker sees them", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } } }, { "unique-id": "onboarding-research-state", "node-type": "data-asset", "name": "/.onboarding-research/{sha256(workspace)}/ (files)", "description": "onboarding research checkpoints for one workspace (state.json under a file lock), beside the workspace and outside its Git graph so nothing reaches a push (control_plane/onboarding_research.py); agent-api is the only writer", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } } }, { "unique-id": "rail-order", "node-type": "data-asset", "name": "agent:rail-order:{subject} (redis key)", "description": "the order of a person's chat rail, a JSON list (control_plane/api_shared.py rail_order); agent-api writes and reads it, in memory when there is no redis", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } } }, { "unique-id": "rail-marks", "node-type": "data-asset", "name": "agent:rail-marks:{subject} (redis hash)", "description": "a person's pins and hides on their own chat rail, one field per mark (p:, h:) (control_plane/api_shared.py rail_marks, mark_row); agent-api writes and reads it, in memory when there is no redis. A mark on a shared meeting is the viewer's own and never the owner's", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "_marks_key", "op": "kv-write" } } ] } } }, { "unique-id": "signin-link-redeemed", "node-type": "data-asset", "name": "vexa:signin-link:redeemed:{jti} (redis key)", "description": "the one-use record of an emailed sign-in link (app/signin_links.py): admin-api sets it with NX when a terminal redeems the link and keeps it until the link would have expired, so a link signs in once across every terminal replica and restart", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "admin-api" ] } } ] } } }, { "unique-id": "workspaces-system", "node-type": "system", "name": "workspaces", "description": "the workspace domain: a person's git repo of durable memory and the contract that addresses it; hosted as a library inside agent, with no runtime of its own (P10)", "metadata": [ { "path": "core/workspaces" } ] }, { "unique-id": "redis-acl-users", "node-type": "data-asset", "name": "Redis ACL users (vexa-unit-*, vexa-bot-*)", "description": "the Redis server's ACL table: agent-api defines one user per agent-worker unit (vexa-unit-*, its unit's four keys: unit:{id}:in and unit:{id}:delegation read-only, unit:{id}:out and unit:{id}:cursor read-write) and meeting-api one per bot session (vexa-bot-*, the segment stream and its meeting's two channels), each removed at the end and swept by age; a restart of Redis is answered by defining them again. Two writers, one each per user-name prefix; with REDIS_WORKLOAD_ACL=shared neither writes", "controls": { "ownership": { "description": "shared writer (P23: one per user, see description)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api", "meeting-api" ] } } ] } } }, { "unique-id": "acl-units-index", "node-type": "data-asset", "name": "vexa:acl:units (redis hash)", "description": "agent-api's index of the worker users it defined: user name -> unit id and grant time; drives the sweep and the restore", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } } }, { "unique-id": "delegation-revoked", "node-type": "data-asset", "name": "vexa:delegation:revoked:{jti} (redis key)", "description": "a revoked delegation token, kept as long as the token would have lived: agent-api writes it when the token's unit ends (control_plane/delegation_revocation.py); identity (admin-api) reads it for every verified vxd_ bearer and refuses the token, and answers 503 while it cannot read the store. The key name is held on both sides by fact delegation-revocation-key (ADR-0045)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "vexa:delegation:revoked:|revoked_key\\(", "op": "set" } } ] } }, "metadata": [ { "contract": "delegation.v1" } ] }, { "unique-id": "session-store", "node-type": "data-asset", "name": "sessions: metadata in agent-api's database, transcript versions in object storage", "description": "ADR-0048: a conversation stored apart from workspaces. Session rows, participants and roles, unaddressed messages and the head version live in agent-api's own database (agent_session*, control_plane/session_store.py); each turn's transcript is one immutable object in object storage. agent-api is the only writer: a worker hands the conversation back on its own output stream (session-bundle) and agent-api saves it only while its base is the head", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "agent_session", "op": "db-write" } } ] } } }, { "unique-id": "delegation-live", "node-type": "data-asset", "name": "vexa:delegation:live:{jti} (redis key)", "description": "the positive record of a delegation token agent-api handed out and has not revoked: written when the token is recorded (before the spawn, and at each refresh), deleted when it is revoked, expiring with the token (control_plane/delegation_revocation.py); identity (admin-api) admits a verified vxd_ bearer only while this key exists and no revocation of it does, so a record the store evicted or never held refuses the token. The key name is held on both sides by fact delegation-live-key (ADR-0045)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "vexa:delegation:live:|live_key\\(", "op": "set" } } ] } }, "metadata": [ { "contract": "delegation.v1" } ] }, { "unique-id": "delegation-records", "node-type": "data-asset", "name": "vexa:delegation:units + vexa:delegation:unit:{id} (redis set + hash)", "description": "agent-api's record of the delegation tokens each unit holds (jti -> exp and mint time), written before the spawn and at each refresh, read by the reaper that revokes them when the unit ends (control_plane/delegation_revocation.py)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "UNITS_KEY|unit_key\\(", "op": "kv-write" } } ] } } }, { "unique-id": "delegation-current", "node-type": "data-asset", "name": "vexa:delegation:current:{id} (redis key)", "description": "the token a live unit currently holds, as agent-api minted it; the half-life refresh re-mints from it (control_plane/delegation_refresh.py). No worker's Redis user can reach it", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "CURRENT_PREFIX", "op": "set" } } ] } } }, { "unique-id": "unit-delegation", "node-type": "data-asset", "name": "unit:{id}:delegation (redis key)", "description": "a live unit's current delegation token, published by agent-api at dispatch and at each half-life refresh; the worker reads it before every turn, write-back and job and rewrites its MCP attachment (worker/engine.py DelegationRefresh). Its Redis user may read it and not write it (%R~). A credential delivered through Redis after boot: the P7 departure ADR-0045 records", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "delegation_key\\(", "op": "set" } } ] } }, "metadata": [ { "contract": "delegation.v1" } ] }, { "unique-id": "unit-fault", "node-type": "data-asset", "name": "unit:{id}:fault (redis key)", "description": "the typed fault that stopped a unit's spawn (the runtime refused it, or could not be reached), recorded by agent-api and read back by agent-api's SSE relay and pending list; cleared by the next spawn, and never written on the unit's out-stream (control_plane/unit_faults.py)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ], "match": "fault_key\\(", "op": "set" } } ] } } }, { "unique-id": "acl-bots-index", "node-type": "data-asset", "name": "vexa:acl:bots (redis hash)", "description": "meeting-api's index of the bot users it defined: user name -> session, meeting and grant time; drives the sweep and the restore", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ] } } ] } } }, { "unique-id": "routine-state", "node-type": "data-asset", "name": "/.routines/ (files)", "description": "routine state outside every workspace mount: approvals/.json (the sha-256 of each routine's bytes a person stood behind; only those arm) and dispatch-signature.v1.json (the one-time re-signing marker); agent-api is the only writer (workspace_routines.py, routine_resign.py)", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } } }, { "unique-id": "routes.v1", "node-type": "contract", "name": "routes.v1", "description": "routes.v1 \u2014 sealed contract (gateway): each domain's routes.v1.json, the routes it asks the edge to serve and each row's scopes and policy (delegation, mcp_reentry, stream, forward), and the verbs rows behind a forward that the domain's own service reads (person: agent-api's route_policy); the gateway assembles its table from them, and validate.mjs holds every manifest in the repo", "metadata": [ { "path": "core/gateway/contracts/routes.v1", "domain": "gateway" } ] }, { "unique-id": "mcp.tools.v1", "node-type": "contract", "name": "mcp.tools.v1", "description": "mcp.tools.v1 \u2014 sealed contract (gateway): each domain's MCP tool manifest, served at /.well-known/mcp-tools.json or mounted by a private deployment; who may call each tool, which credential the edge presents to its door, and its route", "metadata": [ { "path": "core/gateway/contracts/mcp.tools.v1", "domain": "gateway" } ] }, { "unique-id": "meeting-bundle.v1", "node-type": "contract", "name": "meeting-bundle.v1", "description": "meeting-bundle.v1 \u2014 sealed/published contract (deploy): one meeting as a portable zip that any separate Vexa deployment can import (manifest with a SHA-256 per file; meeting, transcript and annotations parts; optional media and workspace parts); nothing deployment-bound is carried; its goldens include malicious bundles the Python importer and the Node re-derivation must both refuse with the same code", "metadata": [ { "path": "deploy/contracts/meeting-bundle.v1", "domain": "deploy" } ] }, { "unique-id": "meeting-bundle-file", "node-type": "data-asset", "name": "meeting bundle (portable file)", "description": "a meeting exported as one meeting-bundle.v1 zip: written by meeting-api's export for the meeting's owner, read by meeting-api's import on this or another deployment as a new meeting the importer owns; the person carries the file between them", "controls": { "ownership": { "description": "single writer: meeting-api's exporter", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "meeting-api" ] } } ] } }, "metadata": [ { "contract": "meeting-bundle.v1" } ] }, { "unique-id": "meeting-bundle-parts", "node-type": "data-asset", "name": "meeting bundle parts (workspace tree + notes page)", "description": "the agent domain's half of a meeting-bundle.v1 export: the bound workspace's tree and the meeting's page on the owner's desk, as one zip agent-api writes for the owner's client, which hands it to meeting-api's POST /meetings/{meeting_id}/export to place in the bundle", "controls": { "ownership": { "description": "single writer: agent-api", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "agent-api" ] } } ] } }, "metadata": [ { "contract": "meeting-bundle.v1" } ] }, { "unique-id": "crm", "node-type": "system", "name": "crm", "description": "ADR-0047: the optional CRM \u2014 the organisation's stable entities beside workspaces; owns the crm_* tables", "metadata": [ { "path": "core/crm" } ] }, { "unique-id": "crm-api", "node-type": "service", "name": "crm-api", "description": "ADR-0047: the CRM's one door \u2014 people, companies, deals and projects with typed fields, owner, relationships, proposals and review, workspace bindings with derived grants, and backlinks from workspace pages. Every caller is resolved by identity; the record domain behind the crm_* tools", "metadata": [ { "path": "core/crm/src/crm" } ], "interfaces": [ { "unique-id": "crm-http", "type": "api" } ] }, { "unique-id": "crm.v1", "node-type": "contract", "name": "crm.v1", "description": "crm.v1 \u2014 the CRM's wire: the record a read answers, the references snapshot a workspace commit carries, change and binding results, the typed refusals, and the desk (Desk, DeskLayout, DeskOp, DeskProposal, ArrangeResult)", "metadata": [ { "path": "core/crm/contracts/crm.v1", "domain": "crm" } ] }, { "unique-id": "crm-records", "node-type": "data-asset", "name": "crm_* tables", "description": "ADR-0047: records, revisions, proposals, match identifiers, page references, workspace rosters and bindings, the audit, the desk (crm_desk placements, append-only crm_desk_layouts arrangement versions, crm_desk_proposals) and cards (records of an x-card type; crm_card_members; crm_card_seen, each person's opened marker; a workspace's board is its bindings; a proposed card is a change proposal with no record yet), in the instance's Postgres, reached as the CRM's own role. crm-api is the only runtime writer; the migrations path (crm-init) writes definitions and the organisation", "controls": { "ownership": { "description": "single writer (P23)", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "crm-api" ], "match": "crm_", "op": "db-write" } } ] } } }, { "unique-id": "signals", "node-type": "system", "name": "signals", "description": "transcript signals: a small company-chosen model listens to live sources (a meeting's verified transcript first) against the listening brief the meeting's agent wrote, and wakes the agent through the company's flow; owns the sig:* keys", "metadata": [ { "path": "core/signals" } ] }, { "unique-id": "signals-service", "node-type": "service", "name": "signals", "description": "one asyncio process, one task per live source under a lease: reads confirmed lines from the verified feed, scores each batch with the signal model (jev or openai-compatible) against the brief, writes annotations, posts meeting.signal when the running score, an address to Vexa, max_wait or the end says so; caps on wakes and model cost per source checked before every call; off unless the company policy turns it on", "metadata": [ { "path": "core/signals/src/meeting_signals" } ], "interfaces": [ { "unique-id": "signals-health", "type": "api" } ] }, { "unique-id": "signals.v1", "node-type": "contract", "name": "signals.v1", "description": "signals.v1 \u2014 the brief signals reads, the annotation it writes (sig:{kind}:{id}), the wake data it hands to flows and the model_signals policy value", "metadata": [ { "path": "core/signals/contracts/signals.v1", "domain": "signals" } ] }, { "unique-id": "sig-annotations", "node-type": "data-asset", "name": "sig:meeting:{row} | sig:chat:{session} (streams)", "description": "one scored line per entry (signals.v1 Annotation, `payload` JSON): segment id, score per brief label, model, brief version; read by the gateway for the terminal's highlights. signals is the only writer, fenced by its lease", "controls": { "ownership": { "description": "single writer", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "signals-service" ], "match": "sig:(meeting|chat):", "op": "xadd" } } ] } }, "metadata": [ { "contract": "signals.v1" }, { "stage": "derived" } ] }, { "unique-id": "signals-state", "node-type": "data-asset", "name": "sig:state|seen|lease|live:*", "description": "signals' own memory per source: the buffer, running score, saved position, caps' counters and a saved-but-unconfirmed wake (sig:state), the segment ids already scored (sig:seen), which instance holds the source (sig:lease) and the sources with recent activity (sig:live*). Written only by signals; every state write is one MULTI under WATCH of the lease", "controls": { "ownership": { "description": "single writer", "requirements": [ { "requirement-url": "calm/controls/single-writer.requirement.json", "config": { "control-id": "vexa-p23-single-writer", "name": "Single-writer ownership", "description": "The producers allowed to write this carrier; gate:dataflow holds the code to this set.", "writers": [ "signals-service" ], "match": "sig:(state|seen|lease|live)", "op": "kv-write" } } ] } }, "metadata": [ { "contract": "signals.v1" }, { "stage": "state" } ] }, { "unique-id": "signal-model", "node-type": "service", "name": "signal model", "description": "the company's signal model: Typesafe Jev (directly or through OpenRouter) or any OpenAI-compatible endpoint (a company's own LiteLLM). Chosen in _global/POLICIES.md model_signals; none by default", "interfaces": [ { "unique-id": "signal-model-endpoint", "type": "api" } ] }, { "unique-id": "model-provider", "node-type": "service", "name": "model provider", "description": "the LLM endpoint an agent turn calls: the deployment's configured gateway, api.anthropic.com, openrouter.ai, or a subject's custom endpoint. A custom endpoint must be on VEXA_MODEL_BASE_URL_ALLOW and always carries the subject's own credential (core/agent/control_plane/model_endpoint.py); a company's own OpenAI-compatible gateway keeps the turn inside", "interfaces": [ { "unique-id": "model-provider-endpoint", "type": "api" } ] }, { "unique-id": "customer-webhook", "node-type": "service", "name": "customer webhook", "description": "a subscriber URL a customer registers for webhook.v1 deliveries (meeting.*, bot.failed, recording.ready, transcription.ready). Every delivery passes the outbound URL guard (core/meetings/services/meeting-api/src/meeting_api/webhooks/ssrf.py): the host is resolved, every address is checked against the refused ranges, and the connection is pinned to the checked address", "interfaces": [ { "unique-id": "customer-webhook-endpoint", "type": "api" } ] } ], "relationships": [ { "unique-id": "agent-composed", "relationship-type": { "composed-of": { "container": "agent", "nodes": [ "agent-api", "event.v1", "invoke.v1", "proactive-card.v1", "blocks.v1", "desktop.v1", "home-card.v1", "home-customer.v1", "routine.v1", "task.v1", "tool.v1", "models.v1", "unit.v1", "credential-broker.v1", "credentials-broker", "credentials-store", "agent-worker", "model-grants", "model-routes", "model-proxy", "out-stream", "unit-in", "va-chat", "imports-status", "onboarding-research-state", "rail-order", "rail-marks", "redis-acl-users", "acl-units-index", "routine-state", "delegation-revoked", "delegation-live", "delegation-records", "delegation-current", "unit-delegation", "unit-fault", "session-store" ] } } }, { "unique-id": "gateway-composed", "relationship-type": { "composed-of": { "container": "gateway-system", "nodes": [ "conformance", "gateway", "api.v1", "logevent.v1", "gateway-identity.v1", "subject-ticket.v1", "ws.v1", "routes.v1", "mcp", "mcp.tools.v1" ] } } }, { "unique-id": "identity-composed", "relationship-type": { "composed-of": { "container": "identity", "nodes": [ "admin-api", "identity.v1", "signin.v1", "identity-db", "delegation.v1", "signin-link-redeemed" ] } } }, { "unique-id": "meetings-composed", "relationship-type": { "composed-of": { "container": "meetings", "nodes": [ "bot", "desktop", "meeting-api", "buffer", "capture-codec", "gmeet-capture", "gmeet-pipeline", "jitsi-capture", "join", "mixed-capture-core", "mixed-pipeline", "no-image-backend", "record-chunker", "recording", "remote-browser", "teams-capture", "whisper", "zoom-capture", "acts.v1", "captured-signal.v1", "flagged-issue.v1", "invocation.v1", "lifecycle.v1", "service-authority.v1", "session-profile.v1", "transcription-language.v1", "transcript.v1", "webhook.v1", "transcription", "segments-stream", "tc-stream", "tc-mutable", "bm-status", "u-meetings", "bot-commands", "segments-table", "recording-blob", "userdata-blob", "sdk-join.v1", "zoom-sdk-capture", "sdk-capture.v1", "acl-bots-index", "meeting-bundle-file", "meeting-bundle-parts" ] } } }, { "unique-id": "service-authority-composed", "relationship-type": { "composed-of": { "container": "service-authority-system", "nodes": [ "service-authority" ] } } }, { "unique-id": "system-webhook-composed", "relationship-type": { "composed-of": { "container": "system-webhook-system", "nodes": [ "system-webhook" ] } } }, { "unique-id": "runtime-composed", "relationship-type": { "composed-of": { "container": "runtime-system", "nodes": [ "runtime.v1", "schedule.v1", "runtime" ] } } }, { "unique-id": "bot-writes-segments-stream", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "segments-stream" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "bot-publishes-mutable", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "tc-mutable" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "collector-reads-segments", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "segments-stream" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "collector-publishes-mutable", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "tc-mutable" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "collector-writes-table", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "segments-table" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "collector-writes-tc", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "tc-stream" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "agent-reads-tc", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "tc-stream" } } }, "metadata": [ { "access": "read" } ], "description": "the transcription watcher's only action feed (a segment registers the meeting, session_end ends it), and the live view agent-api relays (/api/meeting/stream); the collector writes it only for entries it admitted (transcript.v1 FeedEntry)" }, { "unique-id": "gateway-reads-mutable", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "tc-mutable" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "terminal-reads-tc", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "tc-stream" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "terminal-reads-out", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "out-stream" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "terminal-composed", "relationship-type": { "composed-of": { "container": "terminal", "nodes": [ "terminal-app", "terminal-canvas", "terminal-contributions", "terminal-data", "terminal-minutes", "terminal-platform", "terminal-surfaces", "terminal-ui-kit", "terminal-workbench" ] } } }, { "unique-id": "bot-writes-recording", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "recording-blob" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "bot-userdata", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "userdata-blob" } } }, "description": "restore the stored session before launch, with the bots' read-only key pair (BOT_S3_*: Get + List on the userdata prefix and nothing else); the bot never writes the store \u2014 its rotated session goes back through meeting-api (bot-session-writeback)", "protocol": "HTTPS", "metadata": [ { "access": "read" } ] }, { "unique-id": "bot-session-writeback", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "an authenticated bot's rotated browser session, on clean teardown: session-profile.v1's route, PUT /internal/browser-session/{session_uid}, at the URL meeting-api names in the bot's invocation (invocation.v1 sessionWritebackUrl, sent only in authenticated mode; the bot derives none), with Authorization: Bearer (the invocation.v1 session token) admitted for exactly that session_uid, and only from the live authenticated bot \u2014 the newest session spawned on the deployment's identity, of the token's meeting, live or ended under 600 s; anything else is refused (401/403). Carrier: a session-profile.v1 WritebackBody {files: [{path, data (base64)}]} whose every path is one the contract's SessionProfile names, size-bounded per file and in total; remote-browser and meeting-api each read a verbatim copy of the contract", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "ma-session-writeback-userdata", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "userdata-blob" } } }, "description": "stores an admitted session write-back with meeting-api's own storage credentials (S3_*, else MINIO_*) at BOT_S3_ENDPOINT / BOT_S3_BUCKET under BOT_USERDATA_S3_PATH; the bots' key pair stays read-only", "protocol": "HTTPS", "metadata": [ { "access": "write" } ] }, { "unique-id": "remote-browser-userdata", "relationship-type": { "connects": { "source": { "node": "remote-browser" }, "destination": { "node": "userdata-blob" } } }, "description": "provisioning login uploads the confirmed signed-in session", "protocol": "HTTPS", "metadata": [ { "access": "write" } ] }, { "unique-id": "gateway-reads-recording", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "recording-blob" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "platform-composed", "relationship-type": { "composed-of": { "container": "platform", "nodes": [ "redis", "postgres", "object-store", "livekit" ] } } }, { "unique-id": "workers-deployed", "description": "bot + agent-worker are runtime.v1 workloads", "relationship-type": { "deployed-in": { "container": "runtime", "nodes": [ "bot", "agent-worker" ] } } }, { "unique-id": "bot-stt", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "transcription", "interface": "stt-endpoint" } } }, "description": "audio -> first-party STT via TRANSCRIPTION_SERVICE_URL", "protocol": "HTTPS", "metadata": [ { "access": "call" } ], "controls": { "data-egress": { "description": "STT is first-party and self-hostable; default destination is tenant-hosted, so audio need not leave the tenant", "requirements": [ { "requirement-url": "calm/controls/no-egress.requirement.json", "config": { "control-id": "vexa-no-egress", "name": "Tenant data egress", "description": "The posture of tenant data on this edge: where it goes and whether leaving the tenant is approved.", "dataClass": "audio", "destination": "tenant-hosted", "egressApproved": true } } ] } } }, { "unique-id": "bot-commands-read", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "bot-commands" } } }, "description": "SUBSCRIBE acts.v1 commands", "metadata": [ { "access": "read" } ] }, { "unique-id": "ma-status", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "bm-status" } } }, "description": "PUBLISH status", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-umeetings", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "u-meetings" } } }, "description": "PUBLISH per-user status", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-commands", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "bot-commands" } } }, "description": "PUBLISH leave/reconfigure/chat_send", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-recording", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "recording-blob" } } }, "description": "S3 PUT stitched master", "protocol": "HTTPS", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-pg", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "postgres" } } }, "protocol": "JDBC", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-object-store", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "object-store" } } }, "protocol": "HTTPS", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-livekit", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "livekit" } } }, "protocol": "HTTP", "metadata": [ { "access": "write" } ], "description": "creates a call's room with its transcription notice (Twirp room service)" }, { "unique-id": "ma-stt-model", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "transcription", "interface": "stt-endpoint" } } }, "protocol": "HTTPS", "metadata": [ { "access": "read" } ], "description": "asks a deployment-owned STT backend which model it serves (GET /health -> model, cached 5 min) to answer GET /transcription/languages; a customer's own endpoint is never called" }, { "unique-id": "aa-livekit", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "livekit" } } }, "protocol": "HTTP", "metadata": [ { "access": "read" } ], "description": "reads a room's metadata to bind a call to its session" }, { "unique-id": "bot-livekit", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "livekit" } } }, "protocol": "WebSocket", "metadata": [ { "access": "read" } ], "description": "the call listener: joins hidden and subscribe-only, and transcribes every audio track each participant publishes, on that participant's channel" }, { "unique-id": "terminal-livekit", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "livekit" } } }, "protocol": "WebSocket", "metadata": [ { "access": "write" } ], "description": "the terminal's page in a person's browser joins a call itself, not the terminal server (signalling over WebSocket; media over the UDP range)" }, { "unique-id": "aa-object-store", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "object-store" } } }, "protocol": "HTTPS", "metadata": [ { "access": "write", "description": "ADR-0048: session transcript versions (session-store)" } ] }, { "unique-id": "admin-object-store", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "object-store" } } }, "protocol": "HTTPS", "metadata": [ { "access": "write", "description": "people's photos (UI 15g): re-encoded image bytes under person-photos// in the recordings bucket; the person_photos row in identity-db keeps the key; admin-api is the prefix's one writer and deletes it with the person" } ] }, { "unique-id": "aa-postgres", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "postgres" } } }, "protocol": "JDBC", "metadata": [ { "access": "write", "description": "ADR-0048: session metadata, participants and heads (session-store)" } ] }, { "unique-id": "ma-runtime", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "runtime", "interface": "runtime-rest" } } }, "description": "meeting-api drives the kernel with Authorization: Bearer RUNTIME_API_TOKEN (runtime.v1 CallerCredential): POST /workloads to spawn a bot, GET /workloads/{id} to read it and DELETE /workloads/{id} to tear it down; its RuntimeEvents come back signed on rt-ma", "protocol": "HTTPS" }, { "unique-id": "ma-admin-calendar", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "GET /internal/calendar-configs discovers secret-gated calendar connections for sync and disconnect cleanup", "protocol": "HTTPS" }, { "unique-id": "ma-admin-reader-email", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "GET /internal/users/{id}/email (X-Internal-Secret) answers {id, email} for a reader of a shared meeting, asked only on the OWNER's access view (GET /meetings/{id}/access) for readers who redeemed before meeting-api kept a roster; meeting-api writes the address into that meeting's own data.share_viewers (one writer) and a failed lookup leaves the reader listed by id (collector/reader_directory.py)", "protocol": "HTTPS" }, { "unique-id": "ma-admin-writable", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "GET /internal/users/{id}/memberships (X-Internal-Secret), read once per calendar sync run: a new occurrence of a calendar series inherits the series' workspace only while its owner still holds contributor or owner there (R1801-3); an unanswered lookup is 'may write nowhere' and the occurrence is created private (calendar_sync/runner.py, collector/reader_directory.py)", "protocol": "HTTPS" }, { "unique-id": "ma-service-authority", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "service-authority", "interface": "service-authority-rest" } } }, "description": "optional signed service-authority.v1 admit/continue decision; unset is explicit OSS allow-all, configured failure is closed", "protocol": "HTTPS" }, { "unique-id": "ma-system-webhook", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "system-webhook", "interface": "system-webhook-rest" } } }, "description": "optional signed terminal webhook.v1 delivery to a boot-frozen operator destination over HTTPS (plain HTTP only to a private target the operator opts into); customer webhook SSRF policy remains separate", "protocol": "HTTPS" }, { "unique-id": "aa-watch", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "segments-stream" } } }, "description": "the transcription watcher's group agent_copilot: XREADGROUP + XACK each raw entry as a hint only, naming which verified per-meeting feed (tc-stream) to read; it acts on nothing it reads here", "metadata": [ { "access": "read" } ] }, { "unique-id": "aa-runtime", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "runtime", "interface": "runtime-rest" } } }, "description": "agent-api drives the kernel with Authorization: Bearer RUNTIME_API_TOKEN (runtime.v1 CallerCredential): POST /workloads, GET /workloads and GET /workloads/{id} to spawn and track agent-worker workloads, and POST /schedule, GET /schedule and DELETE /schedule/{job_id} for routine jobs (schedule.v1)", "protocol": "HTTPS" }, { "unique-id": "aa-unitout", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "out-stream" } } }, "description": "SSE relay (/api/chat, /api/meeting/stream)", "metadata": [ { "access": "read" } ] }, { "unique-id": "aw-tcnative", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "tc-stream" } } }, "description": "copilot tails transcript", "metadata": [ { "access": "read" } ] }, { "unique-id": "aw-unitout", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "out-stream" } } }, "description": "XADD cards/notes/deltas", "metadata": [ { "access": "write" } ] }, { "unique-id": "aw-unitin", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "unit-in" } } }, "description": "chat path XREADs interactive input", "metadata": [ { "access": "read" } ] }, { "unique-id": "mcp-gw", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "every MCP tool forwards the caller's own bearer (an API key or a worker's delegation token) to the public REST surface; for a worker it also sends back the identity the gateway signed onto the /mcp request (X-Vexa-Internal-Mcp-Identity, gateway-identity.v1 re-entry), the only way a delegation token reaches a REST route", "protocol": "HTTPS" }, { "unique-id": "gw-ma", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "proxy /bots /transcripts /meetings /recordings and per-calendar sync — and, on the service door, the flows tier's allow-listed meetings calls with the subject's identity signed here (scopes bot+tx)", "protocol": "HTTPS" }, { "unique-id": "gw-aa", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "proxy /agent/* with the resolved identity signed (gateway-identity.v1) — and, on the service door, the flows tier's allow-listed agent-api calls over the internal tier", "protocol": "HTTPS" }, { "unique-id": "gw-mcp", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "mcp", "interface": "mcp-http" } } }, "description": "proxy /mcp \u2014 the ONE assembled MCP server for every bearer, a person's key or a worker's delegation token; POST buffered, GET relayed unbuffered (SSE stream)", "protocol": "HTTPS" }, { "unique-id": "gw-admin", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "POST /internal/validate (authz oracle) plus user calendar connection CRUD — and, on the service door, the flows tier's allow-listed identity calls (address and id, ensure a person, settings, is-admin, a room's principal, a bearer's validation, the subject's identity the door signs for meetings calls)", "protocol": "HTTPS" }, { "unique-id": "gw-status", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "bm-status" } } }, "description": "WS fan-out", "metadata": [ { "access": "read" } ] }, { "unique-id": "gw-umeetings", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "u-meetings" } } }, "description": "WS auto-subscribe", "metadata": [ { "access": "read" } ] }, { "unique-id": "gw-chat", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "va-chat" } } }, "description": "WS fan-out", "metadata": [ { "access": "read" } ] }, { "unique-id": "collector-publishes-chat", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "va-chat" } } }, "description": "PUBLISH a ws.v1 chat_message per stored chat segment (collector/ingest.py)", "metadata": [ { "access": "write" } ] }, { "unique-id": "admin-db", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "identity-db" } } }, "protocol": "JDBC", "metadata": [ { "access": "write" } ] }, { "unique-id": "admin-pg", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "postgres" } } }, "protocol": "JDBC", "metadata": [ { "access": "write" } ] }, { "unique-id": "term-gw-rest", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "every REST call a browser makes, via gateway (the terminal's server also calls admin-api and agent-api directly: term-admin-internal, term-agent-internal)", "protocol": "HTTPS" }, { "unique-id": "term-gw-ws", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "gateway", "interface": "gateway-ws" } } }, "description": "live WS via gateway", "protocol": "WebSocket" }, { "unique-id": "term-admin-internal", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "the terminal's server, with the internal secret: sign-in admission, the admin claim, the claim-code check, instance state, the one-use redeem of an emailed sign-in link and the binding of an OAuth sign-in to its provider subject (signin.v1), plus /internal/validate and the settings it edits for the admin", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "signin.v1" } ] }, { "unique-id": "term-agent-internal", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "the terminal's server, with the internal secret: POST /internal/scaffolds (a sign-in's arrival) and GET /internal/has-history", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "term-flows-internal", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "the terminal's server, through the gateway's service door (/to-flows: the door checks its internal secret and forwards with the flows key): POST /mail/sign-in hands an emailed sign-in link to the flows mailer (VEXA_FLOWS_API_URL); on any failure the terminal sends it over its own SMTP", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "dash-gw-rest", "description": "dashboard \u2192 gateway REST (hosted-compat aliases; the hosted-proven wiring)", "relationship-type": { "connects": { "source": { "node": "dashboard" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } } }, { "unique-id": "dash-gw-ws", "description": "dashboard \u2192 gateway /ws (live transcript view)", "relationship-type": { "connects": { "source": { "node": "dashboard" }, "destination": { "node": "gateway", "interface": "gateway-ws" } } } }, { "unique-id": "slim-gw", "description": "Python client; REST via gateway", "relationship-type": { "connects": { "source": { "node": "slim" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "protocol": "HTTPS" }, { "unique-id": "deploy-composed", "relationship-type": { "composed-of": { "container": "deploy", "nodes": [ "execution-targets.v1", "config.v1", "outbound-url.v1", "meeting-bundle.v1" ] } } }, { "unique-id": "extension-gw", "description": "browser extension client; live WS via gateway", "relationship-type": { "connects": { "source": { "node": "extension" }, "destination": { "node": "gateway", "interface": "gateway-ws" } } }, "protocol": "WebSocket" }, { "unique-id": "stack-deployed", "description": "the long-running services ship as the deploy/compose stack (transcription has its own deploy unit)", "relationship-type": { "deployed-in": { "container": "deploy", "nodes": [ "gateway", "meeting-api", "agent-api", "model-proxy", "admin-api", "runtime", "redis", "postgres", "object-store", "transcription" ] } } }, { "unique-id": "flows-composed", "relationship-type": { "composed-of": { "container": "flows", "nodes": [ "flows-engine", "flows-defs", "flows-steps", "flows-schema", "flows-timeline", "flows-api", "flows-worker", "flows-rows", "flows.v1" ] } } }, { "unique-id": "flows-worker-writes-rows", "relationship-type": { "connects": { "source": { "node": "flows-worker" }, "destination": { "node": "flows-rows" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "flows-api-writes-rows", "description": "the second writer, recorded because it is real: POST /events admits a fact in the API process (flows_integrations/flows_api.py \u2192 flows.admit \u2192 INSERT INTO reaction) and the registry writes flow_version there too. The chart carried only flows-worker, so the one shared carrier in this domain read as single-writer", "relationship-type": { "connects": { "source": { "node": "flows-api" }, "destination": { "node": "flows-rows" } } }, "metadata": [ { "access": "write" } ] }, { "unique-id": "flows-api-reads-rows", "relationship-type": { "connects": { "source": { "node": "flows-api" }, "destination": { "node": "flows-rows" } } }, "metadata": [ { "access": "read" } ] }, { "unique-id": "flows-worker-calls-gateway", "description": "every call a flow step makes into another domain goes through the gateway's SERVICE DOOR (core/gateway/services/gateway/src/gateway/service_door.py, port 8002, never published) with the flows tier's one credential VEXA_FLOWS_SERVICE_KEY; flows-api's identity, timeline and mail-admin calls take the same door. The door forwards only its fixed allow-list (FLOWS_OUTBOUND): agent-api, admin-api and crm-api over the internal tier with the named subject, meeting-api with the subject's identity signed by the gateway (scopes bot+tx); anything else is a 403 at the door. A call made for a person (transcript.read, bot.dispatch, chat.autonomous, desk.write, room.bills_to, routine.turn) also carries the subject tickets of the fact or routine that caused it (X-Vexa-Subject-Ticket, subject-ticket.v1), signed by that fact's producer; the door verifies them under the producers' public keys and refuses the call (403 subject_ticket_required / subject_ticket_refused) unless one names that subject, class and meeting. flows holds no INTERNAL_API_SECRET and no admin key, and a domain never knows flows exists", "relationship-type": { "connects": { "source": { "node": "flows-worker" }, "destination": { "node": "gateway" } } } }, { "unique-id": "flows-deployed", "description": "helm only today (deploy/helm/charts/vexa/templates/flows.yaml); the two processes are not services in deploy/compose, so a compose stack runs no flows", "relationship-type": { "deployed-in": { "container": "deploy", "nodes": [ "flows-api", "flows-worker" ] } } }, { "unique-id": "agent-connections", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "credentials-broker", "interface": "credential-broker-rest" } } }, "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "credential-broker.v1", "description": "role agent (Connections routes) and role git (Git credential store); request, list, read, draft, call; no consent, no stored credential returned. Every agent-role and git-role call carries the gateway's signed identity (gateway-identity.v1) unchanged, and the broker acts only for the subject it names" } ], "description": "agent-api to the credential broker, signed role assertions (credential-broker.v1): role agent for the Connections routes (request, list, read, draft, call; no consent, no stored credential returned) and role git for the Git credential store (the person's own Git credentials and their shared workspaces' deploy keys); every call of either role carries the gateway's X-Vexa-Identity for the person, unchanged, and the broker acts only for the subject it names" }, { "unique-id": "terminal-connections", "relationship-type": { "connects": { "source": { "node": "terminal" }, "destination": { "node": "credentials-broker", "interface": "credential-broker-rest" } } }, "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "credential-broker.v1", "description": "role human for the identity-validated person: consent, credential save, disconnect, delete" } ], "description": "the terminal's server to the credential broker, role human for the identity-validated person (credential-broker.v1): consent, credential save, disconnect, delete" }, { "unique-id": "broker-vault", "relationship-type": { "connects": { "source": { "node": "credentials-broker" }, "destination": { "node": "credentials-vault" } } }, "metadata": [ { "access": "req", "description": "optional backend: versioned credential write/read and audit correlation over KV v2" } ] }, { "unique-id": "broker-store", "relationship-type": { "connects": { "source": { "node": "credentials-broker" }, "destination": { "node": "credentials-store" } } }, "metadata": [ { "access": "write", "description": "connection metadata, audit and (default backend) encrypted credential versions" } ] }, { "unique-id": "aw-gw", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "the worker's toolbelt: /mcp and /agent/friction with its per-dispatch delegation token, which identity resolves as the person it acts for. With the model proxy configured, the harness's own /mcp traffic goes through the proxy instead (aw-mp) and the token stays in the worker process, for its in-process calls", "protocol": "HTTPS" }, { "unique-id": "mcp-aa-discover", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "boot assembly: GET /.well-known/mcp-tools.json + /openapi.json \u2014 the agent domain's tools join the one MCP surface", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "mcp.tools.v1" } ] }, { "unique-id": "aa-ma", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "agent-api reads meetings as the caller, X-User-Id (and X-User-Workspaces) over the internal tier (X-Internal-Secret): GET /meetings/{id} (the meeting access lookup behind every meeting-scoped agent route), GET /transcripts/by-id/{id} (a transcript the caller may read), GET /meetings?\u2026 (the schedule digest's three bounded queries, also read by the desktop to place a workspace's last and live call), POST /meetings/{id}/annotate (the minted meeting's recorder). meeting-api decides access; agent-api holds no meetings data", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "api.v1" } ] }, { "unique-id": "aa-admin", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "agent-api asks identity about a person over the internal tier (X-Internal-Secret): GET /internal/users/by-email/{email} (falling back to GET /admin/users/email/{email} with X-Admin-API-Key) to resolve a share's invitee; POST/DELETE/GET /internal/users/{id}/memberships[/{ws}] (the membership index mirror); GET /internal/users/{id}/model-config; GET /internal/users/{id}/is-admin (the _global tier's writer); GET /internal/users/{id}/bot-context (admin overview); GET/PUT /internal/users/{id}/settings (the person's clock and timezone, and their presence switch), GET /internal/presence?ids=\u2026 (many people's presence choice at once, for the desktop and the people strip); GET /internal/users/{id}/photo (a person's photo bytes, asked only after agent-api decided the viewer shares a workspace or chat with them); GET /internal/users/{id}/org (the viewer's org for every workspace access check, cached)", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "aw-flows", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "the worker's temporal block: GET /timeline?format=preamble with the read-only VEXA_FLOWS_TIMELINE_KEY that dispatch stamps only when the deployment minted one (never the operator key); granted by the workload network fences (compose workers network, the Helm workload egress policy)", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "bot-ma", "relationship-type": { "connects": { "source": { "node": "bot" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "the bot's calls back: every lifecycle.v1 event to POST /bots/internal/callback/lifecycle and every recording chunk to POST /internal/recordings/upload, each with Authorization: Bearer (invocation.v1 token), bound to the bot's own session; meeting-api refuses another session's token with 401. An authenticated bot's session write-back is the third call, on its own edge (bot-session-writeback)", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "lifecycle.v1" } ] }, { "unique-id": "rt-aa", "relationship-type": { "connects": { "source": { "node": "runtime" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "a routine's due schedule.v1 job: POST /invocations with the unit.v1 dispatch agent-api compiled and signed (X-Vexa-Dispatch-Signature, HMAC keyed from INTERNAL_API_SECRET); the runtime holds the job opaquely and cannot re-point it at another person or trigger", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "schedule.v1" } ] }, { "unique-id": "rt-ma", "relationship-type": { "connects": { "source": { "node": "runtime" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "every RuntimeEvent for a bot workload to its callbackUrl, POST /runtime/callback, signed X-Runtime-Signature (runtime.v1 CallbackSignature, keyed from RUNTIME_API_TOKEN); meeting-api refuses an unsigned or forged callback with 401", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "runtime.v1" } ] }, { "unique-id": "aa-imports-status", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "imports-status" } } }, "description": "repository import status (workspace_import.py)", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-onboarding-research", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "onboarding-research-state" } } }, "description": "onboarding research checkpoints (onboarding_research.py)", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-rail-order", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "rail-order" } } }, "description": "SET/GET the chat rail order", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-rail-marks", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "rail-marks" } } }, "description": "HSET/HDEL/HGETALL a person's rail pins and hides", "metadata": [ { "access": "write" } ] }, { "unique-id": "admin-signin-link-record", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "signin-link-redeemed" } } }, "description": "SET NX with the link's own expiry (at most an hour) when a terminal redeems an emailed sign-in link; a write that cannot be made refuses the sign-in", "metadata": [ { "access": "write" } ] }, { "unique-id": "workspaces-composed", "relationship-type": { "composed-of": { "container": "workspaces-system", "nodes": [ "workspace.v1" ] } } }, { "unique-id": "plugin-gw", "relationship-type": { "connects": { "source": { "node": "claude-plugin" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "the plugin's HTTP MCP server entry: Claude Code calls the gateway's /mcp with the person's Vexa API key; the plugin itself runs no code", "protocol": "HTTPS", "metadata": [ { "access": "req" } ] }, { "unique-id": "aa-unit-in", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "unit-in" } } }, "description": "XADD the person's next message to a warm unit, signed with the unit's key", "metadata": [ { "access": "write", "contract": "unit.v1" } ] }, { "unique-id": "aa-redis-acl", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "redis-acl-users" } } }, "description": "ACL SETUSER/DELUSER a worker's own user per dispatch; restore after a Redis restart", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-redis-acl", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "redis-acl-users" } } }, "description": "ACL SETUSER/DELUSER a bot's own user per session; restore after a Redis restart", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-acl-index", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "acl-units-index" } } }, "description": "HSET/HDEL the worker users it defined", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-delegation-revoked", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "delegation-revoked" } } }, "description": "SET revoked: for the token's remaining life when the runtime no longer runs its unit", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-delegation-live", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "delegation-live" } } }, "description": "SET live: for the token's life when it is recorded; DEL it when the token is revoked", "metadata": [ { "access": "write" } ] }, { "unique-id": "admin-delegation-live", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "delegation-live" } } }, "description": "EXISTS live: for every verified vxd_ bearer; a token without it is refused (401), a store it cannot read refuses the token (503)", "metadata": [ { "access": "read" } ] }, { "unique-id": "admin-delegation-revoked", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "delegation-revoked" } } }, "description": "EXISTS revoked: for every verified vxd_ bearer; a store it cannot read refuses the token (503), API keys never read it", "metadata": [ { "access": "read" } ] }, { "unique-id": "aa-delegation-records", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "delegation-records" } } }, "description": "HSET/SADD a token's jti against its unit before the spawn and at each refresh; HDEL/SREM as tokens are revoked or expire", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-delegation-current", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "delegation-current" } } }, "description": "SET the unit's current token at dispatch and at each refresh, and GET it to re-mint", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-unit-delegation", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "unit-delegation" } } }, "description": "SET the unit's current token for its worker at dispatch and at each half-life refresh", "metadata": [ { "access": "write" } ] }, { "unique-id": "aw-unit-delegation", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "unit-delegation" } } }, "description": "GET before every turn, write-back and job; read-only to its Redis user", "metadata": [ { "access": "read" } ] }, { "unique-id": "aa-unit-fault", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "unit-fault" } } }, "description": "SET the typed fault a refused spawn ended in; GET it for the SSE relay and the pending list; DEL on the next spawn", "metadata": [ { "access": "write" } ] }, { "unique-id": "ma-acl-index", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "acl-bots-index" } } }, "description": "HSET/HDEL the bot users it defined", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-routine-state", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "routine-state" } } }, "description": "routine approvals and the re-signing marker", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-flows", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "the publish edge: POST /events (desk.unscaffolded, claim.proposed) and POST /friction with the operator key (X-Flows-Operator-Key); GET /flows/pages to land the pages of authored flows in _global/flows/; POST /flows and resume carry the person's routine grant (subject-ticket.v1, signed with agent-api's own key, kept with the flow version) and a message fact carries an event ticket for its recipient", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "flows.v1" } ] }, { "unique-id": "aa-gw", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "the transcription watcher, with VEXA_BOT_API_KEY: GET /meetings to resolve a meeting row to its native id, and POST /meetings/{platform}/{native}/docs to link the meeting's own page on session end", "protocol": "HTTPS", "metadata": [ { "access": "req", "contract": "api.v1" } ] }, { "unique-id": "mcp-flows-discover", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "boot assembly: GET /.well-known/mcp-tools.json + /openapi.json \u2014 the flows domain's tools join the one MCP surface; its operator-keyed tools need the MCP to hold the key its admin_auth names", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "mcp.tools.v1" } ] }, { "unique-id": "mcp-ma-discover", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "meeting-api", "interface": "meeting-api-rest" } } }, "description": "boot assembly: GET /.well-known/mcp-tools.json + /openapi.json on the meetings domain's door; a 404 is a deployed domain that publishes no manifest, and contributes no tools", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "mcp.tools.v1" } ] }, { "unique-id": "mcp-admin-discover", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "boot assembly: GET /.well-known/mcp-tools.json + /openapi.json on identity's door, always configured; a 404 is a domain that publishes no manifest, and contributes no tools", "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "mcp.tools.v1" } ] }, { "unique-id": "ma-writes-bundle", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "meeting-bundle-file" } } }, "description": "GET /meetings/{meeting_id}/export \u2014 the owner's whole meeting as a meeting-bundle.v1 zip", "metadata": [ { "access": "write", "contract": "meeting-bundle.v1" } ] }, { "unique-id": "ma-reads-bundle", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "meeting-bundle-file" } } }, "description": "POST /meetings/import \u2014 validate a meeting-bundle.v1 zip (manifest, every hash, paths, sizes) and land it as a new meeting the importer owns", "metadata": [ { "access": "read", "contract": "meeting-bundle.v1" } ] }, { "unique-id": "agent-writes-bundle-parts", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "meeting-bundle-parts" } } }, "description": "GET /api/meeting/bundle-parts \u2014 the owner's bound workspace tree (never its roster or policy) and the meeting's page", "metadata": [ { "access": "write", "contract": "meeting-bundle.v1" } ] }, { "unique-id": "ma-reads-bundle-parts", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "meeting-bundle-parts" } } }, "description": "POST /meetings/{meeting_id}/export \u2014 the parts placed into the bundle", "metadata": [ { "access": "read", "contract": "meeting-bundle.v1" } ] }, { "unique-id": "agent-reads-bundle", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "meeting-bundle-file" } } }, "description": "POST /api/meeting/bundle-restore \u2014 the bundle's workspace part as a new private workspace of the importer and its notes page on their desk, re-bound to the imported meeting", "metadata": [ { "access": "read", "contract": "meeting-bundle.v1" } ] }, { "unique-id": "crm-composed", "relationship-type": { "composed-of": { "container": "crm", "nodes": [ "crm-api", "crm.v1", "crm-records" ] } } }, { "unique-id": "crm-postgres", "relationship-type": { "connects": { "source": { "node": "crm-api" }, "destination": { "node": "postgres" } } }, "protocol": "JDBC", "metadata": [ { "access": "write", "description": "ADR-0047: the crm_* tables (crm-records), as the CRM's own role" } ] }, { "unique-id": "crm-admin", "relationship-type": { "connects": { "source": { "node": "crm-api" }, "destination": { "node": "admin-api", "interface": "admin-api-rest" } } }, "description": "POST /internal/validate: who the caller is, their live workspace memberships narrowed to a worker's ceiling, and whether the turn is shared; GET /internal/users/{id}/org (only with personal_crm on): whether the caller is an individual served from their own org of one", "protocol": "HTTP" }, { "unique-id": "admin-crm-erase", "relationship-type": { "connects": { "source": { "node": "admin-api" }, "destination": { "node": "crm-api" } } }, "description": "account delete: POST /internal/orgs/p-{id}/erase (internal secret) erases an individual account's personal CRM before identity removes the account (capability personal_crm_erase, CRM_API_URL)", "protocol": "HTTP" }, { "unique-id": "mcp-crm-discover", "relationship-type": { "connects": { "source": { "node": "mcp" }, "destination": { "node": "crm-api", "interface": "crm-http" } } }, "description": "boot assembly and tool calls: GET /.well-known/mcp-tools.json + /openapi.json, then the crm_*, desktop_* and card_* tools with the caller's own credential; present only where CRM_API_URL is set", "protocol": "HTTP" }, { "unique-id": "gw-crm", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "crm-api", "interface": "crm-http" } } }, "description": "the edge's /crm/* forward (routes.v1 `forward`): the record page's read, history and review, the desktop's desk/read, desk/arrange, desk/proposal and desk/undo (served while `desktop` is on), and the cards' card/list, card/read, card/create, card/update, card/members and card/membership (served while `desktop_cards` is on), with the caller's own key, present only where CRM_API_URL is set — and, on the service door, the flows tier's POST /internal/references and /internal/cards/offer over the internal tier", "protocol": "HTTP" }, { "unique-id": "gw-flows-door", "relationship-type": { "connects": { "source": { "node": "gateway" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "the service door's inbound leg (/to-flows): the internal-tier callers of flows-api (the signals service's POST /events/signal, the terminal's POST /mail/sign-in) present X-Internal-Secret to the door, which forwards the allow-listed calls (FLOWS_INBOUND) with X-Vexa-Service-Key, so flows never receives the internal secret", "protocol": "HTTP", "metadata": [ { "access": "req" } ] }, { "unique-id": "crm-agent-policies", "relationship-type": { "connects": { "source": { "node": "crm-api" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "GET /api/workspace/file?path=POLICIES.md&slug=_global over the internal tier (subject crm): the company's desk limits, narrow-only, cached 30 s; optional \u2014 CRM_AGENT_API_URL unset or unreachable means the defaults", "protocol": "HTTP" }, { "unique-id": "signals-composed", "relationship-type": { "composed-of": { "container": "signals", "nodes": [ "signals-service", "signals.v1", "sig-annotations", "signals-state" ] } } }, { "unique-id": "signals-redis", "relationship-type": { "connects": { "source": { "node": "signals-service" }, "destination": { "node": "redis" } } }, "protocol": "TCP", "metadata": [ { "access": "read", "description": "transcription_segments as hints only (own consumer group `signals`, entries acknowledged at once), the collector's verified tc:meeting:{row} (consumer group `signals`, confirmed lines) and agent-api's room:{session}:msgs (consumer group `signals`, a room's messages); none of them written" }, { "access": "write", "description": "its own keys only: sig:meeting:{row} annotations and sig:state|seen|lease|live:*" } ] }, { "unique-id": "signals-agent-listen", "relationship-type": { "connects": { "source": { "node": "signals-service" }, "destination": { "node": "agent-api", "interface": "agent-api-rest" } } }, "description": "GET /internal/meetings/{row}/listen?subject= and GET /internal/chats/{session}/listen?subject= with the internal secret: the listening brief (the agent's rules and model tier included) and the company's signal policy in one answer, cached 30 s; agent-api reads the source as that subject", "protocol": "HTTP" }, { "unique-id": "signals-flows-wake", "relationship-type": { "connects": { "source": { "node": "signals-service" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "POST /events/signal through the gateway's service door (/to-flows: the door checks X-Internal-Secret and forwards with the flows key, so flows never receives the secret; X-Vexa-Service: signals): one event.v1 meeting.signal per wake, data = the buffer; the company's _global flow decides what a wake does. A publish edge: no flows, no wakes", "protocol": "HTTP" }, { "unique-id": "crm-outbox-flows-events", "relationship-type": { "connects": { "source": { "node": "crm-api" }, "destination": { "node": "flows-api", "interface": "flows-http" } } }, "description": "the crm outbox (python -m crm.outbox --watch, the crm-outbox process of the crm image): POST /events with the CRM's publish key (X-Flows-Publisher-Key, VEXA_FLOWS_CRM_PUBLISH_KEY: the CRM's own facts, no other flows route), one crm.record.changed per revision with its event.v2 envelope signed with the CRM's own Ed25519 key (VEXA_FACT_SEAL_KEY_FILE; flows verifies under its public half); marked delivered only on a 202. A publish edge: no flows, rows stay pending", "protocol": "HTTP" }, { "unique-id": "signals-broker-key", "relationship-type": { "connects": { "source": { "node": "signals-service" }, "destination": { "node": "credentials-broker", "interface": "credential-broker-rest" } } }, "protocol": "HTTP", "metadata": [ { "access": "req", "contract": "credential-broker.v1", "description": "role signals: POST /api/internal/signals/model-key \u2014 the signal model's key the policy names (service/signals/ only), kept in memory" } ] }, { "unique-id": "signals-model", "relationship-type": { "connects": { "source": { "node": "signals-service" }, "destination": { "node": "signal-model", "interface": "signal-model-endpoint" } } }, "description": "one call per confirmed line: the line, up to 24 lines before it and the brief's questions; answers a 0..1 score per label, parsed strictly", "protocol": "HTTPS", "metadata": [ { "access": "call" } ], "controls": { "data-egress": { "description": "transcript lines leave the deployment only when the company picks an external signal model (Jev through Typesafe or OpenRouter); a company's own OpenAI-compatible endpoint keeps them inside. Off until the company sets model_signals", "requirements": [ { "requirement-url": "calm/controls/no-egress.requirement.json", "config": { "control-id": "vexa-no-egress", "name": "Tenant data egress", "description": "The posture of tenant data on this edge: where it goes and whether leaving the tenant is approved.", "dataClass": "transcript", "destination": "external-saas", "egressApproved": true } } ] } } }, { "unique-id": "aw-mp", "relationship-type": { "connects": { "source": { "node": "agent-worker" }, "destination": { "node": "model-proxy", "interface": "model-proxy-rest" } } }, "description": "every model request a turn's harness makes (/llm/*, its turn's token as the bearer \u2014 never a provider key) and the harness's MCP toolbelt (/mcp, the same token; the proxy presents the delegation bearer); the worker revokes the token when the last run holding it ends", "protocol": "HTTP", "metadata": [ { "access": "call" } ] }, { "unique-id": "mp-gw", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "gateway", "interface": "gateway-rest" } } }, "description": "a harness's MCP request relayed to the gateway's /mcp with the unit's current delegation token (agent-api's record, else the one sealed at spawn)", "protocol": "HTTP", "metadata": [ { "access": "call" } ] }, { "unique-id": "aa-model-routes", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "model-routes" } } }, "description": "SET a cold spawn's sealed route and the unit's pointer to it; GET the pointer for a message to a running worker", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-model-grants", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "model-grants" } } }, "description": "SET one turn's grant per delivered message (the spawn's entrypoint, every unit-in entry)", "metadata": [ { "access": "write" } ] }, { "unique-id": "mp-model-routes", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "model-routes" } } }, "description": "GET and open (AES-GCM) the route a live grant names", "metadata": [ { "access": "read" } ] }, { "unique-id": "mp-model-grants", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "model-grants" } } }, "description": "GET the grant a request's token names; INCR its request count; DELETE both on revocation", "metadata": [ { "access": "write" } ] }, { "unique-id": "mp-llm-unreported-spend", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "llm-unreported-spend" } } }, "description": "INCRBYFLOAT each relayed call's priced usage onto the turn's unreported figure; read every figure of the payer and the deployment, with the spend ledger, before each model request", "metadata": [ { "access": "write" } ] }, { "unique-id": "aa-llm-unreported-spend", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "llm-unreported-spend" } } }, "description": "the usage meter takes each amount a worker reports off the turn's figure and clears it at turn-complete, recording what is left when the turn reported nothing", "metadata": [ { "access": "write" } ] }, { "unique-id": "mp-delegation-current", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "delegation-current" } } }, "description": "GET the unit's current delegation token to present on a relayed MCP request", "metadata": [ { "access": "read" } ] }, { "unique-id": "mp-model-provider", "relationship-type": { "connects": { "source": { "node": "model-proxy" }, "destination": { "node": "model-provider", "interface": "model-provider-endpoint" } } }, "description": "an agent turn's model request, forwarded by the model proxy with the turn route's credential: the prompt with its meeting grounding (transcript excerpts) and the workspace context the turn reads", "protocol": "HTTPS", "metadata": [ { "access": "call" } ], "controls": { "data-egress": { "description": "transcript excerpts leave the deployment whenever the configured model is an external provider; a company's own gateway keeps them inside. A subject may only point a turn at an allow-listed host (VEXA_MODEL_BASE_URL_ALLOW), with its own credential", "requirements": [ { "requirement-url": "calm/controls/no-egress.requirement.json", "config": { "control-id": "vexa-no-egress", "name": "Tenant data egress", "description": "The posture of tenant data on this edge: where it goes and whether leaving the tenant is approved.", "dataClass": "transcript", "destination": "external-saas", "egressApproved": true } } ] } } }, { "unique-id": "aa-model-provider", "relationship-type": { "connects": { "source": { "node": "agent-api" }, "destination": { "node": "model-provider", "interface": "model-provider-endpoint" } } }, "description": "the one model call a home composition may make (core/agent/control_plane/home_model.py): the cheapest catalog model orders the cards it is handed, at most once per composition", "protocol": "HTTPS", "metadata": [ { "access": "call" } ], "controls": { "data-egress": { "description": "the cards' titles and summaries, derived from the person's meetings, leave the deployment when the cheapest catalog model is an external provider; with no eligible model the home is ranked without a call", "requirements": [ { "requirement-url": "calm/controls/no-egress.requirement.json", "config": { "control-id": "vexa-no-egress", "name": "Tenant data egress", "description": "The posture of tenant data on this edge: where it goes and whether leaving the tenant is approved.", "dataClass": "transcript", "destination": "external-saas", "egressApproved": true } } ] } } }, { "unique-id": "ma-customer-webhook", "relationship-type": { "connects": { "source": { "node": "meeting-api" }, "destination": { "node": "customer-webhook", "interface": "customer-webhook-endpoint" } } }, "description": "signed webhook.v1 delivery of meeting lifecycle, recording and transcription-ready events to the customer's registered URL", "protocol": "HTTPS", "metadata": [ { "access": "call" } ], "controls": { "data-egress": { "description": "meeting metadata (ids, status, timestamps) leaves for a URL the customer chose; the outbound URL guard refuses private, loopback, link-local and metadata addresses and pins the connection to the checked address", "requirements": [ { "requirement-url": "calm/controls/no-egress.requirement.json", "config": { "control-id": "vexa-no-egress", "name": "Tenant data egress", "description": "The posture of tenant data on this edge: where it goes and whether leaving the tenant is approved.", "dataClass": "metadata", "destination": "external-saas", "egressApproved": true } } ] } } } ], "flows": [ { "unique-id": "live-transcript-flow", "name": "live transcript", "description": "raw -> durable collector -> native stream -> render. One render engine; terminal never re-derives.", "transitions": [ { "relationship-unique-id": "bot-writes-segments-stream", "sequence-number": 1, "description": "bot XADDs raw ASR segments" }, { "relationship-unique-id": "collector-reads-segments", "sequence-number": 2, "description": "collector consumes (XREADGROUP collector_group)" }, { "relationship-unique-id": "collector-writes-tc", "sequence-number": 3, "description": "collector writes the native stream (single writer, P23)" }, { "relationship-unique-id": "aw-tcnative", "sequence-number": 4, "description": "the agent reads the native stream for chat grounding" } ] }, { "unique-id": "dispatch-flow", "name": "agent dispatch", "description": "a trigger spawns an isolated agent-worker via the runtime kernel; output streams back to the client.", "transitions": [ { "relationship-unique-id": "aa-runtime", "sequence-number": 1, "description": "agent-api POST /workloads" }, { "relationship-unique-id": "workers-deployed", "sequence-number": 2, "description": "runtime spawns agent-worker container" }, { "relationship-unique-id": "aw-unitout", "sequence-number": 3, "description": "worker XADDs output" }, { "relationship-unique-id": "aa-unitout", "sequence-number": 4, "description": "agent-api relays as SSE" } ] } ] }