Architecture
Concise view of internal structure & responsibilities.
Goals
- Separate presentation (CLI/Rich) from logic (auth, config, clients)
- Safe token lifecycle (acquire, cache, refresh)
- Predictable profile-scoped configuration
- Async I/O for network efficiency
- Minimal global state
Module Map
vantage_cli/
main.py # Typer app + command registration
auth.py # Device code + refresh + persona
cache.py # Token cache load/save
client.py # Low-level HTTP helpers
gql_client.py # Async GraphQL client factory
config.py # Settings + profile mgmt + decorator
constants.py # Paths, filenames, env var names
exceptions.py # Exception hierarchy + Abort helper
format.py # Rich / JSON output helpers
schemas.py # Pydantic models (TokenSet, Persona, Settings, Persona)
time_loop.py # Simple polling / timing utility
Execution Flow
- CLI invoked
- Active profile resolved
- Settings loaded (file + env)
- Tokens loaded / refreshed
- Command executes (GraphQL/HTTP as needed)
- Output rendered (human or JSON)
Authentication Lifecycle
High-level states for token acquisition, caching, usage, and refresh.
Authentication Sequence (Detailed)
Key guarantees:
- No device flow if a valid access token exists.
- Single refresh attempt per command; failures fall back to full device flow.
- Refresh threshold (e.g. < remaining lifetime) triggers proactive renewal.
- Token cache write is atomic (temp file + move) to avoid corruption.
- Abort messages are concise; verbose stack only with
-v
.
Error Handling
- Domain exceptions map to concise messages
- Traceback only with
-v
- Non-zero exit on expected user errors
Models
- TokenSet: access/refresh/expiry
- Persona: identity claims
- Settings: endpoints & client config
Extensibility
- New command groups = sub-app registration
- Decorators inject settings/persona
- Output helpers unify formatting
Performance
- Async network calls
- Early return if tokens valid
- Small JSON read/write footprint
Security
- Token files user-only permissions (expected)
- No token echoing
- Refresh guarded (no infinite retries)
Future Ideas
- Pluggable credential stores
- Streaming subscriptions (GraphQL)
- Verbose timing metrics per command