petfishframework 0.3.2__tar.gz → 0.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. {petfishframework-0.3.2 → petfishframework-0.3.3}/CHANGELOG.md +33 -0
  2. {petfishframework-0.3.2 → petfishframework-0.3.3}/PKG-INFO +2 -2
  3. {petfishframework-0.3.2 → petfishframework-0.3.3}/README.md +1 -1
  4. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/api.md +151 -0
  5. {petfishframework-0.3.2 → petfishframework-0.3.3}/pyproject.toml +1 -1
  6. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/__init__.py +1 -1
  7. {petfishframework-0.3.2 → petfishframework-0.3.3}/uv.lock +5 -5
  8. {petfishframework-0.3.2 → petfishframework-0.3.3}/.env.example +0 -0
  9. {petfishframework-0.3.2 → petfishframework-0.3.3}/.github/workflows/ci.yml +0 -0
  10. {petfishframework-0.3.2 → petfishframework-0.3.3}/.github/workflows/publish.yml +0 -0
  11. {petfishframework-0.3.2 → petfishframework-0.3.3}/.gitignore +0 -0
  12. {petfishframework-0.3.2 → petfishframework-0.3.3}/.sisyphus/plans/v0.1.6-plan.md +0 -0
  13. {petfishframework-0.3.2 → petfishframework-0.3.3}/.sisyphus/plans/v0.2.0-plan.md +0 -0
  14. {petfishframework-0.3.2 → petfishframework-0.3.3}/.sisyphus/plans/v0.3.0-plan.md +0 -0
  15. {petfishframework-0.3.2 → petfishframework-0.3.3}/AGENTS.md +0 -0
  16. {petfishframework-0.3.2 → petfishframework-0.3.3}/AGENTS.md.new +0 -0
  17. {petfishframework-0.3.2 → petfishframework-0.3.3}/CONTRIBUTING.md +0 -0
  18. {petfishframework-0.3.2 → petfishframework-0.3.3}/LICENSE +0 -0
  19. {petfishframework-0.3.2 → petfishframework-0.3.3}/SECURITY.md +0 -0
  20. {petfishframework-0.3.2 → petfishframework-0.3.3}/conftest.py +0 -0
  21. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/architecture.md +0 -0
  22. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/benchmark-results.md +0 -0
  23. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/development-plan.md +0 -0
  24. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/development.md +0 -0
  25. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/enterprise-expense-demo.md +0 -0
  26. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_0_1_4_playground_recommendations.md +0 -0
  27. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_playground_report.md +0 -0
  28. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_production_readiness_roadmap.md +0 -0
  29. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_recommendations.md +0 -0
  30. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_v0_1_6_playground_review.md +0 -0
  31. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_v0_1_7_review.md +0 -0
  32. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_v0_1_8_review.md +0 -0
  33. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_v0_2_1_review.md +0 -0
  34. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/archives/petfishframework_v0_2_2_review.md +0 -0
  35. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/feedbacks/petfishframework_v0_3_0_review.md +0 -0
  36. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/release-checklist.md +0 -0
  37. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/competitor-analysis/README.md +0 -0
  38. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/competitor-analysis/competitor-matrix.md +0 -0
  39. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/competitor-analysis/market-brief.md +0 -0
  40. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/competitor-analysis/positioning-map.md +0 -0
  41. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/competitor-analysis/swot-analysis.md +0 -0
  42. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/literature-review/inclusion-exclusion-criteria.md +0 -0
  43. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/literature-review/literature-matrix.md +0 -0
  44. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/literature-review/literature-review.md +0 -0
  45. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/literature-review/search-strategy.md +0 -0
  46. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/research/reference-repos-absorption.md +0 -0
  47. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/skeleton-completeness-checklist.md +0 -0
  48. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/test-results-report.md +0 -0
  49. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/usage-guide.md +0 -0
  50. {petfishframework-0.3.2 → petfishframework-0.3.3}/docs/validation-roadmap.md +0 -0
  51. {petfishframework-0.3.2 → petfishframework-0.3.3}/initialization-report.md +0 -0
  52. {petfishframework-0.3.2 → petfishframework-0.3.3}/mcp/README.md +0 -0
  53. {petfishframework-0.3.2 → petfishframework-0.3.3}/mcp/connection-checklist.md +0 -0
  54. {petfishframework-0.3.2 → petfishframework-0.3.3}/mcp/mcp-config.example.json +0 -0
  55. {petfishframework-0.3.2 → petfishframework-0.3.3}/opencode.json +0 -0
  56. {petfishframework-0.3.2 → petfishframework-0.3.3}/qa/code-review-checklist.md +0 -0
  57. {petfishframework-0.3.2 → petfishframework-0.3.3}/qa/qa-review.md +0 -0
  58. {petfishframework-0.3.2 → petfishframework-0.3.3}/qa/qc-gate-decision.md +0 -0
  59. {petfishframework-0.3.2 → petfishframework-0.3.3}/qa/test-plan.md +0 -0
  60. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/config.py +0 -0
  61. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/__init__.py +0 -0
  62. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/agent.py +0 -0
  63. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/compiled.py +0 -0
  64. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/contracts.py +0 -0
  65. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/conversation.py +0 -0
  66. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/environment.py +0 -0
  67. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/events.py +0 -0
  68. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/session.py +0 -0
  69. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/structured.py +0 -0
  70. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/core/types.py +0 -0
  71. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/credentials/__init__.py +0 -0
  72. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/credentials/broker.py +0 -0
  73. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/credentials/token.py +0 -0
  74. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/mcp/__init__.py +0 -0
  75. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/mcp/client.py +0 -0
  76. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/mcp/server.py +0 -0
  77. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/mcp/stdio_transport.py +0 -0
  78. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/mcp/wrapper.py +0 -0
  79. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/models/__init__.py +0 -0
  80. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/models/anthropic.py +0 -0
  81. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/models/fake.py +0 -0
  82. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/models/openai.py +0 -0
  83. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/observability/__init__.py +0 -0
  84. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/observability/sinks.py +0 -0
  85. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/permissions/__init__.py +0 -0
  86. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/permissions/model.py +0 -0
  87. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/__init__.py +0 -0
  88. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/conditions.py +0 -0
  89. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/engine.py +0 -0
  90. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/rule.py +0 -0
  91. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/test_runner.py +0 -0
  92. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/policies/validator.py +0 -0
  93. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reasoning/__init__.py +0 -0
  94. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reasoning/lats.py +0 -0
  95. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reasoning/llm_plus_p.py +0 -0
  96. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reasoning/react.py +0 -0
  97. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/__init__.py +0 -0
  98. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/audit_report.py +0 -0
  99. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/cost.py +0 -0
  100. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/cost_report.py +0 -0
  101. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/pass_at_k.py +0 -0
  102. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/replay.py +0 -0
  103. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/retry.py +0 -0
  104. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/reliability/timeout.py +0 -0
  105. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/retrieval/__init__.py +0 -0
  106. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/retrieval/adaptive.py +0 -0
  107. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/retrieval/crag.py +0 -0
  108. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/retrieval/memory_store.py +0 -0
  109. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/__init__.py +0 -0
  110. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/agent_tool.py +0 -0
  111. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/base.py +0 -0
  112. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/calculator.py +0 -0
  113. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/path_planner.py +0 -0
  114. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/registry.py +0 -0
  115. {petfishframework-0.3.2 → petfishframework-0.3.3}/src/petfishframework/tools/word_sorter.py +0 -0
  116. {petfishframework-0.3.2 → petfishframework-0.3.3}/tasks/backlog.md +0 -0
  117. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/integration/__init__.py +0 -0
  118. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/integration/test_anthropic_integration.py +0 -0
  119. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/integration/test_openai_integration.py +0 -0
  120. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/policies/enterprise-expense.tests.yaml +0 -0
  121. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_agent_tool.py +0 -0
  122. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_anthropic_adapter.py +0 -0
  123. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_api_agent_lifecycle.py +0 -0
  124. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_api_edge_cases.py +0 -0
  125. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_api_integration.py +0 -0
  126. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_api_public_surface.py +0 -0
  127. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_api_type_safety.py +0 -0
  128. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_async.py +0 -0
  129. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_audit_report_v2.py +0 -0
  130. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_conversation.py +0 -0
  131. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_credential_broker.py +0 -0
  132. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_credential_integration.py +0 -0
  133. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_degrade.py +0 -0
  134. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_degrade_failclosed.py +0 -0
  135. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_enterprise_demo.py +0 -0
  136. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_m2_m3_m4.py +0 -0
  137. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_mcp.py +0 -0
  138. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_openai_adapter.py +0 -0
  139. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_pass_at_k.py +0 -0
  140. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_permission_semantics.py +0 -0
  141. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_quickstart_smoke.py +0 -0
  142. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_replay.py +0 -0
  143. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_retrieval.py +0 -0
  144. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_retry.py +0 -0
  145. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_skeleton.py +0 -0
  146. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_stdio_transport.py +0 -0
  147. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_streaming.py +0 -0
  148. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_structured.py +0 -0
  149. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_tool_registry.py +0 -0
  150. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v016_semantics.py +0 -0
  151. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v018.py +0 -0
  152. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v019.py +0 -0
  153. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v2_interface_compatibility.py +0 -0
  154. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v2_lats.py +0 -0
  155. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_v2_llm_plus_p.py +0 -0
  156. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_yaml_policy.py +0 -0
  157. {petfishframework-0.3.2 → petfishframework-0.3.3}/tests/test_yaml_policy_suite.py +0 -0
