agentsecure 0.1.2__tar.gz → 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. {agentsecure-0.1.2/agentsecure.egg-info → agentsecure-0.1.4}/PKG-INFO +66 -5
  2. {agentsecure-0.1.2 → agentsecure-0.1.4}/README.md +64 -2
  3. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/__init__.py +1 -2
  4. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/main.py +76 -0
  5. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/policy.py +8 -1
  6. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/project.py +9 -0
  7. agentsecure-0.1.4/agentsecure/cli/proxy.py +283 -0
  8. agentsecure-0.1.4/agentsecure/cli/receipts.py +207 -0
  9. agentsecure-0.1.4/agentsecure/config/__init__.py +1 -0
  10. agentsecure-0.1.4/agentsecure/config/default_agentsecure.json +49 -0
  11. agentsecure-0.1.4/agentsecure/core/agentsecure_md.py +188 -0
  12. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/config.py +113 -4
  13. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/container.py +1 -0
  14. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/key_service.py +2 -19
  15. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/models.py +18 -0
  16. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/product.py +23 -35
  17. agentsecure-0.1.4/agentsecure/core/provider_proxy.py +23 -0
  18. agentsecure-0.1.4/agentsecure/gateway/proxy.py +587 -0
  19. {agentsecure-0.1.2 → agentsecure-0.1.4/agentsecure.egg-info}/PKG-INFO +66 -5
  20. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure.egg-info/SOURCES.txt +11 -1
  21. {agentsecure-0.1.2 → agentsecure-0.1.4}/setup.cfg +7 -4
  22. agentsecure-0.1.4/tests/test_agentsecure_md.py +66 -0
  23. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_cli.py +30 -0
  24. agentsecure-0.1.4/tests/test_cli_proxy.py +116 -0
  25. agentsecure-0.1.4/tests/test_config_validation.py +81 -0
  26. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_product.py +8 -0
  27. agentsecure-0.1.4/tests/test_provider_proxy.py +277 -0
  28. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_secret_scan.py +11 -0
  29. agentsecure-0.1.4/tests/test_version.py +24 -0
  30. agentsecure-0.1.2/agentsecure/gateway/proxy.py +0 -272
  31. agentsecure-0.1.2/agentsecure.egg-info/requires.txt +0 -3
  32. {agentsecure-0.1.2 → agentsecure-0.1.4}/LICENSE +0 -0
  33. {agentsecure-0.1.2 → agentsecure-0.1.4}/NOTICE +0 -0
  34. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/__main__.py +0 -0
  35. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/api/__init__.py +0 -0
  36. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/api/server.py +0 -0
  37. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/api/services.py +0 -0
  38. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/__init__.py +0 -0
  39. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/common.py +0 -0
  40. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/demo.py +0 -0
  41. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/secrets.py +0 -0
  42. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cli/settings.py +0 -0
  43. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/client/__init__.py +0 -0
  44. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/client/wrappers.py +0 -0
  45. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/cloud.py +0 -0
  46. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/__init__.py +0 -0
  47. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/capabilities.py +0 -0
  48. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/command_metadata.py +0 -0
  49. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/config_profiles.py +0 -0
  50. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/policy_mutation.py +0 -0
  51. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/policy_ports.py +0 -0
  52. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/policy_response.py +0 -0
  53. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/policy_validation.py +0 -0
  54. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/core/time.py +0 -0
  55. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/crypto/__init__.py +0 -0
  56. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/crypto/cipher.py +0 -0
  57. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/crypto/key_provider.py +0 -0
  58. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/daemon/__init__.py +0 -0
  59. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/daemon/commands.py +0 -0
  60. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/daemon/policies.py +0 -0
  61. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/daemon/sessions.py +0 -0
  62. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/daemon/supervisor.py +0 -0
  63. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/__init__.py +0 -0
  64. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/dotenv_scanner.py +0 -0
  65. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/env_scanner.py +0 -0
  66. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/patterns.py +0 -0
  67. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/scanner.py +0 -0
  68. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/discovery/suggestions.py +0 -0
  69. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/gateway/__init__.py +0 -0
  70. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/guard/__init__.py +0 -0
  71. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/guard/command.py +0 -0
  72. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/guard/network.py +0 -0
  73. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/guard/sanitizer.py +0 -0
  74. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/guard/wrappers.py +0 -0
  75. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/__init__.py +0 -0
  76. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/audit.py +0 -0
  77. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/encrypted_secret_store.py +0 -0
  78. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/grant_store.py +0 -0
  79. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/local_secret_store.py +0 -0
  80. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/policy.py +0 -0
  81. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/secret_store_factory.py +0 -0
  82. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/implementations/secrets.py +0 -0
  83. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/__init__.py +0 -0
  84. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/audit.py +0 -0
  85. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/grants.py +0 -0
  86. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/key_store.py +0 -0
  87. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/policy.py +0 -0
  88. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/interfaces/secrets.py +0 -0
  89. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/__init__.py +0 -0
  90. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/apply.py +0 -0
  91. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/diff.py +0 -0
  92. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/materializer.py +0 -0
  93. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/rewriter.py +0 -0
  94. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure/workspace/strategies.py +0 -0
  95. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure.egg-info/dependency_links.txt +0 -0
  96. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure.egg-info/entry_points.txt +0 -0
  97. {agentsecure-0.1.2 → agentsecure-0.1.4}/agentsecure.egg-info/top_level.txt +0 -0
  98. {agentsecure-0.1.2 → agentsecure-0.1.4}/pyproject.toml +0 -0
  99. {agentsecure-0.1.2 → agentsecure-0.1.4}/setup.py +0 -0
  100. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_audit.py +0 -0
  101. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_cli_demo.py +0 -0
  102. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_cli_policy.py +0 -0
  103. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_diff.py +0 -0
  104. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_discovery.py +0 -0
  105. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_encrypted_secret_store.py +0 -0
  106. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_env_policy.py +0 -0
  107. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_env_policy_contract.py +0 -0
  108. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_gateway_credentials.py +0 -0
  109. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_guard.py +0 -0
  110. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_guard_network.py +0 -0
  111. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_key_service.py +0 -0
  112. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_policy.py +0 -0
  113. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_policy_mutation.py +0 -0
  114. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_secrets.py +0 -0
  115. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_workspace.py +0 -0
  116. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_workspace_apply.py +0 -0
  117. {agentsecure-0.1.2 → agentsecure-0.1.4}/tests/test_wrappers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentsecure
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Local-first security runtime for AI coding agents
5
5
  Home-page: https://github.com/ShellFrameAI/agentsecure-community
