Two fixes found during live signer-login verification:
1. hasExtension was `computed(() => !!window.nostr)` — window.nostr is a
plain global with no Vue reactivity, so this evaluated once, lazily, on
first read and cached forever. If the extension's content script hadn't
injected yet at that moment (common — extensions often inject slightly
after page scripts start), "SIGN IN WITH EXTENSION" disappeared
permanently, even once the extension finished injecting moments later.
Reported live as "no browser extension or signer option ever shows".
Fixed: hasExtension is now backed by a real ref, seeded from the current
value and upgraded by a short poll (existing waitForSigner() precedent,
same 200ms/timeout shape) so the UI reacts when the extension actually
appears.
2. Added Archipelago's native NIP-07 signer bridge (frontend/public/
nostr-provider.js, copied verbatim from neode-ui/public/nostr-provider.js
— the canonical source) via a <script> tag in index.html. This no-ops
immediately outside an iframe (window === window.top), so a real browser
extension in a standalone tab is unaffected. Inside the Archipelago node
dashboard's iframe, it provides window.nostr backed by the node's own
identity via postMessage to
neode-ui/src/views/appSession/useNostrBridge.ts (already generic — no
per-app allowlist needed for the getPublicKey/signEvent bridge itself,
only for the optional auto-login/identity-picker convenience flow, which
this app doesn't use). Existing login() flow (buildNip98Token ->
POST /api/auth/nostr/session) works unchanged through this bridge.
Together: signing in now works reliably both in the dashboard iframe (no
extension needed at all) and in a direct tab (real extension, now reliably
detected).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first cloud AI agent given the prompt refused it as a suspected prompt
injection: 'nothing else needs to be read' framing, raw-IP fallback, and
being told to wire its own ANTHROPIC_API_KEY into a persistent script. All
three patterns removed; brains are now an operator-supplied optional
OpenAI-compatible endpoint with local heuristics as default. queue/join
documented as blocking ~35s (60s client timeout) matching the real 30s
production QUEUE_TIMEOUT_MS.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Merge BOTFIGHTS.md + BOTFIGHTS-EASY/POLLING/WEBHOOK.md + BOT_SETUP.md into
a single canonical prompt at frontend/public/docs/BOTFIGHTS.md
- Add the previously-undocumented registration step (POST /api/bots,
anonymous, poll vs webhook mode, rate limits, 409/422 behavior)
- Replace the stale botfights.io fallback host with the {{ARENA_URL}} token
(substituted server-side/client-side in later tasks)
- Document the exact HMAC-SHA256 webhook signature derivation, matching
orchestrator.ts (the old bot.js example's verifySignature() was wrong —
it hashed BOT_SECRET directly instead of via the secretHash+signingKey
two-step the server actually uses)
- Document the trash_talk (webhook, snake_case) vs trashTalk (poll,
camelCase) field-naming split, verified against the real zod schemas
- Add the endpoint reference table, troubleshooting table, and arena-as-relay
framing (any node can host an arena; default is the Foundation's)
- Replace root BOTFIGHTS.md with a 4-line stub pointing at the canonical copy
- Delete the four superseded docs (BOTFIGHTS-EASY/POLLING/WEBHOOK.md, BOT_SETUP.md)
- Add /docs/* route to serve markdown setup guides
- Add md to MIME map and SPA catch-all exclusion
- Normalize BOTFIGHTS.md placeholders to YOUR_BOT_ID/YOUR_BOT_SECRET
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
71 static voice files (9.6MB) for round calls, intros, hype lines,
and challenge announces. These play instantly from file instead of
running Kokoro TTS generation in the browser. Dynamic content
(questions, answers, narrations) still uses Kokoro.
Includes Node.js generation script (scripts/generate-voice-files.mjs)
and modified tts.ts to check static file cache before worker generation.
Static audio works even before Kokoro model finishes loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add vite-plugin-pwa with autoUpdate service worker
- Generate SVG + PNG icons (192, 512, apple-touch-icon, favicon)
- Web app manifest with standalone display mode
- Workbox caching: precache assets, cache Google Fonts, NetworkFirst for API
- Apple mobile web app meta tags for iOS home screen
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>