agent-firewall-security 2.2.0__tar.gz → 2.4.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 (220) hide show
  1. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/PKG-INFO +232 -3
  2. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/README.md +231 -2
  3. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/PKG-INFO +232 -3
  4. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/SOURCES.txt +28 -2
  5. agent_firewall_security-2.4.0/firewall/a2a/__init__.py +34 -0
  6. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/a2a/auth.py +81 -4
  7. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adapters/anthropic.py +57 -46
  8. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adapters/generic.py +60 -46
  9. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adapters/openai.py +57 -46
  10. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adversarial/__init__.py +31 -17
  11. agent_firewall_security-2.4.0/firewall/aegis/__init__.py +209 -0
  12. agent_firewall_security-2.4.0/firewall/aegis/blast.py +450 -0
  13. agent_firewall_security-2.4.0/firewall/aegis/controller.py +1177 -0
  14. agent_firewall_security-2.4.0/firewall/aegis/decay.py +267 -0
  15. agent_firewall_security-2.4.0/firewall/aegis/envelope.py +979 -0
  16. agent_firewall_security-2.4.0/firewall/aegis/explain.py +451 -0
  17. agent_firewall_security-2.4.0/firewall/aegis/preflight.py +614 -0
  18. agent_firewall_security-2.4.0/firewall/aegis/response.py +557 -0
  19. agent_firewall_security-2.4.0/firewall/aegis/restriction.py +523 -0
  20. agent_firewall_security-2.4.0/firewall/aegis/state.py +384 -0
  21. agent_firewall_security-2.4.0/firewall/attenuation.py +134 -0
  22. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/authorization.py +37 -0
  23. agent_firewall_security-2.4.0/firewall/benchmarks.py +1191 -0
  24. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/cli_v21.py +20 -4
  25. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/continuous_auth/engine.py +20 -1
  26. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/deception/__init__.py +28 -4
  27. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/defense/mesh.py +20 -1
  28. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/delegation.py +14 -0
  29. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/delegation_budget.py +73 -0
  30. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/evidence_integrity/__init__.py +6 -6
  31. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/immune/engine.py +14 -3
  32. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/intel/__init__.py +2 -0
  33. agent_firewall_security-2.4.0/firewall/intel/engine.py +875 -0
  34. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/invariants/__init__.py +28 -2
  35. agent_firewall_security-2.4.0/firewall/invariants/__main__.py +163 -0
  36. agent_firewall_security-2.4.0/firewall/invariants/exercise.py +399 -0
  37. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/invariants/registry.py +74 -9
  38. agent_firewall_security-2.4.0/firewall/invariants/runtime.py +2683 -0
  39. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/invariants/source.py +1 -1
  40. agent_firewall_security-2.4.0/firewall/policy_analysis/__init__.py +799 -0
  41. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/checkpoint.py +12 -1
  42. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/sdk.py +520 -1
  43. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/security_memory/__init__.py +26 -13
  44. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/introspect.py +43 -0
  45. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/pyproject.toml +1 -1
  46. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_adversarial_defense.py +28 -4
  47. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_deception_integrity.py +2 -2
  48. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_evidence_integrity.py +6 -6
  49. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_invariants.py +56 -90
  50. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_security_memory.py +4 -4
  51. agent_firewall_security-2.4.0/tests/test_v2_3_duplicate_concepts.py +412 -0
  52. agent_firewall_security-2.4.0/tests/test_v2_3_intel_coordination.py +465 -0
  53. agent_firewall_security-2.4.0/tests/test_v2_3_invariant_gate.py +436 -0
  54. agent_firewall_security-2.4.0/tests/test_v2_3_policy_analysis.py +652 -0
  55. agent_firewall_security-2.4.0/tests/test_v2_3_self_attack.py +2686 -0
  56. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_adversarial.py +1468 -0
  57. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_concurrency.py +1155 -0
  58. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_controller.py +1450 -0
  59. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_corrections.py +477 -0
  60. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_fuzz.py +949 -0
  61. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_gate.py +504 -0
  62. agent_firewall_security-2.4.0/tests/test_v2_4_aegis_state.py +633 -0
  63. agent_firewall_security-2.4.0/tests/test_v2_4_attenuation_narrowing.py +369 -0
  64. agent_firewall_security-2.4.0/tests/test_v2_4_benchmarks.py +337 -0
  65. agent_firewall_security-2.4.0/tests/test_v2_4_envelope_soundness.py +154 -0
  66. agent_firewall_security-2.4.0/tests/test_v2_4_integration_boundary.py +979 -0
  67. agent_firewall_security-2.2.0/firewall/a2a/__init__.py +0 -21
  68. agent_firewall_security-2.2.0/firewall/attenuation.py +0 -159
  69. agent_firewall_security-2.2.0/firewall/benchmarks.py +0 -295
  70. agent_firewall_security-2.2.0/firewall/correlation/__init__.py +0 -552
  71. agent_firewall_security-2.2.0/firewall/intel/engine.py +0 -495
  72. agent_firewall_security-2.2.0/firewall/invariants/__main__.py +0 -121
  73. agent_firewall_security-2.2.0/firewall/invariants/runtime.py +0 -1173
  74. agent_firewall_security-2.2.0/firewall/policy_analysis/__init__.py +0 -409
  75. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/dependency_links.txt +0 -0
  76. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/entry_points.txt +0 -0
  77. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/requires.txt +0 -0
  78. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/agent_firewall_security.egg-info/top_level.txt +0 -0
  79. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/__init__.py +0 -0
  80. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adapters/__init__.py +0 -0
  81. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/adapters/normalize.py +0 -0
  82. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/agents/__init__.py +0 -0
  83. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/agents/adapters.py +0 -0
  84. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/agents/base.py +0 -0
  85. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/artifact/__init__.py +0 -0
  86. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/artifact/reader.py +0 -0
  87. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/artifact/writer.py +0 -0
  88. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/attackgraph/__init__.py +0 -0
  89. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/attackgraph/engine.py +0 -0
  90. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/attest/__init__.py +0 -0
  91. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/attest/authority.py +0 -0
  92. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/capability.py +0 -0
  93. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/capability2/__init__.py +0 -0
  94. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/capability2/constraints.py +0 -0
  95. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/cli.py +0 -0
  96. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/cli_v19.py +0 -0
  97. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/cli_v20.py +0 -0
  98. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/containment/__init__.py +0 -0
  99. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/containment/controller.py +0 -0
  100. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/continuous_auth/__init__.py +0 -0
  101. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/continuous_auth/monitor.py +0 -0
  102. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/continuous_auth/predicates.py +0 -0
  103. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/defense/__init__.py +0 -0
  104. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/delegation_lineage.py +0 -0
  105. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/delegation_store.py +0 -0
  106. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/engine.py +0 -0
  107. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/evidence.py +0 -0
  108. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/evidence_graph/__init__.py +0 -0
  109. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/evidence_graph/graph.py +0 -0
  110. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/explain.py +0 -0
  111. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/http.py +0 -0
  112. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ident/__init__.py +0 -0
  113. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ident/registry.py +0 -0
  114. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/identity.py +0 -0
  115. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/immune/__init__.py +0 -0
  116. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/incident/__init__.py +0 -0
  117. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/incident/package.py +0 -0
  118. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/invariants/model.py +0 -0
  119. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/invariants/static.py +0 -0
  120. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/key_management.py +0 -0
  121. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/key_store.py +0 -0
  122. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/lab/__init__.py +0 -0
  123. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/lab/engine.py +0 -0
  124. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/lifecycle.py +0 -0
  125. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/lifecycle_store.py +0 -0
  126. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/mcp.py +0 -0
  127. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/namespace.py +0 -0
  128. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/__init__.py +0 -0
  129. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/attack_path.py +0 -0
  130. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/behavior.py +0 -0
  131. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/correlation.py +0 -0
  132. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/graph.py +0 -0
  133. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/model.py +0 -0
  134. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/response.py +0 -0
  135. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/simulator.py +0 -0
  136. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/network/state.py +0 -0
  137. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/north_star.py +0 -0
  138. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/passport/__init__.py +0 -0
  139. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/passport/builder.py +0 -0
  140. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/platform/__init__.py +0 -0
  141. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/platform/provenance.py +0 -0
  142. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/policy.py +0 -0
  143. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/posture/__init__.py +0 -0
  144. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/posture/engine.py +0 -0
  145. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/protect.py +0 -0
  146. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/provenance/__init__.py +0 -0
  147. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/provenance/registry.py +0 -0
  148. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/__init__.py +0 -0
  149. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/encoding.py +0 -0
  150. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/events.py +0 -0
  151. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/identity.py +0 -0
  152. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/recorder.py +0 -0
  153. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/recorder/redact.py +0 -0
  154. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/refusal_state.py +0 -0
  155. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/replay.py +0 -0
  156. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/replay_store.py +0 -0
  157. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/replaylab/__init__.py +0 -0
  158. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/replaylab/laboratory.py +0 -0
  159. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/research/__init__.py +0 -0
  160. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/research/lab.py +0 -0
  161. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/response2/__init__.py +0 -0
  162. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/response2/adaptive.py +0 -0
  163. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/revocation.py +0 -0
  164. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/revocation_store.py +0 -0
  165. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/risk_context.py +0 -0
  166. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/security_context.py +0 -0
  167. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/security_decision.py +0 -0
  168. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/semantic_chain.py +0 -0
  169. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/__init__.py +0 -0
  170. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/case.py +0 -0
  171. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/recorder.py +0 -0
  172. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/replay.py +0 -0
  173. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/report.py +0 -0
  174. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/rollout.py +0 -0
  175. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/simulation/ruleset.py +0 -0
  176. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/task/__init__.py +0 -0
  177. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/task/registry.py +0 -0
  178. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/timeline/__init__.py +0 -0
  179. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/timeline/graph.py +0 -0
  180. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/timeline/timeline.py +0 -0
  181. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/timeline/trajectory.py +0 -0
  182. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/tools.py +0 -0
  183. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/transport.py +0 -0
  184. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/trust/__init__.py +0 -0
  185. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/trust/graph.py +0 -0
  186. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/twin/__init__.py +0 -0
  187. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/twin/adversarial.py +0 -0
  188. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/twin/twin.py +0 -0
  189. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/__init__.py +0 -0
  190. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/__main__.py +0 -0
  191. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/control.py +0 -0
  192. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/demo.py +0 -0
  193. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/server.py +0 -0
  194. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/service.py +0 -0
  195. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/console.css +0 -0
  196. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/console.js +0 -0
  197. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/control.js +0 -0
  198. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/index.html +0 -0
  199. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/recorder.css +0 -0
  200. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/recorder.js +0 -0
  201. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/soc.css +0 -0
  202. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/soc.js +0 -0
  203. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/v20.css +0 -0
  204. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/v20.js +0 -0
  205. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/v21.css +0 -0
  206. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/static/v21.js +0 -0
  207. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/v18.py +0 -0
  208. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/v19.py +0 -0
  209. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/v20.py +0 -0
  210. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/ui/v21.py +0 -0
  211. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/verify/__init__.py +0 -0
  212. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/firewall/verify/verifier.py +0 -0
  213. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/setup.cfg +0 -0
  214. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_continuous_auth.py +0 -0
  215. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_engine.py +0 -0
  216. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_sdk_continuous_auth.py +0 -0
  217. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_security_decision.py +0 -0
  218. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_adversarial_twin.py +0 -0
  219. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_capability_delegation.py +0 -0
  220. {agent_firewall_security-2.2.0 → agent_firewall_security-2.4.0}/tests/test_v2_2_platform_provenance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-firewall-security
