Bridges

What every bridge out of an agent's sandbox speaks, through link-bridge.

The contract is link-bridge, which link_bridge is, with this machine's keyring beside it (Agent Binding). A bridge is a way out of an agent's sandbox beside its network: the way in, a linked connection's send.sock, the store bridge and the files bridge (Files Bridge), and each of its proxy's routes (Interface). Each takes calls on a Unix socket, one call to a connection.

1. The challenge

The bridge writes {"challenge"}, 64 random hex characters, as a line of JSON (link_bridge::Challenge).

2. Who calls

The caller writes who it is, a line of at most 4 KiB, link_bridge::Proven: {"identity": {"agent", "owner"}, "proof"}, the agent's ID and owner (link_bridge::Identity, each 1 to 64 letters, digits, ., _, - and @), within 5 seconds of the challenge (link_bridge::PROOF_WAIT), the whole exchange.

Its proof

HMAC-SHA256, keyed with the agent's key, of link bridge proof, a zero byte, the challenge, a zero byte, the agent's ID, a zero byte and its owner, in hex (link_bridge::proof).

Its action

Then its action, the bridge's own, as a line of its own, of at most what the bridge takes (link_bridge::CALL_MAX, 48 MiB, at the most: a store's event twice over and a files bridge's largest object as base64).

3. The answer

The bridge looks the agent's key up (link_bridge::Keys) and refuses a call whose agent isn't bound or whose proof isn't that agent's before it reads the action; it takes the caller as its ID and owner alone, never teams it names. It answers with a line, its own or the error envelope, then closes the connection.

The error envelope

link_bridge::Failure, {"error": "<why>"}, with "why" when a caller acts on it: refused (nothing done: who's calling isn't proved, or what it sent isn't a call the bridge reads), busy (nothing done: call again), conflict (nothing done: what the call expected isn't so any more). A bridge's own answers never hold error.

A stream call

A stream call (link_bridge::stream, served by serve_streams) is for a bridge whose answer is bytes as they come, a route's: steps 1 and 2 as above, then the caller sends what the call carries (a request's body) as it comes, without waiting. The bridge answers one line, its verdict (its own, or the error envelope), then its answer as it comes, writing nothing before the verdict. Either side ends it by closing.

What it reaches of another's

A proved call reaches only its own agent's things, unless a role lets it reach another's: a teammate's way in, or a team's folder. Whether it may is link_iam::allows's to say, never the bridge's (Who May Do What). The bridge gives link_bridge::grants the proved identity and the roles it reads at that very call, such as each team's role, and asks for the action on the resource: agent.message on agent:<id>, or bucket.write on bucket:team-<id>/drafts/.

The server

Every bridge runs on one server (link_bridge::serve, or serve_with for one whose answers are async).

Before the proof

Connections not yet proved hold places of their own, 4 of each peer's, the user at the other end (link_bridge::PEER_PROVING), a peer's next closing its own oldest, answered busy, with room for 16 peers (link_bridge::PEERS, 64 in all, PROVING), past which a new peer's is answered busy.

A proved call

A proved call holds one of the bridge's places, one of its agent's and one of its owner's, and is answered busy past any. Its action arrives within the bridge's wait, and its answer is taken within another (link_bridge::Limits, each bridge's own). take_async reads a call's action within 30 seconds (link_bridge::CALL_WAIT).

A caller's side

link_bridge::call and call_at are a caller's side; take and take_async, one call taken by a program that takes its calls itself, with the same deadline before the proof.

The test every bridge passes

Every bridge's tests run link_bridge::conformance::check (the conformance feature) against it, listening: a wrong key, a proof replayed on a new connection, a malformed or overlong Proven, an action it can't read, that none of those runs, a caller that never answers or answers a byte at a time, an action sent a byte at a time, a peer's flood, one agent's calls past its places and everyone's past the bridge's, an answer never taken, and the envelope.