Files
python-sdk/pkg
zeekayandHanzo Dev 1fe73de0c3 hanzo-sandbox: a client for the sandboxes cloud actually serves
The package is named for the cloud app it speaks to — cloud apps/sandbox is
hanzo-sandbox here — so there is one name per concept across the two languages.

Built against the routes rather than guessed:

    GET|POST   /v1/sandboxes           list, create
    GET|DELETE /v1/sandboxes/:id       get, delete
    POST       /v1/sandboxes/:id/exec  argv | command, stdin, dir, timeoutSec
    GET|POST   /v1/sandboxes/:id/fs    read, write

The API key carries the org, and the client sends nothing else. cloud resolves
it through principal.OrgOf(user, org), which returns nothing without a validated
principal — "no validated principal, so the org claim is untrusted" — and the
gateway strips a client-supplied X-Org-Id before a handler sees it. A first cut
took `org` as a required argument and sent the header on every call; that would
have been ignored at best.

Two things the tests found, both real:

  * with no key configured the client still sent `Authorization: Bearer `, an
    empty credential that reads as a present one and hides "no key" behind
    whatever the server says about a bad one. It sends no header now.
  * cloud spells the size field `class`, which python cannot, so Sandbox maps it
    to `cls` at the boundary instead of leaving callers to index a dict.

This is the REMOTE half. hanzo_sandbox.sandbox stays the local one — unshare,
namespaces, a boundary on this machine. Same word, unrelated concerns, separate
modules.

Served by a real HTTP server in the tests, since what breaks in a client of this
shape is the request: path, method, credential.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 19:36:57 -07:00
..