Documentation Index
Fetch the complete documentation index at: https://docs.ixo.world/llms.txt
Use this file to discover all available pages before exploring further.
What identity looks like in code
Two layers — the oracle’s persistent identity, set once at boot via env vars; and per-user identity, validated on every request via UCAN headers.OracleConfig type lives in packages/oracle-runtime/src/plugin-api/types.ts — plugins read the resolved identity off ctx.identity (a OracleIdentity).
| Layer | What it is | Where it comes from |
|---|---|---|
| Oracle identity | DID + Matrix bot user + on-chain entity | OracleConfig (inline) + ORACLE_DID / ORACLE_ENTITY_DID / MATRIX_ORACLE_ADMIN_* env vars |
| User identity | Per-request DID + UCAN capabilities | Headers on every incoming request (x-ucan-delegation, x-did, …) |
One-time oracle setup
Run the CLI to create the oracle's on-chain entity and Matrix account
did:ixo:entity:...), registers linked resources, provisions a Matrix bot account, and writes both oracle.config.json and .env. Run once per deployment — subsequent deploys reuse the identity.See the CLI reference for every flag.Provision the encryption key for per-room secrets
Verify .env has every identity var
After CLI setup, The runtime validates all of these at boot via
.env contains the core identity vars validated by baseEnvSchema:baseEnvSchema; missing vars fail with a clear message.What the runtime loads on boot
After Matrix init completes in the background, the runtime reads two further pieces of secret material from the oracle’s Matrix account room:- UCAN signing mnemonic — used by
UcanServiceto mint downstream-service invocations. - P-256 encryption key — used by
SecretsServiceto decrypt per-room secrets.
/health, /docs, any host or plugin authExcludedRoutes) stay reachable.
Per-request user auth
Every chat request carries headersAuthHeaderMiddleware verifies on protected routes.
| Header | Required | Purpose |
|---|---|---|
x-ucan-delegation | yes | UCAN envelope authorising this user. Missing → 401 Missing x-ucan-delegation header. |
x-did | no | The user’s IXO DID (set by SDK; runtime also derives it from the UCAN). |
x-matrix-access-token | no | For clients that already have a Matrix session. |
x-matrix-homeserver | no | Matrix homeserver for the user. |
x-timezone | no | Propagates to rtCtx.user.timezone. |
x-request-id | no | Correlation ID for logs and traces. |
AuthHeaderMiddleware:
Validates the UCAN delegation
Calls
createUCANValidator with the oracle’s DID as audience. Verifies signature, expiry, and capabilities. Caches the result for 3 minutes (or until the delegation expires, whichever is sooner).Resolves the user's DID
The delegation’s invoker becomes
req.authData.did. Plugin tool handlers read it as rtCtx.user.did.Attaches RuntimeUserContext to the request
The next middleware (
RuntimeContextBuilder) reads req.authData to build the rtCtx.user field handed to every tool handler — see the Runtime context reference.Opt routes out of auth
Two mechanisms to expose public routes — host-level and plugin-level. Both merge onto the runtime’s built-in exclusion list (/health, /docs, …).
From the host — pass authExcludedRoutes to createOracleApp
From a plugin — implement getAuthExcludedRoutes
weather.plugin.ts.Mint downstream UCAN invocations
When a plugin calls a downstream service on the user’s behalf, it does not reuse the user’s UCAN — it mints a fresh invocation signed by the oracle’sSECP_MNEMONIC, delegating from the user’s delegation.
rtCtx.ucan:
| Method | Purpose |
|---|---|
mintInvocation(target, opts?) | Mint a service-targeted invocation. opts.skipCache forces a fresh signature. |
requireCapability(resource, action) | Throws if the user’s delegation doesn’t include the capability. |
hasCapability(resource, action) | Returns a boolean — non-throwing variant. |
resolveServiceDid(serviceUrl) | Resolves a service URL to its did:web:... identifier. Returns null when the DID document is missing or has no id. |
packages/oracle-runtime/src/modules/ucan/ for the service implementation.
What plugins can and cannot do
- Can: read
rtCtx.user.did,rtCtx.user.matrixUserId,rtCtx.user.ucanDelegation,rtCtx.user.timezone. - Can: call
rtCtx.secrets.getIndex()/getValues()to read per-room secrets. - Can: mint downstream invocations via
rtCtx.ucan.mintInvocation. - Cannot: override the oracle’s identity per request.
- Cannot: issue UCANs as anyone other than the oracle itself.
Where to read next
API endpoints
Which routes are auth-protected and which are public.
CLI reference
create-entity, setup-encryption-key, and the rest of identity setup.Runtime context
The full
rtCtx.user, rtCtx.ucan, rtCtx.secrets surface.Environment variables
Every identity-related env var, declared and validated.