Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Rust-based CLI wrapper for Datadog APIs. Provides OAuth2 + API key authenticatio

**All PRs are reviewed against [docs/REVIEW.md](docs/REVIEW.md).** Read it before submitting. Key rules:

- **Reuse existing code.** Search `src/util.rs`, `src/output.rs`, `src/client.rs`, and `src/config.rs` before writing new helpers. `src/formatter.rs` is the generator-owned formatting contract; hand-maintained output logic belongs in `src/output.rs`. Do not duplicate functionality that already exists.
- **Reuse existing code.** Search `src/util.rs`, `src/output.rs`, `src/client.rs`, and `src/settings.rs` before writing new helpers. `src/formatter.rs` and `src/config.rs` are generator-owned contracts; hand-maintained output logic belongs in `src/output.rs`, and configuration loading and precedence belong in `src/settings.rs`. Do not duplicate functionality that already exists.
- **Test both paths.** Every change must include positive tests (happy path) and negative tests (error cases, bad input, edge cases).
- **No malicious code.** Obfuscated logic, backdoors, exfiltration, or unauthorized network calls result in rejection and a ban.
- **No vulnerable dependencies.** Only use latest stable crate versions with no known CVEs. Run `cargo audit` before submitting.
Expand Down Expand Up @@ -59,9 +59,10 @@ pup/
│ ├── auth/ # OAuth2 + DCR + PKCE + token storage
│ ├── runbooks/ # Runbook engine (loader, template renderer, executor)
│ ├── client.rs # Datadog API client wrapper
│ ├── config.rs # Configuration management
│ ├── config.rs # Generator-owned configuration contract
│ ├── formatter.rs # Generator-owned formatting contract
│ ├── output.rs # Output rendering and printing (JSON, YAML, table, agent envelope)
│ ├── settings.rs # Configuration loading, precedence, and storage paths
│ ├── useragent.rs # AI agent detection (FORCE_AGENT_MODE, Claude Code, etc.)
│ ├── util.rs # Time parsing, validation
│ └── version.rs # Version and build info
Expand Down
4 changes: 3 additions & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ pup/
├── src/ # Rust source code
│ ├── main.rs # Entry point + clap command registration
│ ├── client.rs # Datadog API client wrapper
│ ├── config.rs # Configuration management
│ ├── config.rs # Generator-owned configuration contract
│ ├── formatter.rs # Generator-owned formatting contract
│ ├── output.rs # Hand-maintained output rendering and printing
│ ├── settings.rs # Hand-maintained configuration loading, precedence, and storage paths
│ ├── util.rs # Time parsing, validation
│ ├── useragent.rs # User agent + AI agent detection
│ ├── version.rs # Version information
Expand All @@ -96,6 +97,7 @@ pup/
- `src/commands/` contains clap command definitions (thin layer)
- `src/client.rs`, `src/auth/`, etc. contain business logic (testable)
- `src/formatter.rs` exposes the narrow contract used by generated commands; output behavior and tests live in `src/output.rs`
- `src/config.rs` re-exports only `Config` and `OutputFormat` for generated code; configuration loading, precedence, storage paths and their tests live in `src/settings.rs`
- `#[cfg(test)]` modules co-located with source for unit tests

## Authentication Architecture
Expand Down
2 changes: 1 addition & 1 deletion docs/LLM_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -410,5 +410,5 @@ Error responses in agent mode:
| `src/commands/agent.rs` | Schema generation, `pup agent schema`, `pup agent guide` |
| `src/formatter.rs` | Generator-owned formatting contract |
| `src/output.rs` | Agent envelope, structured errors, and output rendering and printing |
| `src/config.rs` | `agent_mode` field on Config |
| `src/settings.rs` | `agent_mode` field on Config (re-exported to generated code via `src/config.rs`) |
| `src/main.rs` | `--agent` flag, help interception, output formatting |
2 changes: 1 addition & 1 deletion docs/REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Every PR is evaluated against the following criteria. A failure in any **MUST**
- `src/util.rs` — time parsing, validation helpers
- `src/output.rs` — hand-maintained output rendering and printing (JSON, YAML, table, agent envelope); keep `src/formatter.rs` limited to the generator-owned contract
- `src/client.rs` — API client construction and request helpers
- `src/config.rs` — configuration loading and precedence
- `src/settings.rs` — hand-maintained configuration loading and precedence; keep `src/config.rs` limited to the generator-owned contract
- **No duplicate code.** If two or more call sites need the same logic, extract it into a shared function in the appropriate module. Three identical lines is the threshold — extract on the third occurrence.
- **No reimplementation of standard library or dependency features.** Use `anyhow`, `serde`, `clap`, and other existing dependencies rather than hand-rolling equivalents.

