Skip to content

feat: rewrite README around the seller journey + harden buyer discovery surfaces#699

Open
OisinKyne wants to merge 2 commits into
mainfrom
oisin/fable-1
Open

feat: rewrite README around the seller journey + harden buyer discovery surfaces#699
OisinKyne wants to merge 2 commits into
mainfrom
oisin/fable-1

Conversation

@OisinKyne

@OisinKyne OisinKyne commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related pushes toward the same goal — making it easier for buyers to find, understand, and pay a seller running the Obol Stack.

README rewrite

The README still pitched "run decentralised infrastructure locally" while the actual product story — sell inference/agents/HTTP services via x402, get discovered, buy from other sellers — lived almost entirely in the Troubleshooting section. obol sell http/agent/pricing/register/info/identity, obol buy inference, and all of obol domain appeared nowhere.

The new README is journey-ordered: Overview → Getting Started → Sell your first paid service → Sell other service types → Run your business → Buy services → Agents/Skills → Models → Networks → Apps. Notables:

  • A "Get discovered" table documenting all six public surfaces (/, /skill.md, /api/services.json, /openapi.json, /.well-known/agent-registration.json, /services/<name>/*).
  • The tunnel moved from a late optional section into step 2 of the sell journey.
  • obol buy inference documented as a first-class CLI command (previously only mentioned via buy.py).
  • Every command example verified against the current cmd/obol flag definitions (e.g. sell inference --network alias --chain default base; agent new positional name + --model/--skills/--objective/--create-wallet).
  • Sections that were accurate (networks, apps, model guidance, troubleshooting, dev setup) kept with minimal edits; the monetize preflight checklist stays in Troubleshooting.

Buyer discovery surface bundle

Four gaps that directly hurt buyer conversion, from the discovery-surface audit:

  1. CORS + caching on catalog routes — new obol-catalog-headers Traefik Middleware (Access-Control-Allow-Origin: *, GET, OPTIONS, Cache-Control: public, max-age=300) attached via ExtensionRef to /skill.md, /openapi.json, /api, and /api/services.json. Browser-based buyers and dashboards could previously not fetch the catalog at all. Deliberately not attached to paid /services/* routes, nor to the ERC-8004 registration routes (those live in per-agent namespaces where a Gateway API ExtensionRef cannot reference an x402-namespace Middleware).
  2. Worked examples in /skill.md — every service block gains a "Try it" section: a 402-probe curl plus, for inference/agent offers, the paid chat-completions request built from internal/buyprompts — byte-identical to the buy.example field services.json publishes, so the two surfaces cannot drift. Model resolution (incl. the Status.AgentResolution fallback for agent offers) extracted into a shared catalogModelName() helper used by both generators.
  3. schemaVersion: "1" on the services.json envelope — first field of the envelope, added to the JSON schema as required. All in-repo consumers verified lenient (plain json.Unmarshal, no DisallowUnknownFields; the storefront's catalog.ts picks named fields; buy.py reads specific keys).
  4. Link: </api/services.json>; rel="catalog" header on 402 responses — both JSON and HTML paths, so an agent landing on a paid endpoint cold can self-serve discovery. Header-only; zero change to verification/settlement logic or the 402 body schema.

Testing

  • Six new tests: headers-middleware rendering, all four catalog routes carry the filter, schemaVersion (decoded + raw wire + fallback envelope), skill.md "Try it" for inference/agent/http fixtures, 402 Link header through the real ForwardAuth middleware (no-payment + invalid-payment rechallenge), and the JSON/HTML PaymentRequired branches.
  • Full suite green: go build ./..., go test ./internal/serviceoffercontroller/... ./internal/x402/... ./internal/schemas/... ./internal/buyprompts/... ./cmd/obol/... ./internal/buy/...
  • Live-verified on a dev cluster (rebuilt serviceoffer-controller): CORS/Cache-Control headers present on catalog routes, Try-it blocks render with real model ids, 402 carries the Link header.

Review focus

  • internal/x402/forwardauth.go / paymentrequired.go: the Link header must be the only behavioral delta — no change to verify/settle flow, status codes, or 402 body.
  • internal/serviceoffercontroller/render.go: the headers Middleware must not be attached to any /services/* paid route (locked by the pre-existing TestBuildHTTPRoute no-filter invariant).
  • internal/schemas/: schemaVersion is required in the schema — acceptable because the controller is the only producer and schema ships in lockstep.

🤖 Generated with Claude Code

@OisinKyne OisinKyne changed the title First clean ups from a fable pass feat: fable pass Jul 5, 2026
@OisinKyne OisinKyne changed the title feat: fable pass feat: rewrite README around the seller journey + harden buyer discovery surfaces Jul 6, 2026
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