Boundlane Sheet D-304 / Forwarding decisions

D-304 Team

Forwarding decisions

The forwarder runs on the developer's machine, next to the sandbox runtime. It sends decisions and requests up to the console, and brings reviews back down. Every connection starts on the machine. The control plane never connects in.

Command: boundlane forwardOutbound only

Run it

boundlane forward
Example output
decisions 12, requests 1, applied 0
decisions 3, requests 0, applied 1
note      bl-web-4f2a approved crates.io:443

It runs until you press Ctrl-C, and looks every five seconds. --every 30s changes that. --once does one pass and exits, which is what a scheduled job or a test wants.

What one pass does

  1. Sync. If the team published a host-only revision, load it onto running sandboxes. A path change is left for the next run, and the note says so.

  2. Ship decisions. Read new allow and deny decisions for each sandbox Boundlane started, turn each into a decision record, and upload them.

  3. Ship requests. Send pending requests for more access, with the agent's reason and any notes the runtime attached.

  4. Apply reviews. For each request a reviewer decided in the console, make the same approve or deny call the terminal would, and mark it applied.

The decision record

One record per decision, with these fields and nothing else: time, sandbox, machine, policy revision, kind of event, allowed or denied, destination, program, rule, and the reason for a deny. A destination is a host and port, or a method and path with the query string removed.

No request bodies, no headers, no terminal output, no file contents, no keys. The full field list is in What our cloud receives.

Reading the runtime's stream

The forwarder watches the runtime's log stream for each sandbox and keeps the position of the last event it read. After a restart, or a dropped connection, it resumes from that position, so nothing is sent twice and nothing in the runtime's buffer is skipped.

If the runtime says events were lost, for example because its buffer filled or it restarted, the forwarder starts again from the current position and sends a gap record: the sandbox and the time span it could not read. The console shows the gap as a row. Those decisions are not recovered from anywhere else, and the console does not pretend otherwise.

When the console is unreachable

Records wait on the machine, in ~/.cache/boundlane/spool/, and upload when the control plane answers again. The queue has a limit. If it fills, records are dropped and the forwarder prints how many, so a hole in the console always has an explanation on the machine.

Requests stay pending while the console is unreachable, and the blocked call stays blocked. The sandbox keeps enforcing its policy the whole time. See When something is down.

When a request changed after review

The runtime can refresh a request after it was filed, or replace the sandbox's draft with the agent's own request for the same host. If a reviewer decided the old version, the runtime refuses the decision. The forwarder does not retry it. It puts the request back on the console as pending, or, if the runtime replaced it, asks for a review of the new one. A person always decides the version that gets applied.

Keep it running

Run it as a login item or a user service, so it starts with the machine. It needs no privileges beyond the developer's own account: it talks to the local runtime the same way boundlane run does, and to the control plane with the machine's token.