Services
Per-service reference of nexus binaries and UIs - inbound surface, dependencies, and persistence
Esta página aún no está disponible en tu idioma.
This page describes what is implemented today for each nexus binary and UI: inbound surface, dependencies, persistence, and how it appears in local Docker Compose.
For how components fit together at a high level, see overview.md. Schemas and wire contracts live in data-model.md and wire-contracts.md.
How to read this page
Section titled “How to read this page”Each runnable component uses the same field names so updates stay mechanical:
- Current responsibility — behavior that exists in the tree now.
- Inbound — ports, protocols, and notable routes.
- Outbound / dependencies — other processes, libraries, or networks touched on the hot path.
- Persistence — durable state owned by this component.
- Compose — service name in deploy/compose/docker-compose.yml (merged with docker-compose.dev.yml for
just devhot reload), if any. - Not in the tree today — capability the binary does not provide (no links to planning docs from this file).
Important split: The nexus-gateway binary and nexus ops serve both mount the same axum app from nexus_gateway::serve::build_app. In the Compose stack, tenant bootstrap (orgs, projects, API keys, provider keys) is served by the Postgres-backed nexus-control-plane and nexus-auth HTTP/gRPC services; the gateway itself performs API-key verification and BYOK lookup through an in-process nexus_control_plane_core ControlPlane handle against the same Postgres database rather than network calls to those services.
Current local-dev data path
Section titled “Current local-dev data path”Typical hands-on flow: operator uses the CLI to write control-plane rows in Postgres, then starts the gateway (CLI or binary). The gateway verifies API keys and loads BYOK secrets from the same ControlPlane instance backed by that database; only the KMS wrapping key (and the dev file audit sink) live in the local state directory.
flowchart LR cli[nexus_CLI] pg[(Postgres_nexus_control)] subgraph localState [State_dir_dot_nexus] kmsNode[FileKms_key] sink[FileSink_audit_log] end cp[ControlPlane] gw[gateway_build_app] up[Upstream_LLM]
cli --> cp cp --> pg cp --> kmsNode cp --> sink gw --> cp gw --> upnexus-control-plane-core and nexus CLI
Section titled “nexus-control-plane-core and nexus CLI”These are not separate Compose services but they are the current implementation of org/project/API-key/provider-key logic and audit emission for mutations.
Current responsibility — In-process domain layer: create and verify Nexus API keys, wrap and store BYOK provider secrets, enforce key expiration, and emit structured audit events for lifecycle operations (org.created, project.created, api_key.created, provider_key.created). Workspace, organization, and project maximum key-age limits constrain only Nexus-generated API keys and developer tokens at mint time; NEXUS_MAX_KEY_AGE_DAYS is the deployment-wide cap for those credentials. BYOK and operator-managed platform provider keys use the separate deployment-wide NEXUS_PROVIDER_KEY_MAX_AGE_DAYS cap. Caps are honored exactly as configured; with no cap set, a requested expiry is accepted however far out it is. Used by the CLI, integration tests, and the gateway via a shared ControlPlane handle.
Inbound — CLI only: top-level commands context, orgs, workspaces, projects, auth, credentials (api-keys, provider-keys, platform-keys), registry (models), ops (serve, bootstrap, status, wallet, registration-codes, registration-invites), and completions (see cli/src/main.rs). Global flags: --database-url (env NEXUS_DATABASE_URL), --tenant-id (env NEXUS_TENANT_ID, default tenant_local), --state-dir (env NEXUS_STATE_DIR, default .nexus) for the local KMS wrapping-key file.
Outbound / dependencies — Store trait against PostgresStore; KmsProvider for provider-key wrapping; AuditSink for events; nexus_registry for model registry reads and management writes.
Persistence — Postgres (nexus_control database, same schema the control-plane service uses). Long-running services load the existing file-KMS wrapping key from NEXUS_KMS_KEY_PATH; they never generate key material. The CLI loads that path when configured and otherwise creates or reuses control-plane.kms.key under its configured state directory for local use.
Compose — The profile-gated cli service uses the Compose-network databases and the same read-only wrapping key as the long-running services.
Not in the tree today — Standalone console-served flows beyond the existing onboarding and management screens.
gateway
Section titled “gateway”Current responsibility — OpenAI-compatible proxy for BYOK chat completions, Responses, embeddings, moderations, image generation/edits/variations, and Nexus-owned file/vector-store lifecycle resources, plus a native Anthropic Messages edge under /anthropic and an OpenAI Agents SDK trace-ingest acknowledgment endpoint: verify Authorization: Bearer nxs_... and reject revoked and expired API keys with HTTP 401 (successful verifications are cached in-process for NEXUS_GATEWAY_API_KEY_CACHE_TTL_SECS, default 5s, so revocation takes effect within that window; 0 disables the cache), resolve model via nexus-registry, pick a billing-eligible endpoint, and decrypt provider keys through a 60-second in-process cache. Expired provider keys are not resolved after their cache entry expires. Clamp max_tokens / max_completion_tokens / max_output_tokens (Responses shape) to the registry ceiling (per attempt, against the ceiling of whichever candidate endpoint that attempt targets, so a fallback to an endpoint with a smaller completion ceiling is clamped to its own limit rather than the first candidate’s; a ceiling of 0 means the registry has no value and the caller’s own limit is left alone), bound each non-streaming attempt by a per-operation-class total-time budget and every upstream response by a size cap (NEXUS_GATEWAY_TIMEOUT_*, NEXUS_GATEWAY_MAX_RESPONSE_BYTES, NEXUS_GATEWAY_MAX_STREAM_BYTES), parse the nexus-classification header and evaluate a gateway.request policy decision (deny on a classification-ceiling violation, carry the email redact obligation), enforce per-API-key rate limits and workspace/org/project spend caps, forward non-streaming JSON or streaming SSE to upstream providers (with multi-provider attempt chains and retries), parse usage, compute exact qualified-rate cost, publish request-analytics envelopes, emit lifecycle/request audit events on the configured AuditSink, and increment gateway metrics. If provider-reported usage cannot match an exact rate after a successful upstream request, the gateway returns the provider result and records a typed billing failure; it does not quarantine on the request path. The ingest billing-health evaluator decides quarantine from request analytics (NEXUS_BILLING_QUARANTINE_*), and the gateway picks up blocks and recoveries through its periodic registry reload. In block mode a blocked endpoint receives no further traffic and therefore cannot re-qualify on its own; an operator restores it with nexus models unquarantine <provider>/<model>. A POST /v1/chat/completions request that carries reasoning_effort plus function tools for an OpenAI reasoning endpoint that supports Responses is served by translating it to the upstream /v1/responses API and reshaping the result back to chat-completions (non-streaming and streaming).
For a failed Titan multi-input embeddings request, completed calls report provider usage before the adapter returns its terminal aggregate error. The executor prices and records only that observed usage, committing the matching PTB escrow amount; it cancels an escrow when none completed.
Inbound — HTTP on BIND_ADDR (default 0.0.0.0:14450 in the binary; CLI ops serve defaults to 127.0.0.1:14450). Routes: GET /healthz, GET /readyz, GET /metrics (from nexus_runtime::build_router), POST /v1/chat/completions, POST /v1/responses, POST /v1/embeddings, POST /v1/moderations, POST /v1/images/generations, POST /v1/images/edits, POST /v1/images/variations, GET /v1/models, GET /v1/models/{id}, POST /v1/traces/ingest (acknowledges OpenAI Agents SDK trace exports), file lifecycle routes under /v1/files, vector-store lifecycle routes under /v1/vector_stores including GET /v1/vector_stores and POST /v1/vector_stores/{id} for list/modify, POST /v1/vector_stores/{id}/search for semantic search, and /v1/vector_stores/{id}/files attach/list/detach (API-key principals, or the internal service token plus scope headers used by the control-plane console proxy). The Anthropic-native edge is nested at /anthropic: POST /anthropic/v1/messages and POST /anthropic/v1/messages/count_tokens. One stub route returns 501 Not Implemented: POST /v1beta/models/gemini-pro:generateContent. Streaming model requests return text/event-stream, pass provider SSE frames through, and inject upstream stream_options.include_usage = true where needed so the final usage chunk can be recorded. Response header x-nexus-request-id is set on successful completions, model retrievals, and artifact lifecycle mutations. A background indexer worker polls pending vector-store attachments and runs chunk → embed (NEXUS_DEFAULT_EMBEDDING_MODEL) → pgvector store, settling attachment status to completed/failed.
Outbound / dependencies — In-process LocalAuthClient and LocalProviderKeyClient on Arc<ControlPlane>; Postgres via NEXUS_DATABASE_URL for control-plane rows and file/vector-store metadata; nexus-object-store for artifact bytes using S3/MinIO (NEXUS_S3_*, NEXUS_ARTIFACTS_BUCKET) or an explicitly configured filesystem root (NEXUS_ARTIFACTS_ROOT_DIR); reqwest to upstream base URL from registry; nexus_registry for spec, endpoint, and cost; optional Redis/Valkey (NEXUS_REDIS_URL) for the response cache, per-key rate limits, and the disallow list; the policy engine (in-process, or the policy service over gRPC via POLICY_GRPC_ENDPOINT); query gRPC for monthly-usage snapshots feeding spend-cap checks; the escrow adapter when NEXUS_GATEWAY_PTB=1; and NATS (NATS_URL) for audit-event fan-out and request.completed analytics envelopes on nexus.requests.<org_id>.<request_id>.
Persistence — Org, project, API-key, provider-key, registry, endpoint pricing-status, billing-failure, file, and vector-store metadata live in the control-plane Postgres database reached through NEXUS_DATABASE_URL. Billing-failure rows preserve raw provider usage and exact missing rate dimensions. Ingest evaluates ClickHouse request analytics over a closed window and records endpoint billing health; NEXUS_BILLING_QUARANTINE_ACTION=block quarantines degraded endpoints, while allow retains routing despite unbillable usage. A healthy evaluation window restores evaluator-owned blocks. File bytes are written to the configured artifact object store; metadata rows keep only scope, lifecycle fields, object keys, hashes, byte counts, and content type. The binary requires an existing 32-byte file-KMS wrapping key at NEXUS_KMS_KEY_PATH; NEXUS_STATE_DIR remains the local audit-file state location. When NATS_URL is set, the binary fans out each audit event to tenant-scoped NATS subjects under nexus.audit.events.<tenant_id> in addition to the local file sink.
Compose — gateway listens on 14450 inside the vortex network; stock compose publishes 14450 to the host.
Not in the tree today — Network calls to separate auth/control-plane processes on the request hot path (the gateway uses its in-process ControlPlane handle).
control-plane
Section titled “control-plane”Current responsibility — Org/project/membership/API-key/provider-key/model-registry HTTP REST and gRPC APIs backed by Postgres, console-facing file/vector-store artifact REST, provider-key deployment discovery for Azure AI Foundry connections, plus KMS-wrapped provider-key secrets, audit-event staging publication, and data-access ingress events used by the console. Provider catalog collection and artifact import are not control-plane HTTP or gRPC surfaces. Foundry discovery only compares and optionally updates one connection’s deployment map; it does not generate or import registry artifacts. Telemetry init and health/metrics surfaces are inherited from nexus_runtime::build_router.
Inbound — HTTP 0.0.0.0:14451 (BIND_ADDR): /healthz, /readyz, /metrics, plus REST under /api/orgs, /api/projects, /api/api-keys (including reporting-dimension assignment routes), /api/provider-keys (including POST /api/provider-keys/:provider_key_id/discover), /api/models* (including the model_registry:read-scoped, provider-filterable GET /api/models/:canonical_model/pricing-history, which uses a bounded limit and opaque activation keyset cursor), /api/workspaces (including reporting-dimension definition routes), /api/audit/data-access/request-viewed, and project-scoped artifact routes for file upload/list/detail/content/delete plus vector-store create/list/detail/modify/delete/attach/detach/search under /api/orgs/:org_id/projects/:project_id/files and /api/orgs/:org_id/projects/:project_id/vector-stores (the search route is a membership-authorized proxy to the gateway search endpoint via NEXUS_GATEWAY_INTERNAL_ENDPOINT + NEXUS_SERVICE_TOKEN). Membership and invitation routes accept the manager, auditor, and user roles. gRPC on CONTROL_PLANE_GRPC_ADDR (default 0.0.0.0:14452) exposes OrgService, ProjectService, ApiKeyService, and ProviderKeyService from nexus-proto.
Outbound / dependencies — Postgres (NEXUS_DATABASE_URL), artifact object storage through nexus-object-store (NEXUS_S3_*, NEXUS_ARTIFACTS_BUCKET, or NEXUS_ARTIFACTS_ROOT_DIR), Azure AI Foundry deployment-listing endpoints for explicit provider-key discovery, optional NATS for tenant-scoped audit fan-out (nexus.audit.events.<tenant_id>), KMS provider for provider-key wrapping, optional OTLP.
Persistence — Postgres (nexus_control): orgs, projects, memberships, API keys, provider keys, reporting-dimension definitions and effective-dated assignments, model registry tables, file/vector-store metadata, audit_events_staging, workspace wallet/settings/transaction/escrow tables. File bytes are stored in the configured artifact object store. The service loads the existing file-KMS wrapping key from NEXUS_KMS_KEY_PATH and fails startup if the file is missing, unreadable, not exactly 32 bytes, or cannot authenticate every stored wrapped credential. Schemas under services/control-plane/migrations/.
Compose — control-plane on 14451 (HTTP) and 14452 (gRPC) inside the vortex network; stock compose publishes 14451 to the host (the gRPC port stays network-only).
Not in the tree today — SCIM/SAML/OIDC user provisioning, invoices, tax handling, and external billing provider settlement beyond the Stripe-backed wallet top-up flow.
admin-control-plane
Section titled “admin-control-plane”Current responsibility — Deployment-administrator APIs for service readiness, user lifecycle, workspace creation and inspection, workspace membership administration, workspace deactivation previews, and operator-funded wallet grants.
Inbound — HTTP on BIND_ADDR (default 0.0.0.0:14431): shared health/metrics routes and admin-token-authenticated routes under /api/platform, /api/users, and /api/workspaces. GET /api/platform/readiness returns one snapshot of the alphabetically ordered fixed service inventory, including the normalized overall status and each service’s normalized status and reported dependency checks; GET /api/platform/readiness/history returns alphabetically ordered fixed-inventory Prometheus samples, deriving service-level healthy, degraded, and unhealthy states from timestamp-aligned dependency checks when they exist. nexus-admin platform health renders the snapshot as a table. POST /api/workspaces/:workspace_id/wallet/grants requires a positive decimal amount, reason, and idempotency key and returns the resulting wallet transaction.
Outbound / dependencies — Auth gRPC for admin-token verification and user profile operations; user profile RPCs receive the administrator bearer token and independently re-verify its active administrator assignment before reading or mutating user state. The readiness aggregator uses one reusable HTTP client to request /readyz from the fixed service endpoints configured at startup, with bounded concurrency, per-probe and whole-snapshot deadlines, and a 64 KiB body limit per probe; configured probe and snapshot deadlines must each be between 1 ms and 10 seconds. Administrator credentials are not forwarded to those endpoints. The Postgres-backed ControlPlane handles workspace, membership, and wallet mutations; optional NATS provides tenant-scoped audit fan-out; optional OTLP exports operator telemetry.
Persistence — Shares the control-plane Postgres schema and writes wallet balances, transactions, workspace state, memberships, and audit staging rows. The service loads the same existing file-KMS wrapping key as the control-plane from NEXUS_KMS_KEY_PATH and does not create key material.
Compose — admin-control-plane listens on 14431 inside the vortex network; stock compose publishes 14431 to the host.
Current responsibility — Email/password user/session lifecycle (sign-up, sign-in, refresh, sign-out), deployment-wide OIDC sign-in, invite-only registration credential checks, HMAC-JWT access tokens, console session cookie, and API-key verification proxied to the in-process control-plane core. Tenant and platform-administrator sessions expire after one hour without an authenticated request by default (AUTH_SESSION_IDLE_TIMEOUT_SECS, set to 0 to disable inactivity expiry); every path that authorizes on a console session token checks and updates its session row, so signing out or exceeding the inactivity limit ends access without waiting for the token’s own expiry. Developer access tokens (nxd_) and gateway API keys carry their own expiry and revocation and are not subject to this inactivity limit. It also issues platform-administrator sessions as a separate credential: administrator access tokens carry the nexus-admin-console audience rather than the tenant nexus-console audience (same AUTH_JWT_SECRET), their session rows carry kind = 'admin' so a refresh token cannot be redeemed on the tenant path, and their access / refresh token lifetimes default to 30 minutes / 12 hours (AUTH_ADMIN_ACCESS_TTL_SECS, AUTH_ADMIN_REFRESH_TTL_SECS) against the tenant 1 day / 30 days. Administrator sign-in, refresh, and token verification each require an active row in the admins table for the deployment tenant, and every administrator rejection returns 401 with no distinguishing detail. See ../decisions/0024-admin-console-trust-boundary.md. REST surface under services/auth/src/rest.rs; gRPC AuthService exposed from services/auth/src/grpc.rs.
Inbound — HTTP 0.0.0.0:14453: /healthz, /readyz, /metrics, REST routes for users/sessions, and administrator session routes POST /api/auth/admin/sign-in, /api/auth/admin/refresh, /api/auth/admin/sign-out, /api/auth/admin/verify-token. gRPC on AUTH_GRPC_ADDR (default 0.0.0.0:14454) serving AuthService, whose VerifyToken accepts only tenant-audience tokens and VerifyAdminToken only administrator-audience tokens.
Outbound / dependencies — Postgres (AUTH_DATABASE_URL for nexus_auth; NEXUS_DATABASE_URL for the control-plane database), KMS provider, optional OTLP. Audit events flow to the staging table and (when NATS_URL is set) tenant-scoped NATS subjects under nexus.audit.events.<tenant_id>. Administrator session events are admin.session.signed_in, admin.session.refreshed, and admin.session.denied (recorded when a correct password belongs to a subject holding no administrator assignment); no token material is recorded.
Persistence — Postgres (nexus_auth): users, sessions (each row carrying kind of 'user' or 'admin'), identities, administrator assignments in admins, and audit_events_staging. Schemas under services/auth/migrations/.
Compose — auth on 14453 (HTTP) and 14454 (gRPC) inside the vortex network; stock compose publishes 14453 to the host (the gRPC port stays network-only).
Not in the tree today — SAML, SCIM, PIV/CAC, MFA, password reset email flows, request authorization beyond verifying the session/API key, and any write path into the admins table (administrator assignments are created by direct SQL insert).
policy
Section titled “policy”Current responsibility — Request-time policy decision point (PDP). Evaluates gateway.request queries and returns an allow/deny decision: classification-ceiling enforcement (denies when a resource’s nexus-classification tier exceeds the subject’s max_classification), a Redis-compatible decision cache, and a policy.decision audit event per evaluation. The gateway can evaluate in-process against the same engine or call this service over gRPC (POLICY_GRPC_ENDPOINT + a nxsvc_ service token).
Inbound — HTTP 0.0.0.0:14455: /healthz, /readyz, /metrics. gRPC on POLICY_GRPC_ADDR (default 0.0.0.0:14456) serving PolicyService.Evaluate from nexus-proto, behind a service-token auth interceptor.
Outbound / dependencies — Optional Redis (NEXUS_REDIS_URL) for the decision cache, optional NATS (NATS_URL) for audit fan-out of policy.decision events, the auth verifier for service-token validation, optional OTLP.
Persistence — None durable; the Redis decision cache is the only external state and is reconstructable.
Compose — policy on 14455 (HTTP) and 14456 (gRPC) inside the vortex network; not published to the host in stock compose.
Not in the tree today — OPA/Cedar policy-as-code authoring, richer ABAC attribute sources, and console/query policy gates beyond the gateway gateway.request enforcement path.
trace-ingest
Section titled “trace-ingest”Current responsibility — Public OTLP/HTTP protobuf intake for tenant-visible agentic traces.
The service verifies project-scoped trace ingest keys against the control-plane store, normalizes incoming spans into Nexus trace records, rejects org/project override attributes that do not match the authenticated key, and publishes trace records to nexus.traces.<org_id>.<trace_id>.<event_id> subjects.
Inbound — HTTP 0.0.0.0:14458: /healthz, /readyz, /metrics, and POST /v1/traces.
Outbound / dependencies — Postgres (NEXUS_DATABASE_URL) for trace ingest key verification, NATS JetStream (NATS_URL) for trace record fan-out, optional OTLP.
Persistence — None directly.
The service writes to NATS; ingest materializes trace metadata into ClickHouse.
Compose — trace-ingest on 14458 in the vortex network and published to the host by the stock Compose file.
ingest
Section titled “ingest”Current responsibility — Durable NATS JetStream consumer for nexus.requests.*.* envelopes published by the gateway and nexus.traces.> records published by trace-ingest.
For request analytics, it resolves inline-or-chunked request/response bodies, verifies blake3 hashes, creates independently decodable zstd frames, and writes organization-isolated packs to the configured S3/MinIO bucket (or filesystem fallback).
It stores exact frame locators with request rows plus normalized qualified usage/cost lines in ClickHouse, then durably publishes a deterministic data.write.request_logged event on nexus.audit.events.<tenant_id> before acknowledging the source message.
For native traces, it writes normalized spans, events, and summary-only artifact references into ClickHouse.
Bootstrap creates the JetStream streams/consumers and applies ClickHouse migrations in services/ingest/migrations/clickhouse/.
Implementation under services/ingest/src/.
Inbound — HTTP 0.0.0.0:14457: /healthz, /readyz, /metrics.
NATS JetStream pull consumers on the nexus_REQUESTS and nexus_TRACES streams.
Outbound / dependencies — NATS (NATS_URL), ClickHouse (CLICKHOUSE_URL/credentials/database), object_store AmazonS3 backend or filesystem root, optional OTLP. Trace context is propagated from JetStream message headers.
Persistence — ClickHouse requests, request_usage_lines, request_cost_lines, qualified pricing and request metrics, trace_spans, trace_events, and trace_artifact_refs tables; body packs under <org_id>/packs/<ulid>.pack, referenced as pack-v1:<bucket>/<key>#<offset>:<length>:zstd.
Compose — ingest on 14457 inside the vortex network; stock compose publishes 14457 to the host.
Not in the tree today — Multi-tier classification buckets / Object Lock, and a PostHog exporter (the query service owns metrics rollups, request feedback, and aggregate OTLP + signed-webhook exporter delivery).
Current responsibility — Durable audit-event consumer for nexus.audit.events.<tenant_id> subjects. Validates canonical audit events, assigns per-tenant sequence numbers, and acknowledges after the idempotent Postgres insert.
A single background sealer closes complete 1,000-event per-tenant Merkle batches as they fill, closes partial batches within five seconds, and flushes recovered or shutdown state without consuming batch sequence numbers on failed seals.
It signs batch envelopes, publishes hourly anchor manifests to the configured archive, and exposes gRPC reads/proofs plus an authenticated HTTP read facade for the console and API consumers. Every successful HTTP event read appends a data_access.audit_viewed event to the store.
Inbound — HTTP 0.0.0.0:14459: /healthz, /readyz, /metrics, plus the bearer-authenticated read facade GET /api/audit/events, GET /api/audit/events/:event_id, GET /api/audit/events/:event_id/proof, and GET /api/audit/filter-options. Facade routes require the audit:read scope and a manager or auditor membership in the requested org (service principals may read tenant-wide). gRPC on AUDIT_GRPC_ADDR (default 0.0.0.0:14460) serving AuditService with the same per-org gate.
Outbound / dependencies — Postgres (AUDIT_DATABASE_URL), NATS (NATS_URL), S3-compatible audit archive or filesystem archive root, auth gRPC for bearer-token verification, optional OTLP.
Persistence — Postgres (nexus_audit): audit_events, audit_tenant_counters, audit_signing_keys, audit_batch_roots, and audit_meta_roots. Archive objects include meta-root manifests and zstd-compressed batch event files.
Compose — audit on 14459 (HTTP) and 14460 (gRPC) inside the vortex network; stock compose publishes 14459 to the host. With the opt-in docker-compose.traefik.yml overlay, PathPrefix(/api/audit) on the nexus hostname also routes here through Traefik (the health/metrics paths are not matched by that route).
Not in the tree today — Browser-based proof verification, SIEM export, and external transparency-log witness.
Current responsibility — Read-facing service over ClickHouse and the bodies object store. HTTP API under /api/requests, /api/requests/facets, /api/requests/:request_id, POST /api/requests/:request_id/feedback, /api/usage, /api/metrics/overview, /api/exports/panel, /api/sessions, /api/sessions/facets, /api/sessions/:session_id/timeline, /api/sessions/:session_id/live (Server-Sent Events bridging nexus.requests.<org>.* NATS messages filtered by org_id+session_id), trace reads under /api/traces/:trace_id/tree, /api/sessions/:session_id/traces, /api/requests/:request_id/trace, /api/traces/:trace_id/spans/:span_id, /api/traces/:trace_id/artifacts/:artifact_id, trace live SSE under /api/sessions/:session_id/traces/live, and /api/body/by-request/:request_id.
Request and session list routes accept server-side filters (q, provider/model, status class / stream mode where applicable) and return total / has_more for console pagination; facet routes return distinct providers and models for filter controls.
The authenticated body proxy parses packed references, pins the pack key to the row’s organization prefix, reads only the exact packed range, decodes one zstd frame, and verifies its stored byte count and BLAKE3 hash before returning JSON.
Trace tree responses sort spans by start time, keep orphan spans as roots, attach events/artifact refs, and join request metadata onto matching LLM spans by request_id. gRPC QueryService (ListRequests, GetRequest, MonthlyUsageSnapshot) returns authenticated query-proxy body URLs rather than object-store URLs; MonthlyUsageSnapshot feeds the gateway’s spend-cap cache. The filesystem fallback /_bodies/*path proxy rejects pack paths and is only mounted when S3 is not configured. The service also owns metrics rollups, request feedback, and aggregate OTLP + signed-webhook exporter delivery for tenant exporter configs.
Inbound — HTTP 0.0.0.0:14461: /healthz, /readyz, /metrics, plus the routes above. gRPC on a dedicated port (QUERY_GRPC_ADDR, default 0.0.0.0:14462 in dev compose).
Outbound / dependencies — ClickHouse for request and trace reads, nexus-object-store for exact-range body reads, the object_store AmazonS3 V4 signer for independently stored trace artifact URLs, NATS for request and trace live SSE, policy gRPC for read authorization, optional OTLP.
Persistence — None (read-only over ClickHouse + object storage).
Compose — query on 14461 (HTTP) and 14462 (gRPC) inside the vortex network; stock compose publishes both to the host.
Not in the tree today — A dedicated MetricsService gRPC surface and an AST-safe SQL rewriter for arbitrary tenant SQL.
console (Next.js)
Section titled “console (Next.js)”Current responsibility — Tenant console. Sign-in/sign-up against the auth service (HTTP-only session cookie), org/project/API-key/provider-key/model management screens against the control-plane REST API, project-scoped Storage UI for files and vector stores through a multipart-capable BFF proxy, a request/session/trace inspection surface backed by query HTTP via Next.js API proxies under app/api/query/**, and an audit log viewer (org and workspace scopes) backed by the audit service’s HTTP read facade via proxies under app/api/audit/**. The model endpoint drawer loads provider-filtered pricing history through its BFF route only after the drawer opens, aborts stale model/provider page requests, and renders planned card/activation intervals separately from actual supersession, provenance, status, and expandable qualified rates. Request/session views include request list, request detail with JSON body viewer, sessions list, session timeline, live session SSE, and trace drill-in links. The trace inspector renders a tree/waterfall, top summary, span detail tabs, payload availability states, and live trace SSE updates without replacing the session timeline. Emits data_access.request_viewed to control-plane on request detail loads; storage and audit reads are recorded server-side by their backing services.
Inbound — HTTP (dev 14449 in Compose). Notable routes: GET /healthz, app routes under /(console)/... (including /o/[org]/p/[project]/storage, /o/[org]/audit, and /w/[workspace]/audit), and API proxies under /api/artifacts/**, /api/models/[canonical_model]/pricing-history, /api/query/**, /api/audit/request-viewed, /api/audit/events, /api/audit/events/[event_id], /api/audit/events/[event_id]/proof, and /api/audit/filter-options.
Outbound / dependencies — auth REST/JWT, control-plane REST, query HTTP (QUERY_HTTP_ENDPOINT), audit HTTP (AUDIT_HTTP_ENDPOINT).
Persistence — Server-side session cookie only.
Compose — console listens on 14449 inside the vortex network; stock compose publishes 14449 to the host.
Not in the tree today — A custom dashboard builder (a usage dashboard ships), policy admin UI, and playground replay. Platform-administrator surfaces are not served by this application; they live in admin-console (below).
admin-console (Next.js)
Section titled “admin-console (Next.js)”Current responsibility — Platform-administrator console, a separate application from the tenant console with its own session. Administrator sign-in against the auth service’s administrator routes holds the access and refresh tokens server-side so the browser never receives a token. The protected shell renders the signed-in administrator’s identity and deployment tenant, and its Platform Health view renders the current bounded service-readiness snapshot with overall status, service and dependency status, observation time, and manual refresh. Protected surfaces live under an (admin) route group whose server layout calls getCurrentAdmin() and redirects to /sign-in when no valid administrator session is present; because that check calls POST /api/auth/admin/verify-token on every render, and the auth service re-checks the admins table on every such call, a revoked assignment or a disabled account loses access without waiting for the access token to expire. Session cookies are nexus_admin_access and nexus_admin_refresh (names distinct from the tenant console’s, since a port does not scope a cookie), both httpOnly and sameSite=strict, with secure gated by NEXUS_SECURE_COOKIES, each expiring at its token’s own expiry. The sign-in form renders one generic failure message for every rejection, so it does not distinguish an unknown email, a wrong password, a disabled user, or a user holding no administrator assignment. Trust-boundary rationale: ../decisions/0024-admin-console-trust-boundary.md.
Inbound — HTTP 14432 (PORT). Routes: GET /healthz, the (auth) route /sign-in, (admin) app routes (/overview, /platform-health), session routes POST /api/session/sign-in, POST /api/session/refresh, POST /api/session/sign-out, GET /api/session/me, authenticated BFF routes GET /api/platform/readiness and GET /api/platform/readiness/history, and GET /api/platform/readiness/history/grafana, which redirects a valid service observation to Grafana Explore with service readiness and dependency-check gauges over the hour before and after that observation.
Outbound / dependencies — auth REST (AUTH_HTTP_ENDPOINT) for POST /api/auth/admin/sign-in, /api/auth/admin/refresh, /api/auth/admin/sign-out, and /api/auth/admin/verify-token; admin-control-plane HTTP (ADMIN_CONTROL_PLANE_HTTP_ENDPOINT) for GET /api/platform/readiness. The readiness BFF attaches the server-held administrator access token, enforces a 1 MiB response limit, rejects malformed snapshots, and, when its allowlisted ADMIN_GRAFANA_ORIGIN is configured, adds per-service Grafana Explore links for Prometheus readiness metrics and Loki logs. It disables caching and returns sanitized errors without exposing the internal endpoint or raw network failures to the browser.
Persistence — Server-side administrator session cookies only.
Compose — admin-console listens on 14432 inside the vortex network; stock compose publishes 14432 to the host. With the opt-in docker-compose.traefik.yml overlay, the NEXUS_ADMIN_CONSOLE_HOSTNAME host rule also routes here through Traefik.
Not in the tree today — Console surfaces for the user, workspace, membership, and wallet-grant APIs on admin-control-plane; granting or revoking administrator assignments (no code path in this repository writes a row into the admins table; creating the first platform administrator requires a direct SQL insert into nexus_auth.admins); and administrator sign-in through an identity provider (the administrator routes accept password credentials only).
Supporting nexus crates (libraries)
Section titled “Supporting nexus crates (libraries)”nexus-proto (crates/nexus-proto) — Generated Rust types from proto. Used for shared contracts across services as gRPC surfaces land; not on the hot path for the current gateway chat handler.
nexus-registry (crates/nexus-registry) — Runtime model registry loaded from the model_registry_* Postgres tables via Registry::load_from_pool; provides model spec parsing, endpoint selection, cost helpers, strict offline artifact validation, and persisted prepare/list/get/approve/reject/apply APIs for import change sets. Provider lanes are open names used for routing and attribution, while each endpoint carries a supported typed backend for adapter dispatch. Apply revalidates artifact and approval bindings and commits under lane-scoped Postgres locking. The gateway holds a hot-swappable in-memory snapshot refreshed by a periodic Postgres poll (60 seconds by default), so committed imports converge without a restart. A from_test_seed helper embeds a small TOML fixture for unit tests.
nexus-registry-artifact (crates/nexus-registry-artifact) — Database- and network-free contract for single-document, per-lane registry artifacts (catalog + rates tables in one JSON file). An optional custom name gives an existing typed provider backend a distinct routing and attribution identity. The crate enforces closed record shapes, provider-name grammar, the canonical content digest, optional Ed25519 signatures, source references, effective intervals, context-band coverage, reference integrity, pricing coverage, and non-routable Bedrock catalog rows, and expands the document into the normalized records the import pipeline persists.
nexus-registry-generator (tools/registry-generator) — Standalone CLI that collects OpenAI and Anthropic catalogs or consumes copied fixtures, emits canonical artifact directories atomically, optionally signs them, and validates them offline. generate --name and from-csv --name bind one custom lane to the selected existing provider backend. Its foundry-csv subcommand lists a live Azure AI Foundry resource’s deployments into an operator CSV pair and, with --prices, fills the rates from the published Azure pricing pages. Bedrock collection is outside this binary.
nexus-control-plane-core (crates/nexus-control-plane-core) — In-process domain layer used by control-plane, auth, the gateway BYOK adapters, and the nexus CLI: org/project/membership CRUD, API-key minting/verification, KMS-wrapped provider keys, audit emission, workspace wallet operations, and the StoreEscrow gateway adapter.
nexus-runtime (crates/nexus-runtime) — Shared service skeleton: config from env, Postgres pool, migrations, health/ready/metrics router, NATS audit fan-out sink, and the Postgres staging audit sink used by control-plane/auth.
nexus-artifact-store (crates/nexus-artifact-store) — Durable Postgres + object-store backed artifact lifecycle state (files, vector stores) shared by the gateway and control-plane.
nexus-object-store (crates/nexus-object-store) — Shared S3-compatible and filesystem object-store abstraction used for artifact bytes, request bodies, and the audit archive.
nexus-trace-core (crates/nexus-trace-core) — Tenant trace record contract shared by trace-ingest, ingest, and query.
nexus-utils (crates/nexus-utils) — Small dependency-free helpers shared across nexus crates and services.
Maintaining this document
Section titled “Maintaining this document”When you merge a change that alters a service’s behaviour, update that section’s Current responsibility, Inbound, Outbound, and Persistence in the same MR (or immediately after) so this file stays an accurate as-built index.