3
- Version: 2.2.0
3
+ Version: 2.4.0
4
4
  Summary: Security and canonical authorization infrastructure for AI agents and automated tool use.
5
5
  Project-URL: Homepage, https://github.com/Shubhbhangoo/agent-firewall
6
6
  Project-URL: Repository, https://github.com/Shubhbhangoo/agent-firewall
@@ -28,6 +28,10 @@ Requires-Dist: hypothesis>=6.0; extra == "dev"
28
28
 
29
29
  Agent Firewall is built around one security boundary: **authorization remains deterministic, explicit, and fail-closed**. Identity, provenance, monitoring, behavioral analysis, simulation, evidence, and response provide security context around that boundary, but they do not become an alternative path to authorization.
30
30
 
31
+ > **v2.4** adds **Aegis**, an adaptive authority control plane: a live grant can be narrowed, suspended, revalidated or revoked while a task is running. It adds no second authorization path — Aegis reaches `FirewallSDK.authorize()` through one gate that can only deny or abstain, and learns what happened through one callback the SDK invokes *after* the decision exists.
32
+ >
33
+ > **v2.3** is a correctness release. It adds no subsystem and no authorization path: the work was to attack v2.2's shipped behaviour, fix the three fail-open paths that broke, stop analytical output from reading as verified when it was not, and make the strict invariant gate something CI can actually fail on.
34
+ >
31
35
  > **v2.2** makes the control plane adaptive: authority is re-evaluated when the state it rested on changes, contradictions between independent claim sources are reported rather than resolved, and the architectural properties the design rests on are checked by code instead of asserted in prose.
