p2.4: restricted workspace for permitted callers

guardian-star context is allowed only when the authenticated caller is in
permit_restricted and mapped to that workspace. Fleet callers remapped to it
still refuse. CLI client.toml: SIFT_CLIENT, then $HERMES_HOME/sift, then ~/.config.
This commit is contained in:
2026-09-23 08:33:58 -07:00
parent 14eb7808ce
commit e36da19f57
10 changed files with 159 additions and 42 deletions
+9 -6
View File
@@ -46,8 +46,8 @@ Out: `search` (P3), URL→content fetch cache (P4), knowledge graph. (Digest + c
3. Digest latency p50 ≤ 20 s with Dixie otherwise idle.
4. **Guardian unaffected**: during a burst of 10 concurrent digests, a guardian-shaped probe
(`max_tokens` 16, thinking off) has p90 ≤ 5 s. (This is the criterion that matters most.)
5. `context` never reaches `guardian-star`: unit test + a live request with a caller mapped
to it is refused.
5. Restricted workspace: fleet caller mapped to `guardian-star` is refused; only
`permit_restricted` callers whose mapped workspace is that name get context.
6. `--recover` returns a snapshot (with `snapshot_at`) for a bot-walled URL that has a Wayback
copy.
@@ -101,9 +101,11 @@ invalidates; context not stored; eviction under size cap; corrupt DB → warn an
list of messages with `content, created_at, peer_id, session_id, workspace_id, token_count`
(verified 2026-09-22). Timeout 3 s; failure → `warnings`, empty `context`, never an error.
- `ws` = the caller's workspace from `keys.toml`. **Config allowlist of workspaces**
(`context.workspaces = ["hermes-fleet"]`); anything else → no context + WARN. **Hard-coded
refusal of `guardian-star`** in code (not just config) with a test — that workspace is
compartmentalised and must never be read by sift.
(`context.workspaces`); anything else → no context + WARN. **Restricted workspace
`guardian-star`**: allowed only when the authenticated caller is in
`context.permit_restricted` *and* that caller's mapped workspace is `guardian-star`.
A fleet caller remapped to it is still refused (tested). Workspace is never taken
from the request.
- Query: the question if given, else title + top 3 headings.
- Return trimmed items: `{peer, content (≤300 chars), created_at, session}`; label clearly
as prior fleet knowledge, not page content.
@@ -156,7 +158,8 @@ digest_ms fallback`. Never log page content, questions longer than 80 chars, or
falls back immediately; a waiter past `queue_wait` falls back), context cancel propagates
(fake server observes the disconnect).
- Chunk selection: document order restored, token budget respected, no-question path.
- Context: allowlist, `guardian-star` refused even if configured, 3 s timeout → warning.
- Context: allowlist, restricted workspace refused for unpermitted callers even if
allowlisted, permitted caller succeeds, 3 s timeout → warning.
- Recover: Wayback JSON parsing (available/unavailable), `id_` rewrite, fake-success fixtures
(meta-refresh to original, "Just a moment", tiny body), archive.today rotation on 429,
redirect-to-private inside an archive response still blocked (guard).