Blame
|
1 | # P2-9: CLI Tool |
||||||
| 2 | ||||||||
| 3 | ## Status |
|||||||
|
4 | Complete — committed to `feat/P2-9-cli-tool` branch. 35 tests passing. |
||||||
|
5 | |||||||
|
6 | ## Deliverables |
||||||
| 7 | ||||||||
| 8 | | File | Description | |
|||||||
| 9 | |------|-------------| |
|||||||
| 10 | | `app/cli/__init__.py` | Package init | |
|||||||
| 11 | | `app/cli/__main__.py` | `python -m app.cli` entry point | |
|||||||
| 12 | | `app/cli/auth.py` | Token storage (save/load/expiry), API URL config, auth header helper | |
|||||||
| 13 | | `app/cli/http.py` | HTTP wrapper with consistent error handling (401/403/404 messages) | |
|||||||
| 14 | | `app/cli/main.py` | Click CLI group with all subcommands | |
|||||||
| 15 | | `app/management/routes.py` | Added `POST /admin/auth/callback` (unauthenticated login endpoint) | |
|||||||
| 16 | | `tests/test_cli.py` | 35 tests covering all commands and error paths | |
|||||||
| 17 | ||||||||
| 18 | ## Commands |
|||||||
|
19 | |||||||
| 20 | | Command | Description | |
|||||||
| 21 | |---------|-------------| |
|||||||
|
22 | | `wikibot login` | Browser OAuth flow → WorkOS AuthKit → localhost callback → exchange code → store JWT. Prompts for username if `needs_username` is true. | |
||||||
|
23 | | `wikibot wiki create <slug>` | Create wiki (options: `--name`, `--purpose`) | |
||||||
| 24 | | `wikibot wiki list` | List wikis in table format | |
|||||||
| 25 | | `wikibot wiki delete <slug>` | Delete wiki (confirmation prompt, `--yes` to skip) | |
|||||||
| 26 | | `wikibot wiki token <slug>` | Regenerate MCP token | |
|||||||
|
27 | | `wikibot wiki grant <slug> <email> <role>` | Grant access (editor/viewer only) | |
||||||
| 28 | | `wikibot wiki revoke <slug> <email>` | Revoke access (resolves email → grantee_id via ACL list) | |
|||||||
| 29 | | `wikibot wiki acl <slug>` | List access grants in table format | |
|||||||
| 30 | ||||||||
| 31 | ## Configuration |
|||||||
| 32 | ||||||||
| 33 | - `WIKIBOT_API_URL` — Base URL (default: `https://dev.wikibot.io`) |
|||||||
| 34 | - `WIKIBOT_WORKOS_CLIENT_ID` — WorkOS client ID (required for login) |
|||||||
| 35 | - `WIKIBOT_WORKOS_AUTHKIT_DOMAIN` — WorkOS AuthKit domain (required for login) |
|||||||
| 36 | - JWT stored at `~/.wikibot/token` with 0600 permissions |
|||||||
| 37 | ||||||||
| 38 | ## Architecture Decisions |
|||||||
| 39 | ||||||||
| 40 | - **HTTP wrapper (`http.py`)** provides `api_request()` and `handle_response()` for consistent error handling across all commands. |
|||||||
| 41 | - **Login flow** constructs the WorkOS auth URL client-side using env vars, rather than redirecting through the server. |
|||||||
| 42 | - **Auth callback** added as unauthenticated route in management middleware (`POST /admin/auth/callback`), since it IS the login endpoint. |
|||||||
| 43 | - **Grant command** restricts roles to editor/viewer only (matching the management API's validation). |
|||||||
| 44 | - **Revoke command** resolves email to grantee_id by fetching the ACL list first. |
|||||||
| 45 | ||||||||
| 46 | ## Test Coverage (35 tests) |
|||||||
| 47 | ||||||||
| 48 | - Auth module: 7 (save/load/empty/missing token, auth header, API URL) |
|||||||
| 49 | - HTTP module: 6 (auth injection, no-auth, response handling 200/401/403/404) |
|||||||
| 50 | - Login: 4 (success, needs_username, exchange failure, missing env vars) |
|||||||
| 51 | - Wiki CRUD: 10 (create success/purpose/error, list/empty, delete confirm/flag/abort) |
|||||||
| 52 | - Token: 1 |
|||||||
| 53 | - Grant: 3 (success, invalid role, owner role rejected) |
|||||||
| 54 | - Revoke: 2 (success, email not found) |
|||||||
| 55 | - ACL list: 2 (with entries, empty) |
|||||||
| 56 | - Error handling: 2 (401 message, network error) |
|||||||