[workspace] resolver = "2" members = [ "crates/aivyx-core", "crates/aivyx-crypto", "crates/aivyx-capability", "crates/aivyx-audit", "crates/aivyx-instance", "crates/aivyx-config", "crates/aivyx-storage", "crates/aivyx-llm", "crates/aivyx-memory", "crates/aivyx-channel", "crates/aivyx-telegram", "crates/aivyx-discord", "crates/aivyx-matrix", "crates/aivyx-proton", "crates/aivyx-signal", "crates/aivyx-slack", "crates/aivyx-mcp", "crates/aivyx-tool", "crates/aivyx-gmail", "crates/aivyx-toolkit", "crates/aivyx-vision", "crates/aivyx-dataread", "crates/aivyx-calendar", "crates/aivyx-google-oauth", "crates/aivyx-drive", "crates/aivyx-contacts", "crates/aivyx-notion", "crates/aivyx-obsidian", "crates/aivyx-n8n", "crates/aivyx-apps", "crates/aivyx-auth-cli", "crates/aivyx-voice", "crates/aivyx-tui", "crates/aivyx-cli", "crates/aivyx-team", "crates/aivyx-team-types", "crates/aivyx-federation", "crates/aivyx-ipc", "crates/aivyx-vertical-sdk", "crates/verticals/aivyx-kitchen", "crates/verticals/aivyx-kitchen-toolkit", # Commercial / private packs (git-ignored, see crates/verticals-private/). # A glob so a dropped-in private pack auto-joins the workspace; Cargo # ignores matches without a Cargo.toml, so an empty dir builds fine. "crates/verticals-private/*", "crates/aivyx-cost", "crates/aivyx-web", # Native desktop shell — links a system webview (WebKitGTK), so like # aivyx-web it's kept OUT of default-members; build it explicitly with # `cargo build -p aivyx-desktop`. "crates/aivyx-desktop", ] # Chapter M — `aivyx-web` is a Dioxus app that only compiles for # `wasm32-unknown-unknown` (web-sys / wasm-bindgen). Excluding it from # `default-members` keeps a bare `cargo build` / `cargo test` (native) from # trying to build it; it is built explicitly with # `cargo build -p aivyx-web --target wasm32-unknown-unknown` (and via `dx` / # CI in M.5). default-members = [ "crates/aivyx-core", "crates/aivyx-crypto", "crates/aivyx-capability", "crates/aivyx-audit", "crates/aivyx-instance", "crates/aivyx-config", "crates/aivyx-storage", "crates/aivyx-llm", "crates/aivyx-memory", "crates/aivyx-channel", "crates/aivyx-telegram", "crates/aivyx-discord", "crates/aivyx-matrix", "crates/aivyx-proton", "crates/aivyx-signal", "crates/aivyx-slack", "crates/aivyx-mcp", "crates/aivyx-tool", "crates/aivyx-gmail", "crates/aivyx-toolkit", "crates/aivyx-vision", "crates/aivyx-dataread", "crates/aivyx-calendar", "crates/aivyx-google-oauth", "crates/aivyx-drive", "crates/aivyx-contacts", "crates/aivyx-notion", "crates/aivyx-obsidian", "crates/aivyx-n8n", "crates/aivyx-apps", "crates/aivyx-auth-cli", "crates/aivyx-voice", "crates/aivyx-tui", "crates/aivyx-cli", "crates/aivyx-team", "crates/aivyx-team-types", "crates/aivyx-federation", "crates/aivyx-ipc", "crates/aivyx-vertical-sdk", "crates/verticals/aivyx-kitchen", "crates/verticals/aivyx-kitchen-toolkit", # Commercial / private packs (git-ignored, see crates/verticals-private/). "crates/verticals-private/*", "crates/aivyx-cost", ] [workspace.package] version = "0.20.1" edition = "2024" rust-version = "1.85" # Chapter Charter (CR.2): relicensed MIT -> BUSL-1.1 (docs/LICENSING.md). # SPDX id is BUSL-1.1 (not "BSL-1.1") so cargo/cargo-deny/scanners parse it; # the personal-use Additional Use Grant + full terms live in ./LICENSE. license = "BUSL-1.1" # Not a crates.io distribution: Aivyx ships as cargo-dist binaries + GHCR # images, never published crates. publish = false makes that explicit (guards # against accidental `cargo publish`) and lets cargo-deny's private.ignore skip # these first-party BUSL-1.1 crates when auditing dependency licenses. publish = false authors = ["Aivyx "] repository = "https://github.com/Aivyx-Agent/aivyx" readme = "README.md" [workspace.dependencies] # Core async runtime — shared so all crates use the same version tokio = { version = "1", features = ["rt-multi-thread", "macros", "sync", "time", "io-std", "signal"] } tokio-util = { version = "0.7", features = ["rt"] } async-trait = "0.1" # Serialization serde = { version = "1", features = ["derive"] } serde_json = "1" # Error handling — per D6 thiserror = "2" # UUIDs for newtype IDs uuid = { version = "1", features = ["v4", "serde"] } # Glob matching for scope attenuation (simple-glob + path-glob qualifier kinds) globset = "0.4" # Audit log: HMAC-SHA256 over canonical JSON per RFC 8785 (per D1 + D4) hmac = "0.13" sha2 = "0.11" serde_jcs = "0.2" # Base64 encoding for binary response bodies in web.fetch (Phase 37) base64 = "0.22" # Federation keystone (Chapter Passport) — Ed25519 agent identity + signatures. # rand 0.8 pins rand_core 0.6 to match ed25519-dalek 2.x's keygen RNG bound. ed25519-dalek = { version = "2", features = ["rand_core"] } # Chapter Freight — the signed pack-bundle container (boring, ubiquitous # formats for a security-relevant artifact; both MIT/Apache-2.0). tar = "0.4" flate2 = "1" rand = "0.8" hex = "0.4" # LLM provider HTTP transport (feature-gated in aivyx-llm via provider-anthropic) reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "stream", "json"] } # WHATWG-compliant URL parsing — already transitive via reqwest; promoted to # a direct workspace dependency (Chapter Rampart hardening) so # `aivyx-core::egress::host_of` parses URLs with the exact same algorithm # `reqwest` uses internally, instead of a hand-rolled parser that could # (and did) disagree with it on edge cases like backslash-authority # splitting and non-dotted-decimal IPv4 literals. url = "2" # Bearer token wrapper — prevents accidental Debug/logging of API keys secrecy = { version = "0.10", features = ["serde"] } # Chapter Keyring — OS credential store for the master passphrase. Pure-Rust # feature selection (sync-secret-service = zbus, crypto-rust = RustCrypto) so it # builds on musl-static without C libsecret/openssl; native backends on # macOS/Windows. `mock` provides an in-memory backend for tests. # `async-io` (not `tokio`) executor: keyring's sync Entry bridges to the async # zbus backend via async-io/smol, so it's safe to call from *inside* our tokio # runtime (a tokio bridge would nest-panic). Pure Rust ⇒ still musl-safe. keyring = { version = "3", default-features = false, features = ["async-secret-service", "crypto-rust", "async-io", "apple-native", "windows-native"] } # Byte stream utilities used by the SSE parser futures-util = "0.3" bytes = "1" # Cron expression parsing for scheduled execution (Phase 26) cron = "0.16" chrono = { version = "0.4", default-features = false, features = ["std", "clock"] } # IANA named-timezone database for `convert.time` (Chapter Abacus AB.2). # MIT OR Apache-2.0; the zone table is bundled (no espeak-style native dep), # so the conversion stays offline like the rest of the utilities pack. chrono-tz = { version = "0.10", default-features = false } # HTTP server for webhook triggers (Phase 27) — already transitive via reqwest hyper = { version = "1", features = ["server", "http1"] } hyper-util = { version = "0.1", features = ["tokio"] } http-body-util = "0.1" # WebSocket support for web UI channel (Phase 39) tokio-tungstenite = "0.26" # File-system change notifications for file-watch triggers (Phase 27) notify = { version = "8", default-features = false, features = ["macos_fsevent"] } # Unix process-group signaling for shell.exec (Phase 42) libc = "0.2" # Phase 68 — SMTP client for the email notify backend. # `default-features = false` + explicit rustls features is # load-bearing: we keep TLS aligned with our existing reqwest # rustls-tls policy and never pull in system openssl by # accident. lettre = { version = "0.11", default-features = false, features = [ "tokio1", "tokio1-rustls-tls", "rustls-native-certs", "smtp-transport", "builder", "hostname", ] } # Phase 101 — JSON Schema validation for tool-call inputs. The # planner validates a known tool's call arguments against the # tool's `input_schema()` before dispatch. # # `default-features = false` is load-bearing: the crate's default # features (`reqwest`, `resolve-http`, `resolve-file`, # `tls-aws-lc-rs`) exist to resolve external `$ref`s over the # network — which the in-tree tool schemas never use, and which # would pull a second TLS stack (`aws-lc-rs`) against the # workspace's rustls-only policy. With defaults off we get the # synchronous in-memory validator and nothing else. jsonschema = { version = "0.46", default-features = false } # Phase 185 — Terminal UI stack for the `aivyx tui` frontend. These # are the FIRST new workspace dependencies since well before Phase # 172, deliberately ending the zero-new-dep streak: a real terminal # UI genuinely requires a terminal-UI library, and ratatui + # crossterm are the load-bearing, widely-audited, pure-Rust choice. # They are QUARANTINED to the `aivyx-tui` crate (and the binary that # launches it) — no substrate crate (`aivyx-core`, # `aivyx-capability`, `aivyx-storage`, `aivyx-crypto`, …) may depend # on them, so the substrate stays dependency-clean. A future audit # should confirm `aivyx-tui` is the only ratatui consumer. ratatui = "0.30" crossterm = "0.29" # Shared Landlock+seccomp process confinement for shell.exec/git.rs, # adopted from the sibling aivyx-coder repo rather than reimplemented here. # Not on crates.io (see aivyx-confine's own README) — pinned by commit SHA. # MUST stay a public repo: aivyx-confine, aivyx-checkpoint, and aivyx-kvcache # were all created 2026-08-16/2026-08-17 as private GitHub repos and adopted # as git dependencies here shortly after. Their privacy went undiscovered as # a problem until it broke the v0.9.0 release workflow on 2026-09-02 (CI's # ambient GITHUB_TOKEN can't authenticate against a different, private repo) # -- found and fixed as Phase 192 (Chapter N) on 2026-09-05. # `./scripts/check-git-deps-public.sh` verifies this reachability and will be # wired into CI (Phase 194) specifically to catch a re-privatization fast. # `default-features = false` here (rather than at the consuming crate): # Cargo's MSRV-aware resolver (edition 2024) forbids a member manifest from # *narrowing* an inherited workspace dependency's `default-features` — only # widening via `features = [...]` is allowed. So the workspace-level entry # starts with the default (`sandbox-backend`, which pulls in Linux-only # `landlock`/`seccompiler`) off, and `aivyx-core`'s target-gated # `[target.'cfg(target_os = "linux")'.dependencies]` table opts it back on # — see that crate's Cargo.toml for why (macOS release build). # Bumped to a08be93 (Phase 193, Chapter N.2): fixes require_enforcement # refusing to run under Landlock's own designed PartiallyEnforced # best-effort degradation, not just the genuine NotEnforced case -- # found because GitHub Actions' ubuntu-22.04 runner kernel only reaches # PartiallyEnforced at this crate's hardcoded LANDLOCK_ABI (V7), which # made every sandboxed shell.exec test fail outright in CI with a # misleading "spawn failed: Invalid argument (os error 22)" (Rust's # process-spawn error-propagation fallback for a pre_exec closure # returning a non-raw-OS-code error, not a genuine kernel EINVAL). Not # CI-only: shell.rs hardcodes require_enforcement=true for production # too, so this also fixes shell.exec for any real end user on a kernel # that doesn't fully support Landlock ABI V7. # Bumped again to 8ee18f2: libc::SYS_kexec_file_load doesn't exist in # this crate's musl bindings for aarch64/riscv64 (present for musl # x86_64/loongarch64/s390x/powerpc64 -- an upstream musl libc binding # gap), which broke the real aarch64-unknown-linux-musl release target # outright (E0425). The only one of the four shipped targets # aivyx-confine had never actually been cross-compiled for before -- # it wasn't adopted until 2026-08-17, after aivyx's last real release. aivyx-confine = { git = "https://github.com/Aivyx-Agent/aivyx-confine", rev = "e4b604e2dfa90a87cb1a6ccb0bb627cda00b3fe8", default-features = false } # Shared git-ref checkpoint/rollback for fs_root's mutating tools # (fs.write, fs.delete, shell.exec), adopted from the sibling aivyx-coder # repo (via aivyx-checkpoint) rather than reimplemented here. Not on # crates.io — pinned by commit SHA. No platform-specific backend (pure # git plumbing, unlike aivyx-confine) so no default-features/target-gating # split is needed. # MUST stay a public repo — see the aivyx-confine entry above for why; # this was the specific dependency whose private-repo auth failure was # traced and fixed in Phase 192 (Chapter N). # # Pinned to 002d5918 (2026-10-02, the "never let a tool write git's own # metadata" hardening): `GitCheckpointer::run_git` now forces # `-c core.fsmonitor=false` on its own unconfined `git add -A`, so even if # a write somehow landed a `core.fsmonitor` entry in a checkpointed repo's # `.git/config`, the checkpointer's own git invocation won't run it. # Defense in depth alongside the tool-level `.git`-write block in # `aivyx-core::tools::fs::touches_git_metadata`. aivyx-checkpoint = { git = "https://github.com/Aivyx-Agent/aivyx-checkpoint", rev = "55f4c93ee87c593f58b5e0ca206263cead98f20d" } # KV-cache persistence against a llama-server backend (LlmPlanner/ # SpecialistFactory `with_kv_cache`), adopted from the sibling aivyx-coder # repo rather than reimplemented here. Not on crates.io — pinned by commit # SHA. No platform-specific backend, same as aivyx-checkpoint, so no # default-features/target-gating split is needed. Centralized here # 2026-08-27 — previously duplicated verbatim across aivyx-core, aivyx-team, # aivyx-cli, and aivyx-channel's own Cargo.toml files. # MUST stay a public repo — see the aivyx-confine entry above for why. aivyx-kvcache = { git = "https://github.com/Aivyx-Agent/aivyx-kvcache", rev = "dd6adc85bf94bdefabdb79f4d60e54c61a190d30" } # Hardware-backed Ed25519 signing via a YubiKey's OpenPGP card applet # (Chapter Passport's optional hardware-identity backend, aivyx-federation's # `IdentitySigner::Hardware`). Same pinned-by-commit-SHA pattern as # aivyx-checkpoint/aivyx-confine/aivyx-kvcache above — MUST stay a public # repo for the same CI-checkout reason (a `git` dependency, unlike a `path` # dependency, does NOT require local filesystem presence to resolve, but it # does require the remote to be reachable). Marked `optional = true` at each # consuming crate (not here) because it transitively needs `libpcsclite` at # build time via `pcsc-sys` — gated behind the `yubikey` Cargo feature, # off by default, so the default workspace build never touches it. aivyx-yubi = { git = "https://github.com/Aivyx-Agent/aivyx-yubi", rev = "6dce9d40aa2698a36bbc62d18359a21a8ba79c9e" } # Prompt-injection phrase-list tripwire (Chapter Picket) for untrusted # tool output (fs.read, web.fetch, every tool-process/MCP tool), # extracted from the sibling aivyx-coder repo rather than reimplemented # here — see docs/superpowers/specs/2026-09-05-injection-guard-design.md. # Not on crates.io — pinned by commit SHA, same as aivyx-checkpoint/ # aivyx-confine/aivyx-kvcache above. No platform-specific backend, so no # default-features/target-gating split is needed. # MUST stay a public repo — see the aivyx-confine entry above for why. aivyx-injection-guard = { git = "https://github.com/Aivyx-Agent/aivyx-injection-guard", rev = "a3eb989ea86b4784a3bd118d21530c5731ae21f6" } aivyx-skills = { git = "https://github.com/Aivyx-Agent/aivyx-skills", rev = "ffaff98acf1bd32955e6abdb659444215218416e" } # Task-aware model routing (capability matching, tiering, discovery), # shared by `aivyx-pa` and `aivyx-coder`. Not on crates.io — pinned by # commit SHA, same pattern as aivyx-checkpoint/aivyx-confine/aivyx-kvcache/ # aivyx-injection-guard/aivyx-skills above. aivyx-route = { git = "https://github.com/Aivyx-Agent/aivyx-route", rev = "d1089d024a735a888e7ffa0669bddada03532542" } # The signed pack-bundle format (Chapter Freight), shared with aivyx-coder. # Extracted from crates/aivyx-pack into its own repo 2026-10-07. Not on # crates.io — pinned by commit SHA, same as the shared crates above. # MUST stay a public repo — see the aivyx-confine entry above for why. aivyx-pack = { git = "https://github.com/Aivyx-Agent/aivyx-pack", rev = "aec62513f35e20ffc59bbc45e299bc8f3a7127f1" } # Shared tool-call grammar (Chapters Stencil/Emboss), extracted 2026-10-18. # MUST stay a public repo — see the aivyx-confine entry above for why. aivyx-stencil = { git = "https://github.com/Aivyx-Agent/aivyx-toolbench", rev = "80d251f7b811a4570bd8912f0e82c0fc9feabb0f" } # Standalone generation backends for the aivyx-vision tool process's # vision.generate_svg / vision.generate_image / vision.generate_3d # (Chapter design docs: # aivyx-ecosystem/docs/superpowers/specs/2026-09-18-aivyx-vision-v1-design.md, # docs/superpowers/specs/2026-09-18-vision-image-3d-adoption-design.md). # Not on crates.io — pinned by commit SHA, same as aivyx-checkpoint/ # aivyx-confine/aivyx-kvcache/aivyx-injection-guard above. All three pinned # to the same rev (Milestone 2 Pass A's merge commit) so they never drift # out of lockstep with each other. No platform-specific backend, so no # target-gating needed. # MUST stay a public repo — see the aivyx-confine entry above for why. aivyx-vision-svg = { git = "https://github.com/Aivyx-Agent/aivyx-vision", rev = "0bc2fa1a687c253ed8b3d957be3f90b625295f23" } aivyx-vision-core = { git = "https://github.com/Aivyx-Agent/aivyx-vision", rev = "0bc2fa1a687c253ed8b3d957be3f90b625295f23" } aivyx-vision-mold = { git = "https://github.com/Aivyx-Agent/aivyx-vision", rev = "0bc2fa1a687c253ed8b3d957be3f90b625295f23" } # The profile that 'dist' will build with [profile.dist] inherits = "release" lto = "thin" [profile.wasm-dev] inherits = "dev" opt-level = 1 [profile.server-dev] inherits = "dev" [profile.android-dev] inherits = "dev" # serde-saphyr 0.0.16 with its `regex < 1.13` cap relaxed, so matrix-sdk 0.19 # (regex 1.13+) and mistralrs-core 0.8.1 (pins serde-saphyr 0.0.16) can share a # lockfile. See vendor/README.md for why and when to remove it. [patch.crates-io] serde-saphyr = { path = "vendor/serde-saphyr" }