Move credential ceremonies into the world web UI and ignore proxy environment

This commit is contained in:
2026-11-12 06:57:34 +00:00
parent e0c2d8bc8b
commit a74ebd11ba
22 changed files with 209 additions and 356 deletions
+23 -14
View File
@@ -1,6 +1,6 @@
# Run Sausage v3 on Citadel
Use the web chat for conversations. The same web port serves host credential pages through `/api/`.
Use the web UI for conversations, passkeys, approvals, and secret entry. The host serves only JSON through `/api/`.
**TL;DR:** Start a separate v3 world, create the SSH tunnel below, and open http://localhost:8080.
The Nix package supplies the userland bundle, source tree, and enabled chat service.
@@ -75,7 +75,7 @@ The chat selects the configured standing agent by default. Choose another conver
Root #1 remains only as history. A standing-agent rename keeps the same conversation.
The page polls for new entries and shows text, collapsed tools, and pending credential requests.
Use **Send** to submit a message and **Stop** to stop the selected conversation's active turn.
The chat never approves credential requests. Its links open the host's approval pages.
The pending-requests banner opens the approval view in the page. The host verifies the passkey assertion.
Agents edit `/srv/www/index.html`. Each request reads the file fresh without a build or restart.
The terminal console remains optional. Each nonempty console line submits a message to the standing conversation.
@@ -105,7 +105,7 @@ From the laptop, create one SSH tunnel:
ssh -N -L 8080:127.0.0.1:8080 citadel.vpn.surma.technology
```
Open **http://localhost:8080** for chat and **http://localhost:8080/api/register** for the first passkey.
Open **http://localhost:8080**. The first-passkey notice opens the Passkeys view.
The host derives the passkey RP ID and origin from the browser request Origin header.
For direct VPN access, passkeys need HTTPS because non-localhost HTTP lacks a secure context.
Passkeys registered for localhost do not transfer to a production hostname.
@@ -113,13 +113,13 @@ Do not expose the server to other people before the first registration.
### Register, create an item, enter a secret
1. Open `/api/register` and choose a label for the first passkey.
1. Select **Register your first passkey** in the chat notice and choose a label.
2. Complete the browser's passkey ceremony.
3. Ask the agent to file an item creation request through `POST /cred/requests`.
4. Review the request on `/api/approve/REQUEST_ID` and approve it with your passkey.
4. Select the request in the pending-requests banner and approve it with your passkey.
5. Read the item's public metadata to find its item ID and stable field ID.
6. Open `/api/entry/ITEM_ID/FIELD_ID` on the web origin.
7. Enter the secret in the blank host form and complete its passkey ceremony.
6. Select **Enter a secret**, then select the item's secret field.
7. Enter the secret in the blank form and complete its passkey ceremony.
Until the first passkey exists, D53 permits unlocked decisions and first registration.
After registration, decisions require a passkey. Additional registrations require an existing passkey.
@@ -139,12 +139,21 @@ They do not return stored secret values.
### Approve a request
The agent or world UI obtains pending requests from `/harness/credential-requests` or `/cred/requests?state=pending`.
Follow the `/api/approve/ID` link on the web origin through the tunnel.
Follow the `/#approve/ID` link on the web origin through the tunnel.
Review the stored summary and public details, choose limits when applicable, then approve or deny.
The world can file a request. It cannot approve its own request.
Sources: [`host API`](../host/src/api/README.md), [`pages.rs`](../host/src/api/pages.rs),
[`edits.rs`](../host/src/cred/edits.rs), and [`app.js`](../host/src/api/app.js).
For a manual Chrome check against a fresh world on port 8080, run:
```sh
node userland/web/browser-check.mjs
```
The script uses agent-browser and a CDP virtual authenticator. It registers a passkey and approves an item creation request.
Set `AGENT_BROWSER_EXECUTABLE_PATH` if Chrome needs an explicit path.
Sources: [`host API`](../host/src/api/README.md), [`credential views`](../userland/web/credentials-view.js),
[`edits.rs`](../host/src/cred/edits.rs), and [`browser cryptography`](../userland/web/credentials.js).
## Models
@@ -155,8 +164,8 @@ There are no model families or project overlays.
Every agent receives the global `prompt` before its role prompt.
The shared prompt explains how agents inspect their own model and the live harness state.
`sausage init` fills `proxy.base_url` and `proxy.api_key` from `PI_PROXY_BASE_URL` and `PI_PROXY_API_KEY` when present.
Otherwise, it leaves them empty. The host and chat still start.
Run `sausage init`, fill `proxy.base_url` and `proxy.api_key` in the config, then run `sausage run`.
Init leaves both settings empty. The host and chat still start.
A model request with missing settings fails with an error that names the config file.
The proxy no longer requires an item in the credentials manager.
The proxy key is intentionally visible to agents. Do not print it or commit the world config.
@@ -225,7 +234,7 @@ World programs call **`http://host.sausage`** through standard WASI HTTP.
The world web server forwards `/api/PATH` to `http://host.sausage/PATH` through WASI HTTP.
It streams response chunks instead of buffering the entire NDJSON body.
The bootstrap page polls `entries?after=` once per second rather than using a persistent stream.
Keep credential approval and secret entry on host pages.
Use the credential views in the web UI. They call only `/api/cred/...` JSON routes.
| Method and route | Result or request |
| --- | --- |
@@ -238,7 +247,7 @@ Keep credential approval and secret entry on host pages.
| `POST /harness/extensions/NAME/actions/ACTION` | `{args:{...},conversationId?:number}` invokes an exported user action. |
| `GET /harness/models` | Public model catalog without authentication data. |
| `GET /harness/extensions` | Loaded extension status. |
| `GET /harness/credential-requests` | Pending conversation requests with host approval links. |
| `GET /harness/credential-requests` | Pending conversation requests with `/#approve/ID` links. |
The `after` cursor is exclusive. Reconnect with the last record ID.
Streams close when the client disconnects or the harness stops.