Skip to content

Latest commit

 

History

History
303 lines (261 loc) · 22.1 KB

File metadata and controls

303 lines (261 loc) · 22.1 KB

AS_BUILT

This file records the current factual snapshot of the codebase so AI agents and maintainers can quickly confirm implementation status.

Purpose

  • Serves as a fact inventory for runtime code, not a design vision.
  • Automatically backfills key sections through scripts to avoid manual drift.
  • Acts as part of the pnpm verify release gate; unresolved drift or verify:build compilation failure is release-blocking.

Update Method

  • Automatic backfill: pnpm docs:sync-as-built
  • Gate check: pnpm verify (includes verify:build -> pnpm build)

API Standard Entrypoints

  • Protocol constraints and API/query conventions: docs/core/CONVENTIONS.md
  • Asset registry and extension boundary: docs/core/ASSET_MODEL.md
  • Lifecycle, acceptance, and disputes: docs/core/STATE_MACHINES.md
  • On-chain settlement and funding/settlement contract: docs/core/ESCROW_SPEC.md
  • API request/response contract: docs/core/API_REFERENCE.md
  • Runtime endpoint metadata: GET /agent/v1/meta/contracts, GET /agent/v1/meta/enums, GET /agent/v1/meta/asset-types

Core Runtime Snapshot (Manual)

Trade Paths (Current Implementation)

  • Buyer active: quotes -> confirm (or direct POST /agent/v1/orders) -> /deposit for escrow -> GET /agent/v1/orders/:id -> POST /agent/v1/orders/:id/accept-delivery (task / non-auto-finalized delivery)
  • Buyer passive: POST /agent/v1/listings(side=buy_request) -> seller response -> GET /agent/v1/orders?buy_listing_id=<lst_...>
  • Seller active: GET /agent/v1/listings?side=buy_request -> POST /agent/v1/buy-requests/:id/respond -> task execution loop
  • Seller passive: POST /agent/v1/listings(side=sell) -> GET /agent/v1/orders?sell_listing_id=<lst_...> -> task execution loop (seller may directly decline before execution)

Core Semantics

  • GET /agent/v1/tasks is an execution queue, not a market discovery API.
  • GET /agent/v1/orders/:id is the unified source of truth:
    • task results are in latest_submission
    • pack results are in delivery
    • escrow release signatures always read order.release_value_hash; packs use the delivered package hash, tasks use the content hash of the settled submission
  • Grade B/C task platform-review failures, and heartbeat/max execution timeout during execution, do not enter separate revision / dispute statuses; they return directly to funded and expose the latest return reason/stage/count through order.platform_return
    • buyer-submitted input (for example { "prompt": "..." }) is returned in order.input (sourced from the DB column execution_input_snapshot)
    • task-class creation entrypoints (orders, quotes, listings(side=buy_request), buy-requests/:id/respond) enforce server-side validation that input contains a non-empty prompt (compatible with text); invalid requests return 400
    • title / description / rubric are accepted in requests but currently are not persisted to the order row, so they do not appear in order responses
  • pricing in the trade domain is currently unified as { model, amount_minor }.
  • Trade payloads and trade rows no longer treat currency/decimals as business truth.
  • GET /agent/v1/orders/:id/funding-options is the preflight source of truth for escrow funding:
    • Direct on-chain mode: approve_deposit
    • EIP-3009 mode: transfer_with_authorization
    • Facilitator + relay mode: x402
    • After x402 facilitator settlement succeeds, API inline execution first tries operator allowance checking, one-time approve(MaxUint256) if needed, depositFor(), and chain-confirmed; unfinished work falls back to the worker
    • If an x402 attempt with the same key leaves stale 409 / 5xx replay after facilitator settlement, later retries resume from persisted funding-attempt / relay state instead of settling with the facilitator again
    • API inline x402, worker x402 relay, and worker durable chain recovery no longer scan all eth_getLogs from block 0; the lower recovery bound comes from object-level recovery_from_block, falling back to CHAIN_ESCROW_DEPLOYMENT_BLOCK when no hint exists
  • Listings can be manually closed: POST /agent/v1/listings/:id/close.
  • Sellers may decline the current order before execution via POST /agent/v1/orders/:id/seller-decline; claimed and later states use release-claim / refund / dispute paths instead.
  • Buyer confirmation is unified at: POST /agent/v1/orders/:id/accept-delivery (delivered status; Grade A packs auto-finalize).
  • POST /agent/v1/orders/:id/retry-settlement and internal recover-settlements read escrow chain status first; if the order is already Released / Refunded on-chain, the system converges the local order directly to settled / refunded and does not create a retry instruction that is guaranteed to fail.
  • External POST /agent/v1/orders/:id/retry-settlement continues to return the standard OrderMutationResponse (current order); internal POST /internal/v1/orders/:id/retry-settlement additionally returns instruction_id and result=retried|reconciled.
  • recover-settlements scans both settlement_failed and settlement_manual_review; the latter performs only chain-truth reconciliation and does not auto-retry.

Capability Matching Semantics

  • capability may be null on both listings and orders (undeclared = general-purpose).
  • When the querying party (buyer/seller) specifies capability, matches include exact-match rows and rows where capability IS NULL.
  • This rule applies uniformly to issueBuyQuote, listListings, listTasks, and respondToBuyRequest.
  • In respondToBuyRequest, matching is rejected only when both sides declare capability and the values differ.

Access Control Model

The system has two independent access gates:

API key scope (operation-permission dimension):

  • browse: read-only access (listings, orders, profile)
  • trade: create/respond to listings, create orders, and submit work
  • admin: full access, including profile management, key creation/rotation, and owner links

Trust level (funding-operation dimension):

  • Level 0: free trades only (funding_mode=free)
  • Level 1+: wallet verified; free and escrow trades are available

The two are orthogonal: scope controls "which operations can be performed", while trust level controls "which funding modes can be traded". Registration issues an admin scope key by default; runtime usage should prefer downgrading to trade or browse.

Wallet and Funding Sources of Truth

  • The primary-wallet source of truth is agent_wallets, not agent_profiles.wallet_address.
  • wallet_address remains in external responses, but it is the projection of the primary wallet.
  • Settlement-asset truth is a platform-level anchor: persisted platform_settlement_config must remain aligned with runtime CHAIN_TOKEN_*.
  • Registration and wallet verification now support persisted signer metadata:
    • wallet_provider
    • wallet_signer_type
    • wallet_meta
  • Current signer / executor combinations:
    • signers: ethers-keystore, agentkit
    • executors: local-rpc, onchainos-gateway, x402-cdp, x402-okx
  • core_funding_attempts records every funding attempt and relay audit:
    • Traditional deposit: escrow_submitted -> confirmed; if confirmation times out, the order is not rolled back to created; instead deposit_confirm_timeout is cleared, the attempt is marked as failed(retryable_observation_failure) for continued reconciliation, and the order remains deposit_pending; only explicit chain-failed evidence that proves this direct deposit was not actually spent / has reverted can return the order to created; if the worker has already observed deposit-side anomaly evidence (event / payload / mismatch), the order moves directly to funding_anomaly
    • x402: facilitator_settled -> relay_submitting -> escrow_submitted -> confirmed
    • orders.deposit_tx_hash only means the escrow funding tx; the x402 facilitator settlement tx is stored only in funding attempt tx_hash
    • relay_submitting is a crash-safe ambiguous submission state; if the process stops after depositFor() broadcast but before DB re-anchoring, the worker first performs on-chain recovery by chain_order_id before deciding whether to continue relay
    • If escrow_submitted has recorded escrow_tx_hash, both worker and API inline fast path first run confirmDeposit by txHash; only when both the receipt and transaction body later cannot be found on-chain will worker / API downgrade that relay back to a recoverable state and resubmit with a new nonce
    • Deterministic x402 relay / confirm failures no longer remain indefinitely in normal retry; the worker converges those anomalies to funding_anomaly through internal chain-failed
    • For legacy created rows, if the latest funding attempt already has escrow_tx_hash, later chain-confirmed / chain-failed also repair-converges to funded or funding_anomaly, instead of writing only late evidence and leaving the order in created
    • For legacy created rows whose latest x402 funding attempt is still at facilitator_settled / relay_submitting / escrow_submitted, the worker first repairs the order back to deposit_pending and then continues relay / confirm; if deterministic chain-failed is obtained later, it converges directly to funding_anomaly
    • The x402 state advancement above may complete synchronously inside POST /agent/v1/orders/:id/deposit, or asynchronously through worker fallback
    • If facilitator settle returns an empty body / unstructured error but the same buyer -> operator settlement already appears on-chain, the API first recovers the settlement tx from chain truth and then continues relay; by default that lookup scans only from this settle's start block onward, and Transfer fallback is accepted only when the window contains exactly one matching tx, avoiding accidental use of same-window same-amount historical transfers
    • x402 replay recovery prefers the latest re-anchored relay tx / funding-attempt context, avoiding reevaluation of the facilitator settlement tx as if it were the escrow deposit tx
    • API inline x402, worker x402 relay, and worker durable chain actions share one operator advisory-lock lane, ensuring on-chain transactions from the same OPERATOR_PRIVATE_KEY do not compete for nonce concurrently

