Reading order: README.md → COMMANDS.md → SCANNER_LOGIC.md → MODULE_INFO.md → PROGRESS.md
Developer guide. One read = full mental model of the codebase.
Cordon/
├── Cargo.toml # Rust manifest + dependencies (name=cordon, v1.0.0)
├── install.sh # One-liner install script (build + ~/.local/bin)
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions CI pipeline
├── config/
│ └── core.toml # Module blueprint (compiled into binary)
├── src/
│ ├── main.rs # Entry point — routes CLI to modules, nothing else
│ ├── cli.rs # Argument structs (clap). No logic.
│ ├── config.rs # Data types + file I/O for all three config layers
│ ├── errors.rs # CordonError typed enum (thiserror)
│ ├── logger.rs # Dual-sink tracing logger (stderr + log file)
│ ├── suggestions.rs # Smart "did you mean?" suggestions & synopses
│ ├── distro.rs # Distro detection (NixOS, Standard)
│ ├── wrapper.rs # Shell wrapper script management (~/.local/bin)
│ ├── commands/ # Standalone subcommand implementations
│ │ ├── check.rs # cordon check
│ │ ├── list.rs # cordon list
│ │ ├── profile.rs # cordon profile (create, list, delete, show)
│ │ ├── status.rs # cordon status
│ │ ├── syscalls.rs # cordon syscalls
│ │ ├── log.rs # cordon log (read last-run.log)
│ │ ├── init.rs # cordon init
│ │ ├── doctor.rs # cordon doctor
│ │ ├── lock.rs # cordon lock (SHA-256 verification)
│ │ └── spec.rs # cordon export/import (JSON specs)
│ ├── scanner/ # System scanner — detects paths, writes system.toml
│ │ ├── mod.rs
│ │ ├── env_resolver.rs # XDG_RUNTIME_DIR + D-Bus + audio socket resolution
│ │ ├── full_scan.rs # Interactive 4-phase scanner
│ │ ├── integrity.rs # 7-step pre-flight check
│ │ └── module_scan.rs # Per-module scan logic
│ └── sandbox/ # bwrap invocation — reads config, never writes it
│ ├── mod.rs
│ ├── builder.rs # Base bwrap command + env var passthrough
│ ├── executor.rs # Orchestrates the full cordon run flow
│ ├── mounts.rs # Applies system + user mounts to bwrap command
│ ├── network.rs # NetworkMode enum
│ ├── proxy.rs # Native Rust domain-filtering HTTP/HTTPS proxy (supply chain safety)
│ ├── seccomp.rs # Seccomp BPF filter — blocks ptrace, kexec, mount, perf
│ └── tracer.rs # Wrap bwrap with strace to detect denied paths
├── COMMANDS.md # Full command reference & future plans
├── MODULE_INFO.md # ← you are here
├── PROGRESS.md # All completed and planned work
├── README.md # User-facing docs
├── SCANNER_LOGIC.md # Internal scanner design and architecture
├── test.sh # CLI regression test suite (143 tests)
| File | Lives at | Who writes it | Who reads it |
|---|---|---|---|
core.toml |
compiled into binary | developer (rebuild required) | scanner at scan time |
system.toml |
~/.config/cordon/ |
full_scan() only |
integrity_check(), bwrap |
profiles.toml |
~/.config/cordon/ |
cordon profile create |
executor.rs profile merge |
cordon.toml |
project directory (walks up) | cordon add / cordon set / developer |
sandbox mounts loop + executor.rs profile merge |
The rule: bwrap never reads env vars or hardcoded paths. Everything it needs is resolved at scan time and stored in system.toml.
The blueprint. Describes every possible module Cordon knows about.
- Compiled into the binary via
include_str!()— cannot be modified at runtime. - Each
[[module]]entry has:name,description,default_dir,required_files,functionality,mode,when,required. whencontrols which activation flag exposes a module:always | network | gui | optional.required = truemeans the sandbox hard-fails if the module is unverified.
Dev note: adding a new module here is the only change needed — the scanner will automatically pick it up.
Pure router. Contains zero business logic.
Parses CLI via clap, then dispatches to the right module. If you add a new subcommand, touch cli.rs (variant), main.rs (dispatch), and suggestions.rs (synopsis & known commands list).
Smart error handling using Levenshtein distance.
KNOWN_COMMANDS— list of all implemented subcommand names (now includingcompletions,wrap,unwrap,man).command_synopsis()— returns a one-line usage string for each command.closest_command()— finds the best match for a typo within 3 edits.print_unknown_command_error()/print_missing_arg_error()— formatted, actionable error printers.
Argument structs only. No logic lives here.
Cliis the top-level clapParser.Commandsis theSubcommandenum:Run { ... },Scan { ... },Add { ... },Remove { ... },Edit {},Set { ... },Unset { ... },Check,List,Status,Profile { ... },Log { ... },Init { ... },Doctor,Completions { ... },Wrap { ... },Unwrap { ... },Man.Runhas:cmd,net,domains,dry_run,gui,optional,debug,quiet,verbose,mem,cpu,pid-limit,timeout,seccomp.#[arg(last = true)]oncmdis what makescordon run -- <cmd>work.
Data types + file I/O for all three config layers. No scanning logic. No bwrap logic.
| Struct | Maps to | Description |
|---|---|---|
CoreModule |
[[module]] in core.toml |
Blueprint entry |
CoreConfig |
entire core.toml |
Container for all CoreModules |
MountEntry |
[[mount]] in system.toml |
Verified path record written by scanner |
SystemConfig |
entire system.toml |
Contains last_scan, cordon_version, vec of MountEntry |
NamedProfile |
[[profile]] in profiles.toml |
Reusable global configuration profile |
ProfilesConfig |
entire profiles.toml |
Contains list of NamedProfile |
UserMount |
[[mount]] in cordon.toml |
User-defined extra mount |
UserConfig |
entire cordon.toml |
Mounts + profile defaults (network, gui, optional) |
bind_type:"ro-bind"/"bind"/"symlink"— maps directly to a bwrap flag.verified:truemeans allrequired_fileswere found at scan time.when: same values ascore.toml— controls whether this mount is applied.
network: Option<String>— default network profile ("disable"/"allow"/"full").gui: Option<bool>— default GUI flag.optional: Option<Vec<String>>— default optional modules.
All three are Option<T> so existing cordon.toml files without them continue to parse correctly.
| Function | Does |
|---|---|
get_config_dir() |
Returns ~/.config/cordon/, creates it if missing |
load_system_config() |
Reads + parses system.toml |
save_system_config() |
Writes system.toml with fd-lock write lock |
get_profiles_path() |
Returns ~/.config/cordon/profiles.toml |
load_profiles() |
Reads + parses profiles.toml |
save_profiles() |
Writes profiles.toml |
find_user_config() |
Walks up the directory tree from cwd looking for cordon.toml |
add_user_mount() |
Appends a UserMount to cordon.toml, creates file if absent |
remove_user_mount() |
Removes a UserMount from cordon.toml by canonical path |
edit_user_config() |
Opens cordon.toml in $EDITOR |
set_profile_field() |
Sets a network, gui, or optional profile default in cordon.toml |
unset_profile_field() |
Removes a profile default flag from cordon.toml |
Owns all path-discovery logic. Has two public functions: full_scan() and integrity_check().
resolve_env_vars(path)— replaces$XDG_RUNTIME_DIRplaceholder incore.tomlpaths.resolve_dbus_socket()— parses$DBUS_SESSION_BUS_ADDRESS, falls back to$XDG_RUNTIME_DIR/bus.resolve_pipewire_socket()/resolve_pulse_socket()— audio socket path resolution.
scan_module_interactive()— called duringfull_scan; handles special cases (D-Bus, missing required paths).scan_module_at()— pure scan at a specific path. Detects symlinks vs real dirs, checksrequired_files.
Interactive, four-phase scanner. The only function that writes system.toml. See SCANNER_LOGIC.md for phase breakdown.
Non-interactive, 7-step pre-flight check. Runs before every cordon run. Returns SystemConfig on success; errors are fatal.
Reads config, never writes it. All paths come from system.toml and cordon.toml.
build_bwrap(project_path, network, dry_run)— sets up namespace isolation flags, pseudo-filesystems, and the project directory bind.apply_environment(bwrap, gui)— adds--setenvargs for safe env vars.
apply_system_mounts()— iteratessystem_config.mounts, filters bywhen, skips unverified.apply_user_mounts()— readscordon.toml; in normal mode, prompts before applying.
Integration point — calls everything else. Key additions in Phase 2.8:
Before anything else, resolves any --profile argument. Then reads the project's cordon.toml and merges profile defaults into the effective flags. Resolution rules (lowest priority to highest): built-in defaults → named profile → cordon.toml → CLI flags.
NetworkMode enum: Disable (default), Allow (proxy), Full (unrestricted).
Native Rust domain-filtering HTTP/HTTPS proxy. Started as a subprocess when --net=allow. Reads allowed domains from proxy.toml and --domain flags.
Seccomp BPF filter generation and compilation using seccompiler.
Wrap bwrap with strace to detect denied paths
- Only
full_scan()writessystem.toml. Nothing else does. integrity_check()never writes anything under normal operation.- No hardcoded paths in the sandbox module. All paths come from
system.tomlandcordon.toml. core.tomlis tamper-proof at runtime. It lives in the binary.verified = falsemounts are never passed to bwrap.- Exit codes are forwarded exactly.
→ PROGRESS.md — what's been built phase by phase, and what's coming next