Skip to content
Open
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
32 changes: 11 additions & 21 deletions .claude/agents/ux-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,23 @@ Purpose:
- review the store surfaces for discoverability, audience fit, docs parity, and developer evaluation quality

Required read order:
1. `.codex/STATE.md`
2. `README.md`
3. `docs/api.md`
4. `docs/architecture.md`
5. `internal/httpapi/server.go`
6. `internal/httpapi/openapi.go`
7. `internal/webui/handler.go`
8. `web/index.html`
9. `web/reference.html`
10. `web/advanced.html`
11. `web/store.js`
12. `web/console.js`
13. `web/style.css`
1. `README.md`
2. `docs/api.md`
3. `docs/architecture.md`
4. `internal/httpapi/server.go`
5. `internal/httpapi/store_public.go`
6. `internal/service/storefront_wallet.go`
7. `frontend/src/App.tsx`
8. `internal/webui/handler.go`

Required output:
- findings ordered by severity
- surface classification:
- store app
- API reference
- advanced/developer tool
- friction points by audience:
- first-time store visitor
- returning store visitor
- first-time shopper
- returning shopper
- first-time developer
- protocol/debug operator
- docs mismatches
- recommendations limited to product structure, discoverability, next-step guidance, and trust-building
- recommendations limited to signed wallet flows, store usability, docs parity, and trust-building

Non-goals:
- no implementation
Expand Down
28 changes: 15 additions & 13 deletions .claude/rules/api-contract.md
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename deposit and withdraw to user_deposit and user_withdraw respectively to give more clarity and leave space for app_withdraw later

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 1538749. i kept the nitrolite protocol intent values as deposit and withdraw, and changed only our session_data intent values to user_deposit and user_withdraw. docs and tests are updated too.

Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
# API Contract Rules

- prefix all API routes with `/api/v1`
- active API routes are only:
- `GET /api/store/bootstrap`
- `POST /api/store/init`
- `POST /api/store/update`
- `GET /api/store/content/{id}`
- amounts are decimal strings, never floats
- error envelope:
```json
{"error":{"code":"snake_case","message":"lowercase message"}}
```
- raw mutation routes in `/advanced` use `requireWriteAccess()`
- `requireWriteAccess()` accepts:
- bearer key
- unlocked write-session cookie
- store product routes are browser-cookie scoped and do not require write unlock for normal use
- `POST /api/v1/app-session/submit-state` is the single store mutation endpoint
- `POST /api/v1/app-session/submit-state` must dispatch from `session_data.action`
- store state-changing routes are wallet-signature scoped
- `POST /api/store/init` verifies `packCreateAppSessionRequestV1(definition, session_data)`
- `POST /api/store/update` verifies `packAppStateUpdateV1(app_state_update)`
- `POST /api/store/update` dispatches from `app_state_update.intent`
- deposit responses are app-signed checkpoints; bootstrap may return `pending_action` until the browser-side Clearnode submit is observed
- `GET /api/store/content/{id}` is a public demo read path and must still require a submitted wallet purchase
- do not present the content read gate as production-grade authorization
- supported public actions are:
- `deposit`
- `user_deposit`
- `purchase`
- `user_withdraw`
- hidden developer-only action:
- `app_withdraw`
- only allowed when write access is present
- server must never trust client purchase price or allocation math
- one browser-scoped store session per asset
- supported demo assets are `yusd` and `yellow`
- one wallet-scoped store session per supported asset
6 changes: 3 additions & 3 deletions .claude/skills/add-store-endpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ Create:
- handler stub
- service/store method stub
- route registration
- OpenAPI entry
- test stubs
- store UI hook if user-facing

Keep:
- decode -> service -> encode shape
- `session_data` as the store mutation contract
- browser-cookie session semantics
- signed wallet request semantics
- `app_state_update.intent` as the store mutation dispatcher
- `session_data.intent` as the store action detail
- decimal string amounts
12 changes: 7 additions & 5 deletions .claude/skills/run-store-demo-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

Sequence:
1. open `/`
2. create or load a store session
3. deposit into the session
4. purchase an item
5. read purchased content
6. withdraw remaining user balance
2. Connect wallet
3. create or load the wallet store session
4. deposit into the app session
5. purchase item `1` for `0.9` YUSD
6. read purchased content
7. withdraw remaining user balance

Require:
- funded demo wallet
- reachable clearnode
- selected asset supported by the catalog
- direct `@yellow-org/sdk` wallet signing available

Output:
- step result
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/trace-store-session-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Trace:
- store handler
- storefront service
- wallet store service
- store persistence
- Nitrolite SDK call chain

Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/update-store-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Check:
- asset switching is clear
- session status is understandable
- purchase and content-access states are explicit
- hidden developer surfaces stay out of the main store nav
- action labels remain `Connect`, `Deposit`, `Withdraw`, and `Purchase`

Output:
- UI/API mismatches
Expand Down
15 changes: 6 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
# Clearnode WebSocket URL - use sandbox for development
CLEARNODE_WS_URL=wss://clearnode-sandbox.yellow.org/v1/ws
# Nitronode endpoint URL
CLEARNODE_WS_URL=wss://nitronode-stress.yellow.org/v1/ws

# Demo signer private key (generate a new key: openssl rand -hex 32)
# This wallet must have sandbox funds. Never use a mainnet key here.
DEMO_PRIVATE_KEY=0xyour_private_key_here

