Serve editable world web files and mount the complete host API (T88)

This commit is contained in:
2026-11-12 00:11:20 +00:00
parent ea155ef70b
commit fc07894d52
35 changed files with 440 additions and 293 deletions
+10 -22
View File
@@ -9,27 +9,15 @@ Credential errors use `{"error":"kind","message":"kind"}` with static, secret-fr
Missing routes return 404. Invalid parameters return 400. Authorization failures return 403.
Conflicts return 409. The filing budget returns 429.
## Host listener
## World web mount
`sausage run WORLD` creates one `Cred`, one `Arc<Api>`, and one process runtime.
The API owns its passkey connection and retains ceremony and rate-limit state.
The hook and the host listener share that API.
The listener handles requests on a dedicated thread.
The console shares the credential store, including its decision notifications.
After the listener binds, the runtime denies its port on every local address.
The listener stops when the console returns.
Options on `sausage run`:
- `--api-listen 127.0.0.1:8090`: the default listener address.
- `--api-rp-id localhost`: the default WebAuthn RP ID.
- `--api-origin http://localhost:8090`: the default browser origin.
The origin must name the host pages, not the world server.
The listener speaks HTTP. A production HTTPS origin needs a reverse proxy to this listener.
The world's UI can link to the host pages. It does not serve their code.
The listener identifies browser calls as `/host/browser`, with the host PID and no conversation.
Passkey proofs supply the approver identity independently of that caller.
The world runs `web.wasm` on port 8080 and serves fresh files from `/srv/www`.
It forwards `/api/PATH` to `http://host.sausage/PATH` through WASI HTTP, including streaming bodies.
The host opens no separate network port.
Browser ceremonies derive the passkey RP ID and origin from the request Origin header.
The host retains separate pending ceremony state per origin against the same credential registry.
After the first registration, every decision and further registration requires a passkey assertion.
Host pages use relative assets and routes so they work under `/api/`.
## Pages and assets
@@ -69,7 +57,7 @@ Reads and granted SSH operations do not spend that budget.
The WASI transport dispatches buffered and streaming responses through one route table.
Harness routes use `http://host.sausage/harness/` and the console's input channel.
The host listener does not expose these routes.
The browser reaches these routes under `/api/harness/`.
The V8 harness answers queries and invokes actions without a second storage reader.
- `GET /harness/conversations`: `{conversations:[...]}` with records, titles, agents, starters, concluded state, and running state.
@@ -132,7 +120,7 @@ A replay or a mismatched binding cannot authorize another action.
- `POST /cred/passkeys/register/finish`: `{"challenge_id":"id","response":{...}}`.
WebAuthn options and responses use the library's browser JSON formats.
The host retains the RP configuration and pending ceremony state.
The host derives the RP configuration from each browser origin and retains pending ceremony state.
Restart discards pending ceremonies but retains registered passkeys.
## Secret entry