From 0d6cff444b7a22949f2dd4f68e4b8804ec9e5b4c Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Fri, 25 Sep 2026 23:50:08 -0700 Subject: [PATCH] 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) --- docs/specs/2026-09-25-roncho-requirements.md | 95 ++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/docs/specs/2026-09-25-roncho-requirements.md b/docs/specs/2026-09-25-roncho-requirements.md index d0454b9..aa49893 100644 --- a/docs/specs/2026-09-25-roncho-requirements.md +++ b/docs/specs/2026-09-25-roncho-requirements.md @@ -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.