aegis-devops 0.3.2__tar.gz → 1.0.0__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.
Files changed (154) hide show
  1. {aegis_devops-0.3.2/src/aegis_devops.egg-info → aegis_devops-1.0.0}/PKG-INFO +82 -19
  2. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/README.md +80 -17
  3. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/pyproject.toml +2 -2
  4. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/__init__.py +1 -1
  5. aegis_devops-1.0.0/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
  6. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/agents.example.yaml +3 -0
  7. aegis_devops-1.0.0/src/aegis_core/_examples/agents.example.yaml.sig +2 -0
  8. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/authority.example.yaml +1 -0
  9. aegis_devops-1.0.0/src/aegis_core/_examples/authority.example.yaml.sig +2 -0
  10. aegis_devops-1.0.0/src/aegis_core/_examples/budget.example.yaml +21 -0
  11. aegis_devops-1.0.0/src/aegis_core/_examples/budget.example.yaml.sig +2 -0
  12. aegis_devops-1.0.0/src/aegis_core/budget/__init__.py +27 -0
  13. aegis_devops-1.0.0/src/aegis_core/budget/accounting.py +693 -0
  14. aegis_devops-1.0.0/src/aegis_core/budget/evaluate.py +259 -0
  15. aegis_devops-1.0.0/src/aegis_core/budget/gate.py +124 -0
  16. aegis_devops-1.0.0/src/aegis_core/budget/logs.py +678 -0
  17. aegis_devops-1.0.0/src/aegis_core/budget/policy.py +235 -0
  18. aegis_devops-1.0.0/src/aegis_core/budget/prices.json +282 -0
  19. aegis_devops-1.0.0/src/aegis_core/budget/prices.yaml +77 -0
  20. aegis_devops-1.0.0/src/aegis_core/budget/pricing.py +186 -0
  21. aegis_devops-1.0.0/src/aegis_core/budget/report.py +205 -0
  22. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/cli.py +175 -2
  23. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/environments.py +98 -28
  24. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/hook.py +208 -42
  25. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/identity.py +17 -3
  26. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/integrations/opencode-plugin.js +51 -12
  27. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/interceptor.py +30 -6
  28. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/parser.py +11 -3
  29. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/store.py +99 -0
  30. {aegis_devops-0.3.2 → aegis_devops-1.0.0/src/aegis_devops.egg-info}/PKG-INFO +82 -19
  31. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_devops.egg-info/SOURCES.txt +19 -0
  32. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_adversarial.py +14 -12
  33. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_authority.py +2 -2
  34. aegis_devops-1.0.0/tests/test_budget_accounting.py +492 -0
  35. aegis_devops-1.0.0/tests/test_budget_cli.py +247 -0
  36. aegis_devops-1.0.0/tests/test_budget_evaluate.py +130 -0
  37. aegis_devops-1.0.0/tests/test_budget_hook.py +274 -0
  38. aegis_devops-1.0.0/tests/test_budget_logs.py +365 -0
  39. aegis_devops-1.0.0/tests/test_budget_policy.py +304 -0
  40. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_docs_consistency.py +31 -0
  41. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_environments.py +47 -1
  42. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_identity.py +36 -0
  43. aegis_devops-1.0.0/tests/test_kubectl_namespace_and_manifests.py +222 -0
  44. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_opencode_plugin.py +37 -0
  45. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_parser.py +7 -5
  46. aegis_devops-1.0.0/tests/test_plugins.py +253 -0
  47. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_signing.py +2 -1
  48. aegis_devops-0.3.2/src/aegis_core/_examples/__pycache__/__init__.cpython-312.pyc +0 -0
  49. aegis_devops-0.3.2/src/aegis_core/_examples/agents.example.yaml.sig +0 -2
  50. aegis_devops-0.3.2/src/aegis_core/_examples/authority.example.yaml.sig +0 -2
  51. aegis_devops-0.3.2/tests/test_plugins.py +0 -112
  52. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/LICENSE +0 -0
  53. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/MANIFEST.in +0 -0
  54. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/setup.cfg +0 -0
  55. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/__init__.py +0 -0
  56. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/constraints.example.yaml +0 -0
  57. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/constraints.example.yaml.sig +0 -0
  58. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/environments.example.yaml +0 -0
  59. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/environments.example.yaml.sig +0 -0
  60. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/example-signing.key +0 -0
  61. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/plan_constraints.example.yaml +0 -0
  62. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/plan_constraints.example.yaml.sig +0 -0
  63. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/repos.example.yaml +0 -0
  64. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/repos.example.yaml.sig +0 -0
  65. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/signers.example.yaml +0 -0
  66. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/signers.example.yaml.sig +0 -0
  67. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/AEGIS-MANIFEST.sig +0 -0
  68. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/PRINCIPALS.yaml +0 -0
  69. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-4001.json +0 -0
  70. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6001.json +0 -0
  71. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6002.json +0 -0
  72. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6003.json +0 -0
  73. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6004.json +0 -0
  74. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6005.json +0 -0
  75. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6006.json +0 -0
  76. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6007.json +0 -0
  77. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6008.json +0 -0
  78. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-6009.json +0 -0
  79. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-789abc.json +0 -0
  80. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-abc123.json +0 -0
  81. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-bcd234.json +0 -0
  82. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/git-def456.json +0 -0
  83. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-1001.json +0 -0
  84. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-1002.json +0 -0
  85. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-2001.json +0 -0
  86. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-2002.json +0 -0
  87. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-3001.json +0 -0
  88. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-3002.json +0 -0
  89. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-3003.json +0 -0
  90. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-3004.json +0 -0
  91. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-3005.json +0 -0
  92. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-5001.json +0 -0
  93. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-5002.json +0 -0
  94. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-5003.json +0 -0
  95. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-5004.json +0 -0
  96. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/jira-5006.json +0 -0
  97. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/plan-1001.json +0 -0
  98. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/plan-1002.json +0 -0
  99. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/plan-1003.json +0 -0
  100. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/plan-1004.json +0 -0
  101. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/plan-5005.json +0 -0
  102. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/_examples/sources/slack-perma-1.json +0 -0
  103. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/adversarial.py +0 -0
  104. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/audit_aws.py +0 -0
  105. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/audit_kubernetes.py +0 -0
  106. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/authority.py +0 -0
  107. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/__init__.py +0 -0
  108. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/base.py +0 -0
  109. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/external.py +0 -0
  110. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/llm.py +0 -0
  111. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/metrics.py +0 -0
  112. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/baselines/opa.py +0 -0
  113. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/compile/__init__.py +0 -0
  114. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/compile/actions/aws.yaml +0 -0
  115. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/compile/aws.py +0 -0
  116. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/compile/kubernetes.py +0 -0
  117. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/config.py +0 -0
  118. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/gitsource.py +0 -0
  119. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/intent.py +0 -0
  120. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/ledger.py +0 -0
  121. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/parsers/__init__.py +0 -0
  122. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/parsers/pulumi.py +0 -0
  123. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/parsers/sql.py +0 -0
  124. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/plan.py +0 -0
  125. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/provenance.py +0 -0
  126. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/shell.py +0 -0
  127. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_core/signing.py +0 -0
  128. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_devops.egg-info/dependency_links.txt +0 -0
  129. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_devops.egg-info/entry_points.txt +0 -0
  130. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_devops.egg-info/requires.txt +0 -0
  131. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/src/aegis_devops.egg-info/top_level.txt +0 -0
  132. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_audit_aws.py +0 -0
  133. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_audit_kubernetes.py +0 -0
  134. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_baselines.py +0 -0
  135. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_benchmark.py +0 -0
  136. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_cli.py +0 -0
  137. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_compile_aws.py +0 -0
  138. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_compile_kubernetes.py +0 -0
  139. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_config.py +0 -0
  140. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_corpus.py +0 -0
  141. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_default_rules.py +0 -0
  142. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_gitsource.py +0 -0
  143. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_hook.py +0 -0
  144. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_intent.py +0 -0
  145. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_interceptor.py +0 -0
  146. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_ledger.py +0 -0
  147. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_parsers_pulumi.py +0 -0
  148. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_parsers_sql.py +0 -0
  149. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_plan.py +0 -0
  150. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_provenance.py +0 -0
  151. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_shell.py +0 -0
  152. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_snapshot.py +0 -0
  153. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_store.py +0 -0
  154. {aegis_devops-0.3.2 → aegis_devops-1.0.0}/tests/test_store_match.py +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aegis-devops