6
6
  Author: ShellFrame AI
@@ -18,11 +18,10 @@ Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Topic :: Security
19
19
  Classifier: Environment :: Console
20
20
  Classifier: Operating System :: OS Independent
21
- Requires-Python: >=3.6
21
+ Requires-Python: >=3.8
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  License-File: NOTICE
25
- Requires-Dist: dataclasses; python_version < "3.7"
26
25
  Dynamic: license-file
27
26
 
28
27
  # AgentSecure Community
@@ -77,12 +76,18 @@ Why:
77
76
 
78
77
  ## Quickstart In A Project
79
78
 
80
- Create a local config:
79
+ Create a local config and repo guidance file:
81
80
 
82
81
  ```bash
83
82
  agentsecure init
84
83
  ```
85
84
 
85
+ This creates `agentsecure.json`, local private state under `.agentsecure/`, and `AGENTSECURE.md`. Review the Markdown file before running agents:
86
+
87
+ ```bash
88
+ agentsecure policy validate
89
+ ```
90
+
86
91
  Create a fake `.env` for testing:
87
92
 
88
93
  ```bash
@@ -108,6 +113,52 @@ By default, `--protect-all` virtualizes discovered secrets. The command output s
108
113
 
109
114
  Denied values are removed only when policy sets `mode: "deny"` for that environment variable. The built-in `agentsecure demo` includes that policy for `DATABASE_URL_PROD` so you can see both behaviors: virtualize and deny.
110
115
 
116
+ ## Provider Proxy Preview
117
+
118
+ Virtual secrets keep real values out of the agent context. Provider proxy mode goes one step further for tools and SDKs that honor `OPENAI_BASE_URL`: the agent gets a virtual key and a local base URL, while AgentSecure injects the real key only when forwarding to the configured provider.
119
+
120
+ Configure OpenAI from `agentsecure.json.provider_catalog.openai`:
121
+
122
+ ```bash
123
+ agentsecure proxy setup openai
124
+ ```
125
+
126
+ Then run the agent:
127
+
128
+ ```bash
129
+ agentsecure run --protect-all -- codex
130
+ ```
131
+
132
+ The agent-visible environment includes:
133
+
134
+ ```text
135
+ OPENAI_API_KEY=virt_openai_...
136
+ OPENAI_BASE_URL=http://127.0.0.1:8765/providers/openai/v1
137
+ ```
138
+
139
+ AgentSecure forwards provider calls to the configured upstream:
140
+
141
+ ```json
142
+ {
143
+ "provider_proxy": {
144
+ "providers": {
145
+ "openai": {
146
+ "upstream": "https://api.openai.com",
147
+ "local_path": "/providers/openai"
148
+ }
149
+ }
150
+ }
151
+ }
152
+ ```
153
+
154
+ Run the proxy proof:
155
+
156
+ ```bash
157
+ agentsecure receipts --proxy
158
+ ```
159
+
160
+ Provider proxy mode is local-only. It is not a system-wide proxy, not TLS MITM, and not browser-wide interception. Tools must use the provider base URL environment variable.
161
+
111
162
  ## What It Demonstrates
112
163
 
113
164
  - Discover likely secrets in `.env` files and environment variables.
@@ -121,7 +172,7 @@ Command-guard mode is a usability guard, not a hard sandbox. A determined proces
121
172
 
122
173
  ## Example Policy
123
174
 
124
- See [examples/agentsecure.community.json](examples/agentsecure.community.json) and [examples/.env.example](examples/.env.example).
175
+ See [examples/agentsecure.community.json](examples/agentsecure.community.json), [examples/AGENTSECURE.md](examples/AGENTSECURE.md), and [examples/.env.example](examples/.env.example).
125
176
 
126
177
  Minimal policy shape:
127
178
 
@@ -150,6 +201,7 @@ Minimal policy shape:
150
201
 
151
202
  ```bash
