q-runtime-core 0.9.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.
- q_runtime_core-0.9.0/LICENSE +3 -0
- q_runtime_core-0.9.0/PKG-INFO +299 -0
- q_runtime_core-0.9.0/README.md +286 -0
- q_runtime_core-0.9.0/pyproject.toml +37 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/PKG-INFO +299 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/SOURCES.txt +69 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/dependency_links.txt +1 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/entry_points.txt +2 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/requires.txt +5 -0
- q_runtime_core-0.9.0/q_runtime_core.egg-info/top_level.txt +1 -0
- q_runtime_core-0.9.0/qruntime/__init__.py +76 -0
- q_runtime_core-0.9.0/qruntime/budget.py +295 -0
- q_runtime_core-0.9.0/qruntime/cli.py +594 -0
- q_runtime_core-0.9.0/qruntime/core/__init__.py +0 -0
- q_runtime_core-0.9.0/qruntime/core/invariants.py +67 -0
- q_runtime_core-0.9.0/qruntime/core/model.py +140 -0
- q_runtime_core-0.9.0/qruntime/core/transition.py +92 -0
- q_runtime_core-0.9.0/qruntime/exceptions.py +132 -0
- q_runtime_core-0.9.0/qruntime/integrations/__init__.py +0 -0
- q_runtime_core-0.9.0/qruntime/integrations/official_x402_demo.py +94 -0
- q_runtime_core-0.9.0/qruntime/loader.py +39 -0
- q_runtime_core-0.9.0/qruntime/policies/__init__.py +0 -0
- q_runtime_core-0.9.0/qruntime/policies/authority.py +1 -0
- q_runtime_core-0.9.0/qruntime/policies/budget.py +1 -0
- q_runtime_core-0.9.0/qruntime/policies/evidence.py +1 -0
- q_runtime_core-0.9.0/qruntime/policy.py +248 -0
- q_runtime_core-0.9.0/qruntime/rails/__init__.py +0 -0
- q_runtime_core-0.9.0/qruntime/rails/simulated.py +4 -0
- q_runtime_core-0.9.0/qruntime/rails/x402.py +284 -0
- q_runtime_core-0.9.0/qruntime/rails/x402_capture.py +194 -0
- q_runtime_core-0.9.0/qruntime/rails/x402_external.py +575 -0
- q_runtime_core-0.9.0/qruntime/rails/x402_external_suite.py +65 -0
- q_runtime_core-0.9.0/qruntime/rails/x402_fullcycle.py +4651 -0
- q_runtime_core-0.9.0/qruntime/rails/x402_verify.py +202 -0
- q_runtime_core-0.9.0/qruntime/results.py +112 -0
- q_runtime_core-0.9.0/qruntime/runtime.py +243 -0
- q_runtime_core-0.9.0/qruntime/spend.py +584 -0
- q_runtime_core-0.9.0/qruntime/verify/__init__.py +0 -0
- q_runtime_core-0.9.0/qruntime/verify/explorer.py +59 -0
- q_runtime_core-0.9.0/qruntime/verify/report.py +38 -0
- q_runtime_core-0.9.0/setup.cfg +4 -0
- q_runtime_core-0.9.0/tests/test_agent_budget.py +536 -0
- q_runtime_core-0.9.0/tests/test_agent_payment_boundary.py +445 -0
- q_runtime_core-0.9.0/tests/test_budget.py +261 -0
- q_runtime_core-0.9.0/tests/test_budget_payment_boundary.py +470 -0
- q_runtime_core-0.9.0/tests/test_budget_reservation.py +576 -0
- q_runtime_core-0.9.0/tests/test_budget_set.py +443 -0
- q_runtime_core-0.9.0/tests/test_cli_intents.py +426 -0
- q_runtime_core-0.9.0/tests/test_crash_consistency.py +3460 -0
- q_runtime_core-0.9.0/tests/test_multiprocess_concurrency.py +2069 -0
- q_runtime_core-0.9.0/tests/test_operational_error_taxonomy.py +109 -0
- q_runtime_core-0.9.0/tests/test_origin_budget.py +400 -0
- q_runtime_core-0.9.0/tests/test_policy.py +231 -0
- q_runtime_core-0.9.0/tests/test_policy_payment_boundary.py +230 -0
- q_runtime_core-0.9.0/tests/test_policy_public_api.py +136 -0
- q_runtime_core-0.9.0/tests/test_public_error_taxonomy.py +128 -0
- q_runtime_core-0.9.0/tests/test_runtime_api.py +227 -0
- q_runtime_core-0.9.0/tests/test_runtime_exceptions.py +139 -0
- q_runtime_core-0.9.0/tests/test_runtime_intents.py +147 -0
- q_runtime_core-0.9.0/tests/test_runtime_policy.py +152 -0
- q_runtime_core-0.9.0/tests/test_sdk_example.py +25 -0
- q_runtime_core-0.9.0/tests/test_session_budget.py +546 -0
- q_runtime_core-0.9.0/tests/test_session_payment_boundary.py +296 -0
- q_runtime_core-0.9.0/tests/test_spend_ledger.py +313 -0
- q_runtime_core-0.9.0/tests/test_store_corruption.py +2159 -0
- q_runtime_core-0.9.0/tests/test_store_migrations.py +730 -0
- q_runtime_core-0.9.0/tests/test_verifier.py +44 -0
- q_runtime_core-0.9.0/tests/test_x402_v03.py +81 -0
- q_runtime_core-0.9.0/tests/test_x402_v04_capture.py +143 -0
- q_runtime_core-0.9.0/tests/test_x402_v05_external.py +412 -0
- q_runtime_core-0.9.0/tests/test_x402_v06_fullcycle.py +2020 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: q-runtime-core
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: Economic invariant verification for autonomous AI-agent workflows
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: PyYAML>=6.0
|
|
9
|
+
Provides-Extra: official-x402
|
|
10
|
+
Requires-Dist: x402[evm,fastapi,requests]<3,>=2.22.0; extra == "official-x402"
|
|
11
|
+
Requires-Dist: uvicorn[standard]>=0.40.0; extra == "official-x402"
|
|
12
|
+
Dynamic: license-file
|
|
13
|
+
|
|
14
|
+
# Q Runtime
|
|
15
|
+
## v0.5-r3 — external-audit false-positive hardening
|
|
16
|
+
|
|
17
|
+
The 2026-09-04 directory audit exposed two detector problems rather than third-party vulnerabilities:
|
|
18
|
+
|
|
19
|
+
- x402's published network support explicitly lists Algorand identifiers whose genesis-hash form falls outside the formal CAIP-2 reference grammar. Q Runtime now recognizes those exact x402-documented identifiers as an upstream profile exception instead of blaming each service.
|
|
20
|
+
- `Cache-Control: no-store, no-cache, must-revalidate, max-age=0` is correctly treated as non-cacheable. The old substring check incorrectly warned whenever `max-age` appeared.
|
|
21
|
+
|
|
22
|
+
Regression result: **39/39 tests passing**. Package version: **0.5.3**.
|
|
23
|
+
|
|
24
|
+
## v0.5-r2 — legacy root-cause classification
|
|
25
|
+
|
|
26
|
+
External validation against Neynar reproduced the same x402 v1 handshake on all three monitored endpoints. r2 therefore adds audit modes and root-cause aggregation:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
qruntime x402 external-audit <URL> --mode strict
|
|
30
|
+
qruntime x402 external-audit <URL> --mode compatibility
|
|
31
|
+
qruntime x402 directory-audit --limit 10 --mode compatibility --out captures\directory.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `strict`: x402 v1 is one `LegacyX402V1Detected` error; body-only v2 is an error.
|
|
35
|
+
- `compatibility`: x402 v1 is one legacy warning/classification; body-only v2 is a warning.
|
|
36
|
+
- v1-derived field mismatches are not double-counted as separate bugs.
|
|
37
|
+
- `external-suite` now treats the grug402 missing-header scenario as `CanonicalPaymentRequiredLocation` in strict mode.
|
|
38
|
+
|
|
39
|
+
Verify v0.5
|
|
40
|
+
|
|
41
|
+
Q Runtime Verify is a protocol-agnostic economic-state verifier for autonomous AI-agent workflows.
|
|
42
|
+
|
|
43
|
+
**Positioning:** Q Runtime finds economic bugs in AI-agent workflows before agents spend real money.
|
|
44
|
+
|
|
45
|
+
**Design rule:** Agents propose. Q verifies. Rails execute.
|
|
46
|
+
|
|
47
|
+
## What v0.5 changes
|
|
48
|
+
|
|
49
|
+
v0.4 proved live HTTP capture against a server we controlled using the official x402 Python SDK. v0.5 moves the validation surface outside our server:
|
|
50
|
+
|
|
51
|
+
- `external-audit` probes an independent public HTTPS x402 endpoint without paying;
|
|
52
|
+
- it refuses to send `PAYMENT-SIGNATURE` or legacy `X-PAYMENT` authorization headers;
|
|
53
|
+
- it audits the observed 402 challenge for protocol/economic invariants;
|
|
54
|
+
- `external-suite` cross-checks Q Runtime against independent QueryLines + grug402 endpoints;
|
|
55
|
+
- `directory-audit` discovers public x402 services through x402 List and safely probes GET-only, non-templated, public-HTTPS endpoints;
|
|
56
|
+
- external reports preserve the HTTP status, response headers, challenge source, decoded requirement and findings;
|
|
57
|
+
- v0.4 capture, quote comparison, official SDK demo, QFlow verifier, and v0.3 trace verifier remain intact.
|
|
58
|
+
|
|
59
|
+
No v0.5 external probe signs, pays, settles, broadcasts a transaction, or asks for a wallet key.
|
|
60
|
+
|
|
61
|
+
## Current external reference set
|
|
62
|
+
|
|
63
|
+
Research date: 2026-09-03.
|
|
64
|
+
|
|
65
|
+
### QueryLines — independent production x402 API
|
|
66
|
+
|
|
67
|
+
`https://api.querylines.com/v1/premium?state=FL`
|
|
68
|
+
|
|
69
|
+
The public x402 List assessment currently reports QueryLines as online with 100% 30-day uptime and 14/14 x402 compliance checks. Its paid endpoints return x402 challenges in the `PAYMENT-REQUIRED` header.
|
|
70
|
+
|
|
71
|
+
### grug402 — independent live testnet behavior catalog
|
|
72
|
+
|
|
73
|
+
The suite uses:
|
|
74
|
+
|
|
75
|
+
- `/api/x402/compliant-get` — compliant baseline;
|
|
76
|
+
- `/api/x402/missing-payment-required` — 402 with missing challenge;
|
|
77
|
+
- `/api/x402/header-raw-json` — non-canonical raw JSON header;
|
|
78
|
+
- `/api/x402/resource-host-mismatch` — advertised resource host does not match the requested host.
|
|
79
|
+
|
|
80
|
+
These negative endpoints are intentionally malformed by grug402. They validate Q Runtime's detector against externally hosted bug classes; they are **not** discoveries by Q Runtime.
|
|
81
|
+
|
|
82
|
+
### x402 List — discovery source
|
|
83
|
+
|
|
84
|
+
`https://x402-list.com/api/v1/`
|
|
85
|
+
|
|
86
|
+
Read access requires no authentication. v0.5 uses directory metadata only to discover public endpoints, then performs unpaid GET probes.
|
|
87
|
+
|
|
88
|
+
## New commands
|
|
89
|
+
|
|
90
|
+
### 1. Audit one independent endpoint
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
qruntime x402 external-audit "https://api.querylines.com/v1/premium?state=FL" `
|
|
94
|
+
--out captures\querylines-premium.json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Expected high-level result for a healthy external implementation:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
PASS — EXTERNAL X402 AUDIT
|
|
101
|
+
HTTP: 402 GET ...
|
|
102
|
+
challenge source: header
|
|
103
|
+
...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Warnings do not make the audit fail. For example, a service may advertise the endpoint URL in `resource.url` while binding query parameters through an extension. v0.5 treats an origin/path mismatch as an error, but an omitted query string as `ResourceQueryBindingExternalized` warning rather than a false protocol failure.
|
|
107
|
+
|
|
108
|
+
### 2. Run the independent cross-implementation suite
|
|
109
|
+
|
|
110
|
+
```powershell
|
|
111
|
+
qruntime x402 external-suite `
|
|
112
|
+
--out captures\external-suite-v05.json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The suite expects the compliant endpoints to pass and the intentionally malformed grug402 endpoints to fail on their corresponding invariants.
|
|
116
|
+
|
|
117
|
+
### 3. Audit a small sample discovered from x402 List
|
|
118
|
+
|
|
119
|
+
```powershell
|
|
120
|
+
qruntime x402 directory-audit `
|
|
121
|
+
--limit 5 `
|
|
122
|
+
--out captures\directory-audit-v05.json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Safety constraints:
|
|
126
|
+
|
|
127
|
+
- GET only;
|
|
128
|
+
- public HTTPS only;
|
|
129
|
+
- endpoint templates containing `{...}` skipped;
|
|
130
|
+
- no payment authorization header;
|
|
131
|
+
- no payment attempted;
|
|
132
|
+
- directory audit limit capped at 50.
|
|
133
|
+
|
|
134
|
+
A directory-audit error is an **observed incompatibility or reachability finding**, not automatically a security vulnerability. Any non-trivial finding must be reproduced and manually classified before disclosure or product claims.
|
|
135
|
+
|
|
136
|
+
## External invariants added/strengthened
|
|
137
|
+
|
|
138
|
+
- `PaymentRequiredStatus` — protected endpoint should produce HTTP 402 for an unpaid challenge.
|
|
139
|
+
- `CanonicalPaymentRequiredEncoding` — canonical v2 header is base64 JSON, not raw JSON/garbage.
|
|
140
|
+
- `PaymentRequirementKnownBeforeAuthorization` — 402 must expose a parseable payment challenge.
|
|
141
|
+
- `X402VersionSupported` — current verifier expects x402 v2.
|
|
142
|
+
- `NonEmptyPaymentRequirements` — `accepts[]` must not be empty.
|
|
143
|
+
- `AtomicAmountCanonical` — amount must be a decimal string of atomic units.
|
|
144
|
+
- `CanonicalNetworkIdentifier` — network must have CAIP-2-like shape.
|
|
145
|
+
- `LiveAuthorizationWindow` — timeout must be a positive integer.
|
|
146
|
+
- `ValidPaymentRecipient` / `ValidPaymentAsset` — EVM recipient/asset must be 20-byte addresses.
|
|
147
|
+
- `PaymentPayloadBoundToResource` — advertised origin/path must match the requested resource.
|
|
148
|
+
- `ResourceQueryBindingExternalized` — warning when query parameters are not reproduced in `resource.url`.
|
|
149
|
+
- `NonCacheablePaymentChallenge` — warns when 402 challenge is explicitly cacheable.
|
|
150
|
+
|
|
151
|
+
## Important correction produced by external validation
|
|
152
|
+
|
|
153
|
+
v0.4's mental model could have treated exact request URL equality as the strongest resource-binding rule. External research showed that a conformant production service can advertise the endpoint in `resource.url` while declaring concrete query inputs in an extension. v0.5 therefore avoids a false positive:
|
|
154
|
+
|
|
155
|
+
- different origin/path → hard failure;
|
|
156
|
+
- both sides specify different queries → hard failure;
|
|
157
|
+
- request has query but `resource.url` omits it → warning requiring extension/application binding review.
|
|
158
|
+
|
|
159
|
+
This is evidence that external validation is already improving the verifier rather than merely confirming our own assumptions.
|
|
160
|
+
|
|
161
|
+
## Tests
|
|
162
|
+
|
|
163
|
+
```powershell
|
|
164
|
+
pytest -q
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Expected for this snapshot:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
33 passed
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The automated tests remain deterministic and do not require internet. Live external commands are a separate experimental layer to be run by the operator.
|
|
174
|
+
|
|
175
|
+
## Scope boundary / evidence standard
|
|
176
|
+
|
|
177
|
+
v0.5 can establish that Q Runtime interoperates with and evaluates externally hosted x402 challenges. It does **not** establish that every reported difference is a bug, exploit, financial loss, or vulnerability.
|
|
178
|
+
|
|
179
|
+
The current decisive gate is:
|
|
180
|
+
|
|
181
|
+
> Can Q Runtime produce a reproducible, non-trivial finding on a third-party x402 flow that was not deliberately constructed as a negative test, survive manual review, and be useful to that service's developer?
|
|
182
|
+
|
|
183
|
+
Do not build Q Runtime Cloud before that gate is crossed.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
## v0.5-r4 precision notes
|
|
187
|
+
|
|
188
|
+
The external auditor distinguishes HTTP storable responses from stale-replay-capable responses. `max-age=0, must-revalidate` is immediately stale and requires revalidation, while positive freshness such as `max-age=300` remains a warning for payment challenges.
|
|
189
|
+
|
|
190
|
+
`maxTimeoutSeconds` is parsed as a core numeric field. Standard known schemes require a positive value; zero on an unknown/custom scheme is reported as scheme-specific semantics rather than treated as a universal protocol failure.
|
|
191
|
+
|
|
192
|
+
Relative `resource.url` values are resolved against the request origin before resource binding comparison. Origin, scheme, or resolved-path mismatches remain errors.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## v0.6 — full-cycle x402 testnet gate
|
|
197
|
+
|
|
198
|
+
v0.6 adds a deterministic verifier for the x402 v2 default `authorization` flow and a deliberately narrow live Base-Sepolia harness.
|
|
199
|
+
|
|
200
|
+
### Deterministic full-cycle checks
|
|
201
|
+
|
|
202
|
+
```powershell
|
|
203
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_safe.json
|
|
204
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_stale_quote.json
|
|
205
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_settlement_pending_retry.json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Expected: safe passes; stale quote fails `PaymentRequirementStableForIntent`; pending retry fails `PaymentStateReconciledBeforeRetry`.
|
|
209
|
+
|
|
210
|
+
### Disposable testnet wallets
|
|
211
|
+
|
|
212
|
+
```powershell
|
|
213
|
+
qruntime x402 create-testnet-wallet --out .secrets\payer.json
|
|
214
|
+
qruntime x402 create-testnet-wallet --out .secrets\merchant.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
These files contain private keys. They are for Base Sepolia testnet only. Never upload, paste, commit, or reuse them for mainnet.
|
|
218
|
+
|
|
219
|
+
### Live settlement safety
|
|
220
|
+
|
|
221
|
+
`live-testnet` is hard-limited to `localhost`/`127.0.0.1`, Base Sepolia (`eip155:84532`), `exact`, and an explicit atomic-unit cap. The key is taken from `Q_RUNTIME_TESTNET_PRIVATE_KEY` by default and is not written to the report.
|
|
222
|
+
|
|
223
|
+
See `RELEASE_v0.6.md` for the complete gate.
|
|
224
|
+
|
|
225
|
+
## Python SDK (v0.7 development)
|
|
226
|
+
|
|
227
|
+
Q Runtime now exposes a public Python API.
|
|
228
|
+
|
|
229
|
+
Minimal example:
|
|
230
|
+
|
|
231
|
+
from qruntime import Runtime
|
|
232
|
+
|
|
233
|
+
runtime = Runtime(
|
|
234
|
+
max_amount_atomic=10_000,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
result = runtime.pay_testnet(
|
|
238
|
+
"http://127.0.0.1:4021/weather",
|
|
239
|
+
intent_id="example-payment-001",
|
|
240
|
+
out="payment.json",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
print(result.transaction)
|
|
244
|
+
print(result.amount_atomic)
|
|
245
|
+
print(result.network)
|
|
246
|
+
|
|
247
|
+
The SDK exposes typed payment and reconciliation results plus payment-safety exceptions.
|
|
248
|
+
|
|
249
|
+
See:
|
|
250
|
+
|
|
251
|
+
- docs/SDK_V07.md
|
|
252
|
+
- examples/runtime_sdk.py
|
|
253
|
+
|
|
254
|
+
The current public payment method is deliberately named pay_testnet() because production/mainnet readiness is not claimed by the v0.7 development line.
|
|
255
|
+
|
|
256
|
+
## v0.7 ? public SDK and operational observability
|
|
257
|
+
|
|
258
|
+
v0.7 promotes the validated economic-safety core into a public Python SDK.
|
|
259
|
+
|
|
260
|
+
The public API now includes:
|
|
261
|
+
|
|
262
|
+
- Runtime
|
|
263
|
+
- RuntimeConfig
|
|
264
|
+
- PaymentResult
|
|
265
|
+
- ReconciliationResult
|
|
266
|
+
- IntentRecord
|
|
267
|
+
- typed payment-safety errors
|
|
268
|
+
- typed settlement/resource errors
|
|
269
|
+
- typed store/reconciliation errors
|
|
270
|
+
|
|
271
|
+
Persistent logical payment state can be inspected without mutating it:
|
|
272
|
+
|
|
273
|
+
qruntime x402 intents
|
|
274
|
+
qruntime x402 intent <intent_id>
|
|
275
|
+
|
|
276
|
+
Operational views include:
|
|
277
|
+
|
|
278
|
+
qruntime x402 intents --state pending
|
|
279
|
+
qruntime x402 intents --state confirmed
|
|
280
|
+
qruntime x402 intents --state failed
|
|
281
|
+
qruntime x402 intents --summary
|
|
282
|
+
|
|
283
|
+
Python applications can use:
|
|
284
|
+
|
|
285
|
+
runtime.list_intents()
|
|
286
|
+
runtime.get_intent(intent_id)
|
|
287
|
+
|
|
288
|
+
The latest v0.7 regression gate is:
|
|
289
|
+
|
|
290
|
+
126 passed
|
|
291
|
+
|
|
292
|
+
The public SDK has also completed a live Base Sepolia payment through a clean-installed wheel, followed by successful reconciliation and same-intent duplicate rejection.
|
|
293
|
+
|
|
294
|
+
The controlled payment path remains testnet-specific and deliberately narrow. Production/mainnet readiness is not claimed.
|
|
295
|
+
|
|
296
|
+
See:
|
|
297
|
+
|
|
298
|
+
- docs/SDK_V07.md
|
|
299
|
+
- VALIDATION-v0.7.0rc1.md
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# Q Runtime
|
|
2
|
+
## v0.5-r3 — external-audit false-positive hardening
|
|
3
|
+
|
|
4
|
+
The 2026-09-04 directory audit exposed two detector problems rather than third-party vulnerabilities:
|
|
5
|
+
|
|
6
|
+
- x402's published network support explicitly lists Algorand identifiers whose genesis-hash form falls outside the formal CAIP-2 reference grammar. Q Runtime now recognizes those exact x402-documented identifiers as an upstream profile exception instead of blaming each service.
|
|
7
|
+
- `Cache-Control: no-store, no-cache, must-revalidate, max-age=0` is correctly treated as non-cacheable. The old substring check incorrectly warned whenever `max-age` appeared.
|
|
8
|
+
|
|
9
|
+
Regression result: **39/39 tests passing**. Package version: **0.5.3**.
|
|
10
|
+
|
|
11
|
+
## v0.5-r2 — legacy root-cause classification
|
|
12
|
+
|
|
13
|
+
External validation against Neynar reproduced the same x402 v1 handshake on all three monitored endpoints. r2 therefore adds audit modes and root-cause aggregation:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
qruntime x402 external-audit <URL> --mode strict
|
|
17
|
+
qruntime x402 external-audit <URL> --mode compatibility
|
|
18
|
+
qruntime x402 directory-audit --limit 10 --mode compatibility --out captures\directory.json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- `strict`: x402 v1 is one `LegacyX402V1Detected` error; body-only v2 is an error.
|
|
22
|
+
- `compatibility`: x402 v1 is one legacy warning/classification; body-only v2 is a warning.
|
|
23
|
+
- v1-derived field mismatches are not double-counted as separate bugs.
|
|
24
|
+
- `external-suite` now treats the grug402 missing-header scenario as `CanonicalPaymentRequiredLocation` in strict mode.
|
|
25
|
+
|
|
26
|
+
Verify v0.5
|
|
27
|
+
|
|
28
|
+
Q Runtime Verify is a protocol-agnostic economic-state verifier for autonomous AI-agent workflows.
|
|
29
|
+
|
|
30
|
+
**Positioning:** Q Runtime finds economic bugs in AI-agent workflows before agents spend real money.
|
|
31
|
+
|
|
32
|
+
**Design rule:** Agents propose. Q verifies. Rails execute.
|
|
33
|
+
|
|
34
|
+
## What v0.5 changes
|
|
35
|
+
|
|
36
|
+
v0.4 proved live HTTP capture against a server we controlled using the official x402 Python SDK. v0.5 moves the validation surface outside our server:
|
|
37
|
+
|
|
38
|
+
- `external-audit` probes an independent public HTTPS x402 endpoint without paying;
|
|
39
|
+
- it refuses to send `PAYMENT-SIGNATURE` or legacy `X-PAYMENT` authorization headers;
|
|
40
|
+
- it audits the observed 402 challenge for protocol/economic invariants;
|
|
41
|
+
- `external-suite` cross-checks Q Runtime against independent QueryLines + grug402 endpoints;
|
|
42
|
+
- `directory-audit` discovers public x402 services through x402 List and safely probes GET-only, non-templated, public-HTTPS endpoints;
|
|
43
|
+
- external reports preserve the HTTP status, response headers, challenge source, decoded requirement and findings;
|
|
44
|
+
- v0.4 capture, quote comparison, official SDK demo, QFlow verifier, and v0.3 trace verifier remain intact.
|
|
45
|
+
|
|
46
|
+
No v0.5 external probe signs, pays, settles, broadcasts a transaction, or asks for a wallet key.
|
|
47
|
+
|
|
48
|
+
## Current external reference set
|
|
49
|
+
|
|
50
|
+
Research date: 2026-09-03.
|
|
51
|
+
|
|
52
|
+
### QueryLines — independent production x402 API
|
|
53
|
+
|
|
54
|
+
`https://api.querylines.com/v1/premium?state=FL`
|
|
55
|
+
|
|
56
|
+
The public x402 List assessment currently reports QueryLines as online with 100% 30-day uptime and 14/14 x402 compliance checks. Its paid endpoints return x402 challenges in the `PAYMENT-REQUIRED` header.
|
|
57
|
+
|
|
58
|
+
### grug402 — independent live testnet behavior catalog
|
|
59
|
+
|
|
60
|
+
The suite uses:
|
|
61
|
+
|
|
62
|
+
- `/api/x402/compliant-get` — compliant baseline;
|
|
63
|
+
- `/api/x402/missing-payment-required` — 402 with missing challenge;
|
|
64
|
+
- `/api/x402/header-raw-json` — non-canonical raw JSON header;
|
|
65
|
+
- `/api/x402/resource-host-mismatch` — advertised resource host does not match the requested host.
|
|
66
|
+
|
|
67
|
+
These negative endpoints are intentionally malformed by grug402. They validate Q Runtime's detector against externally hosted bug classes; they are **not** discoveries by Q Runtime.
|
|
68
|
+
|
|
69
|
+
### x402 List — discovery source
|
|
70
|
+
|
|
71
|
+
`https://x402-list.com/api/v1/`
|
|
72
|
+
|
|
73
|
+
Read access requires no authentication. v0.5 uses directory metadata only to discover public endpoints, then performs unpaid GET probes.
|
|
74
|
+
|
|
75
|
+
## New commands
|
|
76
|
+
|
|
77
|
+
### 1. Audit one independent endpoint
|
|
78
|
+
|
|
79
|
+
```powershell
|
|
80
|
+
qruntime x402 external-audit "https://api.querylines.com/v1/premium?state=FL" `
|
|
81
|
+
--out captures\querylines-premium.json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Expected high-level result for a healthy external implementation:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
PASS — EXTERNAL X402 AUDIT
|
|
88
|
+
HTTP: 402 GET ...
|
|
89
|
+
challenge source: header
|
|
90
|
+
...
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Warnings do not make the audit fail. For example, a service may advertise the endpoint URL in `resource.url` while binding query parameters through an extension. v0.5 treats an origin/path mismatch as an error, but an omitted query string as `ResourceQueryBindingExternalized` warning rather than a false protocol failure.
|
|
94
|
+
|
|
95
|
+
### 2. Run the independent cross-implementation suite
|
|
96
|
+
|
|
97
|
+
```powershell
|
|
98
|
+
qruntime x402 external-suite `
|
|
99
|
+
--out captures\external-suite-v05.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The suite expects the compliant endpoints to pass and the intentionally malformed grug402 endpoints to fail on their corresponding invariants.
|
|
103
|
+
|
|
104
|
+
### 3. Audit a small sample discovered from x402 List
|
|
105
|
+
|
|
106
|
+
```powershell
|
|
107
|
+
qruntime x402 directory-audit `
|
|
108
|
+
--limit 5 `
|
|
109
|
+
--out captures\directory-audit-v05.json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Safety constraints:
|
|
113
|
+
|
|
114
|
+
- GET only;
|
|
115
|
+
- public HTTPS only;
|
|
116
|
+
- endpoint templates containing `{...}` skipped;
|
|
117
|
+
- no payment authorization header;
|
|
118
|
+
- no payment attempted;
|
|
119
|
+
- directory audit limit capped at 50.
|
|
120
|
+
|
|
121
|
+
A directory-audit error is an **observed incompatibility or reachability finding**, not automatically a security vulnerability. Any non-trivial finding must be reproduced and manually classified before disclosure or product claims.
|
|
122
|
+
|
|
123
|
+
## External invariants added/strengthened
|
|
124
|
+
|
|
125
|
+
- `PaymentRequiredStatus` — protected endpoint should produce HTTP 402 for an unpaid challenge.
|
|
126
|
+
- `CanonicalPaymentRequiredEncoding` — canonical v2 header is base64 JSON, not raw JSON/garbage.
|
|
127
|
+
- `PaymentRequirementKnownBeforeAuthorization` — 402 must expose a parseable payment challenge.
|
|
128
|
+
- `X402VersionSupported` — current verifier expects x402 v2.
|
|
129
|
+
- `NonEmptyPaymentRequirements` — `accepts[]` must not be empty.
|
|
130
|
+
- `AtomicAmountCanonical` — amount must be a decimal string of atomic units.
|
|
131
|
+
- `CanonicalNetworkIdentifier` — network must have CAIP-2-like shape.
|
|
132
|
+
- `LiveAuthorizationWindow` — timeout must be a positive integer.
|
|
133
|
+
- `ValidPaymentRecipient` / `ValidPaymentAsset` — EVM recipient/asset must be 20-byte addresses.
|
|
134
|
+
- `PaymentPayloadBoundToResource` — advertised origin/path must match the requested resource.
|
|
135
|
+
- `ResourceQueryBindingExternalized` — warning when query parameters are not reproduced in `resource.url`.
|
|
136
|
+
- `NonCacheablePaymentChallenge` — warns when 402 challenge is explicitly cacheable.
|
|
137
|
+
|
|
138
|
+
## Important correction produced by external validation
|
|
139
|
+
|
|
140
|
+
v0.4's mental model could have treated exact request URL equality as the strongest resource-binding rule. External research showed that a conformant production service can advertise the endpoint in `resource.url` while declaring concrete query inputs in an extension. v0.5 therefore avoids a false positive:
|
|
141
|
+
|
|
142
|
+
- different origin/path → hard failure;
|
|
143
|
+
- both sides specify different queries → hard failure;
|
|
144
|
+
- request has query but `resource.url` omits it → warning requiring extension/application binding review.
|
|
145
|
+
|
|
146
|
+
This is evidence that external validation is already improving the verifier rather than merely confirming our own assumptions.
|
|
147
|
+
|
|
148
|
+
## Tests
|
|
149
|
+
|
|
150
|
+
```powershell
|
|
151
|
+
pytest -q
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Expected for this snapshot:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
33 passed
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The automated tests remain deterministic and do not require internet. Live external commands are a separate experimental layer to be run by the operator.
|
|
161
|
+
|
|
162
|
+
## Scope boundary / evidence standard
|
|
163
|
+
|
|
164
|
+
v0.5 can establish that Q Runtime interoperates with and evaluates externally hosted x402 challenges. It does **not** establish that every reported difference is a bug, exploit, financial loss, or vulnerability.
|
|
165
|
+
|
|
166
|
+
The current decisive gate is:
|
|
167
|
+
|
|
168
|
+
> Can Q Runtime produce a reproducible, non-trivial finding on a third-party x402 flow that was not deliberately constructed as a negative test, survive manual review, and be useful to that service's developer?
|
|
169
|
+
|
|
170
|
+
Do not build Q Runtime Cloud before that gate is crossed.
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## v0.5-r4 precision notes
|
|
174
|
+
|
|
175
|
+
The external auditor distinguishes HTTP storable responses from stale-replay-capable responses. `max-age=0, must-revalidate` is immediately stale and requires revalidation, while positive freshness such as `max-age=300` remains a warning for payment challenges.
|
|
176
|
+
|
|
177
|
+
`maxTimeoutSeconds` is parsed as a core numeric field. Standard known schemes require a positive value; zero on an unknown/custom scheme is reported as scheme-specific semantics rather than treated as a universal protocol failure.
|
|
178
|
+
|
|
179
|
+
Relative `resource.url` values are resolved against the request origin before resource binding comparison. Origin, scheme, or resolved-path mismatches remain errors.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## v0.6 — full-cycle x402 testnet gate
|
|
184
|
+
|
|
185
|
+
v0.6 adds a deterministic verifier for the x402 v2 default `authorization` flow and a deliberately narrow live Base-Sepolia harness.
|
|
186
|
+
|
|
187
|
+
### Deterministic full-cycle checks
|
|
188
|
+
|
|
189
|
+
```powershell
|
|
190
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_safe.json
|
|
191
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_stale_quote.json
|
|
192
|
+
qruntime x402 verify-fullcycle scenarios\fullcycle_settlement_pending_retry.json
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Expected: safe passes; stale quote fails `PaymentRequirementStableForIntent`; pending retry fails `PaymentStateReconciledBeforeRetry`.
|
|
196
|
+
|
|
197
|
+
### Disposable testnet wallets
|
|
198
|
+
|
|
199
|
+
```powershell
|
|
200
|
+
qruntime x402 create-testnet-wallet --out .secrets\payer.json
|
|
201
|
+
qruntime x402 create-testnet-wallet --out .secrets\merchant.json
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
These files contain private keys. They are for Base Sepolia testnet only. Never upload, paste, commit, or reuse them for mainnet.
|
|
205
|
+
|
|
206
|
+
### Live settlement safety
|
|
207
|
+
|
|
208
|
+
`live-testnet` is hard-limited to `localhost`/`127.0.0.1`, Base Sepolia (`eip155:84532`), `exact`, and an explicit atomic-unit cap. The key is taken from `Q_RUNTIME_TESTNET_PRIVATE_KEY` by default and is not written to the report.
|
|
209
|
+
|
|
210
|
+
See `RELEASE_v0.6.md` for the complete gate.
|
|
211
|
+
|
|
212
|
+
## Python SDK (v0.7 development)
|
|
213
|
+
|
|
214
|
+
Q Runtime now exposes a public Python API.
|
|
215
|
+
|
|
216
|
+
Minimal example:
|
|
217
|
+
|
|
218
|
+
from qruntime import Runtime
|
|
219
|
+
|
|
220
|
+
runtime = Runtime(
|
|
221
|
+
max_amount_atomic=10_000,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
result = runtime.pay_testnet(
|
|
225
|
+
"http://127.0.0.1:4021/weather",
|
|
226
|
+
intent_id="example-payment-001",
|
|
227
|
+
out="payment.json",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
print(result.transaction)
|
|
231
|
+
print(result.amount_atomic)
|
|
232
|
+
print(result.network)
|
|
233
|
+
|
|
234
|
+
The SDK exposes typed payment and reconciliation results plus payment-safety exceptions.
|
|
235
|
+
|
|
236
|
+
See:
|
|
237
|
+
|
|
238
|
+
- docs/SDK_V07.md
|
|
239
|
+
- examples/runtime_sdk.py
|
|
240
|
+
|
|
241
|
+
The current public payment method is deliberately named pay_testnet() because production/mainnet readiness is not claimed by the v0.7 development line.
|
|
242
|
+
|
|
243
|
+
## v0.7 ? public SDK and operational observability
|
|
244
|
+
|
|
245
|
+
v0.7 promotes the validated economic-safety core into a public Python SDK.
|
|
246
|
+
|
|
247
|
+
The public API now includes:
|
|
248
|
+
|
|
249
|
+
- Runtime
|
|
250
|
+
- RuntimeConfig
|
|
251
|
+
- PaymentResult
|
|
252
|
+
- ReconciliationResult
|
|
253
|
+
- IntentRecord
|
|
254
|
+
- typed payment-safety errors
|
|
255
|
+
- typed settlement/resource errors
|
|
256
|
+
- typed store/reconciliation errors
|
|
257
|
+
|
|
258
|
+
Persistent logical payment state can be inspected without mutating it:
|
|
259
|
+
|
|
260
|
+
qruntime x402 intents
|
|
261
|
+
qruntime x402 intent <intent_id>
|
|
262
|
+
|
|
263
|
+
Operational views include:
|
|
264
|
+
|
|
265
|
+
qruntime x402 intents --state pending
|
|
266
|
+
qruntime x402 intents --state confirmed
|
|
267
|
+
qruntime x402 intents --state failed
|
|
268
|
+
qruntime x402 intents --summary
|
|
269
|
+
|
|
270
|
+
Python applications can use:
|
|
271
|
+
|
|
272
|
+
runtime.list_intents()
|
|
273
|
+
runtime.get_intent(intent_id)
|
|
274
|
+
|
|
275
|
+
The latest v0.7 regression gate is:
|
|
276
|
+
|
|
277
|
+
126 passed
|
|
278
|
+
|
|
279
|
+
The public SDK has also completed a live Base Sepolia payment through a clean-installed wheel, followed by successful reconciliation and same-intent duplicate rejection.
|
|
280
|
+
|
|
281
|
+
The controlled payment path remains testnet-specific and deliberately narrow. Production/mainnet readiness is not claimed.
|
|
282
|
+
|
|
283
|
+
See:
|
|
284
|
+
|
|
285
|
+
- docs/SDK_V07.md
|
|
286
|
+
- VALIDATION-v0.7.0rc1.md
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "q-runtime-core"
|
|
7
|
+
version = "0.9.0"
|
|
8
|
+
description = "Economic invariant verification for autonomous AI-agent workflows"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = ["PyYAML>=6.0"]
|
|
12
|
+
[project.optional-dependencies]
|
|
13
|
+
official-x402 = [
|
|
14
|
+
"x402[fastapi,requests,evm]>=2.22.0,<3",
|
|
15
|
+
"uvicorn[standard]>=0.40.0",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
qruntime = "qruntime.cli:main"
|
|
21
|
+
|
|
22
|
+
[tool.setuptools.packages.find]
|
|
23
|
+
where = ["."]
|
|
24
|
+
include = ["qruntime*"]
|
|
25
|
+
|
|
26
|
+
[tool.pytest.ini_options]
|
|
27
|
+
testpaths = ["tests"]
|
|
28
|
+
norecursedirs = [
|
|
29
|
+
".git",
|
|
30
|
+
".venv",
|
|
31
|
+
".venv-*",
|
|
32
|
+
"_release_stage",
|
|
33
|
+
"build",
|
|
34
|
+
"dist",
|
|
35
|
+
"dist-*",
|
|
36
|
+
]
|
|
37
|
+
|