Renoxium Docs Pricing Sign in Sign up

Contracts

A contract is the written interface between two tracks (docs/18-build-plan.md, "a track may consume another track's output only through a written contract"; docs/22-development-plan.md, section 2). Both sides build against the merged contract, so the Rust and TypeScript work can run in parallel without waiting on each other's code.

Rules:

  • Only type:contract issues change files here. A breaking change bumps the contract's version and lands in one PR together with both consumers.
  • Each contract has a prose document, a machine-readable schema, and at least one valid and one invalid example per message under examples/<contract>/.
  • Unresolved points are listed at the end of each document under "Open".
ContractBetweenFileIssueStatus
Runtime ops and ctxrenox-runtime (P1) ↔ SDK (P10), cell (P5)ops.md, ctx.d.ts, ops.schema.json#12 (v0), #17, #153, #201, #206, #226, #263, #272, #3151.6.0 (principal, guard, op_authz_*, db.scoped(), realtime, App MCP, jobs; the jobs module's op_jobs_list / _retry / _cancel; implemented by F5-ALL and #297)
Artifact format and route tablecell (P5), gateway (P3), CLI (P11) ↔ control plane (P12)artifact.md, schemas/manifest.schema.json, schemas/route-table.schema.json#15 (v0), #152, #227, #263, #272, #318, #346, #3631.5.2 (v0 accepted; 1.5.1: the platform domain, #363; 1.5.2: renoxium.app)
Meter recordrenox-meter (P4) ↔ billing (P14)meter.md, schemas/meter-record.schema.json#16 (v0), #152, #226, #2720.3
Client eventsclient script (P10) ↔ gateway (P3) ↔ dashboard (P13)client-events.md, schemas/client-event.schema.json#125v0
Error codesevery component ↔ tenantserrors.md#91 (v0), #152, #50, #251, #272, #3150.4 (+ RENOX_JOB_*)
Module manifest, renox.toml [modules], renox.lockbroker (P9) ↔ CLI (P11) ↔ modulesmanifest.md, schemas/module-manifest.schema.json, schemas/renox-lock.schema.json#225, #2721.1
Deploy API, worker control messages, node listenerCLI (P11), cell (P5), dashboard (P13) ↔ control plane (P12)deploy-api.md, schemas/deploy-api.yaml, schemas/node-listener.yaml, schemas/control-messages.schema.json#50, #184, #222, #251, #273, #303, #315, #319, #346, #3630.5.3 (0.5.2: the API, dashboard and tenant hosts, #363; 0.5.3: renoxium.app)

Domains

The reference deployment (#363) uses two domains, split on purpose:

DomainServes
renoxium.app (the platform domain)Tenant apps only: <app>.renoxium.app, preview hosts <app>-<hash>.renoxium.app, the custom-domain CNAME target edge.renoxium.app. On the Public Suffix List (ops/psl/).
renoxium.comThe company and the platform's own services: the site at renoxium.com, dashboard.renoxium.com, api.renoxium.com, mcp.renoxium.com, docs.renoxium.com; mail (security@, abuse@, [email protected]).

Why: a tenant's phishing page must never cost the company domain its reputation, its mail deliverability or the dashboard's cookies (docs/24-threat-model.md C, "Shared-domain reputation" and "Custom domain takeover"). renoxium.app and renoxium.com share the brand but are separate registrable domains, so a block or a bad reputation on one does not reach the other. renox.rs is not used by the platform (it is only the repository's name). Rule: a platform service never lives under the platform domain. The reserved slugs of control/api/src/apps/slugs.ts (api, dashboard, www, and the rest) stay as defence in depth, so no tenant can claim such a name even if an operator puts a service there by mistake.

Both domains are operator configuration (CONTROL_PLATFORM_DOMAIN, CONTROL_DASHBOARD_URL and the other settings of control/api, worker.toml for a node); the values above are the reference deployment, so the contracts stay operator-neutral. A contract that names a host writes <app>.<platform domain> in prose and the reference values in examples.

Schema $id values (https://renoxium.com/contracts/<contract>/v<n>/<file>) are names, not URLs anyone fetches: consumers load the files from this directory and use the $id only to resolve $ref between them. The OpenAPI file schemas/deploy-api.yaml has no $id keyword; its name is https://renoxium.com/contracts/deploy-api/v0/deploy-api.yaml (control/api/src/contract.ts).

Checking

bunx tsc --noEmit -p docs/contracts      # ctx.d.ts and the type-level examples in ctx.usage.ts
bun run docs/contracts/validate.ts       # JSON examples vs schemas, artifact rules V1-V27, meter rule M1 (and the route form per kind in the meter schema), client-event rules CE1-CE2, route rules R1-R3,
                                         # module manifest rules MF1-MF14 (TOML examples and example projects),
                                         # deploy-api.yaml examples and state machines, error catalogue vs ops.md/ctx.d.ts/deploy-api/23-failure-modes.md

Schemas are JSON Schema 2020-12: ops.schema.json at the top level, the others under schemas/; schemas/deploy-api.yaml is OpenAPI 3.1, whose schemas use the same keyword subset and may $ref the files under schemas/. *.valid.json files must validate and *.invalid.json files must not; each invalid file says why in $comment, and [expect: <reason>] in that comment makes validate.ts check it fails for that reason. The TOML examples of manifest.md (examples/manifest/) carry the same [expect: <reason>] in a TOML comment instead. validate.ts has no dependencies and implements only the schema keywords these files use; a schema with any other keyword fails the check.

Source on GitHub