3
- Version: 0.3.2
3
+ Version: 1.0.0
4
4
  Summary: Provenance-backed, authority-aware policy verifier for agentic DevOps actions.
5
5
  Author: Vamshidher Reddy Jannapu Reddy
6
6
  License-Expression: Apache-2.0
7
7
  Project-URL: Homepage, https://github.com/moneytool/aegis-devops
8
8
  Project-URL: Repository, https://github.com/moneytool/aegis-devops
9
9
  Keywords: agentops,agent-security,policy-as-code,provenance,kubernetes,terraform,guardrails,prompt-injection,context-poisoning
10
- Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Environment :: Console
12
12
  Classifier: Intended Audience :: System Administrators
13
13
  Classifier: Intended Audience :: Developers
@@ -46,30 +46,43 @@ become policy.
46
46
 
47
47
  ![Aegis-DevOps blocking an injected kubectl delete](docs/where-it-sits.gif)
48
48
 
49
- ### Install in Claude Code
49
+ ## Try it in 60 seconds
50
+
51
+ **1. Watch it block a pull request (nothing to install).** Open the demo's
52
+ [example PR](https://github.com/moneytool/aegis-devops-demo/pull/1): it deletes a production
53
+ database, and the failing check is Aegis blocking it, with the verdict posted as a comment. Fork
54
+ the [demo repository](https://github.com/moneytool/aegis-devops-demo) to try your own change; no
55
+ cloud account needed.
56
+
57
+ **2. Check a command yourself:**
50
58
 
51
59
  ```bash
52
60
  pip install aegis-devops && aegis init .aegis
53
- claude plugin marketplace add moneytool/aegis-devops
54
- claude plugin install aegis-devops@aegis-devops
61
+ aegis check command --pretty -- "kubectl delete namespace prod" # BLOCK (exit 3)
62
+ aegis check command --pretty -- "kubectl get pods -n prod" # ALLOW (exit 0)
55
63
  ```
56
64
 
57
- ### Install in Gemini CLI
65
+ **3. Put it in front of your coding agent.** In the same project:
58
66
 
59
67
  ```bash
60
- pip install aegis-devops && aegis init .aegis
61
- gemini extensions install https://github.com/moneytool/aegis-devops
68
+ claude plugin marketplace add moneytool/aegis-devops
69
+ claude plugin install aegis-devops@aegis-devops
62
70
  ```
63
71
 
64
- Codex, GitHub Copilot (CLI and VS Code), Cursor and OpenCode:
65
- `aegis install codex|copilot|vscode|cursor|opencode`
66
- (see [Coding agents](docs/agents.md)). It only acts in projects with a `.aegis/` policy, and
67
- only blocks what that policy blocks. It also works as a CI step
68
- (`aegis check terraform plan.json --exit-style ci`) and as a Python library; see
69
- [Quick start](#quick-start). In GitHub Actions, the
70
- [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check) Action
71
- checks a Terraform or OpenTofu plan and comments the verdict on the pull request:
72
- `uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`.
72
+ Then ask Claude Code to delete the `prod` namespace: the hook blocks the command before it runs.
73
+ Gemini CLI: `gemini extensions install https://github.com/moneytool/aegis-devops`. Codex, GitHub
74
+ Copilot (CLI and VS Code), Cursor and OpenCode: `aegis install codex|copilot|vscode|cursor|opencode`
75
+ (see [Coding agents](docs/agents.md)). Aegis only acts in projects with a `.aegis/` policy, and
76
+ only blocks what that policy blocks. `aegis init` writes example rules signed with a public
77
+ example key; replace both before relying on it ([Configuration](docs/configuration.md)). It
78
+ works alongside RBAC and your agent's own permission settings; see
79
+ [Why not RBAC](#why-not-rbac-or-the-agents-own-permission-settings).
80
+
81
+ In CI, the [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check)
82
+ Action checks a Terraform or OpenTofu plan on every pull request
83
+ (`uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`); `aegis check terraform
84
+ plan.json --exit-style ci` does the same in any pipeline, and Aegis also works as a Python
85
+ library ([Quick start](#quick-start)).
73
86
 
74
87
  ## What it does
75
88
 
@@ -226,6 +239,45 @@ about who wrote a rule, but it cannot recompute a hash or fetch a source. Up to
226
239
  rows were scored against all 500 rules, which counted rules the models never saw as resisted
227
240
  poison and understated their susceptibility (0.23–0.33); see [`CHANGELOG.md`](CHANGELOG.md).
228
241
 
242
+ ## Why not RBAC, or the agent's own permission settings?
243
+
244
+ Keep both. Aegis sits alongside them; it doesn't replace either.
245
+
246
+ **Agent permission settings** (Claude Code's allow/deny rules, Copilot's tool approvals and
247
+ similar) decide which commands an agent may run without asking you. They match the command
248
+ text. Claude Code's documentation says a Bash deny rule ["isn't a security boundary around the
249
+ program"](https://code.claude.com/docs/en/permissions#bash-rule-limits), and recommends a
250
+ PreToolUse hook when you need to inspect the full command before it runs. Aegis is that hook. It
251
+ works out what the command will do, so every spelling of the same action reaches the same rule:
252
+
253
+ | Command the agent writes | Aegis with the example policy |
254
+ |---|---|
255
+ | `kubectl delete deploy web -n prod` | BLOCK (`no-delete-in-prod-namespace`) |
256
+ | `kubectl -n prod delete deploy web` | BLOCK, same rule |
257
+ | `/usr/bin/kubectl …`, `sudo kubectl …`, `env kubectl …` | BLOCK, same rule |
258
+ | `bash -c 'kubectl delete deploy web -n prod'` | BLOCK, same rule |
259
+ | `cd /tmp && kubectl delete deploy web -n prod` | BLOCK, same rule |
260
+ | `git -C . push --force origin main` | BLOCK (`git-block-force-push-main`) |
261
+ | `K=kubectl; $K delete deploy web -n prod` | Refused: it can't be checked statically, so the hook denies it and asks for the command on its own |
262
+
263
+ Permission settings also record *what* is allowed, not who decided it. An Aegis rule only gets a
264
+ vote if nobody has changed it since it was signed and its author was allowed to write that kind
265
+ of rule.
266
+
267
+ **RBAC and IAM** decide what an identity may do. A coding agent usually runs with the
268
+ developer's own kubeconfig and cloud credentials, so RBAC sees the developer and grants the
269
+ agent the same rights. Aegis decides each action against the policy: no deletes in the `prod`
270
+ namespace, no `kubectl --as` impersonation, no plan that deletes a database. Once agents do have
271
+ their own identities, the same policy compiles into the platform layer, so it holds even for
272
+ calls that never pass through the hook (an SDK script, a leaked key):
273
+
274
+ - `aegis compile aws`: Service Control Policies scoped to agent identities.
275
+ - `aegis compile kubernetes`: ValidatingAdmissionPolicies scoped to agent identities, plus
276
+ `aegis audit-identity kubernetes` to report the RBAC permissions that would let an agent get
277
+ around them (impersonation, editing admission policies, RBAC escalation).
278
+
279
+ Both are previews; see [server-side enforcement](docs/server-side.md).
280
+
229
281
  ## Why not OPA/Gatekeeper?
230
282
 
231
283
  OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rules**. Aegis
@@ -256,7 +308,11 @@ context a rule can arrive from a ticket or a chat message as easily as from you.
256
308
 
257
309
  The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
258
310
  plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
259
- v0.3.2 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
311
+ v1.0.0 is on PyPI, with the [session budget cap](docs/budget.md). **1.0 is a promise about the
312
+ interface:** the policy file formats, the CLI commands and exit codes, the hook protocol and the
313
+ Action's inputs and outputs stay compatible until 2.0; the server-side compilers and the
314
+ identity audit remain previews ([CHANGELOG](CHANGELOG.md)). It is not a claim that the open gaps
315
+ below are closed. Real LLM baselines have been run: Claude Sonnet 5 through
260
316
  the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
261
317
  through the Codex CLI, and a local `mistral:latest`.
262
318
 
@@ -279,6 +335,7 @@ of anything you care about.
279
335
  | [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
280
336
  | [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, the identity model (`agents.yaml`), rate limits & ledger |
281
337
  | [`docs/server-side.md`](docs/server-side.md) | Preview: compiling the policy to AWS Service Control Policies scoped to agent identities |
338
+ | [`docs/budget.md`](docs/budget.md) | The session budget cap: per-session and per-project-per-day limits in estimated USD or tokens, across Claude Code, Codex, Gemini CLI, OpenCode and Copilot CLI |
282
339
  | [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
283
340
  | [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
284
341
  | [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
@@ -289,7 +346,7 @@ of anything you care about.
289
346
  ## Development
290
347
 
291
348
  ```bash
292
- venv/bin/python -m pytest -q # 1257 passed (last full green run; CI runs this on 3.11/3.13/3.14)
349
+ venv/bin/python -m pytest -q # 1,791 passed (CI runs this on 3.11/3.13/3.14, Linux and macOS)
293
350
  venv/bin/python -m ruff check src tests scripts examples
294
351
  vhs docs/demo.tape # regenerate docs/demo.gif
295
352
  ```
@@ -299,6 +356,12 @@ Reporting a bypass: see [`SECURITY.md`](SECURITY.md) — parser evasion is the l
299
356
  attack surface and the most useful thing to report. Release history is in
300
357
  [`CHANGELOG.md`](CHANGELOG.md).
301
358
 
359
+ ## Support
360
+
361
+ If Aegis-DevOps is useful to you, a ⭐ on [GitHub](https://github.com/moneytool/aegis-devops)
362
+ helps other people find it. Bug reports, ideas and bypasses are welcome too: open an issue, or
363
+ see [`SECURITY.md`](SECURITY.md) for anything that gets a blocked command through.
364
+
302
365
  ## License
303
366
 
304
367
  Apache-2.0 — see [LICENSE](LICENSE).
@@ -13,30 +13,43 @@ become policy.
13
13
 
14
14
  ![Aegis-DevOps blocking an injected kubectl delete](docs/where-it-sits.gif)
15
15
 
16
- ### Install in Claude Code
16
+ ## Try it in 60 seconds
17
+
18
+ **1. Watch it block a pull request (nothing to install).** Open the demo's
19
+ [example PR](https://github.com/moneytool/aegis-devops-demo/pull/1): it deletes a production
20
+ database, and the failing check is Aegis blocking it, with the verdict posted as a comment. Fork
21
+ the [demo repository](https://github.com/moneytool/aegis-devops-demo) to try your own change; no
22
+ cloud account needed.
23
+
24
+ **2. Check a command yourself:**
17
25
 
18
26
  ```bash
19
27
  pip install aegis-devops && aegis init .aegis
20
- claude plugin marketplace add moneytool/aegis-devops
21
- claude plugin install aegis-devops@aegis-devops
28
+ aegis check command --pretty -- "kubectl delete namespace prod" # BLOCK (exit 3)
29
+ aegis check command --pretty -- "kubectl get pods -n prod" # ALLOW (exit 0)
22
30
  ```
23
31
 
24
- ### Install in Gemini CLI
32
+ **3. Put it in front of your coding agent.** In the same project:
25
33
 
26
34
  ```bash
27
- pip install aegis-devops && aegis init .aegis
28
- gemini extensions install https://github.com/moneytool/aegis-devops
35
+ claude plugin marketplace add moneytool/aegis-devops
36
+ claude plugin install aegis-devops@aegis-devops
29
37
  ```
30
38
 
31
- Codex, GitHub Copilot (CLI and VS Code), Cursor and OpenCode:
32
- `aegis install codex|copilot|vscode|cursor|opencode`
33
- (see [Coding agents](docs/agents.md)). It only acts in projects with a `.aegis/` policy, and
34
- only blocks what that policy blocks. It also works as a CI step
35
- (`aegis check terraform plan.json --exit-style ci`) and as a Python library; see
36
- [Quick start](#quick-start). In GitHub Actions, the
37
- [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check) Action
38
- checks a Terraform or OpenTofu plan and comments the verdict on the pull request:
39
- `uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`.
39
+ Then ask Claude Code to delete the `prod` namespace: the hook blocks the command before it runs.
40
+ Gemini CLI: `gemini extensions install https://github.com/moneytool/aegis-devops`. Codex, GitHub
41
+ Copilot (CLI and VS Code), Cursor and OpenCode: `aegis install codex|copilot|vscode|cursor|opencode`
42
+ (see [Coding agents](docs/agents.md)). Aegis only acts in projects with a `.aegis/` policy, and
43
+ only blocks what that policy blocks. `aegis init` writes example rules signed with a public
44
+ example key; replace both before relying on it ([Configuration](docs/configuration.md)). It
45
+ works alongside RBAC and your agent's own permission settings; see
46
+ [Why not RBAC](#why-not-rbac-or-the-agents-own-permission-settings).
47
+
48
+ In CI, the [Aegis-DevOps Plan Check](https://github.com/marketplace/actions/aegis-devops-plan-check)
49
+ Action checks a Terraform or OpenTofu plan on every pull request
50
+ (`uses: moneytool/aegis-devops-action@v1` with `plan: plan.json`); `aegis check terraform
51
+ plan.json --exit-style ci` does the same in any pipeline, and Aegis also works as a Python
52
+ library ([Quick start](#quick-start)).
40
53
 
41
54
  ## What it does
42
55
 
@@ -193,6 +206,45 @@ about who wrote a rule, but it cannot recompute a hash or fetch a source. Up to
193
206
  rows were scored against all 500 rules, which counted rules the models never saw as resisted
194
207
  poison and understated their susceptibility (0.23–0.33); see [`CHANGELOG.md`](CHANGELOG.md).
195
208
 
209
+ ## Why not RBAC, or the agent's own permission settings?
210
+
211
+ Keep both. Aegis sits alongside them; it doesn't replace either.
212
+
213
+ **Agent permission settings** (Claude Code's allow/deny rules, Copilot's tool approvals and
214
+ similar) decide which commands an agent may run without asking you. They match the command
215
+ text. Claude Code's documentation says a Bash deny rule ["isn't a security boundary around the
216
+ program"](https://code.claude.com/docs/en/permissions#bash-rule-limits), and recommends a
217
+ PreToolUse hook when you need to inspect the full command before it runs. Aegis is that hook. It
218
+ works out what the command will do, so every spelling of the same action reaches the same rule:
219
+
220
+ | Command the agent writes | Aegis with the example policy |
221
+ |---|---|
222
+ | `kubectl delete deploy web -n prod` | BLOCK (`no-delete-in-prod-namespace`) |
223
+ | `kubectl -n prod delete deploy web` | BLOCK, same rule |
224
+ | `/usr/bin/kubectl …`, `sudo kubectl …`, `env kubectl …` | BLOCK, same rule |
225
+ | `bash -c 'kubectl delete deploy web -n prod'` | BLOCK, same rule |
226
+ | `cd /tmp && kubectl delete deploy web -n prod` | BLOCK, same rule |
227
+ | `git -C . push --force origin main` | BLOCK (`git-block-force-push-main`) |
228
+ | `K=kubectl; $K delete deploy web -n prod` | Refused: it can't be checked statically, so the hook denies it and asks for the command on its own |
229
+
230
+ Permission settings also record *what* is allowed, not who decided it. An Aegis rule only gets a
231
+ vote if nobody has changed it since it was signed and its author was allowed to write that kind
232
+ of rule.
233
+
234
+ **RBAC and IAM** decide what an identity may do. A coding agent usually runs with the
235
+ developer's own kubeconfig and cloud credentials, so RBAC sees the developer and grants the
236
+ agent the same rights. Aegis decides each action against the policy: no deletes in the `prod`
237
+ namespace, no `kubectl --as` impersonation, no plan that deletes a database. Once agents do have
238
+ their own identities, the same policy compiles into the platform layer, so it holds even for
239
+ calls that never pass through the hook (an SDK script, a leaked key):
240
+
241
+ - `aegis compile aws`: Service Control Policies scoped to agent identities.
242
+ - `aegis compile kubernetes`: ValidatingAdmissionPolicies scoped to agent identities, plus
243
+ `aegis audit-identity kubernetes` to report the RBAC permissions that would let an agent get
244
+ around them (impersonation, editing admission policies, RBAC escalation).
245
+
246
+ Both are previews; see [server-side enforcement](docs/server-side.md).
247
+
196
248
  ## Why not OPA/Gatekeeper?
197
249
 
198
250
  OPA/Gatekeeper evaluates **structured API objects** against **hand-authored rules**. Aegis
@@ -223,7 +275,11 @@ context a rule can arrive from a ticket or a chat message as easily as from you.
223
275
 
224
276
  The engine (constraint store, interceptor, environment mapping, dry-run handling, rate limits,
225
277
  plan-level constraints, and parsers for every tool in "Supported tools") is complete, and
226
- v0.3.2 is on PyPI as an **alpha**. Real LLM baselines have been run: Claude Sonnet 5 through
278
+ v1.0.0 is on PyPI, with the [session budget cap](docs/budget.md). **1.0 is a promise about the
279
+ interface:** the policy file formats, the CLI commands and exit codes, the hook protocol and the
280
+ Action's inputs and outputs stay compatible until 2.0; the server-side compilers and the
281
+ identity audit remain previews ([CHANGELOG](CHANGELOG.md)). It is not a claim that the open gaps
282
+ below are closed. Real LLM baselines have been run: Claude Sonnet 5 through
227
283
  the API (cached in `results/llm-external.md`), Haiku through the Claude Code CLI, `gpt-6-astra`
228
284
  through the Codex CLI, and a local `mistral:latest`.
229
285
 
@@ -246,6 +302,7 @@ of anything you care about.
246
302
  | [`docs/constraints.md`](docs/constraints.md) | Writing constraints, metadata vocabulary, authority policy, environment mapping |
247
303
  | [`docs/configuration.md`](docs/configuration.md) | Configuration/config-dir discovery, signing, source verification, the identity model (`agents.yaml`), rate limits & ledger |
248
304
  | [`docs/server-side.md`](docs/server-side.md) | Preview: compiling the policy to AWS Service Control Policies scoped to agent identities |
305
+ | [`docs/budget.md`](docs/budget.md) | The session budget cap: per-session and per-project-per-day limits in estimated USD or tokens, across Claude Code, Codex, Gemini CLI, OpenCode and Copilot CLI |
249
306
  | [`docs/benchmark.md`](docs/benchmark.md) | Benchmark methodology, full results table, real LLM baselines, agent-harness baselines, corpus, adversarial suite |
250
307
  | [`docs/CONTRIBUTING.md`](docs/CONTRIBUTING.md) | Adding a new parser or tool |
251
308
  | [`docs/dev/PLAN.md`](docs/dev/PLAN.md) | Design plan and open gaps |
@@ -256,7 +313,7 @@ of anything you care about.
256
313
  ## Development
257
314
 
258
315
  ```bash
259
- venv/bin/python -m pytest -q # 1257 passed (last full green run; CI runs this on 3.11/3.13/3.14)
316
+ venv/bin/python -m pytest -q # 1,791 passed (CI runs this on 3.11/3.13/3.14, Linux and macOS)
260
317
  venv/bin/python -m ruff check src tests scripts examples
261
318
  vhs docs/demo.tape # regenerate docs/demo.gif
262
319
  ```
@@ -266,6 +323,12 @@ Reporting a bypass: see [`SECURITY.md`](SECURITY.md) — parser evasion is the l
266
323
  attack surface and the most useful thing to report. Release history is in
267
324
  [`CHANGELOG.md`](CHANGELOG.md).
268
325
 
326
+ ## Support
327
+
328
+ If Aegis-DevOps is useful to you, a ⭐ on [GitHub](https://github.com/moneytool/aegis-devops)
329
+ helps other people find it. Bug reports, ideas and bypasses are welcome too: open an issue, or
330
+ see [`SECURITY.md`](SECURITY.md) for anything that gets a blocked command through.
331
+
269
332
  ## License
270
333
 
271
334
  Apache-2.0 — see [LICENSE](LICENSE).
@@ -25,7 +25,7 @@ keywords = [
25
25
  "context-poisoning",
26
26
  ]
27
27
  classifiers = [
28
- "Development Status :: 3 - Alpha",
28
+ "Development Status :: 4 - Beta",
29
29
  "Environment :: Console",
30
30
  "Intended Audience :: System Administrators",
31
31
  "Intended Audience :: Developers",
@@ -63,7 +63,7 @@ version = {attr = "aegis_core.__version__"}
63
63
  where = ["src"]
64
64
 
65
65
  [tool.setuptools.package-data]
66
- aegis_core = ["_examples/**/*", "integrations/*", "compile/actions/*"]
66
+ aegis_core = ["_examples/**/*", "integrations/*", "compile/actions/*", "budget/*.yaml", "budget/*.json"]
67
67
 
68
68
  [tool.ruff]
69
69
  line-length = 100
@@ -4,4 +4,4 @@ infrastructure actions of AI agents.
4
4
  See the README for what this does and, importantly, what it does not yet do.
5
5
  """
6
6
 
7
- __version__ = "0.3.2"
7
+ __version__ = "1.0.0"
@@ -34,6 +34,9 @@ trusted:
34
34
  - platform: aws
35
35
  kind: source-identity
36
36
  id: alice@example.com
37
+ # A source identity survives role chaining, so an agent started in alice's session would
38
+ # carry it and be exempt. Trust one only if no agent ever runs under it, and say so:
39
+ no_agents: true
37
40
  - platform: github
38
41
  kind: oidc-subject
39
42
  # bound to one reusable workflow at a protected ref, so an agent job in the same
@@ -0,0 +1,2 @@
1
+ aegis-sig-v1
2
+ 2b55b41fc96166220d0d092f84dfee805ee18f791b5181c4b850836c7148042c
@@ -6,6 +6,7 @@ principals:
6
6
  - deletion
7
7
  - configuration
8
8
  - identity # may change agents.yaml, the identity model
9
+ - budget # may change budget.yaml, the budget cap
9
10
  sre_lead:
10
11
  - scaling
11
12
  - configuration
@@ -0,0 +1,2 @@
1
+ aegis-sig-v1
2
+ b2ceb3e6cb27ac15787c4d6b9015065e03b804a6ac837c8fcc4f9895961bd130
@@ -0,0 +1,21 @@
1
+ # The session budget cap (docs/budget.md). Copy to budget.yaml, set your own limits, and sign
2
+ # it with `aegis sign`; its principal must hold the 'budget' class in authority.yaml. Until
3
+ # it is named budget.yaml it does nothing. Then reinstall your agents' hooks (`aegis install
4
+ # <agent>`) so they see every tool call, and check with: aegis budget status
5
+ version: 1
6
+ principal: admin # must hold the 'budget' class in authority.yaml
7
+ unit: usd # usd (estimated from list prices) | tokens; required
8
+ session:
9
+ limit: 20 # per agent session
10
+ warn_at: 0.8 # warn once at 80%
11
+ project_day:
12
+ limit: 100 # every measured session in this project, per day
13
+ warn_at: 0.8
14
+ tz: UTC # the day boundary
15
+ agents: [claude, codex, gemini, opencode, copilot] # only listed agents are measured
16
+ on_unknown_log: allow # allow (warn) | deny: usage Aegis cannot verify
17
+ on_unknown_price: estimate # estimate (warn) | deny: models with no price
18
+ pricing: {} # signed overrides, USD per million tokens:
19
+ # claude-opus-5-5: {input: 4, output: 20, cache_read: 0.2, cache_write: 8}
20
+ copilot:
21
+ premium_requests: 50 # Copilot CLI reports premium requests, not tokens
@@ -0,0 +1,2 @@
1
+ aegis-sig-v1
2
+ d8ad9e56f8548c60028c05c17ce2f46ca190127cbafde00669faef484f3eaea4
@@ -0,0 +1,27 @@
1
+ """Cross-agent session budget cap (design: docs/dev/DESIGN-v1.0-budget-cap.md).
2
+
3
+ * :mod:`~aegis_core.budget.policy` -- the signed ``budget.yaml``;
4
+ * :mod:`~aegis_core.budget.pricing` -- tokens to estimated dollars;
5
+ * :mod:`~aegis_core.budget.logs` -- reading usage from each agent's logs;
6
+ * :mod:`~aegis_core.budget.accounting` -- session records, project/day
7
+ totals, revisions, locks, the inventory and rebuilds;
8
+ * :mod:`~aegis_core.budget.evaluate` -- allow / warn / deny.
9
+ """
10
+
11
+ from aegis_core.budget.accounting import BudgetStore, Snapshot, rebuild, refresh
12
+ from aegis_core.budget.evaluate import ALLOW, DENY, WARN, Verdict, evaluate
13
+ from aegis_core.budget.logs import Locator, default_logs
14
+ from aegis_core.budget.policy import BUDGET_CLASS, BUDGET_FILE, BudgetPolicy, load_budget_policy
15
+ from aegis_core.budget.pricing import PriceTable, load_builtin_table
16
+
17
+
18
+ def price_table(policy: BudgetPolicy) -> PriceTable:
19
+ """The built-in prices with the policy's signed overrides."""
20
+ return PriceTable(load_builtin_table(), policy.pricing)
21
+
22
+
23
+ __all__ = [
24
+ "ALLOW", "BUDGET_CLASS", "BUDGET_FILE", "DENY", "WARN", "BudgetPolicy", "BudgetStore",
25
+ "Locator", "PriceTable", "Snapshot", "Verdict", "default_logs", "evaluate",
26
+ "load_budget_policy", "load_builtin_table", "price_table", "rebuild", "refresh",
27
+ ]