dsp-cli 0.3.1

AI-agent-friendly command-line interface for the DaSCH Service Platform (DSP)
Documentation
[package]
name = "dsp-cli"
# release-please writes this field (registered via .github/release-please/config.json extra-files); never bump it by hand — use a Release-As: commit footer; see docs/src/deployment.md#dsp-cli
version = "0.3.1"
edition = "2024"
rust-version = "1.92"
description = "AI-agent-friendly command-line interface for the DaSCH Service Platform (DSP)"
license = "Apache-2.0"
repository = "https://github.com/dasch-swiss/dsp-repository"
homepage = "https://github.com/dasch-swiss/dsp-repository/tree/main/dsp-cli"
authors = ["Balduin Landolt <balduin.landolt@dasch.swiss>"]
readme = "README.md"
keywords = ["dasch", "dsp", "cli", "digital-humanities", "rdf"]
categories = ["command-line-utilities", "api-bindings"]
# Allowlist (not an exclude list): only what the packaged crate needs to compile and
# describe itself. docs/topics/*.md are include_str!'d at compile time
# (src/actions/docs.rs) and must ship; Cargo.toml/Cargo.lock are auto-included by cargo.
# See dsp-cli/ADR-0011 (crates.io publishing decision).
include = ["src/**/*", "docs/topics/*.md", "README.md", "LICENSE", "CHANGELOG.md"]

[[bin]]
name = "dsp"
path = "src/main.rs"

[lib]
name = "dsp_cli"
path = "src/lib.rs"

[features]
# Live tests against a real DSP environment. Not in CI (dsp-cli/ADR-0009).
live = []

[dependencies]
clap = { version = "4", features = ["derive", "env"] }
thiserror = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["fmt"] }
serde = { workspace = true }
# preserve_order keeps JSON object keys in insertion order, so the `_meta`-first
# envelope is a deterministic contract rather than a BTreeMap alpha-sort accident.
serde_json = { workspace = true }
dotenvy = "0.15"
dirs = "5"
toml = "0.8"
# HTTP client for blocking DSP-API calls (auth, data fetch); rustls avoids OpenSSL build dep.
reqwest = { version = "0.13", default-features = false, features = ["blocking", "json", "rustls", "query"] }
# Percent-encoding for IRI path segments (e.g. encoding IRIs for /admin/projects/iri/{enc-iri}).
# Already transitively present via reqwest; listed directly so the usage is intentional.
percent-encoding = "2"
# Prompts for passwords without echoing; falls back to stdin pipe when not a TTY.
rpassword = "7"
# Timestamps for token acquired_at / expires_at in the auth cache; serde+clock features for serialisation and Utc::now().
# Kept crate-local rather than workspace-inherited: the root workspace.dependencies entry
# leaves default-features on, and default-features cannot be overridden alongside workspace = true.
chrono = { version = "0.4", default-features = false, features = ["serde", "clock"] }
# JWT decoding to extract the exp claim from login response tokens (signature validation disabled — token is freshly issued by the server we just authenticated to).
# v10 no longer bundles a crypto backend: exactly one of `rust_crypto`/`aws_lc_rs` must be chosen. `rust_crypto` is pure Rust (no C toolchain — consistent with the rustls choice above). The production path (`insecure_decode`) never touches it; the tests' `encode` helper does.
jsonwebtoken = { version = "10", features = ["rust_crypto"] }
# Compares the built-in CARGO_PKG_VERSION to the fetched latest version from crates.io (update check, dsp-cli/ADR-0015).
semver = "1"

[dev-dependencies]
insta = { workspace = true }
wiremock = "0.6"
tempfile = "3"
assert_cmd = "2"
predicates = "3"
# Async runtime required by wiremock's MockServer; reqwest::blocking is safe inside #[tokio::test] (spawns its own OS thread).
tokio = { version = "1", default-features = false, features = ["rt", "macros"] }

# Cargo ignores a member's [profile.*] table inside a workspace and prints a warning saying so;
# this section still governs `cargo install dsp-cli` from crates.io, where this manifest is the root.
[profile.release]
lto = "thin"
strip = "symbols"
codegen-units = 1