Skip to content

feat: BDD tests + upstream auth + OASF-enriched ERC-8004 registration#257

Open
bussyjd wants to merge 4 commits intomainfrom
feat/oasf-enriched-registration
Open

feat: BDD tests + upstream auth + OASF-enriched ERC-8004 registration#257
bussyjd wants to merge 4 commits intomainfrom
feat/oasf-enriched-registration

Conversation

@bussyjd
Copy link
Collaborator

@bussyjd bussyjd commented Mar 5, 2026

Summary

Three-commit stack that adds BDD integration tests, upstream auth injection, and OASF-enriched ERC-8004 registration.

Commit 1: BDD integration tests + upstream auth + tunnel URL

  • 7 Gherkin scenarios (77 steps) following the real user journey — no kubectl shortcuts
  • x402-verifier upstreamAuth field: injects Authorization header on paid requests
  • obol tunnel status auto-sets AGENT_BASE_URL on obol-agent
  • Scoped RBAC: agent can only read litellm-secrets in llm namespace

Commit 2: Scoped RBAC

  • Removes secrets:get from cluster-wide ClusterRole
  • Adds namespaced Role+RoleBinding in llm scoped to litellm-secrets only

Commit 3: OASF-enriched registration

  • Registration JSON now includes OASF service entry with skills/domains taxonomy
  • On-chain setMetadata() calls for indexed discovery: x402.supported, service.type
  • discovery.py search --x402-only filters by MetadataSet events
  • CLI flags: --register-skills, --register-domains

BDD Scenarios (7 passing)

Scenario What it validates
Operator sells inference + agent reconciles obol sell http → CRD → 6-stage reconciliation
Unpaid request returns 402 x402 payment gate
Paid request returns real inference EIP-712 → verify → LiteLLM → Ollama
Discovery-to-payment cycle Parse 402 → sign → pay → 200
Paid request through tunnel Full flow via Cloudflare
Agent discovers service through tunnel .well-known → x402Support → OASF skills/domains → probe 402
Operator deletes + cleanup CR + pricing route removed

Three-Layer Discovery Architecture

See PR #256 comment for the full architecture diagram.

Before: Registration was a bare card (name + one endpoint + x402Support).
After: Machine-readable OASF skills/domains + on-chain indexed metadata for log-based filtering.

Test plan

# Against existing cluster (~2min)
OBOL_INTEGRATION_SKIP_BOOTSTRAP=true OBOL_TEST_MODEL=qwen3.5:9b \
  go test -tags integration -v -run TestBDDIntegration -timeout 10m ./internal/x402/

bussyjd added 4 commits March 6, 2026 00:28
Adds the full sell→discover→buy BDD test suite and the upstream auth
injection mechanism, rebased cleanly on current main.

## BDD Integration Tests (godog/Gherkin)

7 scenarios, 75 steps, following the real user journey:
  1. Operator sells inference via CLI + agent reconciles
  2. Unpaid request returns 402 with pricing
  3. Paid request returns real inference (EIP-712 → verify → Ollama)
  4. Full discovery-to-payment cycle
  5. Paid request through Cloudflare tunnel
  6. Agent discovers registered service through tunnel
  7. Operator deletes ServiceOffer + cleanup

TestMain bootstrap: obol stack init/up → model setup → sell pricing →
agent init → sell http → wait for reconciliation. No kubectl shortcuts.

## Upstream Auth Injection

x402-verifier now injects Authorization header on paid requests:
  - RouteRule.UpstreamAuth field in pricing config
  - Verifier sets header in 200 response → Traefik copies via authResponseHeaders
  - monetize.py reads LiteLLM master key → writes upstreamAuth to route
  - Eliminates manual HTTPRoute RequestHeaderModifier patches

## Tunnel URL Injection

`obol tunnel status` auto-sets AGENT_BASE_URL on the obol-agent deployment.
monetize.py reads it to publish the tunnel URL in registration JSON.

Files:
  - internal/x402/features/integration_payment_flow.feature (new)
  - internal/x402/bdd_integration_test.go (new)
  - internal/x402/bdd_integration_steps_test.go (new)
  - internal/x402/config.go (UpstreamAuth field)
  - internal/x402/verifier.go (inject Authorization on 200)
  - internal/embed/skills/sell/scripts/monetize.py (read master key, upstreamAuth)
  - internal/tunnel/tunnel.go (InjectBaseURL, auto-inject on status)
  - internal/embed/infrastructure/.../obol-agent-monetize-rbac.yaml (secrets:get)
The previous commit added secrets:get to the cluster-wide
openclaw-monetize-workload ClusterRole, which gave the agent
read access to ALL secrets in ALL namespaces.

Fix: remove secrets from ClusterRole and add a namespaced Role
in the llm namespace scoped to litellm-secrets only via
resourceNames restriction. Same pattern as the existing
openclaw-x402-pricing Role in the x402 namespace.

Verified:
  - Agent can read litellm-secrets in llm namespace (200 OK)
  - Agent cannot list kube-system secrets (403 Forbidden)
  - All 7 BDD scenarios pass with scoped RBAC
…ering

Enriches agent registration with machine-readable metadata for discovery:

## Off-chain (Registration JSON)
- Add OASF service entry with skills[] and domains[] taxonomy paths
  Default for inference: skills=["natural_language_processing/text_generation/chat_completion"]
  Default for inference: domains=["technology/artificial_intelligence"]
- Build richer description from spec (model name, price, type)
- Always emit supportedTrust field (empty array if none)
- CLI flags: --register-skills, --register-domains for custom taxonomy

## On-chain (setMetadata)
- New _set_metadata_on_chain() in monetize.py — ABI-encodes and signs
  setMetadata(uint256, string, bytes) via remote-signer + eRPC
- Sets "x402.supported" = 0x01 and "service.type" = "inference"|"http"
  after successful register() — indexed MetadataSet events enable
  eth_getLogs topic-based filtering without fetching every JSON

## Discovery
- discovery.py search --x402-only: filter by MetadataSet events where
  indexedMetadataKey == keccak256("x402.supported")
- discovery.py search --filter <key>: generic metadata key filter

## Types
- ServiceDef gains Skills/Domains fields (json:"skills/domains,omitempty")

## BDD
- Discover scenario now validates OASF skills and domains in registration

7 scenarios, 77 steps all pass.
Update obol-stack-dev skill with:
- BDD integration test documentation (7 scenarios, 77 steps)
- How to run: skip-bootstrap (2min) vs full bootstrap (15min)
- TestMain sequence (real user journey, no shortcuts)
- Per-scenario infrastructure (Anvil fork, mock facilitator)
- File locations (feature, test runner, step definitions)
- Updated triggers: x402, sell, buy, BDD, gherkin, payment, monetize
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant