Skip to content

feat(sell): register by default with explicit opt-out#349

Open
bussyjd wants to merge 4 commits intofeat/x402-pre-merge-followupfrom
feature/register-offchain-warning
Open

feat(sell): register by default with explicit opt-out#349
bussyjd wants to merge 4 commits intofeat/x402-pre-merge-followupfrom
feature/register-offchain-warning

Conversation

@bussyjd
Copy link
Copy Markdown
Collaborator

@bussyjd bussyjd commented Apr 17, 2026

Summary

Replaces the warning-only UX with the actual stronger design:

  • obol sell http now registers by default
  • --no-register is the explicit opt-out
  • registration is treated as part of the sell flow, not an optional afterthought
  • the controller no longer treats OffChainOnly as "registered and ready"

Why

The previous UX was not coherent:

  • obol sell http --register could still mean "only publish an off-chain document"
  • Registered=True / OffChainOnly looked like success even when nothing was on-chain
  • users had to mentally stitch together sell http and sell register as two unrelated commands

That is the wrong model.

The product model should be:

  • selling a public service registers it by default
  • if a signer is not available, that is a blocking requirement unless the user explicitly opts out

Flow

Old behavior

flowchart TD
    A[obol sell http --register] --> B[Create ServiceOffer]
    B --> C[Controller publishes off-chain registration doc]
    C --> D{Controller signing key configured?}
    D -- yes --> E[Register on ERC-8004]
    D -- no --> F[Registered=True / OffChainOnly]
Loading

New behavior

flowchart TD
    A[obol sell http] --> B[Create ServiceOffer]
    B --> C[Ensure public route is live]
    C --> D{--no-register?}
    D -- yes --> E[Skip on-chain registration intentionally]
    D -- no --> F[Resolve signer]
    F --> G[Register on ERC-8004]
    G --> H[Controller observes on-chain registration]
    H --> I[Registered=True]
Loading

Seller UX

sequenceDiagram
    participant User
    participant CLI as obol sell http
    participant Ctrl as serviceoffer-controller
    participant Chain as ERC-8004

    User->>CLI: sell http ...
    CLI->>Ctrl: create ServiceOffer
    CLI->>CLI: ensure tunnel / route
    CLI->>CLI: resolve signer
    CLI->>Chain: register agent + metadata
    Ctrl->>Chain: recover registration by owner + URI
    Ctrl-->>User: Ready with Registered=True
Loading

What changed

CLI

  • sell http now enables registration by default
  • added --no-register to skip the automatic on-chain registration step
  • retained --register only as a compatibility no-op / deprecated path
  • added --private-key-file to sell http for explicit registration signer input
  • automatic registration uses the same registration machinery as sell register
  • registration signer must match the payment wallet for the automatic path
  • sell status <name> now prints a human summary including Agent ID and Registration Tx

Controller semantics

  • OffChainOnly is no longer considered ready
  • when the controller has no signing key, it waits for external registration instead of reporting success
  • the controller now recovers externally-created registrations by owner + published URI and then marks the offer registered

Tests / flows

  • updated CLI flag coverage
  • added direct tests for:
    • registration defaults / --no-register conflicts
    • private key material parsing
    • human sell status summary output
  • updated controller phase expectations
  • updated the BDD harness to use the actual default agent wallet as the seller wallet
  • updated flow-06 to use --no-register where registration is intentionally out of scope
  • updated flow-11 to use the unified flow instead of a separate sell register step

Docs

  • updated the public monetize guide
  • updated embedded skill docs and examples that still taught the old --register flow
  • updated the embedded monetize.py help text to mark --register as legacy metadata publishing

Validation

  • go test ./cmd/obol ./internal/serviceoffercontroller ./internal/x402
  • bash -n flows/flow-06-sell-setup.sh flows/flow-11-dual-stack.sh
  • full flow-11 rerun from clean Obol/k3d state: 41/41 passed

Flow-11 artifacts from the passing run

  • seller wallet: 0xC0De030F6C37f490594F93fB99e2756703c4297E
  • seller agent ID: 5008
  • tunnel URL: https://eliminate-counting-bonus-skating.trycloudflare.com
  • buyer signer wallet: 0x9aE40E84fb587fB3B526f5542934c3B2d18D67bF
  • settlement tx: 0xca98062273d612c700dd036aa2bd68c252f1c71e5da6d2bc469e589a98cc5031

User-visible contract

From this PR onward, the intended contract is:

  • obol sell http ... means sell and register
  • obol sell http ... --no-register means sell without on-chain registration on purpose
  • obol sell register remains the advanced/manual repair path, not the normal primary flow

@bussyjd bussyjd marked this pull request as ready for review April 19, 2026 03:45
@bussyjd bussyjd changed the title feat(sell): warn that --register is off-chain only feat(sell): register by default with explicit opt-out Apr 19, 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