An Apache APISIX 3.x plugin (Lua, Apache-2.0) implementing the SAME canonical plugin contract as Kong and litellm-dynamo: the same decision table, the same 402 challenge schema, the same conformance vectors. Allowance credentials verify offline against pinned engine signers (no network call in the request path), units meter from the response payload and tick to the engine asynchronously, and missing/stale/revoked-at-last-sync state denies — fail closed.
Everything decision-shaped lives in apisix/plugins/dynamo/core/*, the byte-identical vendor copy of the Kong core (make audit-plugin-core enforces it); the APISIX host shim handles schema, phases, headers, and timers only.
Field-for-field identical to the Kong plugin's table — expressed as an APISIX JSON schema, attachable per route or as global plugin config: engine_url and engine_signers required; max_stale_seconds, sync_seconds, the four units_per_* metering rates, the x402 seller fields (pay_to, asset, resources), exposure and finality bounds.
Standalone (no etcd): mount the package's apisix/ tree, set
apisix:
extra_lua_path: "/opt/dynamo/?.lua"
plugins:
- dynamo
and attach the plugin to routes in apisix.yaml. Route-level config works the same through the Admin API / etcd in a full deployment. Pinned image: apache/apisix:3.11.0-debian.
cd /Users/steve/dpv1-aug26 && pwd
make test-gateways # the core spec inside the PINNED apisix image
make audit-plugin-core # core byte-identical across gateways
make conformance-apisix # full x402 catalog vs a LIVE APISIX container
make p17 # 10k-vector decision parity vs {reference, litellm, kong}
If a gateway's architecture ever forced divergent behavior, that would be a blocker to resolve openly — never a silent adaptation. To date, none has.