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:
| Key | Carries |
|---|---|
app.odel/context | userId (hashed, or anonymous), timestamp, requestId, plus displayName when the call has one |
app.odel/secrets | The 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.