152
203
  agentsecure init
204
+ agentsecure policy validate
153
205
  agentsecure status
154
206
  agentsecure doctor
155
207
  agentsecure discover
@@ -157,6 +209,9 @@ agentsecure suggest
157
209
  agentsecure env
158
210
  agentsecure keys list
159
211
  agentsecure network list
212
+ agentsecure proxy setup openai
213
+ agentsecure proxy doctor
214
+ agentsecure receipts --proxy
160
215
  ```
161
216
 
162
217
  Run an agent or command through local command guard:
@@ -221,6 +276,12 @@ python3 scripts/secret_scan.py .
221
276
 
222
277
  CI runs tests across supported Python versions and runs the local secret scan.
223
278
 
279
+ ## AGENTSECURE.md
280
+
281
+ `AGENTSECURE.md` is a small repo-level policy guidance file for humans and AI coding agents. In the community release, AgentSecure creates it and validates that it does not contain raw secrets or unsupported raw-secret passthrough modes.
282
+
283
+ Supported community secret modes in the Markdown guidance are `virtualize` and `deny`. Do not use `allow` or `allow_real` for secrets. The Markdown file is guidance plus local validation; it is not a full sandbox by itself.
284
+
224
285
  ## Public Release Boundary
225
286
 
226
287
  This community release does not include hosted backend integration, enterprise policy sync, billing/licensing, production secrets, internal endpoints, or sensitive commercial heuristics. See [OPEN_SOURCE_PLAN.md](OPEN_SOURCE_PLAN.md) and [OPEN_SOURCE_READINESS_REPORT.md](OPEN_SOURCE_READINESS_REPORT.md) for the public/private boundary.
@@ -50,12 +50,18 @@ Why:
50
50
 
51
51
  ## Quickstart In A Project
52
52
 
53
- Create a local config:
53
+ Create a local config and repo guidance file:
54
54
 
55
55
  ```bash
56
56
  agentsecure init