32
36
 
33
37
  ---
@@ -90,6 +94,166 @@ When required evidence is unavailable, verification fails, identity is unknown,
90
94
 
91
95
  ---
92
96
 
97
+ ## What v2.4 adds
98
+
99
+ v2.2 made the platform adaptive *above* the boundary: when watched state
100
+ changed, a decision was re-run. v2.4 makes **authority itself** adaptive. A
101
+ grant that is already in use can be narrowed, suspended, revalidated or
102
+ revoked, and the change is enforced on the next authorization — and, for
103
+ suspension, inside the commit transaction of one already in flight.
104
+
105
+ Aegis is off by default. `FirewallSDK(aegis_enabled=True)` opts in; with no
106
+ controller attached the adaptive gate abstains and v2.3 behaviour is exact.
107
+
108
+ ### One deny-only seam
109
+
110
+ Nine modules, 5,382 lines, none of which imports `firewall.sdk`. Everything
111
+ Aegis does reaches the outside world through two points: `_gate_aegis`, the
112
+ ninth of eleven gates, which can only deny or abstain; and
113
+ `observe_authorization`, which the SDK calls *after* a decision exists.
114
+ Because the callback runs after, no Aegis state can be a precondition of the
115
+ allow it observes. Authority flows from the boundary into Aegis and never the
116
+ other way.
117
+
118
+ ```text
119
+ change -> classify -> KEEP | REVALIDATE | NARROW | SUSPEND | REVOKE
120
+ |
121
+ v
122
+ restriction written
123
+ |
124
+ v
125
+ FirewallSDK.authorize() -> _gate_aegis -> DENY
126
+ ```
127
+
128
+ There is no arrow from Aegis to ALLOW. That absence is the design.
129
+
130
+ ### The authority envelope
131
+
132
+ An `AuthorityEnvelope` is a bound on what a capability may still do, folded
133
+ across its delegation chain by a per-dimension greatest-lower-bound. Twelve
134
+ fields — patterns, tool, time window, constraint bounds, depth, its ceiling,
135
+ issuers, issuer trust, revocation, budget, chain membership, and a bottom
136
+ marker — and every dimension that bounds a request has a named enforcement
137
+ site at the boundary. A dimension with no enforcement site would be
138
+ decoration.
139
+
140
+ The theorem is one-directional and stated that way: if the envelope
141
+ **excludes** a request, the boundary denies it. The converse does not hold,
142
+ and the API is named so that misuse reads wrong — `excludes()` returns a
143
+ reason, `may_admit()` means "this envelope does not itself refuse", and
144
+ `__bool__` **raises** on an envelope, a grant, a preflight, a blast radius
145
+ and a classification, so `if preflight(...)` is an error rather than an
146
+ accidental allow.
147
+
148
+ ### Seven states ordered by residual authority
149
+
150
+ `ISSUED`, `ACTIVE`, `REVALIDATING`, `NARROWED`, `SUSPENDED`, `REVOKED`,
151
+ `EXPIRED`. A transition is legal only if it does not increase residual
152
+ authority. `REVALIDATING -> ACTIVE` is the only edge that restores authority,
153
+ and it requires an `AuthorizationResult` that is allowed, reasoned
154
+ `authorized`, and traced to that capability's fingerprint. `REVOKED` and
155
+ `EXPIRED` are terminal and checked before the ordering rule, so no evidence
156
+ or clock change produces an edge out of either.
157
+
158
+ The state machine is a record and a legality check. It is deliberately **not**
159
+ an enforcement channel: the gate reads restrictions, not states, because
160
+ wiring the state model into the gate would make the authorization path depend
161
+ on a structure whose own updates require an authorization result.
162
+
163
+ ### Unknown never becomes safe
164
+
165
+ An unrecognised trigger is `REVALIDATE`, not `KEEP` (which would make an
166
+ unknown event benign) and not `REVOKE` (which would make any unknown string a
167
+ denial-of-service lever). Nothing maps to `KEEP` at all — it is reachable
168
+ only by establishing five positive conditions, so "nothing changed" must be
169
+ shown rather than assumed. An unreadable budget is exhausted, not unlimited;
170
+ an unreadable restriction matches; unestablished issuer trust is `None`, not
171
+ `True`; an unresolvable chain yields the bottom envelope; a traversal that
172
+ exceeds its bounds is `UNANALYZABLE` rather than a partial answer presented
173
+ as complete. `UNKNOWN_NON_AUTHORIZATION` checks these exhaustively.
174
+
175
+ ### What it does not claim
176
+
177
+ Envelope soundness runs in one direction. `canonical_allow_for` is a
178
+ structural check, not a cryptographic one — it bounds mistakes, not an
179
+ adversary already inside the process. The commit-time re-read covers
180
+ suspension only. The restriction cap trades availability for integrity:
181
+ sixteen narrowings drive a grant to `SUSPEND`, which is fail-closed and still
182
+ a lever. §16 of [`docs/v2.4-aegis.md`](docs/v2.4-aegis.md) is the full list,
183
+ and §17 maps each guarantee to the test file that establishes it.
184
+
185
+ ---
186
+
187
+ ## What v2.3 changes
188
+
189
+ v2.3 adds no subsystem. Three requests that v2.2 allowed are now denied,
190
+ each found by attacking the shipped implementation rather than by reviewing
191
+ the design.
192
+
193
+ ### Three fail-open paths closed
194
+
195
+ - **A non-finite request value satisfied every numeric bound.** Numeric
196
+ constraints are enforced by negation — admit unless `actual > expected` —
197
+ and `NaN` compares `False` against everything, so `{"amount": NaN}` passed
198
+ an `amount_max` of 100 and an `amount_min` of 10 at the same time.
199
+ `json.loads` accepts the bare tokens `NaN`, `Infinity` and `-Infinity`, so
200
+ the value arrived through ordinary request bodies and tool output. Now
201
+ `constraint_denied`.
202
+ - **The first decision taken while a configured dependency was blind
203
+ reported as `authorized`.** v2.2 gated all three revalidation paths but
204
+ not the initial decision, so a capability was allowed once and denied by
205
+ every revalidation of the same request. Now
206
+ `security_dependency_unavailable: <names>`, applied at the boundary — the
207
+ engine still returns a `(bool, reason)` pair and mints no verdict.
208
+ - **Reconfiguring a delegation budget reset the consumed total.** An
209
+ exhausted lineage's whole allowance was restored by an administrative call
210
+ that revoked, re-issued and signed nothing — and the idempotent case was
211
+ the dangerous one, since a startup path re-applying the same limit cleared
212
+ the ledger on every restart. `configure` now adjusts the ceiling and
213
+ leaves the ledger alone.
214
+
215
+ All three share one shape: **an admission must be positively established,
216
+ not inferred from the absence of a violation.** See
217
+ [`docs/v2.3-security-corrections.md`](docs/v2.3-security-corrections.md).
218
+
219
+ ### The self-attack suite
220
+
221
+ `tests/test_v2_3_self_attack.py` is 116 tests, one section per question in
222
+ the mission's final self-attack list, each attempting the attack through the
223
+ real public API. Two rules govern the file: attack through the front door,
224
+ and where the system makes no guarantee, pin the non-guarantee instead of
225
+ faking one. A completeness test maps each of the thirteen questions to its
226
+ section, so deleting one fails rather than quietly shrinking the suite. See
227
+ [`docs/v2.3-self-attack.md`](docs/v2.3-self-attack.md).
228
+
229
+ ### A strict invariant gate that can pass
230
+
231
+ `python -m firewall.invariants --strict` exited 2 on every invocation,
232
+ because seven of the fifteen invariants are claims about live state that a
233
+ source-only run never reaches. A gate that always fails is a gate that gets
234
+ removed, so those seven were effectively ungated in CI.
235
+ `firewall/invariants/exercise.py` builds the canonical estate through the
236
+ SDK's public API only, and CI now runs the source-only and exercised gates
237
+ as separate steps. What a green exercised run establishes is bounded to that
238
+ estate, and the printed output says so. See
239
+ [`docs/v2.3-invariant-gate.md`](docs/v2.3-invariant-gate.md).
240
+
241
+ ### One name, one guarantee
242
+
243
+ Three renames separate a cryptographic result from an analytical one that
244
+ shared its name — `deception.ClaimIntegrityReport`,
245
+ `security_memory.EvidenceCheckpoint`, and
246
+ `AgentSecurityProfile.finding_score`. The third mattered most:
247
+ `MeshState.trust_score` is 0.0 when identity could not be verified, while
248
+ the profile's was 1.0 until something was found, so wiring the profile into
249
+ the mesh's `trust_provider` would have delivered an unchecked agent as fully
250
+ trusted. `firewall.correlation` is deleted; coordination detection moved to
251
+ `firewall.intel`, where every finding carries supporting facts, a rationale
252
+ and `basis="inferred"`. See
253
+ [`docs/v2.3-migration.md`](docs/v2.3-migration.md).
254
+
255
+ ---
256
+
93
257
  ## What v2.2 adds