@@ -2,6 +2,39 @@
2
2
 
3
3
  All notable changes to petfishFramework will be documented in this file.
4
4
 
5
+ ## [0.3.2] — 2026-07-08
6
+
7
+ ### YAML Policy DSL Expansion
8
+ - 13 new condition matchers (total 20): `amount_eq/gte/lte`, generic `field_eq` prefix, `role_count_gte`, `clearance_eq`, `tenant_id_eq`, `classification_eq`, `tags_contains`, `risk_level_eq`, `capabilities_contains`, `requires_credentials`, `session_risk_gt`, `prompt_risk_gt`
9
+ - AND/OR/NOT combinators (`any`/`all`/`not`, nestable in `when:` blocks)
10
+ - Policy schema validation (`policies/validator.py`): validates version, name, rules, effect values
11
+
12
+ ### CredentialBroker Phase 2
13
+ - `BaseTool.credential_name` field — decouple tool name from credential name
14
+ - `ScopedToken.max_uses` + use counting — one-time tokens (`max_uses=1`)
15
+ - `ScopedToken.uses_remaining` property + `use()` method
16
+ - `revoke_all_for_tool(tool_name)` — revoke tokens for a specific tool
17
+ - `revoke_all()` — revoke everything (session-end cleanup)
18
+ - `active_token_count` property + `list_active_tokens()`
19
+ - Environment uses `credential_name` mapping when injecting tokens
20
+ - Session-end credential cleanup
21
+
22
+ ## [0.3.1] — 2026-07-08
23
+
24
+ ### Credential Event Safety (P0 security fix)
25
+ - Event log no longer stores `ScopedToken` objects — replaced with `{"credential_ref": ..., "tool_name": ..., "redacted": True}`
26
+ - Untrusted event sinks cannot access `.get_secret()` via event introspection
27
+
28
+ ### Agent/Session credential_broker API
29
+ - `Agent(credential_broker=broker)` — first-class parameter
30
+ - `Session` passes broker to `RuntimeEnvironment`
31
+ - `RuntimeEnvironment` field renamed `_credential_broker` → `credential_broker`
32
+
33
+ ### Documentation Sync
34
+ - `docs/api.md` version updated
35
+ - README roadmap: v0.3.x (current)
36
+ - README: added YAML Policy Engine + CredentialBroker usage examples
37
+
5
38
  ## [0.3.0] — 2026-07-08
