11 — Operations
Runbooks for the two operator roles in BKA:
- Creator — operating their own creator instance
- Us — operating the central indexer (the only thing we run)
Part A — Creator operations
Day-to-day
The expected creator flow after onboarding:
- Open BKA in the browser
- Compose / draft / publish
- Close
Nothing else is required. No server to restart, no SSL cert to renew (CF handles), no database to back up (GitHub repos are the backup).
Rotating credentials
Every credential is creator-controlled. Rotation paths:
GitHub OAuth token expires or is revoked
- BKA detects 401 on next API call
- Shows "your GitHub sign-in expired, reconnect" with a one-click reauth
- New token replaces the old in localStorage
Cloudflare API token expires or is revoked
- BKA detects 401 on next CF API call (typically when fetching stats or making a Pages config change)
- Shows "your Cloudflare token expired, generate a new one" with deep-link to the CF dashboard pre-filled with the right scopes
- Creator pastes the new token; BKA stores it
Google identity expires
- Standard Google SSO refresh; transparent
Backing up content
Already automatic — content lives in two GitHub repos under the creator's account. Both can be cloned anywhere at any time:
git clone https://github.com/<creator>/<handle>-bka-private.git
git clone https://github.com/<creator>/<handle>-bka-public.git
That's the full backup. No additional steps. For an extra layer of paranoia: GitHub supports per-repo Zip exports from the dashboard.
Migrating to a new GitHub account
If a creator wants to move from one GitHub account to another:
- Use GitHub's repo-transfer feature to move both repos to the new account
- Update the CF Pages project to point at the new repo location (CF dashboard → Pages → project → settings → git → reconnect)
- Sign in to BKA with the new GitHub account; BKA detects the renamed repos via the handle
Cross-account move is rare but supported.
Moving to a new domain
- In CF dashboard, add the new domain to the Pages project
- Add the DNS records (CF gives you the values)
- Wait for SSL to provision (~minutes)
- (Optional) set up redirects from the old domain to the new
BKA's stats tab eventually picks up the new domain when the next CF Analytics fetch happens.
Switching themes
Edit theme.json in the public repo (BKA composer has a theme picker UI that does this for you), commit, push. CF rebuilds with the new theme.
Re-running the onboarding wizard
The settings menu has a "re-run wizard" entry. Useful for:
- Adding a custom domain after initial onboarding
- Provisioning R2 / D1 if opting into comments / subscribers
- Reconnecting an expired CF token
The wizard is idempotent; running it on an already-configured creator skips steps that are already done.
Unregistering from discovery
In settings: "Stop appearing in BKA discovery" → BKA calls the indexer /api/unregister → indexer soft-deletes after 7-day grace.
Creator's site stays up; the indexer just stops pulling their feed.
Leaving BKA entirely
- Repos stay in the creator's GitHub account
- CF Pages site stays on the creator's CF account
- BKA app uninstalls from browser (clear site data)
- Indexer auto-cleans the registration after the next unregister-call OR after 7 days of being unreachable
No "delete my account" action is needed because we don't have an account for them. Identity is Google + GitHub + Cloudflare — all owned by the creator.
Part B — Indexer operations (us)
Stack
- One Cloudflare Worker (the indexer) —
bka-indexerat the binary-blender CF account - One D1 database for the index
- KV namespace for snapshot cache + crawl queue
- Cron trigger every 10 minutes for the crawl scheduler
- Analytics Engine binding for monitoring
- Optional: an admin dashboard route gated by
ADMIN_TOKEN(same pattern as agicore-foundry's admin)
Deploy
Same wrangler workflow as the rest of the binary-blender stack:
cd _Dev/bka-indexer
npx wrangler deploy
npx wrangler secret put GITHUB_TOKEN # bot PAT (limited scopes; see below)
npx wrangler secret put HF_TOKEN # for BabyAI calls
npx wrangler secret put GOOGLE_CLIENT_IDS # comma-separated allowed audiences
npx wrangler secret put ADMIN_TOKEN # for /admin
Secrets
| Secret | Why | Rotation |
|---|---|---|
GITHUB_TOKEN |
Currently no GitHub writes; reserved for future bot-side actions. If unused, omit entirely. | n/a if unused |
HF_TOKEN |
BabyAI proxy auth | rotate yearly or on compromise |
GOOGLE_CLIENT_IDS |
JWT audience allowlist | add new BKA-stack apps as they appear |
ADMIN_TOKEN |
/admin gate |
rotate quarterly |
Monitoring
/admin/stats route renders:
- Total registered creators
- Pull success rate (rolling 24h) per creator (table, sortable)
- Slowest pulls (P95, P99)
- Discovery API qps + latency
- BabyAI call success rate
- D1 + KV usage
Built same shape as agicore-foundry's /admin/usage. Cribbable code.
Abuse handling
What constitutes abuse:
- Creator's feed.json returns malformed data repeatedly → we mark
pausedand stop pulling; show an indexer-side error the creator can see in BKA's stats tab - Creator's feed serves illegal content (CSAM, etc.) → manual report flow; we set
pausedimmediately + email the creator + remove items from index. Source content stays at the creator's edge; that's their problem to handle with their hosting provider (CF) and the law. - A user querying
/api/discoverdoes so absurdly often → rate-limit per IP (10 req/sec, sustained 100 req/min); reject excess with 429. - Someone tries to register a feed they don't control → we validate the feed pulls cleanly + watch for spammy registrations; if abuse becomes a pattern, we add a manual approval step for new registrations.
The indexer's threat model is small because we don't hold content. Worst case: bad metadata appears in discovery. We can purge that quickly.
Takedowns (DMCA / similar)
A takedown request would target a specific URL on a creator's site, not the indexer. We don't have the content; we have a metadata pointer.
Our response: forward the takedown to the creator (via their registered Google email, if they consent to that during registration) and de-index that specific item. The original content remains on the creator's site until they (or their hosting provider, or a court order acting on them) addresses it. This is the same posture as a search engine.
Indexer downtime
If the indexer is offline:
- Creator sites continue to serve normally (they're not in the request path)
- Publishes still work (CF Pages git integration is independent)
- Only the cross-creator discovery API + creator-stats integration are affected
Recovery is just a worker redeploy. Crawl queue resumes from where it left off (KV persists). Lost crawls catch up on the next cron tick.
Scaling (future)
When + if we hit limits:
- D1 5GB: shard by
hash(creator_sub) % N. Each shard is a separate D1 binding. - Worker req/day: cache hot discovery queries in KV with a 1-minute TTL. Most discovery traffic is repeated queries.
- BabyAI rate: same caching helps; long-term, train cheaper specialist LoRAs.
None of these are blockers for v1. All have well-trodden paths.
What we explicitly DON'T operate
To make the discipline visible:
- We don't operate any creator's site. That's CF Pages on their account.
- We don't operate any creator's CDN. Same.
- We don't operate any media servers. GitHub Releases + CF edge cache.
- We don't operate authentication for visitors. Visitors don't authenticate.
- We don't operate analytics for creators' sites. Creators add their own (Plausible / Fathom / nothing).
- We don't operate comments storage. If a creator opts in, comments live in their R2/D1.
- We don't operate email lists. If a creator opts in, subscribers live in their CF account.
The only thing we run is the indexer. That's it. If we ever find ourselves running something else, we should ask whether we've drifted into being a platform.