Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<plan>
<goal>
Produce a written map from the current x402-api compat-shim code paths to the native
boring-tx events the relay now emits, plus a port plan for the polling DO pattern from
landing-page and agent-news. Output: NOTES.md with shim inventory, behavior table,
tx-schemas entry points, relay endpoint shapes, DO API sketch, and risk list.
</goal>

<context>
x402-api v1.6.1 uses x402-stacks ^2.0.1 and @aibtc/tx-schemas ^0.3.0 (installed: 1.0.0).
The middleware at src/middleware/x402.ts calls verifier.settle() from x402-stacks.
All payment event logs carry compat_shim_used: true, paymentId: null,
checkStatusUrl_present: false because extractCanonicalPaymentDetails() falls through to
the "inferred" path — the relay never returned paymentId/checkStatusUrl before boring-tx.

x402-sponsor-relay v1.30.1 now generates paymentId (pay_ prefix) in submitPayment() and
always populates checkStatusUrl on every response. The compat shim path (inferLegacyStatus,
inferLegacyTerminalReason) is needed only for relay responses that predate boring-tx.

Reference repos (read-only):
- landing-page: lib/inbox/payment-contract.ts, lib/inbox/x402-verify.ts
- agent-news: src/routes/payment-status.ts, src/services/x402.ts
- tx-schemas: src/core/*, src/http/*, src/rpc/*
- x402-sponsor-relay: src/rpc.ts (submitPayment, checkPayment), src/endpoints/payment-status.ts
</context>

<task id="1">
<name>Read core source files and reference repos</name>
<files>
src/middleware/x402.ts,
src/utils/payment-status.ts,
src/utils/payment-observability.ts,
src/utils/payment-contract.ts,
src/types.ts,
src/durable-objects/UsageDO.ts,
wrangler.jsonc,
package.json,
~/dev/aibtcdev/tx-schemas/src/core/enums.ts,
~/dev/aibtcdev/tx-schemas/src/core/terminal-reasons.ts,
~/dev/aibtcdev/tx-schemas/src/core/payment.ts,
~/dev/aibtcdev/tx-schemas/src/http/schemas.ts,
~/dev/aibtcdev/tx-schemas/src/rpc/schemas.ts,
~/dev/aibtcdev/x402-sponsor-relay/src/rpc.ts,
~/dev/aibtcdev/x402-sponsor-relay/src/endpoints/payment-status.ts,
~/dev/aibtcdev/agent-news/src/services/x402.ts,
~/dev/aibtcdev/agent-news/src/routes/payment-status.ts
</files>
<action>
Read all listed files to understand:
1. Exactly where compat-shim flags are set and logged in x402-api
2. What fields the relay now emits (paymentId, checkStatusUrl, status, terminalReason)
3. What tx-schemas exports are available under @aibtc/tx-schemas/{core,http,rpc}
4. How agent-news verifyPayment() + payment-status route implement the polling DO
5. What the relay RPC interface looks like (submitPayment, checkPayment signatures)
</action>
<verify>
All files readable without error. Key values extracted:
- current installed tx-schemas version
- compat shim code locations (file:line)
- relay checkStatusUrl URL pattern
- agent-news DO polling implementation skeleton
</verify>
<done>
Complete inventory of all compat-shim touch-points and relay native fields.
</done>
</task>

<task id="2">
<name>Write NOTES.md with all required sections</name>
<files>
.planning/2026-04-22-boring-tx-state-machine/phases/01-research/NOTES.md
</files>
<action>
Create NOTES.md covering all six required sections:
1. Shim inventory - every file, function, and log field carrying compat_shim semantics
2. Behavior comparison table - landing-page vs agent-news vs x402-api
3. tx-schemas entry points - which exports to use in each phase
4. Relay endpoint/response shapes - submitPayment and checkPayment exact types
5. DO public API sketch - concrete TypeScript interface and SQLite schema for PaymentPollingDO
6. Risk list - versioning, #87 coupling, data migration, wrangler migration tag

The DO public API sketch must be concrete enough to implement from (Phase 4 deliverable).
Include the swap point comment at poll() as described in PHASES.md.
</action>
<verify>
NOTES.md exists, has all 6 headings, is not a placeholder, DO sketch includes
TypeScript interface with track/poll/status/derivedHints methods and SQLite CREATE TABLE.
</verify>
<done>
NOTES.md written with substantive content in every section.
</done>
</task>

<task id="3">
<name>Commit PLAN.md and NOTES.md</name>
<files>
.planning/2026-04-22-boring-tx-state-machine/phases/01-research/PLAN.md,
.planning/2026-04-22-boring-tx-state-machine/phases/01-research/NOTES.md
</files>
<action>
Stage both files and commit with message:
docs(planning): phase 1 research notes for boring-tx adoption
</action>
<verify>
git log shows the commit with both files.
</verify>
<done>
Conventional commit in git history.
</done>
</task>
</plan>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Phase 2: Branch Setup + Deps

Date: 2026-04-22
Phase: 02-deps

## Goal

Fresh feature branch `feat/boring-tx-state-machine` off latest `origin/main` with
`@aibtc/tx-schemas` bumped to `^1.0.0`. Baseline `npm run check` and
`npm run deploy:dry-run` clean BEFORE any logic changes.

## What Was Done

### Branch Setup

- Local `main` had diverged from `origin/main` (local had Phase 1 planning commit,
origin/main had 4 newer commits including `e6ba205`, `457e955`, `ed24545`, `46b8693`)
- Stashed `tests/_shared_utils.ts` (Phase 7 staged changes) to keep a clean working tree
- Fetched `origin/main` (latest: `46b8693 chore(main): release 1.6.1`)
- Created `feat/boring-tx-state-machine` off `origin/main`
- Cherry-picked Phase 1 planning commit (`c1b46b5` → `f881569` on feature branch)
- Popped stash to restore `tests/_shared_utils.ts` modification

### Dependency Bump

Phase 1 NOTES.md identified (R1 in Risk List):
- Installed version: `@aibtc/tx-schemas@1.0.0`
- package.json constraint: `^0.3.0` — this does NOT resolve 1.0.0 for 0.x.y semver locking
- Latest published on npm: `1.0.0`
- Action required: bump constraint to `^1.0.0`

Updated `package.json`:
```
"@aibtc/tx-schemas": "^0.3.0" → "@aibtc/tx-schemas": "^1.0.0"
```

Ran `npm install` → `@aibtc/tx-schemas@1.0.0` resolved correctly.

### Patch File Removal (Mechanical Cleanup)

During `npm install`, `patch-package` (postinstall hook) errored applying
`patches/x402-stacks+2.0.1.patch`. Investigation showed the patch changes
(bump HTTP client timeout from 30000ms/15000ms to 120000ms) are now incorporated
upstream in x402-stacks itself — both `dist/verifier-v2.js` and `dist/verifier.js`
already have `timeout: 120000`. The patch file was stale.

Removed: `patches/x402-stacks+2.0.1.patch`

This is a mechanical cleanup — no behavioral change (timeout is 120000ms before and
after). The installed package already contains the desired timeout value.

### Import Path Verification

No import-path changes were required. The existing import in
`src/utils/payment-contract.ts` uses `@aibtc/tx-schemas/core` sub-path:
```ts
import { CanonicalDomainBoundary, PAYMENT_STATES } from "@aibtc/tx-schemas/core";
```
This sub-path was present in v0.3.0 and remains available in v1.0.0 — no breakage.

### Baseline Verification

- `npm run check` (tsc --noEmit): exits 0, no errors
- `npm run deploy:dry-run`: builds successfully (1027.76 KiB / gzip: 272.26 KiB)
- `tests/_shared_utils.ts`: still shows as modified, not committed (preserved for Phase 7)

## Files Changed in Phase 2 Commit

| File | Change |
|------|--------|
| `package.json` | `@aibtc/tx-schemas` constraint `^0.3.0` → `^1.0.0` |
| `package-lock.json` | Lockfile update for tx-schemas resolution |
| `patches/x402-stacks+2.0.1.patch` | Deleted (stale patch, fix now upstream) |
| `.planning/…/phases/02-deps/PLAN.md` | This file |

## Not Included in Commit

- `tests/_shared_utils.ts` — preserved for Phase 7 (NonceTracker + signPaymentWithNonce)
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Phase 9: Verify — Checklist & Results

Date: 2026-04-22

## Verification Checklist

### 1. Working Tree Status
- [x] `git status` — clean
- Only untracked `.claude/` dir (not in src/, tests/, or config)
- No staged or modified files

### 2. Type Check
- [x] `npm run check` — **0 errors**
- `tsc --noEmit` exits cleanly with no output

### 3. Deploy Dry-Run
- [x] `npm run deploy:dry-run` — **clean build**
- Total Upload: 1031.33 KiB / gzip: 273.31 KiB
- `PAYMENT_POLLING_DO (PaymentPollingDO)` binding confirmed present
- All 4 Durable Objects wired: UsageDO, StorageDO, MetricsDO, PaymentPollingDO
- Only expected warning: multiple environments defined, no target specified (non-blocking)

### 4. Quick E2E Tests (npm test)
- [x] `npm test` — **14/14 passed (100.0%)**
- Mode: quick, Tokens: STX, Server: https://x402.aibtc.dev
- Categories: hashing (6), stacks (6), inference (2)
- All stateless endpoints pass

### 5. Full E2E Tests (npm run test:full)
- [ ] `npm run test:full` — **SKIPPED: X402_CLIENT_PK not set in env**
- Note from Phase 7: test:full against live staging would fail
`payment-polling-lifecycle` on X-PAYMENT-ID assertion because the
new header is deployment-gated (not yet deployed). This is expected.
- Path to verify: `npm run dev` (local), then
`X402_WORKER_URL=http://localhost:8787 npm run test:full`

### 6. Unit Tests
- [x] `bun test tests/*.unit.test.ts` — **114 passed, 0 failed**
- 8 files, 340 expect() calls, 198ms
- Files: cloudflare-ai-fallback, model-cache, openrouter-validation,
payment-contract, payment-middleware, payment-observability,
payment-polling-do, payment-status

### 7. Rebase on origin/main
- [x] `git fetch origin` — clean
- [x] `git rebase origin/main` — **already up to date**
- Merge base: `46b86936` (chore(main): release 1.6.2)
- No rebase needed; branch was already cut from current main tip
- [x] Post-rebase `npm run check` — clean (no change)
- [x] Post-rebase `npm test` — 14/14 (no change)

### 8. Commits on Branch
All 8 commits from Phase 1–8 land cleanly on origin/main:

```
250bc32 refactor(payments): simplify post-boring-tx adoption
f409653 test(payments): cover boring-tx lifecycle end-to-end
1ab6e6f feat(payments): add retryable/retryAfter/nextSteps error hints
c44f093 feat(payments): emit native payment.* events, drop compat shim
7ac20c8 feat(payments): add PaymentPollingDO for checkStatusUrl polling
5d218f7 refactor(payments): route payment types through @aibtc/tx-schemas
7a70493 chore(deps): bump @aibtc/tx-schemas for boring-tx state machine
f881569 docs(planning): phase 1 research notes for boring-tx adoption
```

## Result

**PASS** — All blocking checks green. Branch is ready for PR (Phase 10).

Known non-blocking gap: `test:full` payment-polling-lifecycle needs deployed
`X-PAYMENT-ID` header support on the relay side before it will pass against
live staging. Local worker verification is the correct path and is noted in
the PR body.
Loading
Loading