94
258
 
95
259
  ### Continuous authorization
@@ -358,7 +522,9 @@ The architecture is designed around explicit security invariants.
358
522
  - **A check that could not run is not a check that passed.**
359
523
  - **Security failures default toward refusal rather than implicit trust.**
360
524
 
361
- These are implementation properties of the system, not a claim that any deployment is universally secure. Eleven such properties are additionally stated once in `firewall.invariants` and checked by code rather than asserted in prose alone; see [`docs/v2.2-invariants.md`](docs/v2.2-invariants.md).
525
+ These are implementation properties of the system, not a claim that any deployment is universally secure. Fifteen such properties are additionally stated once in `firewall.invariants` and checked by code rather than asserted in prose alone; see [`docs/v2.2-invariants.md`](docs/v2.2-invariants.md) for the invariants themselves, [`docs/v2.3-invariant-gate.md`](docs/v2.3-invariant-gate.md) for what a green gate run does and does not establish, and [`docs/v2.4-aegis.md`](docs/v2.4-aegis.md) for the four the authority control plane adds.
526
+
527
+ Where a property does **not** hold, it is stated rather than left to be inferred. A posture change is detected but does not by itself flip a verdict; `retire_key` is not containment for a stolen key, since a retired key's signatures keep verifying so that rotation does not invalidate capabilities in flight; an `amount_max` ceiling is per request, so two siblings each holding one can spend it twice unless a lineage budget is configured; and possession of a trusted signing key is authority, which no cryptography can undo. [`docs/v2.3-self-attack.md`](docs/v2.3-self-attack.md) records each of these against the test that pins it.
362
528
 
