Repository navigation
Closed
Labels
admin-toolsAdmin interface and management toolsAdmin interface and management toolsenhancementNew feature or requestNew feature or requestsecuritySecurity improvements and vulnerability fixesSecurity improvements and vulnerability fixes
Description
Replace the three MCP servers (src/mcp/: species, member, backfill) with an admin-only REST API under /api/admin/*, authenticated by admin API tokens minted with a CLI inside the prod container. A local client keeps its token in ~/.config/basny/. The #461 cron sync then pushes external data through this API.
Decisions (defaults chosen 2026-10-28; change any of them on the PRs)
- Tokens: random, shown once at mint, and stored only as a SHA-256 hash in a new
admin_api_tokenstable (owner member, name, created, last used, optional expiry, revoked). No expiry by default;--expires-daysis optional. Revoke by id. No scopes: a token can do whatever its admin can. - Auth:
/api/admin/*accepts onlyAuthorization: Bearer. It never accepts the session cookie, so CSRF doesn't apply. Every request re-checks that the token's member is still an admin. JSON errors; rate-limited. - Minting CLI:
admin-token mint|list|revoke, shipped undersrc/so it lands in the image. Run asflyctl ssh console --app basny-bap -C "…". - Writes: go through the existing domain modules that refactor: derive MCP tools from Zod and extract domain operations #549 extracted, with Zod validation. Audit and admin notes are stamped with the token's member.
- Port scope: species and member tools get REST endpoints. Backfill CSV import tools are not ported, since that import is done.
- Order: stacked PRs: the foundation, then the species and member ports in parallel, then deleting MCP. The
mcpkey in prod and stagingCONFIG_JSONis removed only after the deletion is deployed.
Tickets
- Foundation: token table, CLI, bearer middleware,
GET /api/admin/whoami - Species endpoints (ports
species-server-core.ts) - Member endpoints (ports
member-server-core.ts) - Delete MCP servers, SDK dependency, config, and docs
- Decide: enable Wikipedia/GBIF enrichment in prod or remove the External Data page #461: remove the in-app External Data page/sync; scripts push over REST (supersedes Deploy External Data Cron to Production #249)
Documentation (every ticket)
Each PR updates the docs for what it changes:
- Foundation:
docs/ADMIN_API.md(mint, store in~/.config/basny/admin-token, use, revoke), linked from README, the ops skill anddocs/DEPLOY.md; a CONTEXT.md term. - Endpoint ports: one section per resource in
docs/ADMIN_API.md(route, body, response, errors, curl example). - MCP deletion: remove or rewrite every MCP reference:
src/mcp/README.md,.mcp.json, README,docs/app-startup.md,e2e/README.md, CI, eslint and tsconfig config. - Decide: enable Wikipedia/GBIF enrichment in prod or remove the External Data page #461:
scripts/README_EXTERNAL_DATA.md,infrastructure/CRONTAB.md, mobile-audit docs; the REST pusher documents the cron setup.
Metadata
Metadata
Assignees
Labels
admin-toolsAdmin interface and management toolsAdmin interface and management toolsenhancementNew feature or requestNew feature or requestsecuritySecurity improvements and vulnerability fixesSecurity improvements and vulnerability fixes
Activity
Say the REST push to prod waits on #595, and that image downloads wri…
Port the member MCP tools to /api/admin/members
Remove the in-app External Data page; enrichment runs off-box (#461) (#…
Add an admin-only REST API seam with CLI-minted bearer tokens
Let scripts act as an admin over a bearer-token API, not MCP (#597)
Port the species MCP tools to /api/admin/species
Port the species MCP tools to /api/admin/species (#598)
Port the member MCP tools to /api/admin/members
Manage Members over the admin API, with guards against locking yourse…
Delete the MCP servers; the admin API replaces them
Delete the MCP servers; the admin API replaces them (#600)
Push external species data to prod over the admin API (#595, #461)
Push enriched Species data to prod over the admin API, so enrichment …
jra3 commentedon Oct 28, 2026
Note
🤖 Claude Opus 5.5 responding on behalf of John Allen
Every ticket is merged to main: #597 (tokens, CLI, bearer auth), #598 (species endpoints), #599 (member endpoints), #600 (MCP deleted), #601 (external-data pusher). Docs:
docs/ADMIN_API.md,docs/EXTERNAL_DATA_CRON.md.Not in prod yet. After deploying: mint a token (command in ADMIN_API.md), then remove the
mcpkey from prod's and staging's CONFIG_JSON (docs/DEPLOY.md, "After the MCP removal deploys").Follow-ups not filed: an OpenAPI spec generated from the routes' Zod schemas, and keeping image attribution/license through
PUT /species/:id/external-data.