Aegis is a local zero-trust package operation broker. It replaces direct package changes such as sudo apt upgrade or npm install lodash with deterministic planning, local AI review, deterministic policy, and auditable signed execution plans.
Status: 0.4.0. Planning, AI review, plan-bound deterministic policy, Ed25519-signed execution plans, constrained executor (
aegisd), required-control preflight, structured daemon logging, and verifiable tamper-evident audit logging are implemented. Production apply is intentionally conservative: APT is the primary production path; non-APT apply requires pinned/verified evidence and is denied by default when artifacts are mutable or unverified.
Command flow:
User intent
-> deterministic analyzer
-> local model review
-> deterministic policy decision
-> signed execution plan
-> constrained executor (aegisd)
-> tamper-evident audit log
Aegis assumes package managers, package metadata, maintainer scripts, dependency trees, and model output may all be risky inputs. The goal is to prevent accidental direct mutation, block obvious dangerous package operations, and keep privileged execution behind deterministic controls.
The local model is only a reviewer. It never receives root privileges, never executes commands, never approves execution, and never generates shell commands that Aegis executes. Deterministic Rust code parses package manager evidence, computes risk signals, and enforces policy.
Aegis expects an OpenAI-compatible local endpoint:
Base URL: http://localhost:8000/v1
Model: deepseek-v4-flash
Temperature: 0
Defaults can be overridden for local deployments:
export AEGIS_AI_BASE_URL=http://localhost:8000/v1
export AEGIS_AI_MODEL=deepseek-v4-flashSlow local models can tune review timing without changing policy behavior:
export AEGIS_AI_PREFILL_TOKENS_PER_SEC=330
export AEGIS_AI_DECODE_TOKENS_PER_SEC=17
export AEGIS_AI_MODEL_STARTUP_ALLOWANCE_SECS=120
export AEGIS_AI_REVIEW_TIMEOUT_SECS=600If AEGIS_AI_REVIEW_TIMEOUT_SECS is unset, Aegis estimates the review timeout
from prompt size, the configured token rates, and a startup allowance. Review
responses are capped with AEGIS_AI_MAX_OUTPUT_TOKENS (default 4096) to leave
room for local reasoning-token overhead while keeping reviews bounded.
OpenAI-compatible JSON response formatting is used by default; set
AEGIS_AI_RESPONSE_FORMAT_JSON=0 if your local endpoint rejects that option.
One common setup is a vLLM-compatible server exposing the model name above:
vllm serve <local-or-hf-model-path> \
--host 127.0.0.1 \
--port 8000 \
--served-model-name deepseek-v4-flashUse the model path and vLLM flags appropriate for your local installation and hardware. Aegis checks GET http://localhost:8000/v1/models in aegis doctor.
aegis doctor
aegis apt update --plan
aegis apt upgrade --plan
aegis apt install nginx --plan
aegis npm install lodash --plan
aegis pip install requests --plan
aegis docker pull ubuntu:latest --plan
aegis container pull ghcr.io/org/image@sha256:<digest> --plan
aegis nuget install Newtonsoft.Json --plan
aegis vscode install ms-python.python --plan
aegis go get github.com/gin-gonic/gin@v1.10.0 --plan
aegis cargo install ripgrep --planaegis review ~/.local/share/aegis/plans/<plan-id>.json
aegis policy ~/.local/share/aegis/plans/<plan-id>.json
aegis policy ~/.local/share/aegis/plans/<plan-id>.json --review ~/.local/share/aegis/reviews/<plan-id>.review.jsonaegisctl keygen
aegisctl sign --plan <plan.json> --policy <policy.json> --key-id <id> --signer <identity>
aegisctl sign --plan <plan.json> --policy <policy.json> --review <review.json> --key-id <id> --signer <identity>
aegisctl sign --plan <plan.json> --policy <policy.json> --key-id <id> --signer <identity> --snapshot-id <snapshot-id>
aegisctl sign --plan <plan.json> --policy <policy.json> --key-id <id> --signer <identity> --approval-reason <reason> --approval-key-id <approval-key-id> --approval-secret-key-hex <hex>
aegisctl verify --execution-plan <exec-plan.json> --public-key-hex <hex> --approval-public-key-hex <hex>
aegisctl apply --execution-plan <exec-plan.json> --public-key-hex <hex> --approval-public-key-hex <hex>
aegisctl audit-path
aegisctl audit-verify# Root execution gate (runs as root with systemd hardening)
aegisd --public-key-hex <hex>
# Unprivileged AI reviewer
aegis-reviewdDaemon logs are emitted with tracing to stderr. Use RUST_LOG for filtering
and AEGIS_LOG_FORMAT=json for JSON-formatted service logs:
RUST_LOG=info AEGIS_LOG_FORMAT=json aegisd --public-key-hex <hex>Prerequisites:
- Rust stable (MSRV 1.85), with
rustfmtandclippy - Ubuntu-compatible package tools for the ecosystems you want to inspect
- Optional local OpenAI-compatible model endpoint for
aegis review
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo build --releaseOptional local hardening checks:
python3 -m pytest tools/policy-helper/tests
python3 -m ruff check tools/policy-helper
python3 -m mypy tools/policy-helper/src
cargo deny check
cargo auditWorkspace layout:
aegis-types: shared serializable plan, policy, review, execution, approval, and audit event types.aegis-security: pure deterministic helpers for canonical JSON hashing, target-shape detection, deny-plan construction, and deduplication.aegis-core: compatibility facade re-exportingaegis-typesandaegis-security; new internal code should depend on the narrower crates.
Production deployment notes are in docs/PRODUCTION.md. The public release
checklist is in docs/OPEN_SOURCE_RELEASE.md.
Aegis uses explicit argv with std::process::Command; it does not use a shell.
| Ecosystem | Planning behavior | Signed apply argv when policy permits |
| --- | --- |
| apt | dry-run with apt-get -s; apt update --plan describes intended metadata refresh without mutating | apt-get update, apt-get upgrade -y -o Dpkg::Options::=--force-confold, apt-get install -y <validated-package> |
| npm | metadata with npm view <package> --json | npm install --global --prefix /var/lib/aegis/npm-global --ignore-scripts --no-audit --no-fund <validated-package> |
| pip | metadata/environment with python3 -m pip index versions | python3 -m pip install --disable-pip-version-check --no-input --target /var/lib/aegis/pip-packages <validated-package> |
| Docker/Podman | manifest inspect | docker pull <validated-image> or podman --root /var/lib/aegis/podman/storage --runroot /run/aegis/podman pull <validated-image> |
| NuGet | metadata/search with dotnet nuget search | nuget install <validated-package> -OutputDirectory /var/lib/aegis/nuget/packages -NonInteractive |
| VS Code | extension id validation and installed-extension list | code --install-extension <validated-extension> --user-data-dir /var/lib/aegis/vscode/user-data --extensions-dir /var/lib/aegis/vscode/extensions |
| Go | module metadata in a temp cache directory | go install <validated-module>@<version> with managed GOPATH, GOBIN, and GOCACHE |
| Cargo | search with cargo search | cargo install --locked --root /var/lib/aegis/cargo <validated-crate> |
For 0.4.0, deterministic policy denies mutable or unverified non-APT artifacts by default. Container apply requires a digest-pinned image with metadata; Go apply requires an explicit version with checksum database protections. npm, pip, NuGet, VS Code extension, and Cargo production apply remain behind stronger future evidence requirements such as version/digest pins, provenance/signature checks, vulnerability checks, source/tarball inspection, or SBOMs.
Allowed planning subprocesses:
apt-get -s upgradeapt-get -s install <validated-package>npm view <validated-package> --jsonpython3 -m pip index versions <validated-package>python3 -m pip inspectdocker manifest inspect <validated-image>podman manifest inspect <validated-image>dotnet nuget search <validated-package>code --list-extensions --show-versionsgo env GOSUMDB GOPROXY GOPRIVATE GONOSUMDBgo list -m -json <validated-module>from a temp directory under~/.cache/aegis/tmpcargo search <validated-crate> --limit 5- read-only availability checks for
doctor
Forbidden during planning:
sudoapt-get upgradewithout-sapt-get installwithout-snpm installpip installdocker pullpodman pulldotnet add packagenuget installcode --install-extensiongo getcargo install- npm lifecycle scripts
curl | bash- model-generated commands
Production apply is available only through signed execution plans:
aegis <ecosystem> <operation> --plan
aegis review <plan.json>
aegis policy <plan.json> [--review <review.json>]
aegisctl sign --plan <plan.json> --policy <policy.json> [--review <review.json>] --key-id <id> --signer <identity>
aegisctl verify --execution-plan <exec-plan.json> --public-key-hex <hex>
aegisctl apply --execution-plan <exec-plan.json> --public-key-hex <hex>aegisctl sign derives execution argv from the deterministic operation plan. The model never supplies argv, and aegisd validates the signed argv against the same production allowlist before execution.
Policy results include the exact operation-plan hash. aegisctl sign re-runs deterministic policy for the supplied plan and optional AI review, rejects mismatches, and embeds the operation plan, policy result, and optional AI review hash in the signed execution plan. The executor verifies those embedded hashes, signed argv target drift, expiry/freshness, and required controls before running an allowlisted command.
AI review is one-way restrictive: it can escalate deterministic policy to RequireHuman or Deny, but it cannot approve or downgrade a deterministic policy decision.
AllowWithSnapshot requires a snapshot proof such as --snapshot-id. RequireHuman requires an independently signed approval (--approval-secret-key-hex / AEGIS_APPROVAL_SECRET_KEY_HEX) using a key distinct from the execution signing key; aegisctl verify, aegisctl apply, and aegisd verify approvals with --approval-public-key-hex or AEGIS_APPROVAL_PUBLIC_KEY_HEX.
Generated plans are written to:
~/.local/share/aegis/plans/<plan_id>.json
AI reviews are written to:
~/.local/share/aegis/reviews/<plan_id>.review.json
Policy results are written to:
~/.local/share/aegis/policy/<plan_id>.policy.json
Tamper-evident audit events are appended to:
~/.local/share/aegis/audit/audit.ndjson
Set AEGIS_AUDIT_LOG_DIR to move the production audit log (for example to a root-owned /var/log/aegis directory). Each audit event contains a SHA-256 hash chain linking it to the previous event. Verify the chain with:
aegisctl audit-verify
aegisctl audit-verify --path /var/log/aegis/audit.ndjsonThe optional policy helper under tools/policy-helper/ is offline advisory
tooling for policy maintenance. It reads signed execution plans, verifies
execution-plan signatures and human approval signatures against trusted public
keys, and produces a JSON report of recurring approval patterns and candidate
policy-test ideas.
It does not update deterministic policy, approve execution, generate argv, sign
plans, or interact with aegisd. DSPy is used only to structure advisory
analysis from already-verified human feedback.
python -m aegis_policy_helper report \
--execution-plan <execution-plan.json> \
--execution-public-key-hex <execution-public-key-hex> \
--approval-public-key-hex <approval-public-key-hex> \
--out policy-helper-report.json \
--lm openai/deepseek-v4-flash \
--api-base http://localhost:8000/v1 \
--api-key localFrom an uninstalled checkout, prefix the command with
PYTHONPATH=tools/policy-helper/src.
Use --skip-dspy to generate the deterministic sections without calling a
model. Production reports require --execution-public-key-hex; the
--allow-unverified-execution-signature flag exists only for lab fixtures.
Reports are written atomically with private file permissions when --out is
used. Sandbox or lab evidence is intentionally not ingested by v1; future policy
changes suggested by a report must be implemented separately in deterministic
Rust policy with deny-path tests.
Aegis is licensed under the MIT License. See LICENSE.
Security reports should follow SECURITY.md. Contributions should preserve the security invariant and follow CONTRIBUTING.md.
- Add richer package and artifact metadata parsers.
- Add repository trust and snapshot integration.
- Add rollback plan execution.
- Add multi-platform CI matrix.