363
529
  ---
364
530
 
@@ -394,7 +560,7 @@ Verification distinguishes states including `verified`, `failed`, `unverifiable`
394
560
  Python 3.10+ is required.
395
561
 
396
562
  ```bash
397
- pip install agent-firewall-security==2.2.0
563
+ pip install agent-firewall-security==2.3.0
398
564
  ```
399
565
 
400
566
  Development installation:
@@ -442,6 +608,17 @@ The authorization path evaluates the security conditions required by the capabil
442
608
 
443
609
  ## Command surface
444
610
 
611
+ v2.4 adds no new CLI subcommands. One existing command changes what it
612
+ prints: `firewall delegate-authorize` now labels an allow it reached without
613
+ an attached `sdk_provider` as `ALLOWED (relationship only)` and says not to
614
+ enforce on it. The exit status stays 0 — the question asked was answered
615
+ affirmatively — but the answer no longer overstates itself.
616
+
617
+ v2.3 adds no new CLI subcommands. It adds one flag to the invariant
618
+ checker: `python -m firewall.invariants --exercise --strict` builds the
619
+ canonical estate so that all fifteen invariants can be reached, which makes
620
+ `--strict` a gate that can pass and is therefore worth failing.
621
+
445
622
  v2.2 adds no new CLI subcommands. Its one new entry point is the invariant
446
623
  checker, `python -m firewall.invariants`, shown above.
447
624
 
@@ -492,6 +669,50 @@ python -m firewall.benchmarks
492
669
 
493
670
  The repository contains unit, integration, adversarial, hardening, evidence, UI/API, benchmark, and research tests.
494
671
 
672
+ The v2.4 test surface adds 384 tests across eleven files — 4,087 in the suite
673
+ as a whole, on Python 3.10, 3.11 and 3.12 — including stateful security-state
674
+ fuzzing, eight named concurrency races, and an integration-boundary sweep.
675
+ Among the properties covered:
676
+
677
+ - no path from adaptive analysis to an allow, and no Aegis module able to
678
+ construct an `AuthorizationResult`
679
+ - every forbidden transition refused individually: out of `REVOKED`, out of
680
+ `EXPIRED`, `NARROWED` to wider, `SUSPENDED` to `ACTIVE` without a canonical
681
+ allow, and a child exceeding its parent
682
+ - an envelope that excludes a request always accompanied by a boundary that
683
+ denies it
684
+ - no field of the envelope widening under delegation or attenuation
685
+ - a `nan` bound bounding nothing being denied, while an `inf` bound still
686
+ means unbounded
687
+ - a 400-digit integer producing a decision rather than an exception out of
688
+ `authorize()`
689
+ - every authorization-reachable Aegis method total, including against an
690
+ injected hostile controller
691
+ - a restriction written mid-flight being observed, and a suspension being
692
+ caught inside the commit transaction
693
+ - `__bool__` raising on every analysis object, so a truthiness test cannot
694
+ become an allow
695
+ - every integration surface reaching the canonical boundary, with no local
696
+ allow anywhere
697
+ - no dataclass field in the package carrying a default that Python 3.11
698
+ rejects, so a defect that hides on the development interpreter cannot wait
699
+ for CI to find it
700
+
701
+ The v2.3 test surface adds the thirteen-question self-attack suite, which
702
+ covers, among other properties:
703
+
704
+ - a non-finite request value satisfying no numeric ceiling or floor
705
+ - the first decision under a blind dependency being withheld, and agreeing
706
+ with its own revalidations
707
+ - a delegation budget's consumed total surviving reconfiguration
708
+ - erasing or re-pointing the delegation registry failing closed against the
709
+ child's own signature
710
+ - naming an issuer as trusted not importing its keys
711
+ - `revoke_issuer` containing a compromised signer where `retire_key` does not
712
+ - no gate in the firewall reading the untrusted-data taint marker, because a
713
+ type and a signature are the barrier rather than a filter
714
+ - the degradation subtraction being unable to turn a denial into an allow
715
+
495
716
  The v2.2 test surface covers, among other properties:
496
717
 
497
718
  - capability attenuation
@@ -603,6 +824,14 @@ See [`SECURITY.md`](SECURITY.md) for the project's security reporting policy.
603
824
 
604
825
  Detailed specifications are maintained in the repository:
605
826
 
