Admin access: unified privileged-surface auth + admin-ops control surface + Atlas hardening#97
Merged
Merged
Conversation
…on registry Introduce POST /admin/:op (plus a GET /admin/index-stats alias) on the existing server, dispatched through an operation registry so future ops are a one-line registration. Bearer auth reads PATHFINDER_ADMIN_TOKEN with a length-guarded constant-time compare and fails closed: when the token is unset/empty the routes return 503, so the feature can ship before the secret is provisioned. Seed the registry with reindex (full/source/repo, mapping to the orchestrator's existing queue methods, returning 202) and index-stats (reusing getIndexStats and the same projection /health uses). Each invocation is audit-logged and reindex fires a best-effort Slack notice; the registry documents how to add config-reload, setting-set, reembed, atlas-cache-invalidate, and smoke as future ops.
Cover fail-closed 503 when PATHFINDER_ADMIN_TOKEN is unset or empty, 401 on a missing or invalid token, 202 reindex dispatch for the full/source/repo scopes against an injected orchestrator, 400 on malformed bodies, 404 on unknown ops, and the index-stats response shape via an injected getIndexStats.
The reindex op accepted any non-empty source/repo string and returned 202, then silently no-oped in the orchestrator drain when the name was a typo. Now scoped reindexes are validated against getServerConfig().sources: an unknown source returns 400 unknown_source and an unknown repo returns 400 unknown_repo, with the orchestrator only invoked on a match. A throwing config read fails closed as 503 config_unavailable rather than 202. Also widen the test-only orchestrator setter to cover all three queue methods the reindex op calls, log index-stats failures through formatErrorForLog to match the other admin-ops log sites, and drop the dead .catch on the fire-and-forget Slack notify (it never rejects).
Add red-green coverage for the new validation: unknown source/repo return 400, and the happy-path tests now target a source/repo present in the getServerConfig mock so they still reach 202. Make the index-stats failure test deterministic by injecting a throwing getIndexStats and asserting the exact 503 index_unavailable body with no DB detail leak, and add a dispatch 500 no-leak test driving a throwing reindex handler. Drop the `as never` casts on the orchestrator fakes now that the setter type is widened, and supply the missing queue methods on the atlas-ratification fake.
Replace the brittle substring-matched not-pending error in the atlas db module with an exported AtlasSeedNotPendingError, and detect it by instanceof (with a defensive code-string fallback) in the ratification error handler. Add HTTP route tests asserting 409 when approving or rejecting a missing/non-pending candidate.
…-surface auth A wrong bearer token (length mismatch or byte mismatch) on the shared analytics/Atlas/admin-ops auth now returns 401 unauthorized instead of 403 forbidden, per RFC 7235. Update the analytics auth tests to assert the 401 unauthorized shape.
Replace the separate PATHFINDER_ADMIN_TOKEN auth with adminOpsAuth delegating to the shared bearerTokenAuth (requireAnalyticsEnabled: false), so the existing ANALYTICS_TOKEN gates analytics, Atlas ratification, and admin ops with one credential. No new env var. Admin ops now return 503 when no token is configured, 401 on a missing or invalid token, and honor the dev-localhost bypass. Rewrite the admin-ops tests against the shared auth model and drop the as-never casts in favor of typed fixtures.
Describe the bearer token as the shared admin-access credential (ANALYTICS_TOKEN) gating analytics, Atlas ratification, and admin ops, and note the 401-on-wrong-token and dev-localhost-bypass behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a remotely-triggerable admin control surface to the Pathfinder docs-MCP server AND unifies authentication across all privileged surfaces under a single "admin access" credential.
POST /admin/:opoperation registry withreindex(scope: full / source / repo) andindex-statsops, plus aGET /admin/index-statsalias. Reindex validates the requested source/repo against the configured sources (returns 400unknown_source/unknown_reporather than silently accepting). Audit-logged; documented extension points for future ops.bearerTokenAuthagainst the existingANALYTICS_TOKEN. The admin endpoint reuses this already-provisioned credential — no new secret is required. (Removed the separatePATHFINDER_ADMIN_TOKEN/ dedicated admin auth middleware.)401 unauthorizedacross all privileged surfaces (previously analytics/Atlas returned403). Missing-token stays401; no-token-configured stays fail-closed503; analytics-read still404when analytics disabled.AtlasSeedNotPendingError(stablecode: "ATLAS_SEED_NOT_PENDING"), matched cross-module byinstanceof+ code fallback. Added route-level 409 coverage (approve/reject of a non-pending candidate).Security notes
err.message(no DB-URL/connstring exposure).nodeEnv === "development"+ localhost), so a local dev server accepts admin calls without a token. Production is unaffected (the bypass fails closed behindtrust_proxy).Deployment
ANALYTICS_TOKENis already set on the productioncopilotkit-docsservice and now also gates admin-ops. Takes effect on the next deploy.Testing
Review
toDatevalidation, moving the approve-time reindex enqueue outside the DB write's try/catch) and minor admin-ops test-coverage/comment polish.