# Console API key - required for all mutation endpoints (min 32 chars)
# Generate: openssl rand -hex 32
CONSOLE_API_KEY=your_random_32_char_key_here

# Blockchain RPC endpoints (JSON map of chainID -> RPC URL)
BLOCKCHAIN_RPC_URLS={"11155111":"https://sepolia.example.rpc"}

# Home blockchain per asset (JSON map of asset symbol -> chainID)
HOME_BLOCKCHAINS={"yusd":11155111,"yellow":11155111}

# Default amount used when preparing a home channel from on-chain test tokens
STORE_CHANNEL_BOOTSTRAP_AMOUNTS={"yusd":"10","yellow":"10"}

# Optional
PORT=8080
LOG_LEVEL=info
SQLITE_PATH=./data/nitrolite-go-example.db
SQLITE_PATH=./data/nitrolite-store-example.db
STORE_NAME=Nitrolite App Session Store
STORE_APP_ID=default
STORE_APP_PRIVATE_KEY=
MERCHANT_NAME=Nitrolite Sandbox Merchant
MERCHANT_APP_ID=default
25 changes: 12 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# AGENTS

Read order:

1. `README.md`
2. `CLAUDE.md`
3. `docs/api.md`
Expand All @@ -10,25 +11,23 @@ Read order:
7. `internal/nitrolite/manager.go`
8. `internal/service/`
9. `internal/httpapi/`
10. `internal/webui/handler.go`
11. `web/`
10. `frontend/`
11. `internal/webui/handler.go`

Ownership:

- `internal/config`: env parsing and validation
- `internal/store`: SQLite schema, store sessions, purchases
- `internal/signing`: signer abstraction, demo signer, derived store-app signer
- `internal/store`: SQLite wallet sessions and purchases
- `internal/signing`: signer abstraction and store app signer
- `internal/nitrolite`: SDK lifecycle and reconnect manager
- `internal/service`: store orchestration, catalog/content logic, raw SDK-backed business logic
- `internal/httpapi`: decode -> service -> encode, browser cookie flow, write auth, OpenAPI surface
- `internal/webui`: page routing for embedded assets
- `web/`: store UI, embedded reference shell, advanced developer console
- `internal/service`: wallet store orchestration, catalog, signed update verification, and content gating
- `internal/httpapi`: request decode, service calls, and response encoding
- `frontend`: React + direct Nitrolite v1 TypeScript SDK browser flow
- `internal/webui`: embedded asset serving

Current scope:

- same-binary Go server + embedded web assets
- `/` App Session Micropayment Store
- `/reference` OpenAPI-backed embedded explorer
- `/advanced` raw protocol/developer console
- one browser-scoped store session per asset
- same-binary Go server plus embedded frontend assets
- `/` content store
- one wallet-owned store session per asset
- seeded content catalog with purchased-content gating
25 changes: 18 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# CLAUDE

Module:
- `github.com/layer-3/nitrolite-go-example`

- `github.com/layer-3/nitrolite-store-example`

Commands:

```bash
go run ./cmd/server
env CGO_ENABLED=0 GOCACHE=/tmp/nitrolite-go-example-gocache go test ./...
docker build -t nitrolite-go-example .
env CGO_ENABLED=0 GOCACHE=/tmp/nitrolite-store-example-gocache go test $(go list ./... | grep -v '/frontend/node_modules/')
docker build -t nitrolite-store-example .
go vet ./...
gofmt -w .
cd frontend && npm run lint && npm run typecheck && npm run build
```

Key paths:
Expand All @@ -18,11 +21,19 @@ Key paths:
- persistence: `internal/store`
- api: `internal/httpapi`
- services: `internal/service`
- frontend source: `frontend`
- web router: `internal/webui/handler.go`
- web assets: `web`
- embedded assets: `internal/webui/dist`

Product surfaces:

- `/`: App Session Micropayment Store
- `/reference`: embedded API reference
- `/advanced`: raw developer/debug console
- `/`: content store
- `/healthz`: process health
- `/readyz`: Clearnode readiness

Active API:

- `GET /api/store/bootstrap`
- `POST /api/store/init`
- `POST /api/store/update`
- `GET /api/store/content/{id}`
14 changes: 13 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
FROM node:24-bookworm-slim AS frontend-build

WORKDIR /src/frontend

COPY frontend/package.json frontend/package-lock.json ./
COPY frontend/vendor ./vendor
RUN npm ci

COPY frontend ./
RUN npm run build

FROM golang:1.25-bookworm AS build

WORKDIR /src
Expand All @@ -6,6 +17,7 @@ COPY go.mod go.sum ./
RUN go mod download

COPY . .
COPY --from=frontend-build /src/internal/webui/dist ./internal/webui/dist

ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go build -o /out/app ./cmd/server
Expand All @@ -22,7 +34,7 @@ RUN apt-get update \
COPY --from=build /out/app /app/app

ENV PORT=8080
ENV SQLITE_PATH=/app/data/nitrolite-go-example.db
ENV SQLITE_PATH=/app/data/nitrolite-store-example.db
ENV STORE_NAME="Nitrolite App Session Store"
ENV STORE_APP_ID=default
ENV LOG_LEVEL=info
Expand Down
Loading