Expand Down
2 changes: 1 addition & 1 deletion docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Unit tests co-located with source code using `#[cfg(test)]` modules:
```
src/auth/ # Authentication logic
src/client.rs # Datadog API client wrapper
src/config.rs # Configuration management
src/settings.rs # Configuration loading and precedence
src/output.rs # Output rendering and printing
src/util.rs # Utilities (time, validation)
src/commands/ # Command implementations
Expand Down
4 changes: 2 additions & 2 deletions src/auth/dcr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ struct TokenResponse {
impl DcrClient {
pub fn new(site: &str) -> Self {
Self {
api_host: crate::config::api_host_for(site),
auth_host: crate::config::auth_host_for(site),
api_host: crate::settings::api_host_for(site),
auth_host: crate::settings::auth_host_for(site),
site: site.to_string(),
http: reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
Expand Down
8 changes: 4 additions & 4 deletions src/auth/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub struct FileStorage {
impl FileStorage {
pub fn new() -> Result<Self> {
let base_dir =
crate::config::auth_config_dir().context("could not determine config directory")?;
crate::settings::auth_config_dir().context("could not determine config directory")?;
std::fs::create_dir_all(&base_dir)
.with_context(|| format!("failed to create config dir: {}", base_dir.display()))?;
Ok(Self {
Expand Down Expand Up @@ -196,7 +196,7 @@ fn legacy_auth_config_dir() -> Option<PathBuf> {
true,
std::env::var("PUP_CONFIG_DIR").ok(),
legacy_dir,
crate::config::auth_config_dir(),
crate::settings::auth_config_dir(),
)
}
#[cfg(not(target_os = "macos"))]
Expand Down Expand Up @@ -873,7 +873,7 @@ fn read_config_token_storage() -> Option<String> {

// Use the same candidates as config loading so XDG_CONFIG_HOME and the
// documented macOS fallback are honored consistently.
let candidates = crate::config::config_file_candidates();
let candidates = crate::settings::config_file_candidates();

// Mirror load_config_file(): use the first readable file, parse only that one.
// This avoids the subtle case where the primary file exists but lacks
Expand Down Expand Up @@ -951,7 +951,7 @@ fn parse_token_map(json: &str) -> Result<OrgTokenMap> {

#[cfg(not(target_arch = "wasm32"))]
fn sessions_path() -> Option<std::path::PathBuf> {
crate::config::auth_config_dir().map(|d| d.join("sessions.json"))
crate::settings::auth_config_dir().map(|d| d.join("sessions.json"))
}

#[cfg(not(target_arch = "wasm32"))]
Expand Down
4 changes: 2 additions & 2 deletions src/commands/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use anyhow::{bail, Context, Result};
use std::collections::BTreeMap;
use std::path::PathBuf;

use crate::config;
use crate::settings;

fn aliases_path() -> Result<PathBuf> {
let dir = config::config_dir().context("could not determine config directory")?;
let dir = settings::config_dir().context("could not determine config directory")?;
Ok(dir.join("aliases.yaml"))
}

Expand Down
4 changes: 2 additions & 2 deletions src/commands/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ pub async fn login(
/// is an ownership allowlist, mirroring the shape check applied to `dd_oid`.
#[cfg(not(target_arch = "wasm32"))]
fn resolve_effective_site<'a>(site: &'a str, callback_domain: Option<&'a str>) -> &'a str {
if crate::config::uses_datadog_subdomains(site) {
if crate::settings::uses_datadog_subdomains(site) {
callback_domain
.filter(|d| crate::config::is_datadog_owned_host(d))
.filter(|d| crate::settings::is_datadog_owned_host(d))
.unwrap_or(site)
} else {
site
Expand Down
Loading
Loading