aegis-devops 0.1.2__tar.gz → 0.1.3__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.2/src/aegis_devops.egg-info → aegis_devops-0.1.3}/PKG-INFO +20 -6
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/README.md +19 -5
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/__init__.py +1 -1
- aegis_devops-0.1.3/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/constraints.example.yaml +115 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/constraints.example.yaml.sig +2 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig +10 -2
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/PRINCIPALS.yaml +8 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6001.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6002.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6003.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6004.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6005.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6006.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6007.json +15 -0
- aegis_devops-0.1.3/src/aegis_core/_examples/sources/git-6008.json +15 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/__init__.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/llm.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/metrics.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/opa.py +2 -2
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/cli.py +45 -0
- aegis_devops-0.1.3/src/aegis_core/hook.py +481 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/parser.py +41 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/shell.py +9 -3
- {aegis_devops-0.1.2 → aegis_devops-0.1.3/src/aegis_devops.egg-info}/PKG-INFO +20 -6
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_devops.egg-info/SOURCES.txt +11 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_baselines.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_benchmark.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_cli.py +18 -13
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_corpus.py +1 -1
- aegis_devops-0.1.3/tests/test_default_rules.py +110 -0
- aegis_devops-0.1.3/tests/test_hook.py +627 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_parsers_sql.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_store.py +2 -2
- aegis_devops-0.1.2/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
- aegis_devops-0.1.2/src/aegis_core/_examples/constraints.example.yaml.sig +0 -2
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/LICENSE +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/MANIFEST.in +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/pyproject.toml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/setup.cfg +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/__init__.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/authority.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/authority.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/environments.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/environments.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/example-signing.key +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/plan_constraints.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/plan_constraints.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/git-4001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/git-789abc.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/git-abc123.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/git-bcd234.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/git-def456.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-1001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-1002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-2001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-2002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-3001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-3002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-3003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-3004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-3005.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-5001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-5002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-5003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-5004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/jira-5006.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/plan-1001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/plan-1002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/plan-1003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/plan-1004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/plan-5005.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/slack-perma-1.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/adversarial.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/authority.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/base.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/baselines/external.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/config.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/environments.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/intent.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/interceptor.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/ledger.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/parsers/__init__.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/parsers/pulumi.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/parsers/sql.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/plan.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/provenance.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/signing.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/store.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_devops.egg-info/dependency_links.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_devops.egg-info/entry_points.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_devops.egg-info/requires.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_devops.egg-info/top_level.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_adversarial.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_authority.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_config.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_docs_consistency.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_environments.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_intent.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_interceptor.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_ledger.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_parser.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_parsers_pulumi.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_plan.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_provenance.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_shell.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/tests/test_signing.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.3}/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.3
|
|
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
|
|
@@ -81,7 +81,7 @@ BLOCK: kubernetes scale deployment/api-server
|
|
|
81
81
|
citations: no-scale-prod-peak
|
|
82
82
|
covered: True latency_ms: 0.20
|
|
83
83
|
PLAN BLOCK: 1 intent(s)
|
|
84
|
-
STORE: loaded=
|
|
84
|
+
STORE: loaded=29 quarantined=0 principals=3
|
|
85
85
|
warning: using example signing key
|
|
86
86
|
```
|
|
87
87
|
|
|
@@ -92,6 +92,20 @@ a key everyone has. `aegis init` prints the two commands that replace it with yo
|
|
|
92
92
|
replace `constraints.example.yaml` with your own `constraints.yaml` (a real file wins over the
|
|
93
93
|
`.example` one when both exist).
|
|
94
94
|
|
|
95
|
+
### In your coding agent
|
|
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).
|
|
108
|
+
|
|
95
109
|
### From a clone
|
|
96
110
|
|
|
97
111
|
```bash
|
|
@@ -207,13 +221,13 @@ v0.1.0 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonn
|
|
|
207
221
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
208
222
|
through the Codex CLI, and a local `mistral:latest`.
|
|
209
223
|
|
|
210
|
-
What is *not* done is the part the threat model leans on hardest. See `PLAN.md §8`, but in
|
|
224
|
+
What is *not* done is the part the threat model leans on hardest. See `docs/dev/PLAN.md §8`, but in
|
|
211
225
|
short: sources are verified against files on disk rather than real Git/Slack/Jira connectors,
|
|
212
226
|
signing uses a shared secret rather than per-principal public keys, and a `principal` is a
|
|
213
227
|
signed name rather than an identity bound to a commit signature or an SSO group. Until those
|
|
214
228
|
land, Aegis demonstrates that the *decision procedure* is sound; it does not yet prove the
|
|
215
229
|
identities feeding it are. Resource matching is also case-sensitive on names. It is not
|
|
216
|
-
production-ready: read `PLAN.md §8` for the full list of open gaps before putting it in front
|
|
230
|
+
production-ready: read `docs/dev/PLAN.md §8` for the full list of open gaps before putting it in front
|
|
217
231
|
of anything you care about.
|
|
218
232
|
|
|
219
233
|
## Documentation
|
|
@@ -225,10 +239,10 @@ of anything you care about.
|
|
|
225
239
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
226
240
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
227
241
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
228
|
-
| [`PLAN.md`](PLAN.md) | Design plan and open gaps |
|
|
242
|
+
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
229
243
|
| [`SECURITY.md`](SECURITY.md) | Reporting a bypass |
|
|
230
244
|
| [`CHANGELOG.md`](CHANGELOG.md) | Release history |
|
|
231
|
-
| [`REVIEW-4.md`](REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
245
|
+
| [`docs/dev/REVIEW-4.md`](docs/dev/REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
232
246
|
|
|
233
247
|
## Development
|
|
234
248
|
|
|
@@ -49,7 +49,7 @@ BLOCK: kubernetes scale deployment/api-server
|
|
|
49
49
|
citations: no-scale-prod-peak
|
|
50
50
|
covered: True latency_ms: 0.20
|
|
51
51
|
PLAN BLOCK: 1 intent(s)
|
|
52
|
-
STORE: loaded=
|
|
52
|
+
STORE: loaded=29 quarantined=0 principals=3
|
|
53
53
|
warning: using example signing key
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -60,6 +60,20 @@ a key everyone has. `aegis init` prints the two commands that replace it with yo
|
|
|
60
60
|
replace `constraints.example.yaml` with your own `constraints.yaml` (a real file wins over the
|
|
61
61
|
`.example` one when both exist).
|
|
62
62
|
|
|
63
|
+
### In your coding agent
|
|
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).
|
|
76
|
+
|
|
63
77
|
### From a clone
|
|
64
78
|
|
|
65
79
|
```bash
|
|
@@ -175,13 +189,13 @@ v0.1.0 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonn
|
|
|
175
189
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
176
190
|
through the Codex CLI, and a local `mistral:latest`.
|
|
177
191
|
|
|
178
|
-
What is *not* done is the part the threat model leans on hardest. See `PLAN.md §8`, but in
|
|
192
|
+
What is *not* done is the part the threat model leans on hardest. See `docs/dev/PLAN.md §8`, but in
|
|
179
193
|
short: sources are verified against files on disk rather than real Git/Slack/Jira connectors,
|
|
180
194
|
signing uses a shared secret rather than per-principal public keys, and a `principal` is a
|
|
181
195
|
signed name rather than an identity bound to a commit signature or an SSO group. Until those
|
|
182
196
|
land, Aegis demonstrates that the *decision procedure* is sound; it does not yet prove the
|
|
183
197
|
identities feeding it are. Resource matching is also case-sensitive on names. It is not
|
|
184
|
-
production-ready: read `PLAN.md §8` for the full list of open gaps before putting it in front
|
|
198
|
+
production-ready: read `docs/dev/PLAN.md §8` for the full list of open gaps before putting it in front
|
|
185
199
|
of anything you care about.
|
|
186
200
|
|
|
187
201
|
## Documentation
|
|
@@ -193,10 +207,10 @@ of anything you care about.
|
|
|
193
207
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
194
208
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
195
209
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
196
|
-
| [`PLAN.md`](PLAN.md) | Design plan and open gaps |
|
|
210
|
+
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
197
211
|
| [`SECURITY.md`](SECURITY.md) | Reporting a bypass |
|
|
198
212
|
| [`CHANGELOG.md`](CHANGELOG.md) | Release history |
|
|
199
|
-
| [`REVIEW-4.md`](REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
213
|
+
| [`docs/dev/REVIEW-4.md`](docs/dev/REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
200
214
|
|
|
201
215
|
## Development
|
|
202
216
|
|
|
@@ -336,3 +336,118 @@ constraints:
|
|
|
336
336
|
rule_text: Block deleting Helm releases in any production environment (resolved
|
|
337
337
|
from the kube context), whatever the namespace; use the decommission runbook instead.
|
|
338
338
|
provenance_hash: 747653b3b34300a18e4773a0784706fcb0147fb10507e88ce93f2fb5cdcd4df8
|
|
339
|
+
- id: block-terraform-destroy
|
|
340
|
+
provider: terraform
|
|
341
|
+
resource_pattern: workspace/*
|
|
342
|
+
actions:
|
|
343
|
+
- delete
|
|
344
|
+
scope: {}
|
|
345
|
+
time_window: null
|
|
346
|
+
effect: BLOCK
|
|
347
|
+
constraint_class: deletion
|
|
348
|
+
principal: admin
|
|
349
|
+
source_ref: git-6001
|
|
350
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
351
|
+
rule_text: 'Block ''terraform destroy'' and ''tofu destroy'' (and apply -destroy):
|
|
352
|
+
tearing down a whole configuration needs a reviewed plan, not an agent''s command.'
|
|
353
|
+
provenance_hash: 48bd0974d281efa45af89240c0ffc997a4ee7323d07471bb97a4a047081c4178
|
|
354
|
+
- id: block-pulumi-destroy
|
|
355
|
+
provider: pulumi
|
|
356
|
+
resource_pattern: stack/*
|
|
357
|
+
actions:
|
|
358
|
+
- delete
|
|
359
|
+
scope: {}
|
|
360
|
+
time_window: null
|
|
361
|
+
effect: BLOCK
|
|
362
|
+
constraint_class: deletion
|
|
363
|
+
principal: admin
|
|
364
|
+
source_ref: git-6002
|
|
365
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
366
|
+
rule_text: 'Block ''pulumi destroy'' and ''pulumi stack rm'': removing a whole stack
|
|
367
|
+
needs a human.'
|
|
368
|
+
provenance_hash: 41428597dfe6a997f0797c3c700db953399d515447b2857552cbf4635d3e1782
|
|
369
|
+
- id: block-namespace-delete
|
|
370
|
+
provider: kubernetes
|
|
371
|
+
resource_pattern: namespace/*
|
|
372
|
+
actions:
|
|
373
|
+
- delete
|
|
374
|
+
scope: {}
|
|
375
|
+
time_window: null
|
|
376
|
+
effect: BLOCK
|
|
377
|
+
constraint_class: deletion
|
|
378
|
+
principal: admin
|
|
379
|
+
source_ref: git-6003
|
|
380
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
381
|
+
rule_text: 'Block deleting Kubernetes namespaces: it deletes everything inside them.'
|
|
382
|
+
provenance_hash: 44ee6f6790b2e4996f1fa03bc8d79782e876d1aae27dca7630b81a88206de572
|
|
383
|
+
- id: block-s3-bucket-delete
|
|
384
|
+
provider: aws
|
|
385
|
+
resource_pattern: s3/bucket/*
|
|
386
|
+
actions:
|
|
387
|
+
- delete
|
|
388
|
+
scope: {}
|
|
389
|
+
time_window: null
|
|
390
|
+
effect: BLOCK
|
|
391
|
+
constraint_class: deletion
|
|
392
|
+
principal: admin
|
|
393
|
+
source_ref: git-6004
|
|
394
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
395
|
+
rule_text: Block deleting S3 buckets (aws s3 rb, s3api delete-bucket).
|
|
396
|
+
provenance_hash: 27e8b1723128c747f4780969cf2b44f639235bc1e83e4188686618cb23d42125
|
|
397
|
+
- id: block-rds-delete
|
|
398
|
+
provider: aws
|
|
399
|
+
resource_pattern: rds/*
|
|
400
|
+
actions:
|
|
401
|
+
- delete
|
|
402
|
+
scope: {}
|
|
403
|
+
time_window: null
|
|
404
|
+
effect: BLOCK
|
|
405
|
+
constraint_class: deletion
|
|
406
|
+
principal: admin
|
|
407
|
+
source_ref: git-6005
|
|
408
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
409
|
+
rule_text: Block deleting RDS databases, clusters and snapshots.
|
|
410
|
+
provenance_hash: e44c7617a771c4f53260e751bf23b1bf6c1df648e1b0aa6a6629a2a344b60b0d
|
|
411
|
+
- id: block-gcp-project-delete
|
|
412
|
+
provider: gcp
|
|
413
|
+
resource_pattern: project/*
|
|
414
|
+
actions:
|
|
415
|
+
- delete
|
|
416
|
+
scope: {}
|
|
417
|
+
time_window: null
|
|
418
|
+
effect: BLOCK
|
|
419
|
+
constraint_class: deletion
|
|
420
|
+
principal: admin
|
|
421
|
+
source_ref: git-6006
|
|
422
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
423
|
+
rule_text: Block deleting GCP projects.
|
|
424
|
+
provenance_hash: 7e6fe5ce1001c1c8849af9bbbc66ce4c9f4c2303772f77dcbf9fef0d58f2b4a0
|
|
425
|
+
- id: block-azure-resource-group-delete
|
|
426
|
+
provider: azure
|
|
427
|
+
resource_pattern: resource/group/*
|
|
428
|
+
actions:
|
|
429
|
+
- delete
|
|
430
|
+
scope: {}
|
|
431
|
+
time_window: null
|
|
432
|
+
effect: BLOCK
|
|
433
|
+
constraint_class: deletion
|
|
434
|
+
principal: admin
|
|
435
|
+
source_ref: git-6007
|
|
436
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
437
|
+
rule_text: 'Block deleting Azure resource groups: it deletes every resource in them.'
|
|
438
|
+
provenance_hash: 733126d10190f8cdcde09cbbcd6a6aef719b97e9dc8bd070cf3b84aa381029b9
|
|
439
|
+
- id: escalate-argocd-app-delete
|
|
440
|
+
provider: argocd
|
|
441
|
+
resource_pattern: app/*
|
|
442
|
+
actions:
|
|
443
|
+
- delete
|
|
444
|
+
scope: {}
|
|
445
|
+
time_window: null
|
|
446
|
+
effect: ESCALATE
|
|
447
|
+
constraint_class: deletion
|
|
448
|
+
principal: admin
|
|
449
|
+
source_ref: git-6008
|
|
450
|
+
source_timestamp: '2026-09-27T12:00:00+00:00'
|
|
451
|
+
rule_text: Escalate deleting Argo CD applications (with cascade this deletes the
|
|
452
|
+
deployed resources) for human review.
|
|
453
|
+
provenance_hash: dc24eb69ac5c8b66279284b6df19095e3f0096303f3ef18da712a53e5e339aeb
|
{aegis_devops-0.1.2 → aegis_devops-0.1.3}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig
RENAMED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
|
-
"PRINCIPALS.yaml": "
|
|
3
|
+
"PRINCIPALS.yaml": "e2e7025a2092240acede6a88c7f1a4f22d3cdbf5821772fba9e0f91fbfcbcc8f",
|
|
4
4
|
"git-4001.json": "8be2dd6c37ef643b3bc375b15d5d97889b00456285f594e21a3b4d52521e21de",
|
|
5
|
+
"git-6001.json": "6592ca4568f767d71a431490ff3cacdbc699ad92be966f57aed3b0a485844dc5",
|
|
6
|
+
"git-6002.json": "e6286c5fb8a0d2b3c34ca0c841ccede2a477a02f4781115caf4650f4f7c019b8",
|
|
7
|
+
"git-6003.json": "b077ac2d1119f9a90453e762f2186f3f37837d348822016c01a6f145f528b197",
|
|
8
|
+
"git-6004.json": "57d2dc91b3014c3cad329266f7ba57472b2d5053635827afc7ddeda02cd73ee3",
|
|
9
|
+
"git-6005.json": "3fe8ba5cc4cd123fe78f5f4e60f81f8ab38dc0da395d4dbf82634f1359f01803",
|
|
10
|
+
"git-6006.json": "3f6fbfeb34afb3bcb8075f0864047b3641f0016b8817f67288db7f64afd36b58",
|
|
11
|
+
"git-6007.json": "eb84394208274b79792e285c5143dde320a2f4755d9b2922ffb55df07e7c5b9e",
|
|
12
|
+
"git-6008.json": "34d29df94b55a3fa29521246fa17e0966eda93f718a6c41082e6c648569aafa5",
|
|
5
13
|
"git-789abc.json": "48ac500e13d36240ec5c72bf90e96b433a5873d636e9e36f99a73468e7fb5757",
|
|
6
14
|
"git-abc123.json": "ee3751fdcd64cf1dd374bf9f7b73cda723a4aced5053f32501ba9416de89afc7",
|
|
7
15
|
"git-bcd234.json": "a0de7b32bde75735c91504aa7156e7b2ba2ef961d0f439218507e40d0bdfd89a",
|
|
@@ -28,5 +36,5 @@
|
|
|
28
36
|
"slack-perma-1.json": "2c8945a68e413c300ef58fc6a6d3daa8e4d0029a26a454dfad983e2091a188d1"
|
|
29
37
|
},
|
|
30
38
|
"header": "aegis-manifest-v1",
|
|
31
|
-
"sig": "
|
|
39
|
+
"sig": "034812f78b7f502ebcbb9183bfcf88023324ffcd83e82e5d698aee252cd3b824"
|
|
32
40
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "terraform",
|
|
3
|
+
"resource_pattern": "workspace/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6001",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block 'terraform destroy' and 'tofu destroy' (and apply -destroy): tearing down a whole configuration needs a reviewed plan, not an agent's command."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "pulumi",
|
|
3
|
+
"resource_pattern": "stack/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6002",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block 'pulumi destroy' and 'pulumi stack rm': removing a whole stack needs a human."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "kubernetes",
|
|
3
|
+
"resource_pattern": "namespace/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6003",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block deleting Kubernetes namespaces: it deletes everything inside them."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "aws",
|
|
3
|
+
"resource_pattern": "s3/bucket/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6004",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block deleting S3 buckets (aws s3 rb, s3api delete-bucket)."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "aws",
|
|
3
|
+
"resource_pattern": "rds/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6005",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block deleting RDS databases, clusters and snapshots."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "gcp",
|
|
3
|
+
"resource_pattern": "project/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6006",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block deleting GCP projects."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "azure",
|
|
3
|
+
"resource_pattern": "resource/group/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "BLOCK",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6007",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Block deleting Azure resource groups: it deletes every resource in them."
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "argocd",
|
|
3
|
+
"resource_pattern": "app/*",
|
|
4
|
+
"actions": [
|
|
5
|
+
"delete"
|
|
6
|
+
],
|
|
7
|
+
"scope": {},
|
|
8
|
+
"time_window": null,
|
|
9
|
+
"effect": "ESCALATE",
|
|
10
|
+
"constraint_class": "deletion",
|
|
11
|
+
"principal": "admin",
|
|
12
|
+
"source_ref": "git-6008",
|
|
13
|
+
"source_timestamp": "2026-09-27T12:00:00+00:00",
|
|
14
|
+
"rule_text": "Escalate deleting Argo CD applications (with cascade this deletes the deployed resources) for human review."
|
|
15
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Benchmark metrics (PLAN.md §4): confusion matrix, over-block rate,
|
|
1
|
+
"""Benchmark metrics (docs/dev/PLAN.md §4): confusion matrix, over-block rate,
|
|
2
2
|
coverage, poison susceptibility (per attack kind) and latency percentiles.
|
|
3
3
|
|
|
4
4
|
The harness consumes ``Decision`` objects duck-typed: only ``verdict``,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"""Baseline C — OPA/Rego (PLAN.md §4).
|
|
1
|
+
"""Baseline C — OPA/Rego (docs/dev/PLAN.md §4).
|
|
2
2
|
|
|
3
3
|
Like the LLM baseline, this one loads *every* constraint — tampered,
|
|
4
4
|
unauthorized, and forged included — because OPA/Gatekeeper has no concept
|
|
5
5
|
of provenance or authority. It evaluates structured input against
|
|
6
6
|
hand-authored (here, generated) rules, which is exactly the "why not
|
|
7
|
-
OPA/Gatekeeper" distinction PLAN.md §3 draws.
|
|
7
|
+
OPA/Gatekeeper" distinction docs/dev/PLAN.md §3 draws.
|
|
8
8
|
|
|
9
9
|
Known limitation: constraint ``time_window`` is NOT evaluated by the
|
|
10
10
|
generated Rego (OPA has ``time.now_ns`` but wiring day-of-week + local-tz
|
|
@@ -87,6 +87,7 @@ from datetime import UTC, datetime, timedelta
|
|
|
87
87
|
import yaml
|
|
88
88
|
|
|
89
89
|
from aegis_core import config as config_module
|
|
90
|
+
from aegis_core import hook as hook_module
|
|
90
91
|
from aegis_core import signing
|
|
91
92
|
from aegis_core.authority import load_authority_map
|
|
92
93
|
from aegis_core.environments import (
|
|
@@ -449,6 +450,40 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
449
450
|
"--out", default="aegis-signing.key", help="path to write the key to"
|
|
450
451
|
)
|
|
451
452
|
|
|
453
|
+
hook_parser = subparsers.add_parser(
|
|
454
|
+
"hook",
|
|
455
|
+
help="Run as a coding agent's pre-tool hook: read its JSON payload on stdin, answer "
|
|
456
|
+
"in its format (see 'aegis install')",
|
|
457
|
+
)
|
|
458
|
+
hook_parser.add_argument("agent", choices=hook_module.AGENTS)
|
|
459
|
+
hook_parser.add_argument(
|
|
460
|
+
"--escalate-as",
|
|
461
|
+
choices=("ask", "deny"),
|
|
462
|
+
default="ask",
|
|
463
|
+
help="what an ESCALATE verdict becomes: 'ask' the user (default, where the agent "
|
|
464
|
+
"supports it; Codex does not, so it always denies) or 'deny'",
|
|
465
|
+
)
|
|
466
|
+
hook_parser.add_argument(
|
|
467
|
+
"check_args",
|
|
468
|
+
nargs=argparse.REMAINDER,
|
|
469
|
+
help="extra 'aegis check command' options after --, e.g. -- --fail-closed",
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
install_parser = subparsers.add_parser(
|
|
473
|
+
"install", help="Register 'aegis hook' in a coding agent's hook config"
|
|
474
|
+
)
|
|
475
|
+
install_parser.add_argument("agent", choices=hook_module.AGENTS)
|
|
476
|
+
scope = install_parser.add_mutually_exclusive_group()
|
|
477
|
+
scope.add_argument(
|
|
478
|
+
"--user", action="store_true", help="install for every project (the user's config)"
|
|
479
|
+
)
|
|
480
|
+
scope.add_argument(
|
|
481
|
+
"--project", default=".", help="project directory to install into (default: .)"
|
|
482
|
+
)
|
|
483
|
+
install_parser.add_argument(
|
|
484
|
+
"--remove", action="store_true", help="remove the aegis hook instead"
|
|
485
|
+
)
|
|
486
|
+
|
|
452
487
|
return parser
|
|
453
488
|
|
|
454
489
|
|
|
@@ -1000,6 +1035,16 @@ def _run(argv: list[str]) -> int:
|
|
|
1000
1035
|
return _run_init(args)
|
|
1001
1036
|
if args.command == "keygen":
|
|
1002
1037
|
return _run_keygen(args)
|
|
1038
|
+
if args.command == "hook":
|
|
1039
|
+
return hook_module.main_hook(
|
|
1040
|
+
args.agent,
|
|
1041
|
+
escalate_as=args.escalate_as,
|
|
1042
|
+
extra_args=_strip_leading_separator(args.check_args),
|
|
1043
|
+
)
|
|
1044
|
+
if args.command == "install":
|
|
1045
|
+
return hook_module.main_install(
|
|
1046
|
+
args.agent, user=args.user, project=args.project, remove=args.remove
|
|
1047
|
+
)
|
|
1003
1048
|
if args.command != "check":
|
|
1004
1049
|
raise UsageError("unknown command")
|
|
1005
1050
|
|