Contracts
Anything that crosses a boundary, between modules, services, backends or the frontend, is specified in contracts/ as OpenAPI, JSON Schema or a short Markdown spec. No shared code crosses those boundaries, which is what lets the Go edge serve Nest services and a Python backend join later.
What is specified
| Folder | Specifies | Checked by |
|---|---|---|
http/ | The public API as OpenAPI 3.1, and the generator for frontend and k6 types. | Redocly lint, oasdiff, route parity |
events/ | The event envelope and one JSON Schema per event type and version. | Producers and consumers in both backends |
capabilities/ | Request and response schemas for synchronous module-to-module calls. | Catalog parity, focused backend tests and optional split end-to-end checks |
auth/ | Principal, client-context and service assertions, with test vectors. | Vectors in both backends |
edge/ | The route listing the edge reads from each service. | Split end-to-end suite |
realtime/ | The WebSocket protocol, topics and rooms. | Realtime contract test in CI |
telemetry/ | Required resource attributes and what must never be recorded. | Review; local telemetry check |
ai/ | Task definitions and model pricing. | Catalog parity in CI |
audit/ | The hash chain, with vectors, and the export feed format. | Audit end-to-end suite |
privacy/ | The personal data inventory. | Review when a module changes |
HTTP API
contracts/http/openapi.yaml is the source of truth. Both backends must serve exactly its routes, and backend/HTTP-V1.md describes the behaviour behind them. Two extensions carry Bento-specific facts: x-bento-codes lists the problem types an operation can return, andx-bento-local-only marks routes that exist only outside production, such as the billing simulator.
Generated types
make api-generate writes TypeScript types from the spec into both web frontends, mobile and the k6 workloads; make api-check fails when any copy is stale. The generator has its own dependencies in contracts/http.
Breaking changes
CI compares the spec with the merge base on main using oasdiff and fails on a breaking change. Deliberate compatibility adjustments are recorded in breaking-changes-approved.txtwith their rationale; the current entries cover authentication and account-contract tightening.
Events
Every event shares envelope.v1.schema.json: id, type,source, occurredAt, provenance and data. The type ends in its version, as in account.membership_added.v2. A changed payload gets a new version file, and the old one stays listed as superseded until producers stop emitting it. The optional client IP in provenance is personal data, and only Audit reads it.
| Producer | Schemas | Examples |
|---|---|---|
| Identity | 41 | sign_in_succeeded, mfa_enabled, deleted |
| Account | 18 | created, membership_added, purged |
| Files | 12 | upload_completed, trashed, storage_changed |
| AI | 8 | run_requested, run_succeeded |
| Chat | 2 | message_sent, access_denied |
| Integrations | 17 | API-key, webhook, and MCP lifecycle facts |
| Privacy | 5 | export_requested, export_ready |
| Authorization | 3 | role.created, role_assignment.granted |
| Billing | 6 | subscription.changed, payment_failed |
| Audit | 1 | entry.recorded |
| Notifications | 1 | notifications.inbox_changed |
| Operations | 3 | Staff and maintenance lifecycle facts |
Capabilities and assertions
Capabilities are listed with their callers on the architecture page. Across services, three signed assertions carry identity. All use Ed25519, and each has test vectors both backends must pass.
| Assertion | Carried in | Proves |
|---|---|---|
| Principal | X-Bento-Principal | Who the edge authenticated. A JWT with a lifetime of at most 120 seconds; the edge issues 60. |
| Client context | X-Bento-Client | The client's IP address, for Audit, as seen by the edge. |
| Service | Authorization: Bearer | Which service is calling /internal/capabilities/<name> or /internal/routes. |
The edge learns which service owns each route from GET /internal/routes, refreshed every 30 seconds from the services in EDGE_UPSTREAMS. Edges return 404 for /internal/*and strip any assertion a client sends. How every failure is reported is on the Errors page.
Realtime
GET /v1/realtime upgrades to a WebSocket with the subprotocol bento.realtime.v1 and exchanges JSON text frames of at most 16 KiB. The connection is refused with 403 for a foreign origin, 401 without a session, and 429 beyond 20 connections per principal on one instance.
Client operations
subscribe, unsubscribe, presence.join, presence.update, presence.leave, signal, ping.
Server messages
welcome with a 25-second heartbeat, ack, error, hint, stream, presence, signal, pong, closing.
Topics
account:{id}, account:{id}:manage, principal:{id} and ai-run:{runId}, each authorized when subscribed.
Versioning
Additive changes stay in v1. Anything else becomes bento.realtime.v2.
Telemetry
service.name (bento-<backend>-<role>), service.namespace,service.version, deployment.environment.name, bento.backend,bento.role and bento.modules. http.route is the registered pattern, and error.type is the failure code.
IDs, emails, paths or messages as attributes; a principal, email, address or account on security metrics; any AI prompt, input or output; any realtime content; rate-limit or cache keys.
AI, audit and privacy
AI tasks and pricing
Versioned tasks cover document summaries, grounded fact extraction, image description, rubric-based evidence evaluation, draft-only responses and a workspace assistant. Task definitions include bounded inputs, structured outputs and usage pricing; Go and Nest catalog parity is checked in CI. Retrieval contracts cover lexical/semantic search, while inbound MCP exposes scoped AI tools through OAuth and explicit consent. See contracts/ai/README.md and contracts/auth/mcp-oauth.md.
Audit chain and export
hash-chain.md defines how each entry hashes over the previous one, with vectors.export.md defines the JSON Lines feed written to S3 every 5 minutes.
Personal data inventory
inventory.yaml lists every personal data field, payload, object, mail and log, with its purpose, lawful basis, retention and erasure path. See Compliance.