roncho requirements: addendum, status at v0.1.0 and API keys

What Boxmaker checked of v0.1.0 and the fixes on top of it: the
blocking library now builds and its tests pass, but the quoted
blocking-only test command does not compile (ungated async test
files), and nothing is committed or tagged yet. Five MUST items and
nine SHOULD items remain, a queue-status operation among them. New
requirements R23 to R27 prepare for rift turning on API keys: 401/403
as their own error, an empty key refused, one key per client, keys
wiped on drop, and the live suite able to run with a key. Choices
roncho made that Boxmaker accepts are listed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-25 23:50:08 -07:00
co-authored by Claude Opus 5.5
parent f9d6d51098
commit 0d6cff444b
@@ -199,3 +199,98 @@ and record what you found (or "not found") in the compatibility document. Do not
- The compatibility document covers O1 to O13 and Q1 to Q8, dated, with rift's version.
- The fake-server tests of R21 pass with Rust 1.95; the live suite of R22 passes against rift.
- The owner is told the tag, and anything in this document that could not be done, and why.
## 6. Addendum: status at `v0.1.0`, and API keys (2026-09-25, later)
Boxmaker's review of `v0.1.0` (`1e58d25`) and of the fixes on top of it, which were still
uncommitted when checked. Everything marked "checked" was run by Boxmaker's design model on titan
with Rust 1.95, `--offline`, in a scratch target directory; "reported" is the `roncho` agent's word,
not yet checked here.
### 6.1 Fixed since `v0.1.0`
| Item | State |
|---|---|
| The blocking-only library did not build (`src/error.rs` imported `reqwest`, `src/models/chat.rs` imported `futures`) | checked: `cargo build --no-default-features -F blocking` builds |
| `ClientBuilder` derived `Debug` and printed the key | checked: the only `Debug` derive left in `src/blocking/client.rs` is on `Probe` |
| Streaming never sent `"stream": true`, and decoded UTF-8 per socket read | checked: `"stream"` is sent; the UTF-8 test reported |
| Request bodies not asserted; the live suite passed when unset; 200/201 and the 202 body contradicted each other in the compatibility table | reported |
| Tests of the blocking client | checked: `--lib --test blocking_test` with `-F blocking`: 3 and 9 pass, 1 ignored; with `-F tls`: 4 and 9 pass; the default suite passes |
### 6.2 Still to do (MUST)
- **A1** `cargo test --no-default-features -F blocking`, the command quoted as passing, does not
compile: the async test files (`smoke_test.rs`, `client_test.rs` and the others that
`smoke_test.rs` includes) use `roncho::Honcho` and `futures` without a feature gate. Gate each
with `#![cfg(feature = "async")]`, and run both `-F blocking` and `-F tls` (default features
off) wherever the tests are run, so the next break is caught.
- **A2** Commit, push, and tag a new release from a commit that is on `origin`. The tag's message
must name the compatibility document by the name it has at that commit (`v0.1.0` names
`docs/rift-2026-09-25.md`, which the working tree deletes).
- **A3** `query_conclusions`: rift refuses a query without the observer and observed filters. Make
them required in the blocking request type, or refuse before sending.
- **A4** `create_conclusions`: refuse a batch of 0 or more than 100 before sending.
- **A5** Blocking chat drops `response_format` without a word. Send it, or remove it from what the
blocking options accept.
### 6.3 Still to do (SHOULD)
- **A6** Version requirements: `rustls = "=0.23.45"` and `rustls-native-certs = "=0.8.4"` are exact
pins, so every patch release Boxmaker takes would need a `roncho` release. Use the ordinary
caret form (`"0.23.45"`, `"0.8.4"`). Cargo still unifies compatible versions, so Boxmaker's
no-duplicates rule holds.
- **A7** `dial` tries only the first address a name resolves to. Try each in turn, with the
connect timeout per address: a tailnet name can resolve to IPv6 and IPv4, and one may be
unreachable. Say in the README that name resolution itself is not bounded by the timeout.
- **A8** `Message` requires `session_id`, `workspace_id`, `created_at` and `token_count`. Keep
required only what Boxmaker reads (`id`, `content`, `peer_id`, `session_id`, `created_at`,
`metadata`); make the rest optional, so a server that omits one does not fail a whole search.
- **A9** Mark the blocking `Error` `#[non_exhaustive]`, so the variants of 6.4 are not a breaking
change.
- **A10** O14, a new operation: the workspace's queue status
(`GET /v3/workspaces/{id}/queue/status`, from Q3), so Boxmaker can tell when derivation has
caught up after a sync or a rebuild.
- **A11** Tests: the body cap on chunked and close-delimited bodies (only `Content-Length` is
covered); the request of workspace chat and of the probe; a limit on the fake servers' `accept`.
- **A12** Live suite: workspace chat, streaming and `include_evidence`; the time until a conclusion
appears for a new message (Q3), measured a few times; and whether `observe_me: false` and
`reasoning.enabled: false` stop derivation (Q3), since Boxmaker may use them.
- **A13** The async client's share of R20: the 409 on workspace delete as its own error, the key
optional, and the retry policy written down. Boxmaker uses only the blocking client, so this is
for `roncho`'s other users.
- **A14** `SPEC.md` and `AGENTS.md` still say "async throughout" and list `chrono` and `uuid`; the
README's roadmap still lists a blocking API as out of scope.
### 6.4 API keys (new: MUST unless marked)
Rift will turn authentication on. Q1 found that keys are scoped (to a workspace, a peer or a
session) and that key creation is disabled on rift today (`405 "Feature is disabled"`).
- **R23** A 401 or 403 is its own error variant (for example `Unauthorized { status }`), not a
generic status, so `memoryd` can say "the key for workspace X was refused" and point to a runbook
entry.
- **R24** A key set explicitly but empty is a configuration error, not "no key". With keys on,
silently sending no `Authorization` header hides a mistake. An absent key still means no header
(R10).
- **R25** Each client carries its own key, since keys are per workspace: Boxmaker will build one
client per workspace (its trusted and untrusted workspaces, and each fleet workspace it reads),
each with that workspace's key. Say so in the README.
- **R26 (SHOULD)** Hold the key in memory that is wiped when the client is dropped (`zeroize`, which
Boxmaker already locks at 1.9.0), and never copy it into an error or `Debug` output (R10).
- **R27 (SHOULD)** The live suite takes a key from the environment (for example
`RONCHO_LIVE_KEY`), so it can run once rift has authentication, and checks a refused key
(R23). When rift's authentication is on, re-answer Q1 there: what a workspace key may do in
another workspace, and whether a peer-scoped key is read-only as the docs say.
### 6.5 Accepted as `roncho` has them
- The features `blocking` and `tls` (implying `blocking`), with async on by default; Boxmaker uses
`default-features = false`.
- Defaults for the timeouts (10 s connect, 120 s idle read) and the body cap (8 MiB), which the
caller overrides; the write timeout reusing the read timeout.
- The probe as `GET /health` returning a status. It cannot report a version, since Honcho 3.2 has
no version route.
- Streaming as an `Iterator`; models shared with the async client, timestamps as strings.
- The compatibility document not naming rift or its address, if `roncho` is to be public.
Boxmaker keeps those facts in its own documents. The document should still give the date and
the Honcho version and image as far as they are known.