aegis-devops 0.1.3__tar.gz → 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aegis_devops-0.1.3/src/aegis_devops.egg-info → aegis_devops-0.1.4}/PKG-INFO +46 -22
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/README.md +45 -21
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/__init__.py +1 -1
- aegis_devops-0.1.4/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/hook.py +19 -10
- {aegis_devops-0.1.3 → aegis_devops-0.1.4/src/aegis_devops.egg-info}/PKG-INFO +46 -22
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/SOURCES.txt +1 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_default_rules.py +16 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_hook.py +9 -0
- aegis_devops-0.1.4/tests/test_plugins.py +76 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/LICENSE +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/MANIFEST.in +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/pyproject.toml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/setup.cfg +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/__init__.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/authority.example.yaml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/authority.example.yaml.sig +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/constraints.example.yaml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/constraints.example.yaml.sig +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml.sig +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/example-signing.key +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml.sig +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/PRINCIPALS.yaml +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-4001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6003.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6004.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6005.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6006.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6007.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-6008.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-789abc.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-abc123.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-bcd234.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-def456.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-1001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-1002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-2001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-2002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3003.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3004.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3005.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5003.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5004.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5006.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1001.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1002.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1003.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1004.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-5005.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/slack-perma-1.json +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/adversarial.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/authority.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/__init__.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/base.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/external.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/llm.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/metrics.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/baselines/opa.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/cli.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/config.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/environments.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/intent.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/interceptor.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/ledger.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/parser.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/parsers/__init__.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/parsers/pulumi.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/parsers/sql.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/plan.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/provenance.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/shell.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/signing.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/store.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/dependency_links.txt +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/entry_points.txt +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/requires.txt +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/top_level.txt +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_adversarial.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_authority.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_baselines.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_benchmark.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_cli.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_config.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_corpus.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_docs_consistency.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_environments.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_intent.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_interceptor.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_ledger.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_parser.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_parsers_pulumi.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_parsers_sql.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_plan.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_provenance.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_shell.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_signing.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_store.py +0 -0
- {aegis_devops-0.1.3 → aegis_devops-0.1.4}/tests/test_store_match.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aegis-devops
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Provenance-backed, authority-aware policy verifier for agentic DevOps actions.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/moneytool/aegis-devops
|
|
@@ -30,19 +30,34 @@ Provides-Extra: llm
|
|
|
30
30
|
Requires-Dist: anthropic; extra == "llm"
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
|
-
# Aegis-DevOps
|
|
33
|
+
# Aegis-DevOps
|
|
34
34
|
|
|
35
35
|
[](https://doi.org/10.5281/zenodo.22950337)
|
|
36
36
|
[](https://pypi.org/project/aegis-devops/)
|
|
37
37
|
|
|
38
|
-
**
|
|
39
|
-
|
|
38
|
+
**Stop AI agents from running `kubectl delete`, `terraform destroy` or `DROP TABLE` because a
|
|
39
|
+
ticket told them to.**
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
Aegis-DevOps checks every command an agent wants to run before it runs, and blocks it if your
|
|
42
|
+
policy says no. A policy rule only counts if nobody has edited it since it was signed, and if
|
|
43
|
+
its author was allowed to write that kind of rule. So a planted line in a Jira ticket can't
|
|
44
|
+
become policy.
|
|
44
45
|
|
|
45
|
-

|
|
47
|
+
|
|
48
|
+
### Install in Claude Code
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install aegis-devops && aegis init .aegis
|
|
52
|
+
claude plugin marketplace add moneytool/aegis-devops
|
|
53
|
+
claude plugin install aegis-devops@aegis-devops
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Codex, GitHub Copilot (CLI and VS Code) and Cursor: `aegis install codex|copilot|vscode|cursor`
|
|
57
|
+
(see [Coding agents](docs/agents.md)). It only acts in projects with a `.aegis/` policy, and
|
|
58
|
+
only blocks what that policy blocks. It also works as a CI step
|
|
59
|
+
(`aegis check terraform plan.json --exit-style ci`) and as a Python library; see
|
|
60
|
+
[Quick start](#quick-start).
|
|
46
61
|
|
|
47
62
|
## What it does
|
|
48
63
|
|
|
@@ -92,19 +107,7 @@ a key everyone has. `aegis init` prints the two commands that replace it with yo
|
|
|
92
107
|
replace `constraints.example.yaml` with your own `constraints.yaml` (a real file wins over the
|
|
93
108
|
`.example` one when both exist).
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Aegis can check every shell command Claude Code, Codex, GitHub Copilot (CLI and VS Code) or
|
|
98
|
-
Cursor wants to run, before it runs. In Claude Code:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
pip install aegis-devops && aegis init .aegis
|
|
102
|
-
claude plugin marketplace add moneytool/aegis-devops
|
|
103
|
-
claude plugin install aegis-devops@aegis-devops
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
For the others, `aegis install codex|copilot|vscode|cursor`. It only acts in projects with a
|
|
107
|
-
`.aegis/` policy, and only blocks what that policy blocks. See [Coding agents](docs/agents.md).
|
|
110
|
+

|
|
108
111
|
|
|
109
112
|
### From a clone
|
|
110
113
|
|
|
@@ -213,11 +216,31 @@ OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rule
|
|
|
213
216
|
derives **unstructured human constraints** (from Slack, Jira, Git) and applies
|
|
214
217
|
**authority-driven validation** to the agent's intent *before* it reaches the infrastructure.
|
|
215
218
|
|
|
219
|
+
## How it compares
|
|
220
|
+
|
|
221
|
+
Other tools stop destructive commands in coding agents, and cover more agents and more kinds of
|
|
222
|
+
command than Aegis does today. The difference is where the rules come from: Aegis treats every
|
|
223
|
+
rule as a claim that has to be checked (was it changed since it was signed, does its cited
|
|
224
|
+
source back it, was its author allowed to write that kind of rule), because in an agent's
|
|
225
|
+
context a rule can arrive from a ticket or a chat message as easily as from you.
|
|
226
|
+
|
|
227
|
+
| | Aegis-DevOps | [nah](https://github.com/manuelschipper/nah) | [claude-code-safety-net](https://github.com/kenryu42/claude-code-safety-net) | [destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard) |
|
|
228
|
+
|---|---|---|---|---|
|
|
229
|
+
| Guards | Infra commands and plans: kubectl, terraform/tofu, aws/az/gcloud, helm, argocd, flux, git/gh, SQL, pulumi | Git, filesystem, infra CLIs (Terraform, OpenTofu, Pulumi, kubectl, Docker), secrets, publishing | Destructive git and filesystem commands, secret access; cloud CLIs via optional rulebooks | Git, filesystem, databases, Kubernetes, IaC, clouds, Docker and more (50+ packs) |
|
|
230
|
+
| Agents | Claude Code, Codex, Copilot CLI, VS Code, Cursor | Claude Code, Codex, Cursor, Copilot and 10+ more | Claude Code, Codex, Cursor, Copilot CLI, Gemini CLI and 8+ more | Claude Code, Codex, Copilot, Cursor, Gemini CLI and 9+ more |
|
|
231
|
+
| Rules | Signed rules, each citing a source and an author; checked against an authority map (who may assert what) | Built-in deterministic guards; custom guards can only make it stricter | Built-in AST-based protections, configurable presets, community rulebooks | Built-in regex/AST packs, TOML config, custom YAML packs |
|
|
232
|
+
| Rule provenance and authority | Yes: a tampered, forged or unauthorised rule gets no vote | — | — | — |
|
|
233
|
+
| Terraform/Pulumi plan checks | Yes (plan JSON) | Whole-stack destroy commands | Commands via rulebooks | Destroy commands |
|
|
234
|
+
| CI / non-agent use | `aegis check ... --exit-style ci`, Python library | `nah test` | Node.js library mode | `dcg scan` (SARIF) |
|
|
235
|
+
|
|
236
|
+
"—" means the project's README does not describe it. Checked against each project's README on
|
|
237
|
+
2026-09-27; corrections welcome.
|
|
238
|
+
|
|
216
239
|
## Project status / roadmap
|
|
217
240
|
|
|
218
241
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
219
242
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
220
|
-
v0.1.
|
|
243
|
+
v0.1.3 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
221
244
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
222
245
|
through the Codex CLI, and a local `mistral:latest`.
|
|
223
246
|
|
|
@@ -234,6 +257,7 @@ of anything you care about.
|
|
|
234
257
|
|
|
235
258
|
| Page | Covers |
|
|
236
259
|
| :--- | :--- |
|
|
260
|
+
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
237
261
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
238
262
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
239
263
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
# Aegis-DevOps
|
|
1
|
+
# Aegis-DevOps
|
|
2
2
|
|
|
3
3
|
[](https://doi.org/10.5281/zenodo.22950337)
|
|
4
4
|
[](https://pypi.org/project/aegis-devops/)
|
|
5
5
|
|
|
6
|
-
**
|
|
7
|
-
|
|
6
|
+
**Stop AI agents from running `kubectl delete`, `terraform destroy` or `DROP TABLE` because a
|
|
7
|
+
ticket told them to.**
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
Aegis-DevOps checks every command an agent wants to run before it runs, and blocks it if your
|
|
10
|
+
policy says no. A policy rule only counts if nobody has edited it since it was signed, and if
|
|
11
|
+
its author was allowed to write that kind of rule. So a planted line in a Jira ticket can't
|
|
12
|
+
become policy.
|
|
12
13
|
|
|
13
|
-

|
|
15
|
+
|
|
16
|
+
### Install in Claude Code
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install aegis-devops && aegis init .aegis
|
|
20
|
+
claude plugin marketplace add moneytool/aegis-devops
|
|
21
|
+
claude plugin install aegis-devops@aegis-devops
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Codex, GitHub Copilot (CLI and VS Code) and Cursor: `aegis install codex|copilot|vscode|cursor`
|
|
25
|
+
(see [Coding agents](docs/agents.md)). It only acts in projects with a `.aegis/` policy, and
|
|
26
|
+
only blocks what that policy blocks. It also works as a CI step
|
|
27
|
+
(`aegis check terraform plan.json --exit-style ci`) and as a Python library; see
|
|
28
|
+
[Quick start](#quick-start).
|
|
14
29
|
|
|
15
30
|
## What it does
|
|
16
31
|
|
|
@@ -60,19 +75,7 @@ a key everyone has. `aegis init` prints the two commands that replace it with yo
|
|
|
60
75
|
replace `constraints.example.yaml` with your own `constraints.yaml` (a real file wins over the
|
|
61
76
|
`.example` one when both exist).
|
|
62
77
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Aegis can check every shell command Claude Code, Codex, GitHub Copilot (CLI and VS Code) or
|
|
66
|
-
Cursor wants to run, before it runs. In Claude Code:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
pip install aegis-devops && aegis init .aegis
|
|
70
|
-
claude plugin marketplace add moneytool/aegis-devops
|
|
71
|
-
claude plugin install aegis-devops@aegis-devops
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
For the others, `aegis install codex|copilot|vscode|cursor`. It only acts in projects with a
|
|
75
|
-
`.aegis/` policy, and only blocks what that policy blocks. See [Coding agents](docs/agents.md).
|
|
78
|
+

|
|
76
79
|
|
|
77
80
|
### From a clone
|
|
78
81
|
|
|
@@ -181,11 +184,31 @@ OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rule
|
|
|
181
184
|
derives **unstructured human constraints** (from Slack, Jira, Git) and applies
|
|
182
185
|
**authority-driven validation** to the agent's intent *before* it reaches the infrastructure.
|
|
183
186
|
|
|
187
|
+
## How it compares
|
|
188
|
+
|
|
189
|
+
Other tools stop destructive commands in coding agents, and cover more agents and more kinds of
|
|
190
|
+
command than Aegis does today. The difference is where the rules come from: Aegis treats every
|
|
191
|
+
rule as a claim that has to be checked (was it changed since it was signed, does its cited
|
|
192
|
+
source back it, was its author allowed to write that kind of rule), because in an agent's
|
|
193
|
+
context a rule can arrive from a ticket or a chat message as easily as from you.
|
|
194
|
+
|
|
195
|
+
| | Aegis-DevOps | [nah](https://github.com/manuelschipper/nah) | [claude-code-safety-net](https://github.com/kenryu42/claude-code-safety-net) | [destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard) |
|
|
196
|
+
|---|---|---|---|---|
|
|
197
|
+
| Guards | Infra commands and plans: kubectl, terraform/tofu, aws/az/gcloud, helm, argocd, flux, git/gh, SQL, pulumi | Git, filesystem, infra CLIs (Terraform, OpenTofu, Pulumi, kubectl, Docker), secrets, publishing | Destructive git and filesystem commands, secret access; cloud CLIs via optional rulebooks | Git, filesystem, databases, Kubernetes, IaC, clouds, Docker and more (50+ packs) |
|
|
198
|
+
| Agents | Claude Code, Codex, Copilot CLI, VS Code, Cursor | Claude Code, Codex, Cursor, Copilot and 10+ more | Claude Code, Codex, Cursor, Copilot CLI, Gemini CLI and 8+ more | Claude Code, Codex, Copilot, Cursor, Gemini CLI and 9+ more |
|
|
199
|
+
| Rules | Signed rules, each citing a source and an author; checked against an authority map (who may assert what) | Built-in deterministic guards; custom guards can only make it stricter | Built-in AST-based protections, configurable presets, community rulebooks | Built-in regex/AST packs, TOML config, custom YAML packs |
|
|
200
|
+
| Rule provenance and authority | Yes: a tampered, forged or unauthorised rule gets no vote | — | — | — |
|
|
201
|
+
| Terraform/Pulumi plan checks | Yes (plan JSON) | Whole-stack destroy commands | Commands via rulebooks | Destroy commands |
|
|
202
|
+
| CI / non-agent use | `aegis check ... --exit-style ci`, Python library | `nah test` | Node.js library mode | `dcg scan` (SARIF) |
|
|
203
|
+
|
|
204
|
+
"—" means the project's README does not describe it. Checked against each project's README on
|
|
205
|
+
2026-09-27; corrections welcome.
|
|
206
|
+
|
|
184
207
|
## Project status / roadmap
|
|
185
208
|
|
|
186
209
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
187
210
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
188
|
-
v0.1.
|
|
211
|
+
v0.1.3 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
189
212
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
190
213
|
through the Codex CLI, and a local `mistral:latest`.
|
|
191
214
|
|
|
@@ -202,6 +225,7 @@ of anything you care about.
|
|
|
202
225
|
|
|
203
226
|
| Page | Covers |
|
|
204
227
|
| :--- | :--- |
|
|
228
|
+
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
205
229
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
206
230
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
207
231
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
@@ -255,6 +255,21 @@ def decide(command: str, config_dir: Path, extra_args: list[str] | None = None)
|
|
|
255
255
|
# --- replying --------------------------------------------------------------------
|
|
256
256
|
|
|
257
257
|
|
|
258
|
+
def _both_shapes(decision: str, reason: str) -> dict:
|
|
259
|
+
"""Copilot CLI reads a top-level ``permissionDecision``; VS Code reads
|
|
260
|
+
``hookSpecificOutput``. Both read the same ``.github/hooks`` files and
|
|
261
|
+
the same Copilot plugins, so their reply carries both."""
|
|
262
|
+
return {
|
|
263
|
+
"permissionDecision": decision,
|
|
264
|
+
"permissionDecisionReason": reason,
|
|
265
|
+
"hookSpecificOutput": {
|
|
266
|
+
"hookEventName": "PreToolUse",
|
|
267
|
+
"permissionDecision": decision,
|
|
268
|
+
"permissionDecisionReason": reason,
|
|
269
|
+
},
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
258
273
|
def render(agent: str, verdict: HookVerdict, *, escalate_as: str = "ask") -> tuple[int, str, str]:
|
|
259
274
|
"""``(exit_code, stdout, stderr)`` for this agent. Deny is exit 2 +
|
|
260
275
|
stderr (Cursor: its JSON on exit 0); ask is each agent's own JSON with
|
|
@@ -273,11 +288,8 @@ def render(agent: str, verdict: HookVerdict, *, escalate_as: str = "ask") -> tup
|
|
|
273
288
|
"codex": {"hookSpecificOutput": {
|
|
274
289
|
"hookEventName": "PreToolUse", "permissionDecision": "deny",
|
|
275
290
|
"permissionDecisionReason": reason}},
|
|
276
|
-
"copilot":
|
|
277
|
-
"vscode":
|
|
278
|
-
"hookSpecificOutput": {"hookEventName": "PreToolUse",
|
|
279
|
-
"permissionDecision": "deny",
|
|
280
|
-
"permissionDecisionReason": reason}},
|
|
291
|
+
"copilot": _both_shapes("deny", reason),
|
|
292
|
+
"vscode": _both_shapes("deny", reason),
|
|
281
293
|
"cursor": {"permission": "deny", "user_message": reason, "agent_message": reason},
|
|
282
294
|
}[agent]
|
|
283
295
|
if agent == "cursor":
|
|
@@ -291,11 +303,8 @@ def render(agent: str, verdict: HookVerdict, *, escalate_as: str = "ask") -> tup
|
|
|
291
303
|
"claude": {"hookSpecificOutput": {
|
|
292
304
|
"hookEventName": "PreToolUse", "permissionDecision": "ask",
|
|
293
305
|
"permissionDecisionReason": reason}},
|
|
294
|
-
"copilot":
|
|
295
|
-
"vscode":
|
|
296
|
-
"hookSpecificOutput": {"hookEventName": "PreToolUse",
|
|
297
|
-
"permissionDecision": "ask",
|
|
298
|
-
"permissionDecisionReason": reason}},
|
|
306
|
+
"copilot": _both_shapes("ask", reason),
|
|
307
|
+
"vscode": _both_shapes("ask", reason),
|
|
299
308
|
"cursor": {"permission": "ask", "user_message": reason, "agent_message": reason},
|
|
300
309
|
}[agent]
|
|
301
310
|
return EXIT_ALLOW, json.dumps(body), ""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aegis-devops
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Provenance-backed, authority-aware policy verifier for agentic DevOps actions.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://github.com/moneytool/aegis-devops
|
|
@@ -30,19 +30,34 @@ Provides-Extra: llm
|
|
|
30
30
|
Requires-Dist: anthropic; extra == "llm"
|
|
31
31
|
Dynamic: license-file
|
|
32
32
|
|
|
33
|
-
# Aegis-DevOps
|
|
33
|
+
# Aegis-DevOps
|
|
34
34
|
|
|
35
35
|
[](https://doi.org/10.5281/zenodo.22950337)
|
|
36
36
|
[](https://pypi.org/project/aegis-devops/)
|
|
37
37
|
|
|
38
|
-
**
|
|
39
|
-
|
|
38
|
+
**Stop AI agents from running `kubectl delete`, `terraform destroy` or `DROP TABLE` because a
|
|
39
|
+
ticket told them to.**
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
Aegis-DevOps checks every command an agent wants to run before it runs, and blocks it if your
|
|
42
|
+
policy says no. A policy rule only counts if nobody has edited it since it was signed, and if
|
|
43
|
+
its author was allowed to write that kind of rule. So a planted line in a Jira ticket can't
|
|
44
|
+
become policy.
|
|
44
45
|
|
|
45
|
-

|
|
47
|
+
|
|
48
|
+
### Install in Claude Code
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install aegis-devops && aegis init .aegis
|
|
52
|
+
claude plugin marketplace add moneytool/aegis-devops
|
|
53
|
+
claude plugin install aegis-devops@aegis-devops
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Codex, GitHub Copilot (CLI and VS Code) and Cursor: `aegis install codex|copilot|vscode|cursor`
|
|
57
|
+
(see [Coding agents](docs/agents.md)). It only acts in projects with a `.aegis/` policy, and
|
|
58
|
+
only blocks what that policy blocks. It also works as a CI step
|
|
59
|
+
(`aegis check terraform plan.json --exit-style ci`) and as a Python library; see
|
|
60
|
+
[Quick start](#quick-start).
|
|
46
61
|
|
|
47
62
|
## What it does
|
|
48
63
|
|
|
@@ -92,19 +107,7 @@ a key everyone has. `aegis init` prints the two commands that replace it with yo
|
|
|
92
107
|
replace `constraints.example.yaml` with your own `constraints.yaml` (a real file wins over the
|
|
93
108
|
`.example` one when both exist).
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Aegis can check every shell command Claude Code, Codex, GitHub Copilot (CLI and VS Code) or
|
|
98
|
-
Cursor wants to run, before it runs. In Claude Code:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
pip install aegis-devops && aegis init .aegis
|
|
102
|
-
claude plugin marketplace add moneytool/aegis-devops
|
|
103
|
-
claude plugin install aegis-devops@aegis-devops
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
For the others, `aegis install codex|copilot|vscode|cursor`. It only acts in projects with a
|
|
107
|
-
`.aegis/` policy, and only blocks what that policy blocks. See [Coding agents](docs/agents.md).
|
|
110
|
+

|
|
108
111
|
|
|
109
112
|
### From a clone
|
|
110
113
|
|
|
@@ -213,11 +216,31 @@ OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rule
|
|
|
213
216
|
derives **unstructured human constraints** (from Slack, Jira, Git) and applies
|
|
214
217
|
**authority-driven validation** to the agent's intent *before* it reaches the infrastructure.
|
|
215
218
|
|
|
219
|
+
## How it compares
|
|
220
|
+
|
|
221
|
+
Other tools stop destructive commands in coding agents, and cover more agents and more kinds of
|
|
222
|
+
command than Aegis does today. The difference is where the rules come from: Aegis treats every
|
|
223
|
+
rule as a claim that has to be checked (was it changed since it was signed, does its cited
|
|
224
|
+
source back it, was its author allowed to write that kind of rule), because in an agent's
|
|
225
|
+
context a rule can arrive from a ticket or a chat message as easily as from you.
|
|
226
|
+
|
|
227
|
+
| | Aegis-DevOps | [nah](https://github.com/manuelschipper/nah) | [claude-code-safety-net](https://github.com/kenryu42/claude-code-safety-net) | [destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard) |
|
|
228
|
+
|---|---|---|---|---|
|
|
229
|
+
| Guards | Infra commands and plans: kubectl, terraform/tofu, aws/az/gcloud, helm, argocd, flux, git/gh, SQL, pulumi | Git, filesystem, infra CLIs (Terraform, OpenTofu, Pulumi, kubectl, Docker), secrets, publishing | Destructive git and filesystem commands, secret access; cloud CLIs via optional rulebooks | Git, filesystem, databases, Kubernetes, IaC, clouds, Docker and more (50+ packs) |
|
|
230
|
+
| Agents | Claude Code, Codex, Copilot CLI, VS Code, Cursor | Claude Code, Codex, Cursor, Copilot and 10+ more | Claude Code, Codex, Cursor, Copilot CLI, Gemini CLI and 8+ more | Claude Code, Codex, Copilot, Cursor, Gemini CLI and 9+ more |
|
|
231
|
+
| Rules | Signed rules, each citing a source and an author; checked against an authority map (who may assert what) | Built-in deterministic guards; custom guards can only make it stricter | Built-in AST-based protections, configurable presets, community rulebooks | Built-in regex/AST packs, TOML config, custom YAML packs |
|
|
232
|
+
| Rule provenance and authority | Yes: a tampered, forged or unauthorised rule gets no vote | — | — | — |
|
|
233
|
+
| Terraform/Pulumi plan checks | Yes (plan JSON) | Whole-stack destroy commands | Commands via rulebooks | Destroy commands |
|
|
234
|
+
| CI / non-agent use | `aegis check ... --exit-style ci`, Python library | `nah test` | Node.js library mode | `dcg scan` (SARIF) |
|
|
235
|
+
|
|
236
|
+
"—" means the project's README does not describe it. Checked against each project's README on
|
|
237
|
+
2026-09-27; corrections welcome.
|
|
238
|
+
|
|
216
239
|
## Project status / roadmap
|
|
217
240
|
|
|
218
241
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
219
242
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
220
|
-
v0.1.
|
|
243
|
+
v0.1.3 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
221
244
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
222
245
|
through the Codex CLI, and a local `mistral:latest`.
|
|
223
246
|
|
|
@@ -234,6 +257,7 @@ of anything you care about.
|
|
|
234
257
|
|
|
235
258
|
| Page | Covers |
|
|
236
259
|
| :--- | :--- |
|
|
260
|
+
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
237
261
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
238
262
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
239
263
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
@@ -108,3 +108,19 @@ def test_plan_json_intents_are_not_caught_by_the_workspace_rule(capsys):
|
|
|
108
108
|
"name": "b", "change": {"actions": ["delete"]}}]}
|
|
109
109
|
[intent] = from_terraform_plan(plan)
|
|
110
110
|
assert not intent.resource.startswith("workspace/")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_forged_sources_differ_from_sources_in_one_file_only():
|
|
114
|
+
"""data/sources-forged/ is data/sources/ with jira-1001.json edited, for
|
|
115
|
+
the --sources demo. Any other difference (a source missing after new
|
|
116
|
+
rules were added) quarantines more rules and breaks the demo."""
|
|
117
|
+
from pathlib import Path
|
|
118
|
+
|
|
119
|
+
real, forged = Path("data/sources"), Path("data/sources-forged")
|
|
120
|
+
names = {p.name for p in real.iterdir()} | {p.name for p in forged.iterdir()}
|
|
121
|
+
differing = sorted(
|
|
122
|
+
n for n in names - {"AEGIS-MANIFEST.sig"}
|
|
123
|
+
if not (real / n).exists() or not (forged / n).exists()
|
|
124
|
+
or (real / n).read_bytes() != (forged / n).read_bytes()
|
|
125
|
+
)
|
|
126
|
+
assert differing == ["jira-1001.json"]
|
|
@@ -625,3 +625,12 @@ def test_remove_deletes_a_file_that_only_held_our_hook(tmp_path, monkeypatch):
|
|
|
625
625
|
def test_cursor_allow_is_explicit_when_opted_in(opted_in_project):
|
|
626
626
|
code, out, _err = run("cursor", payload_for("cursor", "ls -la"))
|
|
627
627
|
assert (code, json.loads(out)) == (0, {"permission": "allow"})
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
def test_copilot_reply_carries_the_vscode_shape_too(opted_in_project):
|
|
631
|
+
# Copilot plugins and .github/hooks are read by both Copilot CLI and VS Code
|
|
632
|
+
code, out, _err = run("copilot", payload_for("copilot", BLOCK_COMMAND))
|
|
633
|
+
body = json.loads(out)
|
|
634
|
+
assert code == 2
|
|
635
|
+
assert body["permissionDecision"] == "deny"
|
|
636
|
+
assert body["hookSpecificOutput"]["permissionDecision"] == "deny"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Packaging of the Claude Code and Copilot plugins, and the wrapper script
|
|
2
|
+
they both run when ``aegis`` itself may be missing."""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from aegis_core import __version__
|
|
12
|
+
|
|
13
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
14
|
+
WRAPPER = ROOT / "hooks" / "aegis-hook.sh"
|
|
15
|
+
COPILOT = ROOT / "plugins" / "copilot"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_copilot_plugin_manifest():
|
|
19
|
+
manifest = json.loads((COPILOT / "plugin.json").read_text())
|
|
20
|
+
assert manifest["$schema"] == "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"
|
|
21
|
+
assert manifest["name"] == "aegis-devops"
|
|
22
|
+
# awesome-copilot pins a semver version to a release tag
|
|
23
|
+
assert manifest["version"] == __version__
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_copilot_plugin_hook_runs_the_wrapper():
|
|
27
|
+
hooks = json.loads((COPILOT / "com.github.copilot" / "hooks" / "hooks.json").read_text())
|
|
28
|
+
[entry] = hooks["hooks"]["preToolUse"]
|
|
29
|
+
assert entry["bash"] == '"${PLUGIN_ROOT}"/aegis-hook.sh copilot'
|
|
30
|
+
assert (COPILOT / "aegis-hook.sh").stat().st_mode & 0o111
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_copilot_wrapper_is_a_copy_of_the_claude_one():
|
|
34
|
+
# a plugin can only ship files inside its own folder
|
|
35
|
+
assert (COPILOT / "aegis-hook.sh").read_bytes() == WRAPPER.read_bytes()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_claude_plugin_hook_runs_the_wrapper():
|
|
39
|
+
hooks = json.loads((ROOT / "hooks" / "hooks.json").read_text())
|
|
40
|
+
[entry] = hooks["hooks"]["PreToolUse"]
|
|
41
|
+
assert entry["matcher"] == "Bash"
|
|
42
|
+
assert entry["hooks"][0]["command"] == '"${CLAUDE_PLUGIN_ROOT}"/hooks/aegis-hook.sh claude'
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# --- the wrapper with no aegis installed --------------------------------------------
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _run_wrapper(tmp_path, command, *, opted_in):
|
|
49
|
+
home, project = tmp_path / "home", tmp_path / "project"
|
|
50
|
+
home.mkdir()
|
|
51
|
+
project.mkdir()
|
|
52
|
+
if opted_in:
|
|
53
|
+
(project / ".aegis").mkdir()
|
|
54
|
+
env = {"HOME": str(home), "PATH": "/usr/bin:/bin"} # no aegis, no uvx
|
|
55
|
+
payload = json.dumps({"toolName": "bash", "toolArgs": {"command": command}})
|
|
56
|
+
proc = subprocess.run(
|
|
57
|
+
["bash", str(WRAPPER), "copilot"], input=payload, capture_output=True, text=True,
|
|
58
|
+
cwd=project, env=env, check=False,
|
|
59
|
+
)
|
|
60
|
+
return proc.returncode, proc.stderr
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.mark.skipif(os.name == "nt", reason="bash wrapper")
|
|
64
|
+
@pytest.mark.parametrize("command", ["ls -la", "kubectl delete nodes --all"])
|
|
65
|
+
def test_wrapper_without_aegis_allows_everything_outside_opted_in_projects(tmp_path, command):
|
|
66
|
+
assert _run_wrapper(tmp_path, command, opted_in=False) == (0, "")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@pytest.mark.skipif(os.name == "nt", reason="bash wrapper")
|
|
70
|
+
def test_wrapper_without_aegis_blocks_only_infra_in_opted_in_projects(tmp_path):
|
|
71
|
+
code, err = _run_wrapper(tmp_path, "kubectl get pods", opted_in=True)
|
|
72
|
+
assert code == 2
|
|
73
|
+
assert "pip install aegis-devops" in err
|
|
74
|
+
(tmp_path / "home").rename(tmp_path / "old-home")
|
|
75
|
+
(tmp_path / "project").rename(tmp_path / "old-project")
|
|
76
|
+
assert _run_wrapper(tmp_path, "ls -la", opted_in=True) == (0, "")
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/authority.example.yaml.sig
RENAMED
|
File without changes
|
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/constraints.example.yaml.sig
RENAMED
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml
RENAMED
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml.sig
RENAMED
|
File without changes
|
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml
RENAMED
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml.sig
RENAMED
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aegis_devops-0.1.3 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/slack-perma-1.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|