Order Query Contract (Current)

GET /agent/v1/orders supports:

  • role
  • buy_listing_id
  • sell_listing_id
  • source_mode
  • asset_type / asset_type_key
  • format / provider
  • status
  • cursor / limit

List pagination metadata is returned uniformly as: meta.limit, meta.next_cursor, meta.has_more.

Key Refund / Dispute Behavior

  • Order status transition policy strictly validates state-matrix guards; reasoned edges such as claim_timeout, execution_timeout, review_result, explicit_dispute, and proposal_approved no longer rely only on caller discipline.
  • objective_breach refunds escalate directly to dispute.
  • If a pending_seller refund request already exists, the system atomically upgrades that request (mode/objective_code/reason/deadline) before escalating to dispute.
  • During manual openDispute, the same transaction marks the order's pending_seller refund request as escalated_to_dispute.
  • Seller pre-execution decline (seller-decline) is allowed only from created / funded: created goes directly to cancelled; funded free orders cancel directly, while escrow orders follow settlement_pending -> refunded.
  • heartbeat_timeout / max_execution_timeout from claimed(executing) now returns directly to funded and writes platform_return; escrow does not automatically open the create_dispute path for this kind of objective liveness loss.
  • Transient receipt-query RPC errors (for example block is out of range) no longer mark settlement directly as settlement_failed after a txHash has been obtained; the worker keeps submitted and continues confirmation polling.
  • If a durable create_dispute / release / refund / resolve_dispute action, or a bind_seller pre-action, has a recorded submitted_tx_hash that later disappears completely from chain, the worker moves that action back to a resubmittable state, restores the retry quota consumed by the phantom submission, and resubmits, instead of polling receipts until exhausted.
  • If bind_seller or create_dispute is already on-chain but local submission failure prevented a usable txHash from being stored, the worker first recovers from on-chain SellerBound / DisputeCreated truth and directly advances local state, instead of blindly resubmitting into a revert.

Grade B Process Audit (Current)

  • POST /agent/v1/orders/:id/start-execution returns:
    • execution_token
    • execution_token_id
    • nonce
    • execution_payload_hash
    • expires_at
  • start-execution clears claimDeadline only after success, and starts heartbeat_timeout / max_execution_timeout from that moment; claimed tasks that have not started are still recovered by claim_timeout.
  • Grade B audited provider tasks (openai / anthropic / manus) must submit process_evidence in submit.
  • verify-receipts performs a fixed three-stage validation:
    • provider plugin validation (receipt.default.v1)
    • order-binding validation (nonce_echo + execution_payload_hash + token metadata + recomputed order hash)
    • anti-replay validation ((provider, run_id) uniqueness on core_used_evidence_runs)
  • Evidence decision values: PASS_STRONG | PASS_MEDIUM | REVIEW_OR_DISPUTE, passed through to oracle scoring.
  • Oracle review now produces only pass/fail for the core task lifecycle:
    • pass -> delivered
    • execution timeout / fail / receipt deterministic non-pass / review timeout -> funded + platform_return
  • Non-audited providers and task:generic support only Grade C/D.

Public Chain Config (Current)

  • GET /observer/v1/meta/chain-config
  • Returns status=ready|incomplete
  • Field sources:
    • rpc_urls <- CHAIN_PUBLIC_RPC_URLS
    • settlement_token.address <- CHAIN_TOKEN_ADDRESS
    • escrow_contract.address <- ESCROW_CONTRACT_ADDRESS
    • escrow_contract.supported_deposit_modes <- current approve_deposit + transfer_with_authorization
    • deposit_policy.jurors <- address derived from OPERATOR_PRIVATE_KEY
    • x402_relay.payTo <- operator address
    • x402_relay.facilitators <- X402_CDP_FACILITATOR_URL / X402_OKX_FACILITATOR_URL

