Commit 5a1e6b6
* feat(buyer-agent-registry): caching + rate-limit + audit emission (#380)
Three composable wrappers around the BuyerAgentRegistry Protocol that
the v3 seller's Tier 2 commercial-identity gate hits on every dispatch.
Without them, every resolve runs a SQL query — including negative paths
an enumeration probe will spam, making the lookup endpoint a
credential-stuffing oracle.
* CachingBuyerAgentRegistry — TTL + LRU cache, default 60s / 4096
entries. Caches BOTH positive and negative resolutions; the negative
cache closes the enumeration probe path so a probe walking arbitrary
agent_url strings hits the DB at most once per (tenant, key) per TTL
window. Hit-callback hook for Prometheus / OpenTelemetry counters.
* RateLimitedBuyerAgentRegistry — per-(tenant, lookup-key) token
bucket, default 100 RPS. On exhaustion raises PERMISSION_DENIED with
NO details and a generic message — wire-uniform with the registry-
miss path from PR #393. A distinct RATE_LIMITED code or populated
details would itself be an enumeration oracle.
* AuditingBuyerAgentRegistry — terminal wrapper emitting one
AuditEvent per DB outcome (resolved / miss). The cache and rate-
limit layers also accept the same audit_sink kwarg so cached_hit /
cached_miss / rate_limited outcomes land in the same trail.
The wrappers stack outside-in. Adopters compose Caching(RateLimited(
Auditing(SQL-backed))) — the cache shortcuts repeated lookups before
the rate limiter or DB sees them; the rate limiter stops probe traffic
before the DB; the audit layer captures every actual lookup.
Wires the v3 reference seller's TenantScopedBuyerAgentRegistry into
the production stack with the same audit sink at every layer so SecOps
can reconstruct every resolve attempt. The make_registry factory
accepts ttl_seconds / rps_per_tenant / max_entries overrides for
adopters with different SLA / volume requirements.
Tests: tests/test_buyer_agent_registry_cache.py (23 tests covering
cache hit / miss / TTL expiry / LRU eviction / rate-limit threshold
+ refill / audit emission per outcome / sink-failure isolation /
end-to-end composition).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(buyer-agent-registry): hold lock in invalidate/clear (PR #407 fix-pack)
Code reviewer flagged that CachingBuyerAgentRegistry.invalidate() and
clear() mutated self._cache without holding self._lock. _store()'s
move_to_end / popitem(last=False) eviction races with concurrent
admin invalidate calls, risking RuntimeError or LRU-order corruption.
Convert both to async + acquire the lock before mutating. Test
updated to await the new coroutine.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* ci: retrigger
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e6dfaad commit 5a1e6b6
5 files changed
Lines changed: 1319 additions & 4 deletions
File tree
- examples/v3_reference_seller/src
- src/adcp/decisioning
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | | - | |
110 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
111 | 116 | | |
112 | 117 | | |
113 | 118 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| 30 | + | |
29 | 31 | | |
| 32 | + | |
30 | 33 | | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
35 | 38 | | |
| 39 | + | |
| 40 | + | |
36 | 41 | | |
37 | 42 | | |
38 | 43 | | |
| |||
130 | 135 | | |
131 | 136 | | |
132 | 137 | | |
133 | | - | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
134 | 146 | | |
135 | 147 | | |
136 | | - | |
137 | | - | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
138 | 184 | | |
139 | 185 | | |
140 | 186 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
90 | 95 | | |
91 | 96 | | |
92 | 97 | | |
| |||
173 | 178 | | |
174 | 179 | | |
175 | 180 | | |
| 181 | + | |
176 | 182 | | |
177 | 183 | | |
178 | 184 | | |
179 | 185 | | |
180 | 186 | | |
181 | 187 | | |
182 | 188 | | |
| 189 | + | |
183 | 190 | | |
184 | 191 | | |
185 | 192 | | |
| |||
207 | 214 | | |
208 | 215 | | |
209 | 216 | | |
| 217 | + | |
210 | 218 | | |
211 | 219 | | |
212 | 220 | | |
| |||
0 commit comments