57
57
  ```
58
58
 
59
+ This creates `agentsecure.json`, local private state under `.agentsecure/`, and `AGENTSECURE.md`. Review the Markdown file before running agents:
60
+
61
+ ```bash
62
+ agentsecure policy validate
63
+ ```
64
+
59
65
  Create a fake `.env` for testing:
60
66
 
61
67
  ```bash
@@ -81,6 +87,52 @@ By default, `--protect-all` virtualizes discovered secrets. The command output s
81
87
 
82
88
  Denied values are removed only when policy sets `mode: "deny"` for that environment variable. The built-in `agentsecure demo` includes that policy for `DATABASE_URL_PROD` so you can see both behaviors: virtualize and deny.
83
89
 
90
+ ## Provider Proxy Preview
91
+
92
+ Virtual secrets keep real values out of the agent context. Provider proxy mode goes one step further for tools and SDKs that honor `OPENAI_BASE_URL`: the agent gets a virtual key and a local base URL, while AgentSecure injects the real key only when forwarding to the configured provider.
93
+
94
+ Configure OpenAI from `agentsecure.json.provider_catalog.openai`:
95
+
96
+ ```bash
97
+ agentsecure proxy setup openai
98
+ ```
99
+
100
+ Then run the agent:
101
+
102
+ ```bash
103
+ agentsecure run --protect-all -- codex
104
+ ```
105
+
106
+ The agent-visible environment includes:
107
+
108
+ ```text
109
+ OPENAI_API_KEY=virt_openai_...
110
+ OPENAI_BASE_URL=http://127.0.0.1:8765/providers/openai/v1
111
+ ```
112
+
113
+ AgentSecure forwards provider calls to the configured upstream:
114
+
115
+ ```json
116
+ {
117
+ "provider_proxy": {
118
+ "providers": {
119
+ "openai": {
120
+ "upstream": "https://api.openai.com",
121
+ "local_path": "/providers/openai"
122
+ }
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ Run the proxy proof:
129
+
130
+ ```bash
131
+ agentsecure receipts --proxy
132
+ ```
133
+
134
+ Provider proxy mode is local-only. It is not a system-wide proxy, not TLS MITM, and not browser-wide interception. Tools must use the provider base URL environment variable.
135
+
84
136
  ## What It Demonstrates
85
137
 
86
138
  - Discover likely secrets in `.env` files and environment variables.
@@ -94,7 +146,7 @@ Command-guard mode is a usability guard, not a hard sandbox. A determined proces
94
146
 
95
147
  ## Example Policy
96
148
 
97
- See [examples/agentsecure.community.json](examples/agentsecure.community.json) and [examples/.env.example](examples/.env.example).
149
+ See [examples/agentsecure.community.json](examples/agentsecure.community.json), [examples/AGENTSECURE.md](examples/AGENTSECURE.md), and [examples/.env.example](examples/.env.example).
98
150
 
99
151
  Minimal policy shape:
100
152
 
@@ -123,6 +175,7 @@ Minimal policy shape:
123
175
 
124
176
  ```bash
125
177
  agentsecure init
178
+ agentsecure policy validate
126
179
  agentsecure status
127
180
  agentsecure doctor
128
181
  agentsecure discover
@@ -130,6 +183,9 @@ agentsecure suggest
130
183
  agentsecure env
131
184
  agentsecure keys list
132
185
  agentsecure network list