827
+ - `docs/v2.4-aegis.md`
828
+ - `docs/v2.4-aegis-design.md`
829
+ - `docs/v2.4-performance.md`
830
+ - `docs/v2.4-migration.md`
831
+ - `docs/v2.3-security-corrections.md`
832
+ - `docs/v2.3-self-attack.md`
833
+ - `docs/v2.3-invariant-gate.md`
834
+ - `docs/v2.3-migration.md`
606
835
  - `docs/v2.2-architecture.md`
607
836
  - `docs/v2.2-security-model.md`
608
837
  - `docs/v2.2-threat-model.md`
@@ -4,6 +4,10 @@
4
4
 
5
5
  Agent Firewall is built around one security boundary: **authorization remains deterministic, explicit, and fail-closed**. Identity, provenance, monitoring, behavioral analysis, simulation, evidence, and response provide security context around that boundary, but they do not become an alternative path to authorization.
6
6
 
7
+ > **v2.4** adds **Aegis**, an adaptive authority control plane: a live grant can be narrowed, suspended, revalidated or revoked while a task is running. It adds no second authorization path — Aegis reaches `FirewallSDK.authorize()` through one gate that can only deny or abstain, and learns what happened through one callback the SDK invokes *after* the decision exists.
8
+ >
9
+ > **v2.3** is a correctness release. It adds no subsystem and no authorization path: the work was to attack v2.2's shipped behaviour, fix the three fail-open paths that broke, stop analytical output from reading as verified when it was not, and make the strict invariant gate something CI can actually fail on.
10
+ >
7
11
  > **v2.2** makes the control plane adaptive: authority is re-evaluated when the state it rested on changes, contradictions between independent claim sources are reported rather than resolved, and the architectural properties the design rests on are checked by code instead of asserted in prose.
8
12
 
9
13
  ---
@@ -66,6 +70,166 @@ When required evidence is unavailable, verification fails, identity is unknown,
66
70
 
67
71
  ---
68
72
 