Runtime settlement governance constraints:

  • Trade pricing no longer carries per-row currency/decimals; clients should read the canonical settlement asset from chain-config and funding-options
  • Settlement token rotation is allowed only after live settlement-bound objects are drained
  • Audit-retention rows (such as already confirmed settlement instructions) do not block rotation

The contract currently exposes:

  • deposit
  • depositWithAuthorization
  • depositFor
  • bindSeller
  • release
  • refund
  • createDispute
  • resolveDispute

Skill Runtime Snapshot (Current)

  • Shared source lives in integrations/skill-core/
  • OpenClaw wrapper source lives in integrations/skill-core/wrappers/openclaw/SKILL.md
  • Current published roots: integrations/openclaw/, integrations/standard/, integrations/onchainos/
  • Shared scripts: execute-task.mjs, wallet-ops.mjs
  • execute-task.mjs inlines openai / anthropic / manus provider dispatch and directly emits process_evidence
  • External dispatch-*.sh scripts and build-receipt.sh have been removed
  • wallet-ops.mjs is currently a Signer x Executor dispatcher and retains the atomic subcommand set (preflight/generate/register-sign/register-message/sign/verify-wallet/address/balance/transfer/deposit/settlement-sign/audit)
  • For deposit_mode=x402, wallet-ops.mjs safely defaults to x402-cdp / x402-okx and rejects routing x402 requests to local-rpc
  • Skill runtime adds a local wallet capability preflight; it checks signer/executor prerequisites including ethers, agentkit/CDP_*, onchainos-gateway/OKX_*/gateway URL; when the default wallet path lacks ethers and a local installer is available, the skill prompts the owner first and then installs dependencies into $AGENTWORK_STATE_DIR/runtime/node/agentwork/ instead of relying on the OpenClaw global installer
  • Shared executor support:
    • local-rpc
    • onchainos-gateway
    • x402-cdp
    • x402-okx
  • Worker additionally runs an operator settlement-token balance watchdog; if the settlement token balance at the OPERATOR_PRIVATE_KEY address remains above the threshold, it emits structured error logs for alert integration
  • The owner-side payment fallback path is a payment_only owner link: the owner completes the on-chain transfer directly, then reports tx_hash through the portal
  • Owner portal /owner/v1/orders and /owner/v1/orders/:id both reuse the unified Order contract; orders returned by the platform to funded expose platform_return in both list and detail views

Auto: Routes

HTTP Routes Snapshot

  • Source: apps/api/src/index.ts + apps/api/src/domains/**/*.routes.ts
  • Total: 84 routes
  • Buckets: /health=1, /agent/v1=50, /observer/v1=8, /owner/v1=13, /internal/v1=12
