aegis-devops 0.1.2__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.2/src/aegis_devops.egg-info → aegis_devops-0.1.4}/PKG-INFO +52 -14
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/README.md +51 -13
- {aegis_devops-0.1.2 → 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.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/constraints.example.yaml +115 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/constraints.example.yaml.sig +2 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig +10 -2
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/PRINCIPALS.yaml +8 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6001.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6002.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6003.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6004.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6005.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6006.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6007.json +15 -0
- aegis_devops-0.1.4/src/aegis_core/_examples/sources/git-6008.json +15 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/__init__.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/llm.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/metrics.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/opa.py +2 -2
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/cli.py +45 -0
- aegis_devops-0.1.4/src/aegis_core/hook.py +490 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/parser.py +41 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/shell.py +9 -3
- {aegis_devops-0.1.2 → aegis_devops-0.1.4/src/aegis_devops.egg-info}/PKG-INFO +52 -14
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/SOURCES.txt +12 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_baselines.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_benchmark.py +1 -1
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_cli.py +18 -13
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_corpus.py +1 -1
- aegis_devops-0.1.4/tests/test_default_rules.py +126 -0
- aegis_devops-0.1.4/tests/test_hook.py +636 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_parsers_sql.py +1 -1
- aegis_devops-0.1.4/tests/test_plugins.py +76 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/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.4}/LICENSE +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/MANIFEST.in +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/pyproject.toml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/setup.cfg +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/__init__.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/authority.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/authority.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/environments.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/example-signing.key +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/plan_constraints.example.yaml.sig +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-4001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-789abc.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-abc123.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-bcd234.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/git-def456.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-1001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-1002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-2001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-2002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-3005.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/jira-5006.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1001.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1002.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1003.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-1004.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/plan-5005.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/_examples/sources/slack-perma-1.json +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/adversarial.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/authority.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/base.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/baselines/external.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/config.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/environments.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/intent.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/interceptor.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/ledger.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/parsers/__init__.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/parsers/pulumi.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/parsers/sql.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/plan.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/provenance.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/signing.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_core/store.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/dependency_links.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/entry_points.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/requires.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/src/aegis_devops.egg-info/top_level.txt +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_adversarial.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_authority.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_config.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_docs_consistency.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_environments.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_intent.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_interceptor.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_ledger.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_parser.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_parsers_pulumi.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_plan.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_provenance.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_shell.py +0 -0
- {aegis_devops-0.1.2 → aegis_devops-0.1.4}/tests/test_signing.py +0 -0
- {aegis_devops-0.1.2 → 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
|
|
|
@@ -81,7 +96,7 @@ BLOCK: kubernetes scale deployment/api-server
|
|
|
81
96
|
citations: no-scale-prod-peak
|
|
82
97
|
covered: True latency_ms: 0.20
|
|
83
98
|
PLAN BLOCK: 1 intent(s)
|
|
84
|
-
STORE: loaded=
|
|
99
|
+
STORE: loaded=29 quarantined=0 principals=3
|
|
85
100
|
warning: using example signing key
|
|
86
101
|
```
|
|
87
102
|
|
|
@@ -92,6 +107,8 @@ 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
|
|
|
110
|
+

|
|
111
|
+
|
|
95
112
|
### From a clone
|
|
96
113
|
|
|
97
114
|
```bash
|
|
@@ -199,36 +216,57 @@ OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rule
|
|
|
199
216
|
derives **unstructured human constraints** (from Slack, Jira, Git) and applies
|
|
200
217
|
**authority-driven validation** to the agent's intent *before* it reaches the infrastructure.
|
|
201
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
|
+
|
|
202
239
|
## Project status / roadmap
|
|
203
240
|
|
|
204
241
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
205
242
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
206
|
-
v0.1.
|
|
243
|
+
v0.1.3 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
207
244
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
208
245
|
through the Codex CLI, and a local `mistral:latest`.
|
|
209
246
|
|
|
210
|
-
What is *not* done is the part the threat model leans on hardest. See `PLAN.md §8`, but in
|
|
247
|
+
What is *not* done is the part the threat model leans on hardest. See `docs/dev/PLAN.md §8`, but in
|
|
211
248
|
short: sources are verified against files on disk rather than real Git/Slack/Jira connectors,
|
|
212
249
|
signing uses a shared secret rather than per-principal public keys, and a `principal` is a
|
|
213
250
|
signed name rather than an identity bound to a commit signature or an SSO group. Until those
|
|
214
251
|
land, Aegis demonstrates that the *decision procedure* is sound; it does not yet prove the
|
|
215
252
|
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
|
|
253
|
+
production-ready: read `docs/dev/PLAN.md §8` for the full list of open gaps before putting it in front
|
|
217
254
|
of anything you care about.
|
|
218
255
|
|
|
219
256
|
## Documentation
|
|
220
257
|
|
|
221
258
|
| Page | Covers |
|
|
222
259
|
| :--- | :--- |
|
|
260
|
+
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
223
261
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
224
262
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
225
263
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
226
264
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
227
265
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
228
|
-
| [`PLAN.md`](PLAN.md) | Design plan and open gaps |
|
|
266
|
+
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
229
267
|
| [`SECURITY.md`](SECURITY.md) | Reporting a bypass |
|
|
230
268
|
| [`CHANGELOG.md`](CHANGELOG.md) | Release history |
|
|
231
|
-
| [`REVIEW-4.md`](REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
269
|
+
| [`docs/dev/REVIEW-4.md`](docs/dev/REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
232
270
|
|
|
233
271
|
## Development
|
|
234
272
|
|
|
@@ -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
|
|
|
@@ -49,7 +64,7 @@ BLOCK: kubernetes scale deployment/api-server
|
|
|
49
64
|
citations: no-scale-prod-peak
|
|
50
65
|
covered: True latency_ms: 0.20
|
|
51
66
|
PLAN BLOCK: 1 intent(s)
|
|
52
|
-
STORE: loaded=
|
|
67
|
+
STORE: loaded=29 quarantined=0 principals=3
|
|
53
68
|
warning: using example signing key
|
|
54
69
|
```
|
|
55
70
|
|
|
@@ -60,6 +75,8 @@ 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
|
|
|
78
|
+

|
|
79
|
+
|
|
63
80
|
### From a clone
|
|
64
81
|
|
|
65
82
|
```bash
|
|
@@ -167,36 +184,57 @@ OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rule
|
|
|
167
184
|
derives **unstructured human constraints** (from Slack, Jira, Git) and applies
|
|
168
185
|
**authority-driven validation** to the agent's intent *before* it reaches the infrastructure.
|
|
169
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
|
+
|
|
170
207
|
## Project status / roadmap
|
|
171
208
|
|
|
172
209
|
The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
|
|
173
210
|
plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
|
|
174
|
-
v0.1.
|
|
211
|
+
v0.1.3 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
|
|
175
212
|
the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
|
|
176
213
|
through the Codex CLI, and a local `mistral:latest`.
|
|
177
214
|
|
|
178
|
-
What is *not* done is the part the threat model leans on hardest. See `PLAN.md §8`, but in
|
|
215
|
+
What is *not* done is the part the threat model leans on hardest. See `docs/dev/PLAN.md §8`, but in
|
|
179
216
|
short: sources are verified against files on disk rather than real Git/Slack/Jira connectors,
|
|
180
217
|
signing uses a shared secret rather than per-principal public keys, and a `principal` is a
|
|
181
218
|
signed name rather than an identity bound to a commit signature or an SSO group. Until those
|
|
182
219
|
land, Aegis demonstrates that the *decision procedure* is sound; it does not yet prove the
|
|
183
220
|
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
|
|
221
|
+
production-ready: read `docs/dev/PLAN.md §8` for the full list of open gaps before putting it in front
|
|
185
222
|
of anything you care about.
|
|
186
223
|
|
|
187
224
|
## Documentation
|
|
188
225
|
|
|
189
226
|
| Page | Covers |
|
|
190
227
|
| :--- | :--- |
|
|
228
|
+
| [`docs/agents.md`](docs/agents.md) | Claude Code, Codex, Copilot, VS Code and Cursor: install, what gets blocked |
|
|
191
229
|
| [`docs/cli.md`](docs/cli.md) | Exit codes, store health, the Claude Code hook, argv forms, compound commands, dry runs, library usage |
|
|
192
230
|
| [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
|
|
193
231
|
| [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, rate limits & ledger |
|
|
194
232
|
| [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
|
|
195
233
|
| [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
|
|
196
|
-
| [`PLAN.md`](PLAN.md) | Design plan and open gaps |
|
|
234
|
+
| [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
|
|
197
235
|
| [`SECURITY.md`](SECURITY.md) | Reporting a bypass |
|
|
198
236
|
| [`CHANGELOG.md`](CHANGELOG.md) | Release history |
|
|
199
|
-
| [`REVIEW-4.md`](REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
237
|
+
| [`docs/dev/REVIEW-4.md`](docs/dev/REVIEW-4.md) | Corpus/oracle rewrite (independent oracle, intent-level holdout) |
|
|
200
238
|
|
|
201
239
|
## Development
|
|
202
240
|
|
|
@@ -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.4}/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
|