73
+ ## What v2.4 adds
74
+
75
+ v2.2 made the platform adaptive *above* the boundary: when watched state
76
+ changed, a decision was re-run. v2.4 makes **authority itself** adaptive. A
77
+ grant that is already in use can be narrowed, suspended, revalidated or
78
+ revoked, and the change is enforced on the next authorization — and, for
79
+ suspension, inside the commit transaction of one already in flight.
80
+
81
+ Aegis is off by default. `FirewallSDK(aegis_enabled=True)` opts in; with no
82
+ controller attached the adaptive gate abstains and v2.3 behaviour is exact.
83
+
84
+ ### One deny-only seam
85
+
86
+ Nine modules, 5,382 lines, none of which imports `firewall.sdk`. Everything
87
+ Aegis does reaches the outside world through two points: `_gate_aegis`, the
88
+ ninth of eleven gates, which can only deny or abstain; and
89
+ `observe_authorization`, which the SDK calls *after* a decision exists.
90
+ Because the callback runs after, no Aegis state can be a precondition of the
91
+ allow it observes. Authority flows from the boundary into Aegis and never the
92
+ other way.
93
+
94
+ ```text
95
+ change -> classify -> KEEP | REVALIDATE | NARROW | SUSPEND | REVOKE
96
+ |
97
+ v
98
+ restriction written
99
+ |
100
+ v
101
+ FirewallSDK.authorize() -> _gate_aegis -> DENY
102
+ ```
103
+
104
+ There is no arrow from Aegis to ALLOW. That absence is the design.
105
+
106
+ ### The authority envelope
107
+
108
+ An `AuthorityEnvelope` is a bound on what a capability may still do, folded
109
+ across its delegation chain by a per-dimension greatest-lower-bound. Twelve
110
+ fields — patterns, tool, time window, constraint bounds, depth, its ceiling,
111
+ issuers, issuer trust, revocation, budget, chain membership, and a bottom
112
+ marker — and every dimension that bounds a request has a named enforcement
113
+ site at the boundary. A dimension with no enforcement site would be
114
+ decoration.
115
+
116
+ The theorem is one-directional and stated that way: if the envelope
117
+ **excludes** a request, the boundary denies it. The converse does not hold,
118
+ and the API is named so that misuse reads wrong — `excludes()` returns a
119
+ reason, `may_admit()` means "this envelope does not itself refuse", and
120
+ `__bool__` **raises** on an envelope, a grant, a preflight, a blast radius
121
+ and a classification, so `if preflight(...)` is an error rather than an
122
+ accidental allow.
123
+
124
+ ### Seven states ordered by residual authority
125
+
126
+ `ISSUED`, `ACTIVE`, `REVALIDATING`, `NARROWED`, `SUSPENDED`, `REVOKED`,
127
+ `EXPIRED`. A transition is legal only if it does not increase residual
128
+ authority. `REVALIDATING -> ACTIVE` is the only edge that restores authority,
129
+ and it requires an `AuthorizationResult` that is allowed, reasoned
130
+ `authorized`, and traced to that capability's fingerprint. `REVOKED` and
131
+ `EXPIRED` are terminal and checked before the ordering rule, so no evidence
132
+ or clock change produces an edge out of either.
133
+
134
+ The state machine is a record and a legality check. It is deliberately **not**
135
+ an enforcement channel: the gate reads restrictions, not states, because
136
+ wiring the state model into the gate would make the authorization path depend
137
+ on a structure whose own updates require an authorization result.
138
+
139
+ ### Unknown never becomes safe
140
+
141
+ An unrecognised trigger is `REVALIDATE`, not `KEEP` (which would make an
142
+ unknown event benign) and not `REVOKE` (which would make any unknown string a
143
+ denial-of-service lever). Nothing maps to `KEEP` at all — it is reachable
144
+ only by establishing five positive conditions, so "nothing changed" must be
145
+ shown rather than assumed. An unreadable budget is exhausted, not unlimited;
146
+ an unreadable restriction matches; unestablished issuer trust is `None`, not
147
+ `True`; an unresolvable chain yields the bottom envelope; a traversal that
148
+ exceeds its bounds is `UNANALYZABLE` rather than a partial answer presented
149
+ as complete. `UNKNOWN_NON_AUTHORIZATION` checks these exhaustively.
150
+
151
+ ### What it does not claim
152
+
153
+ Envelope soundness runs in one direction. `canonical_allow_for` is a
154
+ structural check, not a cryptographic one — it bounds mistakes, not an
155
+ adversary already inside the process. The commit-time re-read covers
156
+ suspension only. The restriction cap trades availability for integrity:
157
+ sixteen narrowings drive a grant to `SUSPEND`, which is fail-closed and still
158
+ a lever. §16 of [`docs/v2.4-aegis.md`](docs/v2.4-aegis.md) is the full list,
159
+ and §17 maps each guarantee to the test file that establishes it.
160
+
161
+ ---
162
+
163
+ ## What v2.3 changes
164
+
165
+ v2.3 adds no subsystem. Three requests that v2.2 allowed are now denied,
166
+ each found by attacking the shipped implementation rather than by reviewing
167
+ the design.
168
+
169
+ ### Three fail-open paths closed
170
+
171
+ - **A non-finite request value satisfied every numeric bound.** Numeric
172
+ constraints are enforced by negation — admit unless `actual > expected` —
173
+ and `NaN` compares `False` against everything, so `{"amount": NaN}` passed
174
+ an `amount_max` of 100 and an `amount_min` of 10 at the same time.
175
+ `json.loads` accepts the bare tokens `NaN`, `Infinity` and `-Infinity`, so
176
+ the value arrived through ordinary request bodies and tool output. Now
177
+ `constraint_denied`.
178
+ - **The first decision taken while a configured dependency was blind
179
+ reported as `authorized`.** v2.2 gated all three revalidation paths but
180
+ not the initial decision, so a capability was allowed once and denied by
181
+ every revalidation of the same request. Now
182
+ `security_dependency_unavailable: <names>`, applied at the boundary — the
183
+ engine still returns a `(bool, reason)` pair and mints no verdict.
184
+ - **Reconfiguring a delegation budget reset the consumed total.** An
185
+ exhausted lineage's whole allowance was restored by an administrative call
186
+ that revoked, re-issued and signed nothing — and the idempotent case was
187
+ the dangerous one, since a startup path re-applying the same limit cleared
188
+ the ledger on every restart. `configure` now adjusts the ceiling and
189
+ leaves the ledger alone.
190
+
191
+ All three share one shape: **an admission must be positively established,
192
+ not inferred from the absence of a violation.** See
193
+ [`docs/v2.3-security-corrections.md`](docs/v2.3-security-corrections.md).
194
+
195
+ ### The self-attack suite
196
+
197
+ `tests/test_v2_3_self_attack.py` is 116 tests, one section per question in
198
+ the mission's final self-attack list, each attempting the attack through the
199
+ real public API. Two rules govern the file: attack through the front door,
200
+ and where the system makes no guarantee, pin the non-guarantee instead of
201
+ faking one. A completeness test maps each of the thirteen questions to its
202
+ section, so deleting one fails rather than quietly shrinking the suite. See
203
+ [`docs/v2.3-self-attack.md`](docs/v2.3-self-attack.md).
204
+
205
+ ### A strict invariant gate that can pass
206
+
207
+ `python -m firewall.invariants --strict` exited 2 on every invocation,
208
+ because seven of the fifteen invariants are claims about live state that a
209
+ source-only run never reaches. A gate that always fails is a gate that gets
210
+ removed, so those seven were effectively ungated in CI.
211
+ `firewall/invariants/exercise.py` builds the canonical estate through the
212
+ SDK's public API only, and CI now runs the source-only and exercised gates
213
+ as separate steps. What a green exercised run establishes is bounded to that
214
+ estate, and the printed output says so. See
215
+ [`docs/v2.3-invariant-gate.md`](docs/v2.3-invariant-gate.md).
216
+
217
+ ### One name, one guarantee
218
+
219
+ Three renames separate a cryptographic result from an analytical one that
220
+ shared its name — `deception.ClaimIntegrityReport`,
221
+ `security_memory.EvidenceCheckpoint`, and
222
+ `AgentSecurityProfile.finding_score`. The third mattered most:
223
+ `MeshState.trust_score` is 0.0 when identity could not be verified, while
224
+ the profile's was 1.0 until something was found, so wiring the profile into
225
+ the mesh's `trust_provider` would have delivered an unchecked agent as fully
226
+ trusted. `firewall.correlation` is deleted; coordination detection moved to
227
+ `firewall.intel`, where every finding carries supporting facts, a rationale
228
+ and `basis="inferred"`. See
229
+ [`docs/v2.3-migration.md`](docs/v2.3-migration.md).
230
+
231
+ ---
232
+
69
233
  ## What v2.2 adds
70
234
 
71
235
  ### Continuous authorization
@@ -334,7 +498,9 @@ The architecture is designed around explicit security invariants.
334
498
  - **A check that could not run is not a check that passed.**
335
499
  - **Security failures default toward refusal rather than implicit trust.**
336
500
 
