Odel

The Odel envelope

Send each caller's identity and their own credentials to your gateway's server in _meta — what rides, what does not, and what it asks of people who already installed.

A gateway puts Odel in front of a server you run. By default Odel relays the call and nothing else: your upstream credentials go out as headers, and the JSON-RPC message reaches your server as the client wrote it.

The Odel envelope adds one thing. On the gateway's Sharing card in the developer portal, the Odel envelope switch attaches Odel's own _meta to each tools/call, carrying who is calling and the credentials that caller supplied when they installed the gateway. It is what makes a server written with @odel/module-sdk work behind a gateway instead of only as a module hosted on Odel.

The switch is off until you turn it on, and only an admin or owner of the organization that owns the gateway can move it. A registry entry cannot have one: the server belongs to its vendor, not to your organization, and the portal refuses the change.

What rides in _meta

Two keys, both under Odel's reserved app.odel/ prefix:

KeyCarries
app.odel/contextuserId (hashed, or anonymous), timestamp, requestId, plus displayName when the call has one
app.odel/secretsThe per-user credentials this caller entered when they installed the gateway

The two are separate so that identity can be logged and the secret map cannot. Read them with getModuleContext and getRequiredSecret — see Context and secrets.

What does not ride in it

app.odel/secrets is the installer's own values and nothing else. The credentials you set on the gateway — the shared ones every caller uses, any static headers, and an upstream OAuth token — stay where they were: in the request headers. Turning the envelope on does not move them, and a server that goes looking for them in _meta finds nothing.

This is the mistake worth naming, because it is silent: your server reads app.odel/secrets, finds no key under the name of the shared credential, and either fails a request it should have served or falls back to something it should not. The credential was in the header the whole time.

Only tools/call

The envelope is attached to tools/call and no other method. tools/list, initialize, resources/read and everything else reach your server without it.

app.odel/* is Odel's namespace on every method, not only the ones it writes. A client that puts its own app.odel/context or app.odel/secrets on any request has those keys removed before the message leaves Odel, so your server cannot be handed a forged identity or a forged credential. On tools/call the whole _meta is replaced with Odel's — a client's other _meta keys go with it. On every other method the rest of _meta survives, so a progressToken still reaches you.

Headers are unchanged

Turning the envelope on changes nothing about the headers. Your upstream credentials arrive exactly as they did before, and they remain the only evidence a request came from Odel. Nothing in _meta is signed: a request carrying a well-formed app.odel/context is not proof of anything on its own. Authenticate the caller with the credential in the header, then read the envelope for who it is acting for.

Turning it on asks people to confirm again

Before someone's first envelope-on call, they have to have seen what it sends. The install page tells them:

This module runs on the creator's own server; Odel relays your calls to it. Your identity and the credentials you enter here are sent to that server with each call.

An install made before you turned the switch on never saw that line. So flipping the switch on marks every existing install as needing confirmation: the next call each of them makes is refused with the ordinary install challenge, their client sends them to the install page, and one click puts them back. They keep their credentials and their upstream sign-in — the click records the disclosure, nothing else.

Plan the flip

Every current user of the gateway is interrupted once, at whatever moment their client next calls. Turning the envelope back off costs nothing: an install that consented is still an install, and no one is asked anything.

On this page