docs: scope the media/IndeeHub/AIUI work from on-device evidence
Every item was observed on archi-dev-box or read from source, not inferred: the content-card parser mispairing titles with the previous description (the real cause of "idiotic responses" — the model's prose was correct), IndeeHub's three independent faults (empty public library, Nostr-only private auth, relay 502 on loopback), the fleet-wide gate bug that 401s credential-less PWA manifest fetches and app-owned auth endpoints, and AI Data Access grants living in per-origin localStorage when they are a property of the node. Input for a research + plan pass, explicitly not the plan itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7c23505d8c
commit
71bf4f3eaf
@@ -0,0 +1,98 @@
|
||||
# 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 Bitcoin` captioned with *The Rise and Rise of Bitcoin*'s description
|
||||
- `Cryptopia` captioned with *The Bitcoin Standard*'s
|
||||
- `Documentaries:` and `Narrative Films:` rendered as if they were titles
|
||||
- `The Social Network` captioned 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
|
||||
|
||||
1. **Content source.** Films are `projects` in IndeeHub's NestJS API
|
||||
(`GET /api/projects` via its own nginx; port 4000 is not host-mapped; `/graphql` is 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; `owned` is Archipelago's own paid-content store. So AIUI has never had
|
||||
a path to IndeeHub content and would render nothing even if wired.
|
||||
2. **Signer / auth.** `GET /api/projects/private` → 401
|
||||
`{"message":"Cognito authentication is disabled. Use Nostr login."}`. Private films need
|
||||
a **Nostr session**. `/api/auth/nostr/session` 401s 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).
|
||||
3. **Relay is down independently.** `/relay` returns **502 direct on loopback**, bypassing
|
||||
the gate — IndeeHub's own nginx cannot reach the relay container. `wss://relay.damus.io`
|
||||
also 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` / `.svg` 404 — missing app icon.
|
||||
|
||||
## Suggested sequencing (to be challenged by the research pass)
|
||||
|
||||
1. **C** — fleet-wide, user-visible, security-critical. Blocks any app with its own login.
|
||||
2. **D** — one RPC; unblocks every AI content path and stops false "broken" reports.
|
||||
3. **A** — parser fix now, structured-output contract as the real answer.
|
||||
4. **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.
|
||||
Reference in New Issue
Block a user