186
+ agentsecure proxy setup openai
187
+ agentsecure proxy doctor
188
+ agentsecure receipts --proxy
133
189
  ```
134
190
 
135
191
  Run an agent or command through local command guard:
@@ -194,6 +250,12 @@ python3 scripts/secret_scan.py .
194
250
 
195
251
  CI runs tests across supported Python versions and runs the local secret scan.
196
252
 
253
+ ## AGENTSECURE.md
254
+
255
+ `AGENTSECURE.md` is a small repo-level policy guidance file for humans and AI coding agents. In the community release, AgentSecure creates it and validates that it does not contain raw secrets or unsupported raw-secret passthrough modes.
256
+
257
+ Supported community secret modes in the Markdown guidance are `virtualize` and `deny`. Do not use `allow` or `allow_real` for secrets. The Markdown file is guidance plus local validation; it is not a full sandbox by itself.
258
+
197
259
  ## Public Release Boundary
198
260
 
199
261
  This community release does not include hosted backend integration, enterprise policy sync, billing/licensing, production secrets, internal endpoints, or sensitive commercial heuristics. See [OPEN_SOURCE_PLAN.md](OPEN_SOURCE_PLAN.md) and [OPEN_SOURCE_READINESS_REPORT.md](OPEN_SOURCE_READINESS_REPORT.md) for the public/private boundary.
@@ -1,4 +1,3 @@
1
1
  """AgentSecure local-first security runtime."""
2
2
 
3
- __version__ = "0.1.0"
4
-
3
+ __version__ = "0.1.4"
@@ -14,6 +14,7 @@ import time
14
14
  from typing import Any, Dict, List, Optional
15
15
  from urllib.request import Request, urlopen
16
16
 
17
+ from agentsecure import __version__
17
18
  from agentsecure.cloud import CloudError, CloudRuntimeService
18
19
  from agentsecure.api.server import LocalApiServer
19
20
  from agentsecure.api.services import ApiServices
@@ -32,6 +33,8 @@ from agentsecure.cli.project import (
32
33
  show_status,
33
34
  uninstall_agentsecure,
34
35
  )
36
+ from agentsecure.cli.proxy import add_proxy_subparser, handle_proxy
37
+ from agentsecure.cli.receipts import handle_receipts
35
38
  from agentsecure.cli.secrets import (
36
39
  discover_secrets,
37
40
  handle_keys,
@@ -47,6 +50,7 @@ from agentsecure.cli.settings import (
47
50
  handle_setup,
48
51
  )
49
52
  from agentsecure.client.wrappers import AgentWrapperInstaller, SUPPORTED_AGENTS
53
+ from agentsecure.core.agentsecure_md import AGENTSECURE_MD, agentsecure_md_status
50
54
  from agentsecure.core.command_metadata import safe_command_metadata
51
55
  from agentsecure.core.config import ConfigError, JsonConfigLoader, JsonConfigWriter
52
56
  from agentsecure.core.config_profiles import (
@@ -57,6 +61,7 @@ from agentsecure.core.capabilities import broker_url_for_env
57
61
  from agentsecure.core.container import Container
58
62
  from agentsecure.core.key_service import KeyManagementError, KeyManagementService
59
63
  from agentsecure.core.models import AgentSecureConfig, DiscoveredSecret, ProcessRequest, SecretReplacement
64
+ from agentsecure.core.provider_proxy import configured_provider_base_url, provider_base_local_path
60
65
  from agentsecure.core.product import ProductService
61
66
  from agentsecure.core.time import DurationError
62
67
  from agentsecure.daemon.commands import CommandExecutor, CommandPoller
@@ -116,6 +121,10 @@ def main(argv: Optional[List[str]] = None) -> int:
116
121
  return handle_files(args)
117
122
  if args.command == "network":
118
123
  return handle_network(args)
124
+ if args.command == "proxy":
125
+ return handle_proxy(args)
126
+ if args.command == "receipts":
127
+ return handle_receipts(args)
119
128
  if args.command == "policy":
120
129
  return handle_policy(args)
121
130
  if args.command == "setup":
@@ -138,6 +147,7 @@ def main(argv: Optional[List[str]] = None) -> int:
138
147
 
139
148
  def build_parser() -> argparse.ArgumentParser:
140
149
  parser = argparse.ArgumentParser(prog="agentsecure")
150
+ parser.add_argument("--version", action="version", version="agentsecure %s" % __version__)
141
151
  parser.add_argument(
142
152
  "--config",
143
153
  default="agentsecure.json",
@@ -225,6 +235,9 @@ def build_parser() -> argparse.ArgumentParser:
225
235
  network_remove_parser = network_subparsers.add_parser("remove", help="Remove domains from credential allowlist")
226
236
  network_remove_parser.add_argument("domains", nargs="+")
227
237
 
238
+ add_proxy_subparser(subparsers)
239
+ receipts_parser = subparsers.add_parser("receipts", help="Run replayable AgentSecure proof receipts")
240
+ receipts_parser.add_argument("--proxy", action="store_true", help="Run provider proxy receipts")
228
241
  add_policy_subparser(subparsers)
229
242
 
230
243
  setup_parser = subparsers.add_parser("setup", help="Install local protected agent command wrappers")
@@ -254,6 +267,10 @@ def build_parser() -> argparse.ArgumentParser:
254
267
 
255
268
 
256
269
  def run_agent(args: argparse.Namespace) -> int:
270
+ policy_doc = agentsecure_md_status(AGENTSECURE_MD)
271
+ if policy_doc.get("exists"):
272
+ state = "valid" if policy_doc.get("ok") else "needs review"
273
+ print("AgentSecure policy guidance: %s (%s)" % (AGENTSECURE_MD, state), flush=True)
257
274
  cloud = CloudRuntimeService() if _cloud_features_enabled() else None
258
275
  if cloud:
259
276
  _apply_cloud_runtime_defaults(args, cloud)
@@ -266,6 +283,7 @@ def run_agent(args: argparse.Namespace) -> int:
266
283
  if isinstance(replacements, int):
267
284
  return replacements
268
285
  container = Container.from_config_path(args.config)
286
+ replacements.extend(_configured_secret_replacements(container, replacements))
269
287
  run_cwd = os.getcwd()
270
288
  workspace_session = None
271
289
  materializer = WorkspaceMaterializer(_workspace_base_for_runtime(run_cwd, args.runtime))
@@ -346,6 +364,7 @@ def run_agent(args: argparse.Namespace) -> int:
346
364
  env = os.environ.copy()
347
365
  for env_name in container.config.env_policy.rules:
348
366
  env.pop(env_name, None)
367
+ _strip_backing_secret_environment(env, container)
349
368
  env.update(container.virtual_env_provider.build_environment())
350
369
  if args.runtime == "command-guard":
351
370
  CommandGuardWrapperInstaller(args.config).install(env)
@@ -354,6 +373,7 @@ def run_agent(args: argparse.Namespace) -> int:
354
373
  env["AGENTSECURE_SESSION_ID"] = session_id
355
374
  proxy_url = _proxy_url(gateway_host, gateway_port, session_id)
356
375
  _apply_proxy_environment(env, proxy_url)
376
+ _apply_provider_proxy_environment(env, container, gateway_host, gateway_port)
357
377
  command_metadata = safe_command_metadata(argv)
358
378
  container.audit_logger.record(
359
379
  "agent_started",
@@ -625,6 +645,7 @@ def _start_local_gateway_thread(container: Container, host: str, port: int):
625
645
  container.token_resolver,
626
646
  container.audit_logger,
627
647
  container.bindings,
648
+ container.config.provider_proxy,
628
649
  )
629
650
 
630
651
  def run_gateway_thread() -> None:
@@ -809,6 +830,59 @@ def _apply_proxy_environment(env, proxy_url: str) -> None:
809
830
  env["no_proxy"] = no_proxy
810
831
 
811
832
 
833
+ def _apply_provider_proxy_environment(env, container: Container, gateway_host: str, gateway_port: int) -> None:
834
+ if not container.config.provider_proxy.enabled:
835
+ return
836
+ raw = dict(container.config.raw)
837
+ gateway = dict(raw.get("gateway", {}))
838
+ gateway["host"] = gateway_host
839
+ gateway["port"] = gateway_port
840
+ raw["gateway"] = gateway
841
+ for provider in container.config.provider_proxy.providers.values():
842
+ provider_data = {
843
+ "local_path": provider_base_local_path(provider.local_path, provider.allow_paths),
844
+ }
845
+ env[provider.base_url_env] = configured_provider_base_url(raw, provider_data)
846
+
847
+
848
+ def _strip_backing_secret_environment(env, container: Container) -> None:
849
+ for binding in container.config.secrets:
850
+ if binding.real_secret_env:
851
+ env.pop(binding.real_secret_env, None)
852
+
853
+
854
+ def _configured_secret_replacements(container: Container, existing: List[SecretReplacement]) -> List[SecretReplacement]:
855
+ existing_names = set(replacement.name for replacement in existing)
856
+ replacements = []
857
+ for binding in container.config.secrets:
858
+ if binding.env_name in existing_names:
859
+ continue
860
+ real_value = container.token_resolver.resolve(binding.virtual_token) or ""
861
+ if not real_value:
862
+ continue
863
+ rule = container.config.env_policy.rule_for(binding.env_name)
864
+ if rule.mode == "deny":
865
+ replacements.append(
866
+ SecretReplacement(
867
+ source="configured",
868
+ name=binding.env_name,
869
+ real_value=real_value,
870
+ virtual_value="",
871
+ action="remove",
872
+ )
873
+ )
874
+ elif rule.mode != "broker":
875
+ replacements.append(
876
+ SecretReplacement(
877
+ source="configured",
878
+ name=binding.env_name,
879
+ real_value=real_value,
880
+ virtual_value=binding.virtual_token,
881
+ )
882
+ )
883
+ return replacements
884
+
885
+
812
886
  def _merge_no_proxy(existing: str) -> str:
813
887
  defaults = [
814
888
  "localhost",
@@ -825,6 +899,8 @@ def _merge_no_proxy(existing: str) -> str:
825
899
  if not value:
826
900
  continue
827
901
  key = value.lower()
902
+ if key == "*":
903
+ continue
828
904
  if key not in seen:
829
905
  values.append(value)
830
906
  seen.add(key)
@@ -2,6 +2,7 @@ import argparse
2
2
  import json
3
3
  import sys
4
4
 
5
+ from agentsecure.core.agentsecure_md import AGENTSECURE_MD, validate_agentsecure_md
5
6
  from agentsecure.core.config import ConfigError
6
7
  from agentsecure.core.policy_mutation import LocalPolicyMutationService
7
8
 
@@ -14,11 +15,17 @@ def add_policy_subparser(subparsers) -> None:
14
15
  policy_preview_parser.add_argument("--json-file", help="Read mutation JSON from this file instead of stdin")
15
16
  policy_apply_parser = policy_subparsers.add_parser("apply-local", help="Apply local policy changes from JSON")
16
17
  policy_apply_parser.add_argument("--json-file", help="Read mutation JSON from this file instead of stdin")
18
+ validate_parser = policy_subparsers.add_parser("validate", help="Validate AGENTSECURE.md policy guidance")
19
+ validate_parser.add_argument("--file", default=AGENTSECURE_MD, help="AGENTSECURE.md path")
17
20
 
18
21
 
19
22
  def handle_policy(args: argparse.Namespace) -> int:
20
- service = LocalPolicyMutationService(args.config)
21
23
  try:
24
+ if args.policy_command == "validate":
25
+ payload = validate_agentsecure_md(args.file)
26
+ print(json.dumps(payload, indent=2, sort_keys=True))
27
+ return 0 if payload["ok"] else 1
28
+ service = LocalPolicyMutationService(args.config)
22
29
  if args.policy_command == "review":
23
30
  payload = service.review()
24
31
  elif args.policy_command == "preview":
@@ -4,6 +4,7 @@ import os
4
4
  import shutil
5
5
 
6
6
  from agentsecure.cli.common import scanner
7
+ from agentsecure.core.agentsecure_md import AGENTSECURE_MD
7
8
  from agentsecure.core.product import ProductService
8
9
  from agentsecure.workspace.materializer import make_tree_writable
9
10
 
@@ -32,6 +33,14 @@ def show_status(args: argparse.Namespace) -> int:
32
33
  return 0
33
34
  print("AgentSecure status")
34
35
  print("Config: %s (%s)" % (result["config_path"], "found" if result["config_exists"] else "missing"))
36
+ agentsecure_md = result.get("agentsecure_md", {})
37
+ print(
38
+ "AGENTSECURE.md: %s (%s)"
39
+ % (
40
+ agentsecure_md.get("path", AGENTSECURE_MD),
41
+ "valid" if agentsecure_md.get("exists") and agentsecure_md.get("ok") else "missing" if not agentsecure_md.get("exists") else "needs review",
42
+ )
43
+ )
35
44
  print("Configured secrets: %s" % result["configured_secrets"])
36
45
  print("Discovered secrets: %s" % result["discovered_secrets"])
37
46
  grants = result["grants"]