6
39
 
7
40
  ### v0.3.0 Policy Engine + Credential Broker Integration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: petfishframework
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: A lightweight runtime framework for reliable, auditable, budget-aware, and permission-aware AI agents.
5
5
  Project-URL: Homepage, https://github.com/kylecui/petfishFramework
6
6
  Project-URL: Documentation, https://github.com/kylecui/petfishFramework/tree/master/docs
@@ -34,7 +34,7 @@ Description-Content-Type: text/markdown
34
34
 
35
35
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
36
36
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/kylecui/petfishFramework/blob/master/LICENSE)
37
- [![Tests: 284](https://img.shields.io/badge/tests-259-brightgreen.svg)](https://github.com/kylecui/petfishFramework/tree/master/tests/)
37
+ [![Tests: 284](https://img.shields.io/badge/tests-284-brightgreen.svg)](https://github.com/kylecui/petfishFramework/tree/master/tests/)
38
38
 
39
39
  **Status: Alpha** — API may change. Core runtime works; see [Roadmap](#roadmap).
40
40
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/kylecui/petfishFramework/blob/master/LICENSE)
7
- [![Tests: 284](https://img.shields.io/badge/tests-259-brightgreen.svg)](https://github.com/kylecui/petfishFramework/tree/master/tests/)
7
+ [![Tests: 284](https://img.shields.io/badge/tests-284-brightgreen.svg)](https://github.com/kylecui/petfishFramework/tree/master/tests/)
8
8
 
9
9
  **Status: Alpha** — API may change. Core runtime works; see [Roadmap](#roadmap).
10
10
 
@@ -1294,3 +1294,154 @@ decision.policy_name # "enterprise-expense-policy"
1294
1294
  ```
1295
1295
 
1296
1296
  This lets audit logs trace each decision back to the policy file version that produced it.
1297
+
1298
+ ### AND/OR/NOT Combinators (v0.3.2)
1299
+
1300
+ `when:` blocks support `any`/`all`/`not` combinators:
1301
+
1302
+ ```yaml
1303
+ when:
1304
+ any:
1305
+ - action.tool_name: approve_payment
1306
+ - action.tool_name: transfer_funds
1307
+
1308
+ when:
1309
+ not:
1310
+ subject.role_in: [admin]
1311
+
1312
+ when:
1313
+ not:
1314
+ any:
1315
+ - subject.role_in: [admin]
1316
+ - subject.clearance_eq: secret
1317
+ ```
1318
+
1319
+ ### Full matcher list (v0.3.2)
1320
+
1321
+ | Key | Description | Example |
1322
+ |---|---|---|
1323
+ | `action.tool_name` | Exact tool name match | `approve_payment` |
1324
+ | `subject.role_in` | Any role in list matches | `[finance, admin]` |
1325
+ | `subject.role_not_in` | No role in list matches | `[intern]` |
1326
+ | `subject.role_count_gte` | Subject has ≥ N roles | `2` |
1327
+ | `subject.clearance_eq` | Clearance level match | `confidential` |
1328
+ | `subject.tenant_id_eq` | Tenant ID match | `acme-corp` |
1329
+ | `action.args.amount_gt` | `args["amount"] > value` | `5000` |
1330
+ | `action.args.amount_lt` | `args["amount"] < value` | `100` |
1331
+ | `action.args.amount_eq` | `args["amount"] == value` | `500` |
1332
+ | `action.args.amount_gte` | `args["amount"] >= value` | `1000` |
1333
+ | `action.args.amount_lte` | `args["amount"] <= value` | `200` |
1334
+ | `action.args.<field>_eq` | Generic field equality (prefix matcher) | `recipient_eq: alice@` |
1335
+ | `resource.classification_eq` | Resource classification match | `internal` |
1336
+ | `resource.tags_contains` | Resource has any of the listed tags | `[pii, sensitive]` |
1337
+ | `tool.side_effect` | Match tool metadata | `true` |
1338
+ | `tool.external_egress` | Match tool metadata | `true` |
1339
+ | `tool.requires_credentials` | Match tool metadata | `true` |
1340
+ | `tool.risk_level_eq` | Match risk level | `high` |
1341
+ | `tool.capabilities_contains` | Tool has any of listed capabilities | `[network, fs:write]` |
1342
+ | `context.session_risk_gt` | `context.session_risk > value` | `0.5` |
1343
+ | `context.prompt_risk_gt` | `context.prompt_risk > value` | `0.7` |
1344
+
1345
+ Unknown condition keys are fail-closed (return `False`).
1346
+
1347
+ ### Policy schema validation (v0.3.2)
1348
+
1349
+ ```python
1350
+ from petfishframework.policies.validator import validate_policy, validate_policy_file
1351
+
1352
+ errors = validate_policy_file("enterprise-expense.yaml")
1353
+ if errors:
1354
+ for err in errors:
1355
+ print(f" - {err}")
1356
+ ```
1357
+
1358
+ Checks: version exists, name exists, rules is a list, each rule has name + valid effect, priority is integer.
1359
+
1360
+ ---
1361
+
1362
+ ## 16. Credential Broker
1363
+
1364
+ ### CredentialBroker
1365
+
1366
+ ```python
1367
+ from petfishframework.credentials import CredentialBroker
1368
+
1369
+ broker = CredentialBroker(default_ttl_s=3600)
1370
+ broker.register_credential("github_app", os.environ["GITHUB_TOKEN"])
1371
+ broker.register_credential("db_connection", "postgres://...")
1372
+ ```
1373
+
1374
+ | Method | Description |
1375
+ |---|---|
1376
+ | `register_credential(name, secret)` | Register a real credential |
1377
+ | `issue_token(name, tool_name, ttl_s=None, max_uses=0)` | Issue a scoped, time-limited token |
1378
+ | `validate_token(token_id)` | Check if token is valid (not expired, not revoked) |
1379
+ | `revoke_token(token_id)` | Revoke a single token |
1380
+ | `revoke_all_for_tool(tool_name)` | Revoke all tokens for a specific tool (v0.3.2) |
1381
+ | `revoke_all()` | Revoke all active tokens (session-end cleanup) (v0.3.2) |
1382
+ | `cleanup_expired()` | Remove expired tokens, returns count removed |
1383
+ | `active_token_count` | Property: number of active tokens (v0.3.2) |
1384
+ | `list_active_tokens()` | Return list of active token_ids (v0.3.2) |
1385
+
1386
+ ### ScopedToken
1387
+
1388
+ ```python
1389
+ token = broker.issue_token("github_app", tool_name="github_tool", max_uses=1)
1390
+ token.token_id # unique ID
1391
+ token.tool_name # "github_tool"
1392
+ token.is_valid() # True (not expired, uses remaining)
1393
+ token.get_secret() # returns the actual secret (consumes one use if max_uses set)
1394
+ token.uses_remaining # remaining uses (v0.3.2)
1395
+ ```
1396
+
1397
+ `__repr__` and `__str__` never expose the secret:
1398
+ ```python
1399
+ repr(token) # "ScopedToken(token_id='abc...', tool_name='github_tool', ...)"
1400
+ str(token) # "ScopedToken(abc..., tool=github_tool, valid=True)"
1401
+ ```
1402
+
1403
+ ### Agent Integration
1404
+
1405
+ ```python
1406
+ agent = Agent(
1407
+ model=model,
1408
+ reasoning=ReAct(),
1409
+ tools=tools,
1410
+ credential_broker=broker,
1411
+ )
1412
+ # Tools with requires_credentials=True receive a ScopedToken in args["_credential_token"]
1413
+ ```
1414
+
1415
+ ### Tool credential_name (v0.3.2)
1416
+
1417
+ ```python
1418
+ @dataclass
1419
+ class GitHubTool(BaseTool):
1420
+ name: str = "github_create_issue"
1421
+ requires_credentials: bool = True
1422
+ credential_name: str = "github_app" # maps to broker credential name
1423
+ ```
1424
+
1425
+ ### Event Log Safety
1426
+
1427
+ ScopedToken objects are **never** stored in event data. The Environment replaces them with:
1428
+
1429
+ ```python
1430
+ {"credential_ref": "token_id", "tool_name": "github_tool", "redacted": True}
1431
+ ```
1432
+
1433
+ ### One-time Tokens (v0.3.2)
1434
+
1435
+ ```python
1436
+ token = broker.issue_token("secret_key", tool_name="signing_tool", max_uses=1)
1437
+ token.get_secret() # works, uses_remaining becomes 0
1438
+ token.get_secret() # raises ValueError("max uses exceeded")
1439
+ ```
1440
+
1441
+ ### Session-End Cleanup
1442
+
1443
+ ```python
1444
+ # In Session._finalize_run():
1445
+ if session.credential_broker:
1446
+ session.credential_broker.cleanup_expired()
1447
+ ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "petfishframework"
7
- version = "0.3.2"
7
+ version = "0.3.3"
8
8
  description = "A lightweight runtime framework for reliable, auditable, budget-aware, and permission-aware AI agents."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -15,7 +15,7 @@ from .reasoning import LATS, LLMPlusP, ReAct
15
15
  from .reliability.replay import ReplayMode
16
16
  from .tools.base import BaseTool
17
17
 
18
- __version__ = "0.3.2"
18
+ __version__ = "0.3.3"
19
19
 
20
20
  __all__ = [
21
21
  "Agent",
@@ -427,7 +427,7 @@ name = "exceptiongroup"
427
427
  version = "1.3.1"
428
428
  source = { registry = "https://pypi.org/simple" }
429
429
  dependencies = [
430
- { name = "typing-extensions" },
430
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
431
431
  ]
432
432
  sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
433
433
  wheels = [
@@ -506,7 +506,7 @@ name = "importlib-metadata"
506
506
  version = "9.0.0"
507
507
  source = { registry = "https://pypi.org/simple" }
508
508
  dependencies = [
509
- { name = "zipp" },
509
+ { name = "zipp", marker = "python_full_version < '3.14'" },
510
510
  ]
511
511
  sdist = { url = "https://files.pythonhosted.org/packages/a9/01/15bb152d77b21318514a96f43af312635eb2500c96b55398d020c93d86ea/importlib_metadata-9.0.0.tar.gz", hash = "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc", size = 56405, upload-time = "2026-03-20T06:42:56.999Z" }
512
512
  wheels = [
@@ -995,7 +995,7 @@ wheels = [
995
995
 
996
996
  [[package]]
997
997
  name = "petfishframework"
998
- version = "0.3.2"
998
+ version = "0.3.3"
999
999
  source = { editable = "." }
1000
1000
  dependencies = [
1001
1001
  { name = "pyyaml" },
@@ -1742,8 +1742,8 @@ name = "secretstorage"
1742
1742
  version = "3.5.0"
1743
1743
  source = { registry = "https://pypi.org/simple" }
1744
1744
  dependencies = [
1745
- { name = "cryptography" },
1746
- { name = "jeepney" },
1745
+ { name = "cryptography", marker = "python_full_version >= '3.15' or sys_platform != 'win32'" },
1746
+ { name = "jeepney", marker = "python_full_version >= '3.15' or sys_platform != 'win32'" },
1747
1747
  ]
1748
1748
  sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" }
1749
1749
  wheels = [