docs: measured IndeeHub content inventory — the library is empty

"What films are there from my peers" has three causes behind one answer, and
only one is being worked. The tool gap is in flight in a concurrent session
(content_list + SURFACE_TOOLS). Separately and unowned: AIUI declares six
context categories while the broker serves ten, so media/search/ai-local/notes
cannot be requested by AIUI at all — sanitizeMedia sits behind a door AIUI
cannot open, which is likely why the model claimed no capability rather than
reporting an empty library.

And the part neither fixes: measured with a real node-signed Nostr session
through the gate, /api/projects and /api/projects/private both return 0 items.
A correct "0 results" will be indistinguishable from a broken tool, so seed a
project or verify against a peer that has content before calling it done.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-07 04:49:46 -04:00
co-authored by Claude Opus 5
parent 289c19443a
commit f7c541e867
@@ -0,0 +1,83 @@
# IndeeHub content inventory on archi-dev-box — 2026-08-07
Measured, not inferred. Written as a separate file because the surfaces todo and the
resume doc were being edited by a concurrent session at the time.
## The operator's report
Asked AIUI "what films are there to watch from my peers", and the assistant replied
that it *"[doesn't] have a tool that lets me query the content library of IndeedHub"*
and told them to open `localhost:7778` themselves.
Two separate defects sit behind that one answer. **They have different fixes and only
one of them is being worked.**
## 1. The tool gap — already in flight, do not duplicate
A concurrent session is adding a `content_list` tool with `own` / `peers` /
`purchased` / `films` scopes, a `SURFACE_TOOLS` list so grid-ready results are
RENDERED rather than narrated, and a test that every advertised scope reaches a real
dispatch handler. Its own comment names this symptom ("it could find no peer
content"). Uncommitted at the time of writing — `assistant/tools.rs`,
`archyBridge.ts`, `contextBroker.ts` and 7 more.
## 2. The category union is narrower in AIUI than in the broker — SEPARATE, unowned
The broker serves **ten** categories (`neode-ui/src/types/aiui-protocol.ts`):
apps system network wallet files media search ai-local notes bitcoin
AIUI declares **six**, in two places:
aiui/packages/app/src/composables/useArchy.ts:11
aiui/packages/app/src/services/archyBridge.ts:8
→ apps system network wallet files bitcoin
`media`, `search`, `ai-local` and `notes` cannot be requested by AIUI at all — the
string never appears in its source. `contextBroker.fetchAndSanitize` has a working
`case 'media': return this.sanitizeMedia(appStore)` arm on the other side of a door
AIUI cannot open. This is very likely why the model reported having no capability
rather than reporting an empty library.
Whether `content_list` supersedes this or runs beside it is a real design question:
the content scopes and the context categories are two different channels. Decide it
deliberately rather than letting the union drift further.
## 3. The library is EMPTY — the part that will not be fixed by either
Measured on archi-dev-box, with a real Nostr session obtained through the gate
(node-signed NIP-98 → JWT):
| endpoint | auth | result |
|---|---|---|
| `GET /api/projects` | none | `[]`**0 items** |
| `GET /api/projects/private` | Bearer (valid nostr-session) | `[]`**0 items** |
| `GET /api/projects/mine` | Bearer | 404 `"Film not found"` — route does not exist |
So once the tool lands, the honest answer to "what films are there to watch" **from
this node's own library is still "none"**. Anything the operator sees must come from
the `peers` scope — the federated browse over FIPS with Tor fallback, which is the
slow path the concurrent session just made progressive so it no longer blocks `own`.
**Do not let a correct "0 results" read as the tool still being broken.** When
verifying the `content_list` work, seed at least one project into IndeeHub first, or
verify against a peer node that has content — otherwise a fully working tool and a
completely broken one produce the same empty grid. That ambiguity is the same trap
recorded for the AI grants ("ungranted" and "empty library" were indistinguishable).
## Verification recipe (reusable)
The node can sign a real NIP-98 event itself, so IndeeHub's authenticated API can be
exercised with no browser and no extension:
1. `auth.login` on `127.0.0.1:5678/rpc/v1` → capture the `session` **and**
`csrf_token` cookies from the Set-Cookie headers (curl's jar drops session cookies).
2. `node.nostr-pubkey` → the node's pubkey.
3. `node.nostr-sign` with a kind-27235 event, tags `[["u", <exact url>], ["method","POST"]]`.
**The CSRF header is required for signing**`node.nostr-pubkey` is exempt, the
sign is not, and it 401s without it.
4. `POST /api/auth/nostr/session` with `Authorization: Nostr <base64(signed)>` → JWT.
5. Use `Authorization: Bearer <accessToken>` for the private endpoints.
Both the NIP-98 login and the app's own bearer now survive the gate — see
`RESUME-2026-08-06-media-loop.md` item 1.