0.12 — control-plane carve
0.12 reorganizes the backend around a single front door and server-derived identity.-
Planned meetings. A meeting is now one record from plan to transcript: create it ahead with
POST /meetings(title, time, optional link, optional workspace binding), edit/delete while planned, and the eventual bot spawn claims the same record. Members of a bound workspace see the plan, the live feed, and the transcript. See Meetings and Plan and share a meeting. -
Auto-join.
scheduledmeans the bot joins: a sweep sends the bot at start time (per-meeting toggle, loud failures). See the Meetings API. -
Calendar sync. Paste a secret ICS address (
PUT /user/calendar) and upcoming meetings with Meet/Zoom/Teams links import as planned meetings — no OAuth. See Calendar sync. -
One gateway. All public traffic enters through the gateway (
API_GATEWAY_HOST_PORT, default18056); it carries authentication and per-route scopes and routes to the internal services. -
Server-derived identity. The gateway resolves your
X-API-Key→ user and injects identity downstream. Asubjectin a request body or query is ignored — the server never trusts the client for identity. See Authentication and Identity & trust. -
Agent control plane. Dispatch, chat, routines, events, and workspace reads are unified under the
Agent API at the
/agent/*prefix (the legacy/api/*alias still resolves). -
Compose-based self-host. The open core brings the whole control plane up with
make all(Docker Compose) on a single Linux host. See Deployment. -
Open Knowledge Format workspaces. The workspace knowledge graph (
kg/) is an OKF v0.1 bundle: the entity frontmatter contract is a strict superset of OKF, seeds ship generatedindex.mdlistings, and the whole knowledge base is portable to any OKF consumer. See Browse the workspace.
Migrating from 0.10
- Route through the gateway. Point clients at the gateway base URL and send
X-API-Key; stop calling internal services directly. - Drop client-supplied identity. Remove any
subject/ user id you sent in bodies or query strings — it’s now derived from the key. - Use the
/agent/*prefix for control-plane routes (the old/api/*alias still works during transition). - Re-check your secrets. Set real values for
ADMIN_TOKEN,INTERNAL_API_SECRET,VEXA_DISPATCH_SIGNING_KEY, and DB/MinIO credentials — see Configuration.
Parity with the 0.10.x line
The publicapi.v1 contract is sealed hash-equal to main’s OpenAPI 1.5.0 and enforced in CI
(gate:contract-version), so the wire surface is identical by construction. Two honest caveats
follow from that:
- A sealed endpoint is not automatically a wired capability — some contract routes are not mounted in the open-core control plane yet, and this page says which.
- Anything
mainmerged after 1.5.0 is by definition not in 0.12 until a contract revision.
Not yet in 0.12
| Capability (0.10.x has it) | Status in 0.12 | Honest note |
|---|---|---|
Mid-call bot config — PUT /bots/{platform}/{id}/config (change language/task live) | contract-sealed, not wired | The gateway mounts and forwards it, but the live bot-control plane isn’t wired in the open-core meeting-api — authenticated calls return the downstream 404. Flagged in the Meetings API reference. |
Voice agent — POST /bots/{platform}/{id}/speak (TTS into the call) | contract-sealed, not wired | Proven at contract level (acts.v1 + the mock-bot speak-ack gate); the real path returns 404 in the shipped stack. Contract-ready, not user-ready. |
| Interactive bots beyond speak — in-meeting chat, screen share, avatar | contract-sealed, not wired | The chat/screen/avatar endpoints are in the sealed api.v1, but the 0.12 gateway does not mount them (edge probe: 404). Planned back in the 0.12.x line — same honest framing as config/speak. |
Transcript share links — POST /transcripts/…/share + GET /public/transcripts/{id}.txt | contract-sealed, not mounted | Verified: both routes are in the sealed api.v1; neither is mounted at the 0.12 gateway (edge probe: 404). The feature was dashboard-coupled in 0.10.x. |
GET …/participants — meeting participants endpoint (main PR #453) | post-seal | Merged into main after the 1.5.0 seal; planned back in the 0.12.x line with the next api.v1 contract revision. |
discord as a non-bot ingest platform (main PR #452) | post-seal | The 0.12 platform enum is google_meet / zoom / teams — a contract test asserts DELETE /bots/discord/… → 422. Planned back in the 0.12.x line with the next api.v1 contract revision. |
| Zoom bring-your-own OBF/ZAK tokens + native SDK path (main PR #320) | not carried — planned back in the 0.12.x Zoom track | Verified: the carved bot joins Zoom via the web client only (buildZoomWebClientUrl → app.zoom.us/wc/…/join); no ZAK/OBF token handling and no native-SDK branch exist yet. Authorized-join (tokens and/or SDK) returns with the 0.12.x Zoom work. |
Segment-latency env knobs (main PR #447: MIN_AUDIO_DURATION_SEC, SUBMIT_INTERVAL_SEC, IDLE_TIMEOUT_SEC) | partial | The three knobs exist as programmatic config (SpeakerStreamManagerConfig: minAudioDuration / submitInterval / idleTimeoutSec), but nothing reads them from the environment — a deployment cannot opt into low-latency mode without code. |
max_concurrent_bots=0 treated as depleted, not unlimited (main PR #456) | carried (fixed 2026-07-04) | The gap was found while fact-checking this page and fixed the same day (0.12 PR #44, mirroring main’s #456): a cap of 0 now rejects the spawn as depleted, with a regression test. |
| Swagger/OpenAPI auth-scheme fixes (main PRs #319, #336) | not carried | The 0.12 admin-api declares both APIKeyHeaders without scheme_name — the exact collapsed-scheme Swagger bug #319 fixed; the 0.12 gateway declares no OpenAPI security schemes at all. Cosmetic-but-real DX gap in the served docs (the sealed contract is unaffected). |
| Dashboard-authz + schedule-callback hardening (main PR #406) | superseded by architecture | 0.12 scheduling compiles schedule.v1 jobs that the runtime scheduler fires internally — there is no exposed schedule-callback endpoint to harden. The vendored dashboard rides as an optional compose overlay behind the gateway. |
| Hardened Python Docker builds (main PR #435) | superseded | 0.12 rebuilt all of its images. |
Verified carried (previously uncertain)
- Stop a bot —
DELETE /bots/{platform}/{native_meeting_id}is mounted and live end-to-end: the gateway forwards it and the meeting-api stop router handles it (leave command over redis + direct runtime teardown for a still-booting bot), with route-level tests. - Google Meet lobby-timeout vs host-denial (main PR #460) — carried in a stronger typed
form: admission ends in a typed
AdmissionOutcome(denial|lobby_timeout|join_failure); a denial maps torejected, a lobby timeout to the retryableawaiting_admission_timeout. - WS subscription authz for hex-derived native IDs (main PR #385) — subsumed: the 0.12 authorize-subscribe hop authorizes on DB ownership first; URL constructability is advisory only, so Vexa-generated 16-hex Teams IDs subscribe fine.
- Token scoping (main PR #436 territory) — present: admin token mint issues
vxa_<scope>_…tokens, accepts multi-scope?scopes=bot,tx, and the gateway enforces per-route scopes.
Known defects carried (flagged, not hidden)
- max-bots cap has a TOCTOU race — concurrent
POST /botscan overspill the per-user cap (bounded; reproduced and asserted by the stress lane; likely shared withmain). The atomic fix is on the enhancement list.
What 0.12 delivers instead
- One front door — a single gateway with auth + per-route scopes; server-derived identity
(client-supplied
subjectis ignored everywhere). - The agent control plane — dispatch, streamed chat, routines (cron/event), events, and workspace APIs; sandboxed CLI agents over an OKF v0.1 git workspace.
- Sealed, frozen contracts —
api.v1hash-equal tomain’s OpenAPI 1.5.0, enforced bygate:contract-version; parity itself is a gate (gate:parity). - A gate system
maindoesn’t have — module isolation, acyclic import graph, one front door per module, fail-loud fault surfacing, complete mediation (default-deny), per-service health, license/SBOM cleanliness, an architecture-compliance map. - A real-stack proof lane —
gate:compose+ MOCK_BOT drives the full control plane (join/reject/crash/timeout, recordings, webhook envelopes, WS frames) on every change. - Architecture as code — a validated FINOS CALM model with generated views, enforced in CI.
- The lite / compose / helm deploy trio —
deploy/lite(the whole control plane in one container, process runtime backend),deploy/compose(make all), anddeploy/helm(charts/vexa, bots spawn as Pods viaRUNTIME_BACKEND=k8s). All three are supported deploy paths; lite and helm docs land with the 0.12.x docs push (tracked inDOCS-GAPS.md). - An MCP server for the public API — the 0.10.6 meeting-control MCP service is ported
(9 tools + 4 prompts, stateless, every call authorized by the gateway with the caller’s key)
and runs as its own compose service today. Direction: one MCP server servicing all of Vexa’s
capabilities, fronted by the gateway — no separate service; the standalone port is an interim
exposure until the gateway mounts
/mcp. - The terminal workbench — the primary client surface (docs pending); the vendored dashboard remains available as an optional compose overlay.
- Honest roadmap/status docs — capabilities are claimed only with a green gate behind them.
Release-notes decisions (resolved by the maintainer, 2026-07-04)
- Vexa Lite ships as a supported deploy path — the lite/compose/helm trio; the release-image validation matrix proves it from published images, and its docs land with the 0.12.x docs push.
- MCP: the ported meeting-control server is carried as its own compose service for now; the direction is one MCP server servicing all of Vexa’s capabilities, fronted by the gateway — no separate service long-term.
- Interactive bots (chat / screen share / avatar): planned back in the 0.12.x line — contract-sealed today, control plane not yet wired.
discordingest andGET …/participants: planned back in the 0.12.x line with the nextapi.v1contract revision.
Versioning
Vexa follows semantic-ish versioning at theMAJOR.MINOR line; breaking changes are called out in the
GitHub release notes and mirrored in the migration section above. Pin a specific image with IMAGE_TAG
so deploys are reproducible.