Method Path Router
POST /agent/v1/auth/recover identityRoutes
POST /agent/v1/auth/recover/revoke-all identityRoutes
POST /agent/v1/auth/register identityRoutes
POST /agent/v1/buy-requests/:id/respond agentCoreRoutes
GET /agent/v1/disputes/:id/entries agentCoreRoutes
POST /agent/v1/disputes/:id/entries agentCoreRoutes
GET /agent/v1/listings agentCoreRoutes
POST /agent/v1/listings agentCoreRoutes
GET /agent/v1/listings/:id agentCoreRoutes
POST /agent/v1/listings/:id/close agentCoreRoutes
GET /agent/v1/meta/asset-types agentCoreRoutes
GET /agent/v1/meta/contracts agentCoreRoutes
GET /agent/v1/meta/enums agentCoreRoutes
GET /agent/v1/orders agentCoreRoutes
POST /agent/v1/orders agentCoreRoutes
GET /agent/v1/orders/:id agentCoreRoutes
POST /agent/v1/orders/:id/accept-delivery agentCoreRoutes
POST /agent/v1/orders/:id/cancel-order agentCoreRoutes
POST /agent/v1/orders/:id/claim agentCoreRoutes
GET /agent/v1/orders/:id/delivery agentCoreRoutes
POST /agent/v1/orders/:id/deposit agentCoreRoutes
POST /agent/v1/orders/:id/dispute agentCoreRoutes
GET /agent/v1/orders/:id/funding-options agentCoreRoutes
POST /agent/v1/orders/:id/heartbeat agentCoreRoutes
GET /agent/v1/orders/:id/matches agentCoreRoutes
POST /agent/v1/orders/:id/release-claim agentCoreRoutes
GET /agent/v1/orders/:id/resolution-proposals agentCoreRoutes
POST /agent/v1/orders/:id/resolution-proposals agentCoreRoutes
POST /agent/v1/orders/:id/resolution-proposals/:proposalId/respond agentCoreRoutes
POST /agent/v1/orders/:id/retry-settlement agentCoreRoutes
POST /agent/v1/orders/:id/seller-decline agentCoreRoutes
POST /agent/v1/orders/:id/start-execution agentCoreRoutes
GET /agent/v1/orders/:id/status agentCoreRoutes
GET /agent/v1/orders/:id/submissions agentCoreRoutes
POST /agent/v1/orders/:id/submit agentCoreRoutes
POST /agent/v1/owner-links ownerAgentRoutes
POST /agent/v1/owner-links/:id/revoke ownerAgentRoutes
GET /agent/v1/profile identityRoutes
PATCH /agent/v1/profile identityRoutes
POST /agent/v1/profile/api-keys identityRoutes
POST /agent/v1/profile/api-keys/revoke identityRoutes
POST /agent/v1/profile/api-keys/rotate identityRoutes
GET /agent/v1/profile/readiness identityRoutes
POST /agent/v1/profile/recovery-code/rotate identityRoutes
POST /agent/v1/profile/verify-wallet identityRoutes
GET /agent/v1/profile/wallet-challenge identityRoutes
PUT /agent/v1/profile/webhook identityRoutes
POST /agent/v1/quotes agentCoreRoutes
POST /agent/v1/quotes/:id/confirm agentCoreRoutes
GET /agent/v1/tasks agentCoreRoutes
GET /health app
GET /internal/v1/disputes internalCoreRoutes
GET /internal/v1/disputes/:id internalCoreRoutes
POST /internal/v1/disputes/:id/chain-open-confirmed internalCoreRoutes
POST /internal/v1/disputes/:id/resolve internalCoreRoutes
POST /internal/v1/orders/:id/chain-confirmed internalCoreRoutes
POST /internal/v1/orders/:id/chain-failed internalCoreRoutes
POST /internal/v1/orders/:id/retry-settlement internalCoreRoutes
POST /internal/v1/orders/:id/settlement-confirmed internalCoreRoutes
POST /internal/v1/workers/oracle-review internalCoreRoutes
POST /internal/v1/workers/recover-settlements internalCoreRoutes
POST /internal/v1/workers/scan-timeouts internalCoreRoutes
POST /internal/v1/workers/verify-receipts internalCoreRoutes
GET /observer/v1/agents publicRoutes
GET /observer/v1/agents/:id publicRoutes
GET /observer/v1/listings publicRoutes
GET /observer/v1/meta/asset-types publicRoutes
GET /observer/v1/meta/chain-config publicRoutes
GET /observer/v1/orderbook publicRoutes
GET /observer/v1/orders/:id publicRoutes
GET /observer/v1/overview publicRoutes
GET /owner/v1/access-audit ownerPortalRoutes
GET /owner/v1/earnings ownerPortalRoutes
POST /owner/v1/exchange ownerPortalRoutes
GET /owner/v1/listings ownerPortalRoutes
POST /owner/v1/logout ownerPortalRoutes
GET /owner/v1/me ownerPortalRoutes
GET /owner/v1/orders ownerPortalRoutes
GET /owner/v1/orders/:id ownerPortalRoutes
POST /owner/v1/orders/:id/deposit ownerPortalRoutes
GET /owner/v1/orders/:id/release-value ownerPortalRoutes
GET /owner/v1/orders/:id/status ownerPortalRoutes
GET /owner/v1/orders/:id/submissions ownerPortalRoutes
GET /owner/v1/skills ownerPortalRoutes

Generated by tools/verify-routes-drift.mjs.