feat(auth): multi-org OAuth session support via --org flag#139
Merged
platinummonkey merged 4 commits intomainfrom Feb 28, 2026
Merged
feat(auth): multi-org OAuth session support via --org flag#139platinummonkey merged 4 commits intomainfrom
platinummonkey merged 4 commits intomainfrom
Conversation
Adds global --org flag enabling multiple named OAuth sessions for Datadog parent/child sub-organizations. Users can now authenticate to child orgs without falling back to API/App key auth. - Add --org global flag to Cli (works across all 283 commands) - Add DD_ORG env var support (flag > env > config file > default) - Add AuthActions::List / pup auth list to view stored sessions - Storage key: tokens_<site> (default) or tokens_<site>_<org> (named) - Client credentials remain site-scoped (shared across orgs per site) - Add SessionEntry + sessions.json registry (~/.config/pup/sessions.json) - Update login/logout/status/token/refresh to pass org through storage - Logout with --org only removes that org's tokens (safe by default) - Add --org to agent schema global_flags for AI assistant awareness Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Instead of one keychain/file entry per org (tokens_<site>_<org>), store
all orgs for a site under a single entry (tokens_<site>) as a JSON map:
{"__default__": {...}, "prod-child": {...}, "staging-child": {...}}
This means the keychain entry count stays at one per site regardless of
how many orgs are added, avoiding per-item authorization dialogs after
a binary upgrade (when the new binary isn't yet in each item's ACL).
Migration is transparent: on first read, a bare TokenSet (old format)
is promoted to {"__default__": <tokens>} without any user action.
- Remove token_key() helper (no longer needed)
- Add OrgTokenMap, DEFAULT_ORG_KEY, org_map_key(), parse_token_map()
- Rewrite save/load/delete token methods for FileStorage, KeychainStorage,
and LocalStorageBackend to use the map-in-single-entry approach
- delete_tokens removes the entry entirely when the last org is deleted
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Covers the new logic introduced by the multi-org and keychain-consolidation work. No tests existed for any of this before this commit. config.rs: - config_dir() now respects PUP_CONFIG_DIR on native builds (enables isolated test dirs; matches existing WASI behaviour) - test_config_dir_returns_path: guard with ENV_LOCK + clear PUP_CONFIG_DIR - test_config_dir_respects_override: new test for the override path storage.rs (21 new tests): - org_map_key: None, empty string, named org (3) - parse_token_map: new map format, multiple orgs, legacy bare-TokenSet migration, invalid JSON (4) - FileStorage: save/load default org, save/load named org, multiple orgs write to one file, org isolation, delete last org removes file, delete one org preserves others, delete nonexistent is ok, legacy file migration (8) - Session registry: empty list, save and list, dedup, remove, remove nonexistent (5) - TempDir helper for self-cleaning test directories (no external crate) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Previously list() bypassed the formatter entirely — it eprintln'd a human-readable preview to stderr and then println'd JSON, resulting in both appearing together in the terminal regardless of output mode. Now list() delegates to formatter::output(cfg, &sessions), which: - --output=json (default): prints only JSON, no extra lines - --output=table: prints a table with site/org columns - --output=yaml: prints YAML - agent mode: prints JSON only (same as default) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
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
Adds
--org <name>as a global flag enabling multiple named OAuth sessions for Datadog parent/child sub-organizations. Users can now authenticate to child orgs without falling back to API/App key auth.Closes #134
Changes
--orgglobal flag — works across all 283 commands; also readable viaDD_ORGenv var andconfig.yamlpup auth list— new subcommand listing all stored sessions as JSON/table/YAML via the formattertokens_<site>), so the entry count stays at one per site regardless of how many orgs are added. Avoids per-item authorization dialogs after binary upgrades.TokenSetfiles/entries are promoted to the new map format on first read; no user action required~/.config/pup/sessions.jsontracks org labels (no secrets) forpup auth listpup auth logout --org <name>— removes only the named org's tokens; client credentials (DCR) are preserved since they are site-scoped and shared across orgsStorage key design
tokens_datadoghq_com{"__default__": {...}}tokens_datadoghq_com{"__default__": {...}, "prod-child": {...}}client_datadoghq_com{...}Usage
Testing
org_map_key,parse_token_map(including legacy migration),FileStoragemap behaviour (multiple orgs, single file, delete semantics), and the session registry (save, list, dedup, remove)PUP_CONFIG_DIRenv var now respected on native builds (matches existing WASI behaviour) to enable isolated test directoriescargo clippy -- -D warningsandcargo fmt --checkcleanCommits
feat(auth): add --org flag for multi-org OAuth session supportrefactor(auth): consolidate org tokens into one keychain entry per sitetest(auth): add tests for multi-org storage logicfix(auth): route pup auth list through formatter for clean output🤖 Generated with Claude Code