chore: initialize monorepo with project scaffolding, configs, and CI setup

This commit is contained in:
oib
2025-09-27 06:05:25 +02:00
commit c1926136fb
171 changed files with 13708 additions and 0 deletions

235
docs/bootstrap/examples.md Normal file
View File

@ -0,0 +1,235 @@
# examples/ — Minimal runnable examples for integrators
This folder contains three self-contained, copy-pasteable starters that demonstrate how to talk to the coordinator API, submit jobs, poll status, and (optionally) verify signed receipts.
```
examples/
├─ explorer-webexplorer-web/ # (docs live elsewhere; not a runnable example)
├─ quickstart-client-python/ # Minimal Python client
├─ quickstart-client-js/ # Minimal Node/Browser client
└─ receipts-sign-verify/ # Receipt format + sign/verify demos
```
> Conventions: Debian 12/13, zsh, no sudo, run as root if you like. Keep env in a `.env` file. Replace example URLs/tokens with your own.
---
## 1) quickstart-client-python/
### What this shows
- Create a job request
- Submit to `COORDINATOR_URL`
- Poll job status until `succeeded|failed|timeout`
- Fetch the result payload
- (Optional) Save the receipt JSON for later verification
### Files Windsurf should ensure exist
- `main.py` — the tiny client (≈ 80120 LOC)
- `requirements.txt``httpx`, `python-dotenv` (and `pydantic` if you want models)
- `.env.example``COORDINATOR_URL`, `API_TOKEN`
- `README.md` — one-screen run guide
### How to run
```sh
cd examples/quickstart-client-python
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Prepare environment
cp .env.example .env
# edit .env → set COORDINATOR_URL=https://api.local.test:8443, API_TOKEN=xyz
# Run
python main.py --prompt "hello compute" --timeout 60
# Outputs:
# - logs to stdout
# - writes ./out/result.json
# - writes ./out/receipt.json (if provided by the coordinator)
```
### Coordinator endpoints the code should touch
- `POST /v1/jobs` → returns `{ job_id }`
- `GET /v1/jobs/{job_id}` → returns `{ status, progress?, result? }`
- `GET /v1/jobs/{job_id}/receipt` → returns `{ receipt }` (optional)
Keep the client resilient: exponential backoff (100ms → 2s), total wall-time cap from `--timeout`.
---
## 2) quickstart-client-js/
### What this shows
- Identical flow to the Python quickstart
- Two variants: Node (fetch via `undici`) and Browser (native `fetch`)
### Files Windsurf should ensure exist
- `node/`
- `package.json``undici`, `dotenv`
- `index.js` — Node example client
- `.env.example`
- `README.md`
- `browser/`
- `index.html` — minimal UI with a Prompt box + “Run” button
- `app.js` — client logic (no build step)
- `README.md`
### How to run (Node)
```sh
cd examples/quickstart-client-js/node
npm i
cp .env.example .env
# edit .env → set COORDINATOR_URL, API_TOKEN
node index.js "hello compute"
```
### How to run (Browser)
```sh
cd examples/quickstart-client-js/browser
# Serve statically (choose one)
python3 -m http.server 8080
# or
busybox httpd -f -p 8080
```
Open `http://localhost:8080` and paste your coordinator URL + token in the form.
The app:
- `POST /v1/jobs`
- polls `GET /v1/jobs/{id}` every 1s (with a 60s guard)
- downloads `receipt.json` if available
---
## 3) receipts-sign-verify/
### What this shows
- Receipt JSON structure used by AITBC examples
- Deterministic signing over a canonicalized JSON (RFC 8785-style or stable key order)
- Ed25519 signing & verifying in Python and JS
- CLI snippets to verify receipts offline
> If the project standardizes on another curve, swap the libs accordingly. For Ed25519:
> - Python: `pynacl`
> - JS: `@noble/ed25519`
### Files Windsurf should ensure exist
- `spec.md` — human-readable schema (see below)
- `python/`
- `verify.py``python verify.py ./samples/receipt.json ./pubkeys/poolhub_ed25519.pub`
- `requirements.txt``pynacl`
- `js/`
- `verify.mjs``node js/verify.mjs ./samples/receipt.json ./pubkeys/poolhub_ed25519.pub`
- `package.json``@noble/ed25519`
- `samples/receipt.json` — realistic sample
- `pubkeys/poolhub_ed25519.pub` — PEM or raw 32-byte hex
### Minimal receipt schema (for `spec.md`)
```jsonc
{
"version": "1",
"job_id": "string",
"client_id": "string",
"miner_id": "string",
"started_at": "2025-09-26T14:00:00Z",
"completed_at": "2025-09-26T14:00:07Z",
"units_billed": 123, // e.g., “AIToken compute units”
"result_hash": "sha256:…", // hex
"metadata": { "model": "…" }, // optional, stable ordering for signing
"signature": {
"alg": "Ed25519",
"key_id": "poolhub-ed25519-2025-09",
"sig": "base64url…" // signature over canonicalized receipt WITHOUT this signature object
}
}
```
### CLI usage
**Python**
```sh
cd examples/receipts-sign-verify/python
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python verify.py ../samples/receipt.json ../pubkeys/poolhub_ed25519.pub
# exit code 0 = valid, non-zero = invalid
```
**Node**
```sh
cd examples/receipts-sign-verify/js
npm i
node verify.mjs ../samples/receipt.json ../pubkeys/poolhub_ed25519.pub
```
**Implementation notes for Windsurf**
- Canonicalize JSON before hashing/signing (stable key order, UTF-8, no trailing spaces).
- Sign bytes of `sha256(canonical_json_without_signature_block)`.
- Reject if `completed_at < started_at`, unknown `alg`, or mismatched `result_hash`.
---
## Shared environment
All quickstarts read the following from `.env` or in-page form fields:
```
COORDINATOR_URL=https://api.local.test:8443
API_TOKEN=replace-me
# Optional: REQUEST_TIMEOUT_SEC=60
```
HTTP headers to include:
```
Authorization: Bearer <API_TOKEN>
Content-Type: application/json
```
---
## Windsurf checklist (do this automatically)
1. **Create folders & files**
- `quickstart-client-python/{main.py,requirements.txt,.env.example,README.md}`
- `quickstart-client-js/node/{index.js,package.json,.env.example,README.md}`
- `quickstart-client-js/browser/{index.html,app.js,README.md}`
- `receipts-sign-verify/{spec.md,samples/receipt.json,pubkeys/poolhub_ed25519.pub}`
- `receipts-sign-verify/python/{verify.py,requirements.txt}`
- `receipts-sign-verify/js/{verify.mjs,package.json}`
2. **Fill templates**
- Implement `POST /v1/jobs`, `GET /v1/jobs/{id}`, `GET /v1/jobs/{id}/receipt` calls.
- Poll with backoff; stop at terminal states; write `out/result.json` & `out/receipt.json`.
3. **Wire Ed25519 libs**
- Python: `pynacl` verify(`public_key`, `message`, `signature`)
- JS: `@noble/ed25519` verifySync
4. **Add DX niceties**
- `.env.example` everywhere
- `README.md` with copy-paste run steps (no global installs)
- Minimal logging and clear non-zero exit on failure
5. **Smoke tests**
- Python quickstart runs end-to-end with a mock coordinator (use our tiny FastAPI mock if available).
- JS Node client runs with `.env`.
- Browser client works via `http://localhost:8080`.
---
## Troubleshooting
- **401 Unauthorized** → check `API_TOKEN`, CORS (browser), or missing `Authorization` header.
- **CORS in browser** → coordinator must set:
- `Access-Control-Allow-Origin: *` (or your host)
- `Access-Control-Allow-Headers: Authorization, Content-Type`
- `Access-Control-Allow-Methods: GET, POST, OPTIONS`
- **Receipt verify fails** → most often due to non-canonical JSON or wrong public key.
---
## License & reuse
Keep examples MIT-licensed. Add a short header to each file:
```
MIT © AITBC Examples — This is demo code; use at your own risk.
```