Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7.7 KiB
Media, IndeeHub & AIUI quality — scope from on-device evidence
Written 2026-08-06, end of session. Every item below was observed on archi-dev-box or read from source — none is inferred. This is the input for a proper research + plan pass, not the plan itself.
A. The content-card parser is the "idiotic responses" bug
Operator-visible symptom: asking for Bitcoin films produced good model prose, then cards that were wrong:
Banking on Bitcoincaptioned with The Rise and Rise of Bitcoin's descriptionCryptopiacaptioned with The Bitcoin Standard'sDocumentaries:andNarrative Films:rendered as if they were titlesThe Social Networkcaptioned with Related Financial/Tech Films:
Cause is updatePanelFromText (useContentPanel.ts) pairing title n with description
n-1 and not excluding section headers. The model was not at fault — the card layer
mangled correct prose. Fix the parser before touching prompts.
Deeper question for the research pass: a regex over prose is the wrong contract entirely. The model should return structured recommendations (tool call / JSON), and the grid should render those. D-12 already says node content is the source of truth for these buckets; text-scraping is the legacy path that should shrink, not be patched forever.
B. IndeeHub — three independent faults
- Content source. Films are
projectsin IndeeHub's NestJS API (GET /api/projectsvia its own nginx; port 4000 is not host-mapped;/graphqlis the SPA catch-all, NOT an API). On this node/api/projects/count={"count":0}— the public library is genuinely empty.content.owned-list(content.rs) has no IndeeHub linkage;ownedis Archipelago's own paid-content store. So AIUI has never had a path to IndeeHub content and would render nothing even if wired. - Signer / auth.
GET /api/projects/private→ 401{"message":"Cognito authentication is disabled. Use Nostr login."}. Private films need a Nostr session./api/auth/nostr/session401s through the gate (see C). An adapter must therefore authenticate as the user — which lands on the phase's non-negotiable: keys stay out of the browser and the model, so this belongs node-side behind a capability grant. Same shape as follow-on Phase C (Nostr first-class). - Relay is down independently.
/relayreturns 502 direct on loopback, bypassing the gate — IndeeHub's own nginx cannot reach the relay container.wss://relay.damus.ioalso fails from that page. Not a gate fault.
C. The app gate breaks apps that own their auth — FLEET-WIDE, highest priority
Verified: http://<node>:7778/manifest.json → 401 + the gate's login HTML.
- A PWA manifest is fetched WITHOUT credentials unless the tag sets
crossorigin="use-credentials". The cookie is never sent, so the gate 401s it even when fully logged in. This hits every gated app with a PWA manifest, not just IndeeHub. - The app's service worker serves the cached shell, so the SPA boots ("Backend connected at /api — real mode active") and only then does every network call 401 — which is why it looks like an app bug rather than a gate bug.
- The gate also intercepts the app's own
/api/auth/nostr/session, so IndeeHub can never establish its own session. "Nostr login failed" / "Sovereign identity generation failed" are all this one cause.
Same class as the .125 cookie-strip that broke every companion UI. The gate needs a
stated policy for (a) credential-less subresource fetches the browser sends by design and
(b) app-owned auth endpoints once a valid gate session exists. Each exemption is a hole in
a security control and needs its own written justification — do not batch-fix this.
D. AI Data Access grants do not survive — wrong storage layer
aiPermissions.ts persists to localStorage (archipelago-ai-permissions). No logout path
clears it (only SystemDangerZone, by design). localStorage is per-origin, and a node has
many: 192.168.63.240, 100.69.68.39, <host>.local, the Tailscale name. Granting on one
and returning via another shows everything off — which is exactly what "turns them all off"
looks like, and what made a films search look broken tonight.
These grants are a property of the NODE ("what may the AI read"), not of one browser at one address. They belong node-side behind an RPC, with localStorage as an offline fallback and a migration so existing local grants are not silently dropped.
E. Also observed, unowned
/api/app-catalog→ 502, repeatedly, on the dashboard.- AIUI web search blocked by CSP (
connect-src http://<node>:*/aiui/) — confirms the already-recorded 13-09 decision that the web-search setting must drive the CSP node-side. Failed to scroll to index N after 10 attempts— ChatWindow scroll bug, cosmetic but loud.strfry.png/.svg404 — missing app icon.
Suggested sequencing (to be challenged by the research pass)
- C — fleet-wide, user-visible, security-critical. Blocks any app with its own login.
- D — one RPC; unblocks every AI content path and stops false "broken" reports.
- A — parser fix now, structured-output contract as the real answer.
- B — needs C and D first; the signer question is a design decision, not a task.
Nostr-first framing (per feedback_nostr_first_solutions)
Worth researching rather than assuming: IndeeHub already speaks Nostr for identity, and the
node already holds Nostr identity material. A single node-side signer serving both the
dashboard and gated apps (NIP-07-style bridge, already precedented by nostr-provider.js)
would address B-2, the app-auth half of C, and Phase C's zaps at once. Media identity/
distribution over Nostr (NIP-94/NIP-71 style events, Blossom for blobs) is the obvious
frame for "all the media types" and should be evaluated against the current
content.* RPC model before more sources are bolted onto it.
F. Added by operator 2026-08-06, late — not yet started
- Cmd/Ctrl+K search → AIUI. Choosing "search with AIUI" from the command palette must open the EXPANDED chat with the typed query actually sent to AIUI and answered — today it does not carry the words through. Wire the palette's query into the chat open path.
- Mock data types. Add more mock content types for dev/preview, and make the whole content path performant (the grid, the fan-out, the panel).
- Node questions — full coverage. Every "ask the node about itself" question class should
be answerable: apps, system, network, wallet, bitcoin, files, media, search, ai-local,
notes are the declared
AIContextCategoryset in contextBroker'sfetchAndSanitize. Audit each for real coverage rather than a stub. - AIUI seed/history as design input. The operator asked that the solution be researched from AIUI's own seed/history and the project's Nostr-first ethos, not invented fresh.
G. Status of the fixes made 2026-08-06
Shipped + deployed to archi-dev-box: content-grid sequence guard (aac81503), owned/peer
scopes wired (11b9cb50), per-scope permission logging (7c23505d), warm-up app status
(c65ee03a), scheme-following app frames (f09ff102), per-node CA + Settings flow
(aab74127), app-port TLS with HTTP on the same socket (7515166a), key perms for the
daemon (1dfd9e72).
Shipped, NOT yet deployed: the credential-less allowlist that fixes the IndeeHub
regression — release build was in flight at end of session. Deploy is:
install -m 755 core/target/release/archipelago /usr/local/bin/archipelago then
systemctl restart archipelago (containers are unaffected — verified, they live in
/user.slice, not the service cgroup), then re-test curl -o /dev/null -w "%{http_code}" http://<node>:7778/manifest.json — expect 200, not 401.