337
- These are implementation properties of the system, not a claim that any deployment is universally secure. Eleven such properties are additionally stated once in `firewall.invariants` and checked by code rather than asserted in prose alone; see [`docs/v2.2-invariants.md`](docs/v2.2-invariants.md).
501
+ These are implementation properties of the system, not a claim that any deployment is universally secure. Fifteen such properties are additionally stated once in `firewall.invariants` and checked by code rather than asserted in prose alone; see [`docs/v2.2-invariants.md`](docs/v2.2-invariants.md) for the invariants themselves, [`docs/v2.3-invariant-gate.md`](docs/v2.3-invariant-gate.md) for what a green gate run does and does not establish, and [`docs/v2.4-aegis.md`](docs/v2.4-aegis.md) for the four the authority control plane adds.
502
+
503
+ Where a property does **not** hold, it is stated rather than left to be inferred. A posture change is detected but does not by itself flip a verdict; `retire_key` is not containment for a stolen key, since a retired key's signatures keep verifying so that rotation does not invalidate capabilities in flight; an `amount_max` ceiling is per request, so two siblings each holding one can spend it twice unless a lineage budget is configured; and possession of a trusted signing key is authority, which no cryptography can undo. [`docs/v2.3-self-attack.md`](docs/v2.3-self-attack.md) records each of these against the test that pins it.
338
504
 
339
505
  ---
340
506
 
@@ -370,7 +536,7 @@ Verification distinguishes states including `verified`, `failed`, `unverifiable`
370
536
  Python 3.10+ is required.
371
537
 
372
538
  ```bash
373
- pip install agent-firewall-security==2.2.0
539
+ pip install agent-firewall-security==2.3.0
374
540
  ```
375
541
 
376
542
  Development installation:
@@ -418,6 +584,17 @@ The authorization path evaluates the security conditions required by the capabil
418
584
 
419
585
  ## Command surface
420
586
 
587
+ v2.4 adds no new CLI subcommands. One existing command changes what it
588
+ prints: `firewall delegate-authorize` now labels an allow it reached without
589
+ an attached `sdk_provider` as `ALLOWED (relationship only)` and says not to
590
+ enforce on it. The exit status stays 0 — the question asked was answered
591
+ affirmatively — but the answer no longer overstates itself.
592
+
593
+ v2.3 adds no new CLI subcommands. It adds one flag to the invariant
594
+ checker: `python -m firewall.invariants --exercise --strict` builds the
595
+ canonical estate so that all fifteen invariants can be reached, which makes
596
+ `--strict` a gate that can pass and is therefore worth failing.
597
+
421
598
  v2.2 adds no new CLI subcommands. Its one new entry point is the invariant
422
599
  checker, `python -m firewall.invariants`, shown above.
423
600
 
@@ -468,6 +645,50 @@ python -m firewall.benchmarks
468
645
 
469
646
  The repository contains unit, integration, adversarial, hardening, evidence, UI/API, benchmark, and research tests.
470
647
 
648
+ The v2.4 test surface adds 384 tests across eleven files — 4,087 in the suite
649
+ as a whole, on Python 3.10, 3.11 and 3.12 — including stateful security-state
650
+ fuzzing, eight named concurrency races, and an integration-boundary sweep.
651
+ Among the properties covered:
652
+
653
+ - no path from adaptive analysis to an allow, and no Aegis module able to
654
+ construct an `AuthorizationResult`
655
+ - every forbidden transition refused individually: out of `REVOKED`, out of
656
+ `EXPIRED`, `NARROWED` to wider, `SUSPENDED` to `ACTIVE` without a canonical
657
+ allow, and a child exceeding its parent
658
+ - an envelope that excludes a request always accompanied by a boundary that
659
+ denies it
660
+ - no field of the envelope widening under delegation or attenuation
661
+ - a `nan` bound bounding nothing being denied, while an `inf` bound still
662
+ means unbounded
663
+ - a 400-digit integer producing a decision rather than an exception out of
664
+ `authorize()`
665
+ - every authorization-reachable Aegis method total, including against an
666
+ injected hostile controller
667
+ - a restriction written mid-flight being observed, and a suspension being
668
+ caught inside the commit transaction
669
+ - `__bool__` raising on every analysis object, so a truthiness test cannot
670
+ become an allow
671
+ - every integration surface reaching the canonical boundary, with no local
672
+ allow anywhere
673
+ - no dataclass field in the package carrying a default that Python 3.11
674
+ rejects, so a defect that hides on the development interpreter cannot wait
675
+ for CI to find it
676
+
677
+ The v2.3 test surface adds the thirteen-question self-attack suite, which
678
+ covers, among other properties:
679
+
680
+ - a non-finite request value satisfying no numeric ceiling or floor
681
+ - the first decision under a blind dependency being withheld, and agreeing
682
+ with its own revalidations
683
+ - a delegation budget's consumed total surviving reconfiguration
684
+ - erasing or re-pointing the delegation registry failing closed against the
685
+ child's own signature
686
+ - naming an issuer as trusted not importing its keys
687
+ - `revoke_issuer` containing a compromised signer where `retire_key` does not
688
+ - no gate in the firewall reading the untrusted-data taint marker, because a
689
+ type and a signature are the barrier rather than a filter
690
+ - the degradation subtraction being unable to turn a denial into an allow
691
+
471
692
  The v2.2 test surface covers, among other properties:
472
693
 
473
694
  - capability attenuation
@@ -579,6 +800,14 @@ See [`SECURITY.md`](SECURITY.md) for the project's security reporting policy.
579
800
 
580
801
  Detailed specifications are maintained in the repository:
581
802
 
803
+ - `docs/v2.4-aegis.md`
804
+ - `docs/v2.4-aegis-design.md`
805
+ - `docs/v2.4-performance.md`
806
+ - `docs/v2.4-migration.md`
807
+ - `docs/v2.3-security-corrections.md`
808
+ - `docs/v2.3-self-attack.md`
809
+ - `docs/v2.3-invariant-gate.md`
810
+ - `docs/v2.3-migration.md`
582
811
  - `docs/v2.2-architecture.md`
583
812
  - `docs/v2.2-security-model.md`
584
813
  - `docs/v2.2-threat-model.md`