P2-9: CLI Tool

Status

Complete — committed to feat/P2-9-cli-tool branch. 35 tests passing.

Deliverables

File Description
app/cli/__init__.py Package init
app/cli/__main__.py python -m app.cli entry point
app/cli/auth.py Token storage (save/load/expiry), API URL config, auth header helper
app/cli/http.py HTTP wrapper with consistent error handling (401/403/404 messages)
app/cli/main.py Click CLI group with all subcommands
app/management/routes.py Added POST /admin/auth/callback (unauthenticated login endpoint)
tests/test_cli.py 35 tests covering all commands and error paths

Commands

Command Description
wikibot login Browser OAuth flow → WorkOS AuthKit → localhost callback → exchange code → store JWT. Prompts for username if needs_username is true.
wikibot wiki create <slug> Create wiki (options: --name, --purpose)
wikibot wiki list List wikis in table format
wikibot wiki delete <slug> Delete wiki (confirmation prompt, --yes to skip)
wikibot wiki token <slug> Regenerate MCP token
wikibot wiki grant <slug> <email> <role> Grant access (editor/viewer only)
wikibot wiki revoke <slug> <email> Revoke access (resolves email → grantee_id via ACL list)
wikibot wiki acl <slug> List access grants in table format

Configuration

  • WIKIBOT_API_URL — Base URL (default: https://dev.wikibot.io)
  • WIKIBOT_WORKOS_CLIENT_ID — WorkOS client ID (required for login)
  • WIKIBOT_WORKOS_AUTHKIT_DOMAIN — WorkOS AuthKit domain (required for login)
  • JWT stored at ~/.wikibot/token with 0600 permissions

Architecture Decisions

  • HTTP wrapper (http.py) provides api_request() and handle_response() for consistent error handling across all commands.
  • Login flow constructs the WorkOS auth URL client-side using env vars, rather than redirecting through the server.
  • Auth callback added as unauthenticated route in management middleware (POST /admin/auth/callback), since it IS the login endpoint.
  • Grant command restricts roles to editor/viewer only (matching the management API's validation).
  • Revoke command resolves email to grantee_id by fetching the ACL list first.

Test Coverage (35 tests)

  • Auth module: 7 (save/load/empty/missing token, auth header, API URL)
  • HTTP module: 6 (auth injection, no-auth, response handling 200/401/403/404)
  • Login: 4 (success, needs_username, exchange failure, missing env vars)
  • Wiki CRUD: 10 (create success/purpose/error, list/empty, delete confirm/flag/abort)
  • Token: 1
  • Grant: 3 (success, invalid role, owner role rejected)
  • Revoke: 2 (success, email not found)
  • ACL list: 2 (with entries, empty)
  • Error handling: 2 (401 message, network error)
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9