From bbb72194687b8e9604f06c8ef0d9a276723ddf5a Mon Sep 17 00:00:00 2001 From: kapustazh <51422901+kapustazh@users.noreply.github.com> Date: Thu, 8 Oct 2026 18:45:55 +0200 Subject: [PATCH 1/2] docs: clarify B2B positioning and structure README --- ...20261008T163453Z-readme-b2b-positioning.md | 78 ++++ README.md | 417 ++++-------------- docs/DEVELOPER_GUIDE.md | 336 ++++++++++++++ 3 files changed, 496 insertions(+), 335 deletions(-) create mode 100644 .agent/context/20261008T163453Z-readme-b2b-positioning.md create mode 100644 docs/DEVELOPER_GUIDE.md diff --git a/.agent/context/20261008T163453Z-readme-b2b-positioning.md b/.agent/context/20261008T163453Z-readme-b2b-positioning.md new file mode 100644 index 0000000..2230a0d --- /dev/null +++ b/.agent/context/20261008T163453Z-readme-b2b-positioning.md @@ -0,0 +1,78 @@ +# Session Context: B2B README positioning + +## Date/time + +- UTC: 2026-10-08T16:34:53Z + +## User goal + +Refresh README for investors and partners and create a PR. + +## Original prompt/request + +Create a more structured startup README. Interview clarified B2B agent builders +as initial focus, internal agent operators as prospective buyers, and service +platforms as prospective partners. No customers or pilot feedback yet. Use +work@kapustazh.dev for enquiries; website changes come later. + +## Assumptions + +- Invite customer discovery, integration discussions, and early pilots. +- Retain documented testnet evidence without claiming new live validation. + +## Plan + +1. Rewrite overview; preserve technical reference in developer guide. +2. Validate documentation, commit, push draft PR and observe CI. + User explicitly requested skipping FreePi on continuation. + +## Key decisions + +- Explain duplicate payment recovery rather than blockchain double spending. +- No accelerator relationship or traction claim. +- No implementation, deployment, or payment changes. + +## Files/components touched + +- README.md: B2B problem, buyer, evidence, stage, contact, documentation links. +- docs/DEVELOPER_GUIDE.md: existing technical README content with corrected links. +- This context record. + +## Commands/checks + +- Local Markdown link existence check: PASS. +- git diff --check: PASS. +- corepack pnpm install --frozen-lockfile: PASS. +- corepack pnpm lint, typecheck, and format:check: PASS. +- Runtime: Node 22.23.2; repository pins 24.19.0, CI must verify pinned runtime. +- Prettier --check and repository-configured markdownlint-cli2: PASS. +- Default markdownlint-cli initially reported inherited table/HTML conventions; + rerun with repository CLI2 configuration passed after removing emphasis-as-heading. +- Test matrix: behavior cases not applicable to documentation-only changes. + +## External-doc findings + +- No integration/version changes. Claims grounded in existing live evidence. + +## Unresolved questions + +- Pricing and customer demand remain unvalidated. + +## Git and PR state + +- Branch: feature/readme-b2b-positioning +- Base: origin/develop a60836b1acdb4a71aa1aaffd09f0a40f25903924 +- Commit: uncommitted. +- PR: draft to be created after push; GitHub authentication verified. +- CI: not run. + +## Review gates + +- Gate A: SKIPPED at explicit user instruction: "we don't need freepi here. chill". +- Gate B: SKIPPED at the same instruction. No passing review is claimed. +- Deviation from .agent/IMPLEMENTATION_LOOP.md is explicit; PR remains draft. + +## Handoff/next steps + +1. Create draft PR and report validation and gate deviation. +2. A human reviews and merges; do not mark ready or merge automatically. diff --git a/README.md b/README.md index a41e962..233dbff 100644 --- a/README.md +++ b/README.md @@ -19,370 +19,117 @@ **One job. Many retries. One settlement.** -OneShot protects an approved business obligation from duplicate committed -settlements through retries, crashes, lost responses, queue redelivery, -parallel workers, and multiple agent instances. +OneShot is a settlement engine for companies building AI agents that purchase +paid tools and services. It keeps one approved business obligation tied to at +most one committed settlement, even when a job retries, crashes, or loses the +payment response. -Product direction: **resumable paid tools for business agents** — resume the -job, not the payment. The settlement engine includes one team-operated testnet -report supplier, task-bound order/result delivery, a one-tool MCP endpoint for -agents, and separate public (`/`), agent-docs (`/docs/mcp`), and authenticated -cabinet (`/app`) routes. Resumable external work requires supplier support; this -is not a guarantee of exactly-once execution for arbitrary tools. +Early-stage prototype · Arc Testnet only · Seeking feedback and pilot partners. -The cardinality it protects is: +[Discuss an integration or pilot](mailto:work@kapustazh.dev) · +[Developer guide](docs/DEVELOPER_GUIDE.md) · +[Architecture](docs/DOMAIN_ARCHITECTURE.md) -```text -1 Business Intent / N Attempts / at most 1 committed Settlement -``` +## Why OneShot -## The problem +An agent pays for a service. The connection drops before the receipt arrives. +A replacement agent cannot tell whether payment succeeded. Retrying can pay +twice; stopping leaves the job unfinished and an operator investigating. -An autonomous agent is told to make a business payment for 1.25 USDC. It -submits the payment. The connection drops before the response arrives. +OneShot gives retries a durable identity and preserves payment evidence. An +uncertain payment enters `UNKNOWN` and must be reconciled before any decision +to retry payment. A missing or delayed index result never proves non-payment. -The agent now cannot tell the difference between: +The goal is to help teams recover interrupted agent workflows with a clear +record of what was approved, attempted, and settled. -- the payment never left, and -- the payment succeeded and the receipt was lost. +## Who we are building for -Retrying might pay twice. Not retrying might never pay at all. Most systems -guess. Guessing with money is how you get duplicate settlements. +Our initial focus is **B2B teams building AI agents** that buy paid API +operations or digital results. Companies running those agents internally are +prospective buyers; platforms selling services to agents are prospective +integration partners. -OneShot refuses to guess. An uncertain outcome becomes a durable `UNKNOWN` -state that must be reconciled from authoritative evidence before anything else -happens. **Absence of proof that a payment happened is never treated as proof -that it did not.** +A representative workflow is an agent buying a company report. If payment +succeeds but delivery fails, a replacement agent resumes the original job and +retrieves its result without a replacement payment. Supplier delivery recovery +requires the supplier to support stable order identity and result retrieval. ## How it works -```mermaid -flowchart TB - Clients[Agent API client and operator console] --> API[apps/api] - API --> Domain[packages/domain] - Domain --> Contracts[packages/contracts] - Domain --> Storage[packages/storage-postgres] - Storage --> DB[(PostgreSQL)] - Storage --> Outbox[Transactional outbox] - Outbox --> Worker[Settlement worker] - Outbox --> RecoveryWorker[Reconciliation worker] - Worker --> Domain - RecoveryWorker --> Reconciliation[packages/reconciliation] - Reconciliation --> SafetyCore[Deterministic recovery safety core] - SafetyCore --> Command[Versioned reconciliation command] - Command --> Domain - - Domain --> AuthPort[AuthorizationPort] - Domain --> SettlementPort[SettlementPort] - Reconciliation --> EvidencePort[EvidencePort] - Reconciliation --> IndexPort[IndexViewPort] - Reconciliation --> AdvisorPort[RecoveryAdvisorPort] - - AuthPort --> PrivyAdapter[packages/privy-adapter] - SettlementPort --> PrivyAdapter - EvidencePort --> ArcAdapter[packages/arc-adapter] - IndexPort -.-> GraphAdapter[Graph recovery adapter] - AdvisorPort -.-> RecoveryAgent[LLM recovery agent] - - PrivyAdapter --> Privy[Privy wallet and policy] - ArcAdapter --> Arc[Arc USDC and RPC] - GraphAdapter -.-> Studio[Subgraph Studio GraphQL] - GraphAdapter -.-> MCP[Optional Subgraph MCP] - Studio -.-> GraphIndex[OneShot Arc Subgraph] - MCP -.-> GraphIndex -``` - -Solid edges are implemented. Dashed runtime edges are bounded production paths: -the active Arc Testnet profile uses authenticated, pinned Subgraph Studio -GraphQL; Subgraph MCP remains an optional fail-closed adapter for deployments -served by The Graph Network. The recovery agent remains advisory. Neither -external index evidence nor model advice can authorize settlement. - -### The state machine - -Every Business Intent moves through durable, compare-and-set transitions. Only -one of them grants the right to touch the outside world. - -```mermaid -stateDiagram-v2 - [*] --> AUTHORIZING: intent accepted - AUTHORIZING --> REJECTED: policy denies - AUTHORIZING --> READY: policy authorizes - READY --> SUBMITTING: atomic owner grant - SUBMITTING --> COMMITTED: verified receipt and Transfer - SUBMITTING --> FAILED_SAFE: proof of no submission - SUBMITTING --> UNKNOWN: timeout, crash, or doubt - UNKNOWN --> COMMITTED: verified success - UNKNOWN --> FAILED_SAFE: proof of no effect - UNKNOWN --> UNKNOWN: pending, not found, or unavailable - COMMITTED --> [*] - REJECTED --> [*] -``` - -`UNKNOWN` never grants permission to submit again. It is resolved by evidence -or escalated to a human. - -## Design rules - -These are enforced in code and tests, not by convention: - -- **A stable `business_intent_id` survives everything.** Retries, restarts, - redelivery, and parallel workers all converge on the same intent. -- **One atomic transition grants submission ownership.** Exactly one worker - crosses the external boundary. -- **Doubt fails closed.** A timeout, reset, truncated response, or any - unrecognized error is treated as _possibly submitted_, never as a safe retry. -- **A successful receipt is not confirmation.** Settlement is committed only - when the receipt carries exactly one matching ERC-20 Transfer, to the expected - recipient, for the exact amount, from the configured token. -- **Money is integer atomic units and `bigint`.** No JavaScript floating point - touches a monetary value anywhere. -- **External indexes are evidence, never authority.** An empty or delayed index - result cannot authorize a payment. - -## Integrations - -| System | Role | -| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Privy** | Corporate wallet, scoped authorization, and spending policy | -| **Arc** | USDC settlement rail (Arc Testnet, chain `5042002`) | -| **The Graph** | Arc USDC Subgraph discovery through the admitted Studio GraphQL path (optional MCP for Network-served deployments); evidence only, never settlement authority | - -Privy authorizes and constrains the wallet action. It is not the duplicate -lock: OneShot's durable state is. - -## Repository layout +1. **Record the obligation.** One stable business intent survives retries, + restarts, and multiple agent instances. +2. **Control settlement.** Durable, atomic state grants submission ownership; + authorization and spending policy constrain the worker-owned wallet action. +3. **Resolve uncertainty.** Reconcile ambiguous outcomes against provider and + Arc receipt evidence. Hold unresolved payments for further investigation. +4. **Resume delivery.** Keep the supplier result separate from settlement so + downstream failures do not erase an existing payment. ```text -apps/api HTTP seam, MCP endpoint, personal MCP credentials -apps/web landing, agent docs, and operator workspace -apps/worker settlement and reconciliation workers -packages/brand brand tokens, commit-ring mark, hero geometry -packages/supplier-adapter idempotent team-operated testnet report connector -packages/contracts frozen v1 contract pack, OpenAPI, fixtures -packages/domain intent, attempt, and settlement state -packages/storage-postgres durable ledger and migrations -packages/arc-adapter Arc profiles, money, receipts, readiness -packages/privy-adapter authorization, requests, policy, adapters -packages/reconciliation recovery evidence and safety core -packages/settlement-ui policy, authorization, and settlement evidence UI -packages/recovery-ui synthetic recovery evidence viewer -packages/testkit-* simulators and sanitized fixtures -subgraph Arc Testnet USDC transfer indexer +1 Business Intent / N Attempts / at most 1 committed Settlement ``` -## Quick start - -Requires Node `24.19.0`, pnpm `11.19.0`, and PostgreSQL for integration tests. - -```bash -pnpm install -pnpm lint && pnpm typecheck && pnpm build -pnpm test -pnpm test:browser -pnpm build:frontend -pnpm --filter @oneshot/web dev -``` - -Open `http://localhost:3000/` for the public landing page, `/docs/mcp` for the -agent connection guide, and `/app` for the authenticated workspace. The -workspace composes five sections — Overview, Payment services, Requests, -Payment proof, and Profile. Payment proof reads the configured OneShot API and -projects the frozen `recovery-view` API into the C05 timeline model, with -labelled fail-closed fallbacks for legacy or unavailable evidence, and -distinguishes a Graph observation that is still pending from proof that no -payment happened. Profile issues and rotates the personal MCP bearer. The P5 -browser acceptance suite runs with Playwright/Chromium in CI. - -Authenticated site activity is read-only: the API automatically queries the -configured Arc subgraph for every payer wallet recorded in the workspace, -records bounded Graph observations, and displays one audit row for every site -payment request, including rejected, failed-safe, uncertain, and committed -outcomes. Indexed transfers are linked to settlements and unmatched transfers -remain visible. Every committed settlement captures Graph evidence through a -durable, idempotent outbox job, including a backfill for settlements that -predate that capture. Graph absence or lag never changes payment authority; a -missing or reverted transfer event is not proof that no payment happened. - -A browser caller's workspace is derived from its verified Privy subject, so -jobs, results, and activity are scoped to the signed-in operator rather than to -a caller-supplied identifier. - -Integration tests need a database: - -```bash -pnpm test:integration -``` - -Copy `.env.example` to `.env` and `apps/web/.env.example` to -`apps/web/.env.local`, then fill in placeholders. Never commit a real secret; -see `docs/settlement/SETTLEMENT_CONFIG_V1.md` for how each variable is -classified. - -### Operator sign-in - -Privy operator login is optional and separate from the Privy wallet and -settlement-policy adapter in `packages/privy-adapter`. Set all three API -variables together: `PRIVY_AUTH_APP_ID`, `PRIVY_AUTH_VERIFICATION_KEY`, and -`PRIVY_AUTH_ALLOWED_SUBJECTS`. A partial configuration makes the API refuse to -start. With none set, the API accepts only `SERVICE_BEARER_TOKEN`; worker and -agent clients continue to use that service credential. - -The Team Report browser flow uses a separate user-funded path: after the quote, -the connected Privy Ethereum wallet is shown the exact Arc Testnet USDC -transfer and signs it in the browser. The API stores the payer binding and -accepts the job only after verifying the submitted receipt. The server-side -Privy execution wallet remains for worker-owned settlement operations; it is -not the payer for a Team Report started from Tools. - -Bootstrap an operator by setting `VITE_PRIVY_APP_ID`, starting the web app, -signing in, copying the DID shown by the console, adding that DID to -`PRIVY_AUTH_ALLOWED_SUBJECTS`, and then starting the API. Copy the public ES256 -verification key from Privy Dashboard → Configuration → App settings → Basics -→ Verify with key instead into runtime environment configuration. Never commit -the key. This boundary does not use the Privy app secret; never add that secret -to its configuration. - -To verify a configured Arc endpoint really is the chain and token you think it -is: - -```bash -pnpm --filter @oneshot/arc-adapter probe -``` - -That command is read-only. It cannot sign, send, or mutate anything. - -To view the standalone recovery fixture UI locally: - -```bash -pnpm --filter @oneshot/recovery-ui dev -``` - -Open `http://localhost:5173/?scenario=aged-unknown`. The public Wrangler target -uses the same clearly labelled synthetic viewer. Wrangler's build hook creates -the static bundle before local preview or `pnpm deploy`, including on a fresh -Cloudflare Workers Build checkout. - -## API - -### Arc Testnet transfer demo - -The resumable job flow uses a deliberately labelled team-operated supplier -until an external supplier is selected. In Payment services, enter the exact Arc -Testnet recipient and USDC amount for the purchase. The amount must be within -the settlement cap. A committed job's settlement and ArcScan evidence remain -authoritative; delivery resume never submits a replacement payment. - -`pnpm demo:r4` runs the response-loss drill offline by default. The live mode -requires an explicit Arc Testnet confirmation and the reviewed worker hook; -it emits a sanitized trace and stops at `HOLD`/`INCOMPLETE` when settlement, -Studio evidence or the supplier result cannot be proven. - -For a safe rehearsal, use a small integer quote such as `10000` atomic USDC -(`0.01 USDC`), fund only the Privy testnet wallet, and use a second team-owned -Arc Testnet wallet as the recipient. This proves the Privy/Arc settlement rail; -it is not a claim of third-party supplier execution. - -The cabinet follows a two-step approval flow: enter a company/domain, recipient -wallet and USDC amount, request the live quote, review amount/recipient/ -network/expiry, then explicitly approve payment. The generated task key is -shown for retries; users do not need to invent one. After settlement, the job -list links directly to ArcScan and keeps the supplier result separate from -payment evidence. - -| Method | Path | Purpose | -| ------ | ------------------------------------- | -------------------------------------------------------------- | -| `POST` | `/v1/intents` | Create an intent; an identical replay returns the same result | -| `GET` | `/v1/intents/{id}` | Authoritative intent, attempts, settlement, evidence | -| `POST` | `/v1/intents/{id}/reconcile` | Trigger read-only reconciliation; never submits | -| `GET` | `/v1/intents/{id}/recovery-view` | Local authority plus labelled provider observations | -| `POST` | `/v1/jobs` | Start/replay one workspace-scoped team report task | -| `POST` | `/v1/jobs/quote` | Return a non-chargeable quote before explicit approval | -| `POST` | `/v1/jobs/user-wallet/prepare` | Bind a payer wallet and return the exact transfer to sign | -| `GET` | `/v1/jobs` | List workspace jobs and delivery state | -| `GET` | `/v1/jobs/{jobId}` | Read a workspace-owned job | -| `POST` | `/v1/jobs/{jobId}/user-wallet/submit` | Bind a signed transaction hash and verify its receipt | -| `POST` | `/v1/jobs/{jobId}/resume` | Resume original supplier delivery; never submits payment | -| `GET` | `/v1/jobs/{jobId}/result` | Retrieve an existing supplier result; never submits payment | -| `GET` | `/v1/activity` | Last bounded Graph activity observation and local comparison | -| `POST` | `/v1/activity/refresh` | Manually refresh Graph activity; no settlement action | -| `GET` | `/v1/metrics` | Operational metrics | -| `GET` | `/health/live` | Process liveness | -| `GET` | `/health/ready` | Configuration and Arc identity readiness | - -The contract is defined in `packages/contracts/openapi/openapi.v1.json`. +OneShot owns intent and settlement state. Privy provides wallet access and +scoped authorization on the worker-owned settlement path; Arc provides the +USDC settlement rail. The Graph discovers recovery candidates and supplies +observations, while Arc verifies them. Index results and model advice cannot +authorize settlement. -### Agent access (MCP) +Browser and MCP user-wallet flows use a separate payer-bound path: the user's +wallet signs and broadcasts the transaction, and OneShot verifies its receipt. +An MCP bearer authenticates a workspace; it cannot sign or broadcast payments. -Agents reach the same durable job path through one Streamable HTTP MCP -endpoint. The flow is non-custodial: `arc_payment` creates or replays a -payer-bound job and returns the exact Arc Testnet USDC transaction request, the -user's own wallet signs and broadcasts it, and `arc_payment_submit` hands back -the transaction hash so OneShot can bind it and verify the receipt and its -single matching `Transfer` log. +## What exists today -The MCP bearer authenticates a workspace. It does not authorize a server payer -and cannot sign or broadcast anything. Personal bearers are issued from the -authenticated Profile and stored only as SHA-256 digests; the legacy -operator-controlled `ONESHOT_MCP_BEARER_TOKEN` remains optional. +| Area | Current evidence and limits | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Settlement engine | Durable intent ledger, API, settlement workers, and reconciliation core are implemented. | +| Testnet payment and recovery | Repository evidence records a live 1.00 USDC Privy-authorized Arc Testnet settlement, policy denials with zero broadcasts, and a lost-response drill that recovered the original settlement without another payment. | +| Agent and operator access | Browser workspace and MCP tools `arc_payment` and `arc_payment_submit` are implemented. A live end-to-end MCP payment trace remains pending in the documented status. | +| Paid job delivery | A team-operated testnet report supplier supports task/order binding and separate delivery/result retrieval. Third-party supplier execution is not demonstrated. | +| Graph recovery | Studio GraphQL discovery is implemented. Fresh live evidence of its material effect on model-assisted recovery remains pending; sponsor qualification is not verified. | -| Method | Path | Purpose | -| ------ | ------------------------------ | -------------------------------------------------------------- | -| `ALL` | `/mcp` | MCP endpoint exposing `arc_payment` and `arc_payment_submit` | -| `GET` | `/v1/profile/mcp-token` | Report whether this workspace holds a personal MCP bearer | -| `POST` | `/v1/profile/mcp-token` | Issue a personal MCP bearer; only its digest is stored | -| `POST` | `/v1/profile/mcp-token/rotate` | Replace the personal MCP bearer | +See [live settlement evidence](docs/settlement/LIVE_EVIDENCE.md) and the +[qualification report](packages/reconciliation/docs/c06/QUALIFICATION_REPORT.md) +for the recorded runs and their limitations. These are prototype evidence, +not production-scale validation. Mainnet is disabled. -These operator and agent-transport routes sit outside the frozen v1 contract -pack. See [`docs/MCP_ARC_PAYMENT.md`](docs/MCP_ARC_PAYMENT.md) for deployment, -client configuration, and the live walkthrough, or open `/docs/mcp` in the -running web app. +## Stage and next steps -## Project status +OneShot is built by a two-person team and is currently validating its customer +problem. We do not yet have customers, paying pilots, or a validated customer +feedback loop. Pricing is undecided; subscription and per-transaction models +are options to test with prospective buyers. -Under active development. **Testnet only.** +Our next priority is customer discovery with agent builders and internal +automation teams, followed by a narrowly scoped pilot. We want to understand +how teams handle ambiguous payments today, what recovery costs them, and where +OneShot would fit into their existing stack. -| Area | Status | -| -------------------------------------- | ---------------------------------------------------------------------------------------------- | -| Durable intent ledger, API, worker | Implemented | -| Settlement adapters and error taxonomy | Implemented; simulator-tested and live-verified on Arc Testnet through Privy | -| Recovery evidence and safety core | Live Graph/Vertex path implemented; deterministic core remains authoritative | -| Graph discovery and LLM recovery agent | Studio GraphQL path implemented; fresh sponsor trace pending; deterministic core remains final | -| Resumable team report job | Local code: task/order/intent binding, separate delivery and result retrieval | -| User-wallet payments (browser and MCP) | Local code: payer binding, wallet-side signing, receipt and `Transfer` verification | -| Agent MCP endpoint | Deployed; bearer authentication and tool discovery verified, no live MCP payment trace yet | -| Public landing, agent docs, cabinet | Local code at `/`, `/docs/mcp`, and `/app`; live R4 demonstration evidence remains pending | +We are also seeking service-platform partners to test payment and delivery +recovery together. Broad supplier support and exactly-once execution of +arbitrary tools are outside the current demonstrated scope. -**One live testnet settlement has been executed.** A Privy-controlled execution -wallet and scoped policy authorized one 1.00 USDC Arc Testnet transfer; live -wrong-recipient and above-cap denials produced zero broadcasts. A lost-response -drill entered `UNKNOWN` and reconciled to that original settlement without a -replacement payment. Privy and Arc are `QUALIFIED` for the documented testnet -claim; see `docs/settlement/LIVE_EVIDENCE.md` and -`packages/reconciliation/docs/c06/QUALIFICATION_REPORT.md`. +## Talk to us -The Graph recovery path is currently `NOT VERIFIED` for sponsor qualification: -Studio GraphQL is implemented, but a fresh live trace showing its material -effect on the model and deterministic core is still required. +Building agents that purchase services, running them inside your company, or +selling tools to agents? We would like to hear how you handle retries and lost +payment responses, and discuss a technical integration or early pilot. -Arc Mainnet is not configured. Its profile carries no chain ID, RPC, explorer, -or token value by design, and enabling it requires published official values -plus explicit human authorization. +**[work@kapustazh.dev](mailto:work@kapustazh.dev)** -## Documentation +## Explore the project -| Document | Contents | -| ------------------------------------------------------------------------ | -------------------------------------------------------- | -| [`plan.md`](plan.md) | Product plan, scope, and delivery gates | -| [`docs/DOMAIN_ARCHITECTURE.md`](docs/DOMAIN_ARCHITECTURE.md) | Domain model and boundaries | -| [`docs/MCP_ARC_PAYMENT.md`](docs/MCP_ARC_PAYMENT.md) | One-tool MCP deployment and live walkthrough | -| [`docs/RECOVERY_HARDENING.md`](docs/RECOVERY_HARDENING.md) | Recovery, runtime, authentication, and metrics contracts | -| [`milestones/CONTRACTS.md`](milestones/CONTRACTS.md) | Frozen v1 contract pack | -| [`docs/settlement/`](docs/settlement/) | Settlement config, provider setup, live evidence | -| [`packages/reconciliation/docs/c06/`](packages/reconciliation/docs/c06/) | C06 demo and qualification evidence index | -| [`docs/RELEASE_CHECKLIST.md`](docs/RELEASE_CHECKLIST.md) | R5 release evidence and submission checklist | -| [`AGENTS.md`](AGENTS.md) | Contribution policy and review gates | +| Resource | Purpose | +| -------------------------------------------------- | ------------------------------------------------------------------------------- | +| [Developer guide](docs/DEVELOPER_GUIDE.md) | Local setup, operator sign-in, repository layout, API routes, and state machine | +| [Domain architecture](docs/DOMAIN_ARCHITECTURE.md) | Ownership, domain model, and system boundaries | +| [Agent connection guide](docs/MCP_ARC_PAYMENT.md) | MCP deployment, client configuration, and walkthrough | +| [Recovery hardening](docs/RECOVERY_HARDENING.md) | Recovery, authentication, and operational contracts | +| [Product plan](plan.md) | Scope, roadmap, and delivery gates | +| [Contribution policy](AGENTS.md) | Repository policies and review requirements | ## License -MIT. See [`LICENSE`](LICENSE). +MIT. See [LICENSE](LICENSE). diff --git a/docs/DEVELOPER_GUIDE.md b/docs/DEVELOPER_GUIDE.md new file mode 100644 index 0000000..281161f --- /dev/null +++ b/docs/DEVELOPER_GUIDE.md @@ -0,0 +1,336 @@ +# OneShot developer guide + +For the product overview and partnership enquiries, see [README](../README.md). + +## How it works + +```mermaid +flowchart TB + Clients[Agent API client and operator console] --> API[apps/api] + API --> Domain[packages/domain] + Domain --> Contracts[packages/contracts] + Domain --> Storage[packages/storage-postgres] + Storage --> DB[(PostgreSQL)] + Storage --> Outbox[Transactional outbox] + Outbox --> Worker[Settlement worker] + Outbox --> RecoveryWorker[Reconciliation worker] + Worker --> Domain + RecoveryWorker --> Reconciliation[packages/reconciliation] + Reconciliation --> SafetyCore[Deterministic recovery safety core] + SafetyCore --> Command[Versioned reconciliation command] + Command --> Domain + + Domain --> AuthPort[AuthorizationPort] + Domain --> SettlementPort[SettlementPort] + Reconciliation --> EvidencePort[EvidencePort] + Reconciliation --> IndexPort[IndexViewPort] + Reconciliation --> AdvisorPort[RecoveryAdvisorPort] + + AuthPort --> PrivyAdapter[packages/privy-adapter] + SettlementPort --> PrivyAdapter + EvidencePort --> ArcAdapter[packages/arc-adapter] + IndexPort -.-> GraphAdapter[Graph recovery adapter] + AdvisorPort -.-> RecoveryAgent[LLM recovery agent] + + PrivyAdapter --> Privy[Privy wallet and policy] + ArcAdapter --> Arc[Arc USDC and RPC] + GraphAdapter -.-> Studio[Subgraph Studio GraphQL] + GraphAdapter -.-> MCP[Optional Subgraph MCP] + Studio -.-> GraphIndex[OneShot Arc Subgraph] + MCP -.-> GraphIndex +``` + +Solid edges are implemented. Dashed runtime edges are bounded production paths: +the active Arc Testnet profile uses authenticated, pinned Subgraph Studio +GraphQL; Subgraph MCP remains an optional fail-closed adapter for deployments +served by The Graph Network. The recovery agent remains advisory. Neither +external index evidence nor model advice can authorize settlement. + +### The state machine + +Every Business Intent moves through durable, compare-and-set transitions. Only +one of them grants the right to touch the outside world. + +```mermaid +stateDiagram-v2 + [*] --> AUTHORIZING: intent accepted + AUTHORIZING --> REJECTED: policy denies + AUTHORIZING --> READY: policy authorizes + READY --> SUBMITTING: atomic owner grant + SUBMITTING --> COMMITTED: verified receipt and Transfer + SUBMITTING --> FAILED_SAFE: proof of no submission + SUBMITTING --> UNKNOWN: timeout, crash, or doubt + UNKNOWN --> COMMITTED: verified success + UNKNOWN --> FAILED_SAFE: proof of no effect + UNKNOWN --> UNKNOWN: pending, not found, or unavailable + COMMITTED --> [*] + REJECTED --> [*] +``` + +`UNKNOWN` never grants permission to submit again. It is resolved by evidence +or escalated to a human. + +## Design rules + +These are enforced in code and tests, not by convention: + +- **A stable `business_intent_id` survives everything.** Retries, restarts, + redelivery, and parallel workers all converge on the same intent. +- **One atomic transition grants submission ownership.** Exactly one worker + crosses the external boundary. +- **Doubt fails closed.** A timeout, reset, truncated response, or any + unrecognized error is treated as _possibly submitted_, never as a safe retry. +- **A successful receipt is not confirmation.** Settlement is committed only + when the receipt carries exactly one matching ERC-20 Transfer, to the expected + recipient, for the exact amount, from the configured token. +- **Money is integer atomic units and `bigint`.** No JavaScript floating point + touches a monetary value anywhere. +- **External indexes are evidence, never authority.** An empty or delayed index + result cannot authorize a payment. + +## Integrations + +| System | Role | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Privy** | Corporate wallet, scoped authorization, and spending policy | +| **Arc** | USDC settlement rail (Arc Testnet, chain `5042002`) | +| **The Graph** | Arc USDC Subgraph discovery through the admitted Studio GraphQL path (optional MCP for Network-served deployments); evidence only, never settlement authority | + +Privy authorizes and constrains the wallet action. It is not the duplicate +lock: OneShot's durable state is. + +## Repository layout + +```text +apps/api HTTP seam, MCP endpoint, personal MCP credentials +apps/web landing, agent docs, and operator workspace +apps/worker settlement and reconciliation workers +packages/brand brand tokens, commit-ring mark, hero geometry +packages/supplier-adapter idempotent team-operated testnet report connector +packages/contracts frozen v1 contract pack, OpenAPI, fixtures +packages/domain intent, attempt, and settlement state +packages/storage-postgres durable ledger and migrations +packages/arc-adapter Arc profiles, money, receipts, readiness +packages/privy-adapter authorization, requests, policy, adapters +packages/reconciliation recovery evidence and safety core +packages/settlement-ui policy, authorization, and settlement evidence UI +packages/recovery-ui synthetic recovery evidence viewer +packages/testkit-* simulators and sanitized fixtures +subgraph Arc Testnet USDC transfer indexer +``` + +## Quick start + +Requires Node `24.19.0`, pnpm `11.19.0`, and PostgreSQL for integration tests. + +```bash +pnpm install +pnpm lint && pnpm typecheck && pnpm build +pnpm test +pnpm test:browser +pnpm build:frontend +pnpm --filter @oneshot/web dev +``` + +Open `http://localhost:3000/` for the public landing page, `/docs/mcp` for the +agent connection guide, and `/app` for the authenticated workspace. The +workspace composes five sections — Overview, Payment services, Requests, +Payment proof, and Profile. Payment proof reads the configured OneShot API and +projects the frozen `recovery-view` API into the C05 timeline model, with +labelled fail-closed fallbacks for legacy or unavailable evidence, and +distinguishes a Graph observation that is still pending from proof that no +payment happened. Profile issues and rotates the personal MCP bearer. The P5 +browser acceptance suite runs with Playwright/Chromium in CI. + +Authenticated site activity is read-only: the API automatically queries the +configured Arc subgraph for every payer wallet recorded in the workspace, +records bounded Graph observations, and displays one audit row for every site +payment request, including rejected, failed-safe, uncertain, and committed +outcomes. Indexed transfers are linked to settlements and unmatched transfers +remain visible. Every committed settlement captures Graph evidence through a +durable, idempotent outbox job, including a backfill for settlements that +predate that capture. Graph absence or lag never changes payment authority; a +missing or reverted transfer event is not proof that no payment happened. + +A browser caller's workspace is derived from its verified Privy subject, so +jobs, results, and activity are scoped to the signed-in operator rather than to +a caller-supplied identifier. + +Integration tests need a database: + +```bash +pnpm test:integration +``` + +Copy `.env.example` to `.env` and `apps/web/.env.example` to +`apps/web/.env.local`, then fill in placeholders. Never commit a real secret; +see `docs/settlement/SETTLEMENT_CONFIG_V1.md` for how each variable is +classified. + +### Operator sign-in + +Privy operator login is optional and separate from the Privy wallet and +settlement-policy adapter in `packages/privy-adapter`. Set all three API +variables together: `PRIVY_AUTH_APP_ID`, `PRIVY_AUTH_VERIFICATION_KEY`, and +`PRIVY_AUTH_ALLOWED_SUBJECTS`. A partial configuration makes the API refuse to +start. With none set, the API accepts only `SERVICE_BEARER_TOKEN`; worker and +agent clients continue to use that service credential. + +The Team Report browser flow uses a separate user-funded path: after the quote, +the connected Privy Ethereum wallet is shown the exact Arc Testnet USDC +transfer and signs it in the browser. The API stores the payer binding and +accepts the job only after verifying the submitted receipt. The server-side +Privy execution wallet remains for worker-owned settlement operations; it is +not the payer for a Team Report started from Tools. + +Bootstrap an operator by setting `VITE_PRIVY_APP_ID`, starting the web app, +signing in, copying the DID shown by the console, adding that DID to +`PRIVY_AUTH_ALLOWED_SUBJECTS`, and then starting the API. Copy the public ES256 +verification key from Privy Dashboard → Configuration → App settings → Basics +→ Verify with key instead into runtime environment configuration. Never commit +the key. This boundary does not use the Privy app secret; never add that secret +to its configuration. + +To verify a configured Arc endpoint really is the chain and token you think it +is: + +```bash +pnpm --filter @oneshot/arc-adapter probe +``` + +That command is read-only. It cannot sign, send, or mutate anything. + +To view the standalone recovery fixture UI locally: + +```bash +pnpm --filter @oneshot/recovery-ui dev +``` + +Open `http://localhost:5173/?scenario=aged-unknown`. The public Wrangler target +uses the same clearly labelled synthetic viewer. Wrangler's build hook creates +the static bundle before local preview or `pnpm deploy`, including on a fresh +Cloudflare Workers Build checkout. + +## API + +### Arc Testnet transfer demo + +The resumable job flow uses a deliberately labelled team-operated supplier +until an external supplier is selected. In Payment services, enter the exact Arc +Testnet recipient and USDC amount for the purchase. The amount must be within +the settlement cap. A committed job's settlement and ArcScan evidence remain +authoritative; delivery resume never submits a replacement payment. + +`pnpm demo:r4` runs the response-loss drill offline by default. The live mode +requires an explicit Arc Testnet confirmation and the reviewed worker hook; +it emits a sanitized trace and stops at `HOLD`/`INCOMPLETE` when settlement, +Studio evidence or the supplier result cannot be proven. + +For a safe rehearsal, use a small integer quote such as `10000` atomic USDC +(`0.01 USDC`), fund only the Privy testnet wallet, and use a second team-owned +Arc Testnet wallet as the recipient. This proves the Privy/Arc settlement rail; +it is not a claim of third-party supplier execution. + +The cabinet follows a two-step approval flow: enter a company/domain, recipient +wallet and USDC amount, request the live quote, review amount/recipient/ +network/expiry, then explicitly approve payment. The generated task key is +shown for retries; users do not need to invent one. After settlement, the job +list links directly to ArcScan and keeps the supplier result separate from +payment evidence. + +| Method | Path | Purpose | +| ------ | ------------------------------------- | ------------------------------------------------------------- | +| `POST` | `/v1/intents` | Create an intent; an identical replay returns the same result | +| `GET` | `/v1/intents/{id}` | Authoritative intent, attempts, settlement, evidence | +| `POST` | `/v1/intents/{id}/reconcile` | Trigger read-only reconciliation; never submits | +| `GET` | `/v1/intents/{id}/recovery-view` | Local authority plus labelled provider observations | +| `POST` | `/v1/jobs` | Start/replay one workspace-scoped team report task | +| `POST` | `/v1/jobs/quote` | Return a non-chargeable quote before explicit approval | +| `POST` | `/v1/jobs/user-wallet/prepare` | Bind a payer wallet and return the exact transfer to sign | +| `GET` | `/v1/jobs` | List workspace jobs and delivery state | +| `GET` | `/v1/jobs/{jobId}` | Read a workspace-owned job | +| `POST` | `/v1/jobs/{jobId}/user-wallet/submit` | Bind a signed transaction hash and verify its receipt | +| `POST` | `/v1/jobs/{jobId}/resume` | Resume original supplier delivery; never submits payment | +| `GET` | `/v1/jobs/{jobId}/result` | Retrieve an existing supplier result; never submits payment | +| `GET` | `/v1/activity` | Last bounded Graph activity observation and local comparison | +| `POST` | `/v1/activity/refresh` | Manually refresh Graph activity; no settlement action | +| `GET` | `/v1/metrics` | Operational metrics | +| `GET` | `/health/live` | Process liveness | +| `GET` | `/health/ready` | Configuration and Arc identity readiness | + +The contract is defined in `packages/contracts/openapi/openapi.v1.json`. + +### Agent access (MCP) + +Agents reach the same durable job path through one Streamable HTTP MCP +endpoint. The flow is non-custodial: `arc_payment` creates or replays a +payer-bound job and returns the exact Arc Testnet USDC transaction request, the +user's own wallet signs and broadcasts it, and `arc_payment_submit` hands back +the transaction hash so OneShot can bind it and verify the receipt and its +single matching `Transfer` log. + +The MCP bearer authenticates a workspace. It does not authorize a server payer +and cannot sign or broadcast anything. Personal bearers are issued from the +authenticated Profile and stored only as SHA-256 digests; the legacy +operator-controlled `ONESHOT_MCP_BEARER_TOKEN` remains optional. + +| Method | Path | Purpose | +| ------ | ------------------------------ | ------------------------------------------------------------ | +| `ALL` | `/mcp` | MCP endpoint exposing `arc_payment` and `arc_payment_submit` | +| `GET` | `/v1/profile/mcp-token` | Report whether this workspace holds a personal MCP bearer | +| `POST` | `/v1/profile/mcp-token` | Issue a personal MCP bearer; only its digest is stored | +| `POST` | `/v1/profile/mcp-token/rotate` | Replace the personal MCP bearer | + +These operator and agent-transport routes sit outside the frozen v1 contract +pack. See [`docs/MCP_ARC_PAYMENT.md`](../docs/MCP_ARC_PAYMENT.md) for deployment, +client configuration, and the live walkthrough, or open `/docs/mcp` in the +running web app. + +## Project status + +Under active development. **Testnet only.** + +| Area | Status | +| -------------------------------------- | ---------------------------------------------------------------------------------------------- | +| Durable intent ledger, API, worker | Implemented | +| Settlement adapters and error taxonomy | Implemented; simulator-tested and live-verified on Arc Testnet through Privy | +| Recovery evidence and safety core | Live Graph/Vertex path implemented; deterministic core remains authoritative | +| Graph discovery and LLM recovery agent | Studio GraphQL path implemented; fresh sponsor trace pending; deterministic core remains final | +| Resumable team report job | Local code: task/order/intent binding, separate delivery and result retrieval | +| User-wallet payments (browser and MCP) | Local code: payer binding, wallet-side signing, receipt and `Transfer` verification | +| Agent MCP endpoint | Deployed; bearer authentication and tool discovery verified, no live MCP payment trace yet | +| Public landing, agent docs, cabinet | Local code at `/`, `/docs/mcp`, and `/app`; live R4 demonstration evidence remains pending | + +**One live testnet settlement has been executed.** A Privy-controlled execution +wallet and scoped policy authorized one 1.00 USDC Arc Testnet transfer; live +wrong-recipient and above-cap denials produced zero broadcasts. A lost-response +drill entered `UNKNOWN` and reconciled to that original settlement without a +replacement payment. Privy and Arc are `QUALIFIED` for the documented testnet +claim; see `docs/settlement/LIVE_EVIDENCE.md` and +`packages/reconciliation/docs/c06/QUALIFICATION_REPORT.md`. + +The Graph recovery path is currently `NOT VERIFIED` for sponsor qualification: +Studio GraphQL is implemented, but a fresh live trace showing its material +effect on the model and deterministic core is still required. + +Arc Mainnet is not configured. Its profile carries no chain ID, RPC, explorer, +or token value by design, and enabling it requires published official values +plus explicit human authorization. + +## Documentation + +| Document | Contents | +| --------------------------------------------------------------------------- | -------------------------------------------------------- | +| [`plan.md`](../plan.md) | Product plan, scope, and delivery gates | +| [`docs/DOMAIN_ARCHITECTURE.md`](../docs/DOMAIN_ARCHITECTURE.md) | Domain model and boundaries | +| [`docs/MCP_ARC_PAYMENT.md`](../docs/MCP_ARC_PAYMENT.md) | MCP deployment and live walkthrough | +| [`docs/RECOVERY_HARDENING.md`](../docs/RECOVERY_HARDENING.md) | Recovery, runtime, authentication, and metrics contracts | +| [`milestones/CONTRACTS.md`](../milestones/CONTRACTS.md) | Frozen v1 contract pack | +| [`docs/settlement/`](../docs/settlement/) | Settlement config, provider setup, live evidence | +| [`packages/reconciliation/docs/c06/`](../packages/reconciliation/docs/c06/) | C06 demo and qualification evidence index | +| [`docs/RELEASE_CHECKLIST.md`](../docs/RELEASE_CHECKLIST.md) | R5 release evidence and submission checklist | +| [`AGENTS.md`](../AGENTS.md) | Contribution policy and review gates | + +## License + +MIT. See [`LICENSE`](../LICENSE). From 0117448549981f5bca10901c9aba2d8ccf53950a Mon Sep 17 00:00:00 2001 From: kapustazh <51422901+kapustazh@users.noreply.github.com> Date: Thu, 8 Oct 2026 18:46:37 +0200 Subject: [PATCH 2/2] docs: record README PR handoff --- .../context/20261008T163453Z-readme-b2b-positioning.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.agent/context/20261008T163453Z-readme-b2b-positioning.md b/.agent/context/20261008T163453Z-readme-b2b-positioning.md index 2230a0d..c4a5ad6 100644 --- a/.agent/context/20261008T163453Z-readme-b2b-positioning.md +++ b/.agent/context/20261008T163453Z-readme-b2b-positioning.md @@ -62,9 +62,11 @@ work@kapustazh.dev for enquiries; website changes come later. - Branch: feature/readme-b2b-positioning - Base: origin/develop a60836b1acdb4a71aa1aaffd09f0a40f25903924 -- Commit: uncommitted. -- PR: draft to be created after push; GitHub authentication verified. -- CI: not run. +- Documentation commit: bbb72194687b8e9604f06c8ef0d9a276723ddf5a. +- PR: https://github.com/SWOFART/OneShot/pull/148 (draft, targets develop). +- CI: triggered; repository-policy, Markdown/Mermaid, ESLint/TypeScript, + browser acceptance, and Workers build pending at creation. +- This context-only follow-up records PR state; CI must validate final head. ## Review gates @@ -74,5 +76,5 @@ work@kapustazh.dev for enquiries; website changes come later. ## Handoff/next steps -1. Create draft PR and report validation and gate deviation. +1. PR created; local validation passed. CI remains pending at handoff. 2. A human reviews and merges; do not mark ready or merge automatically.