43 lines
4.1 KiB
Markdown
43 lines
4.1 KiB
Markdown
# Honen.com — reverse, farm, OpenAI gateway
|
|
|
|
AI course-builder platform running Claude behind a Vercel AI-SDK v5 SSE stream, plus a cloud sandbox reachable over MCP. Fully reversed 2026-10; toolkit: local `C:/Users/User/tmp/honen_toolkit/` (`honen_api.py` stdlib client, `honen_farm.py`, `gateway.py`), public repo `github.com/gbonnet65923/honen-toolkit` (secret-free; the card-hitter script is deliberately NOT in the repo).
|
|
|
|
## Auth & provisioning (no captcha anywhere)
|
|
|
|
1. `POST /api/auth/signup {email, password, name}` → sets `courses_session` cookie. Gmail `+alias` works. ~2.7s/account full provision.
|
|
2. `POST /api/workspaces/create-personal {}` → personal workspace.
|
|
3. `POST /api/user/onboarding` — profileData: `ageRange, education, howDidYouHear, useCase, complete:true` (field values discovered in the onboarding JS chunk, step-ID driven).
|
|
4. `POST /api/workspaces/get {}` → `workspace.id`.
|
|
5. `POST /api/mcp/token` → bearer for `POST /api/mcp/mcp` (JSON-RPC 2.0, server `honen-generic-mcp v2.0.0`; tools include sandbox bash).
|
|
6. Session check: `GET /api/auth/session` (GET, not POST — POST gives 405).
|
|
|
|
Their own `GET /openapi.json` is public — pull it first for the endpoint map.
|
|
|
|
## Billing / trial
|
|
|
|
- `POST /api/billing/plans/list {}` — plan/price IDs ROTATE; never hardcode, always re-pull.
|
|
- `POST /api/billing/subscription/checkout {planId, interval:"MONTHLY", stripePriceId, workspaceId}` → `checkoutUrl` (Stripe hosted, SINGLE-USE).
|
|
- Pro trial = 7 days $0, card required (no SEPA/ACH, ~35 coupon codes probed → 0 valid).
|
|
- **UA-issued cards (generated AND real) always hit issuer SCA**: `setup_intent.status=requires_action`. Automated submits surface as instant "Please try again. ⚠️" with no confirm POST. The ONLY working activation = manual: generate fresh checkout URL for a fresh account, user opens it in a real browser and approves 3DS in their banking app, then verify server-side. See payment-hitter §14 "Manual 3DS handoff".
|
|
- Verify: `POST /api/billing/subscription/get {}` → `{planSlug:"pro", status:"TRIALING", trialEnd}`. **Pitfall:** pass `{}` WITHOUT workspaceId on personal workspaces — including it gives 403 "Personal workspaces use account-level billing". Same for usage/get.
|
|
- Tiers: free = 15 AI msgs/mo + 1 fast build; Pro trial = 999,999 msgs + 16 fast builds. Sandbox bash via MCP is quota-free on both.
|
|
|
|
## Chat / stream parsing
|
|
|
|
- `POST /api/workspace-assistant/chat` and `/api/courses/editor-chat` — AI SDK v5 SSE: events are typed JSON lines (`text-delta`, tool events with name/input/output), NOT OpenAI-style `data: {choices}`. Parse by event type; keep `sessionId` from the response for conversation continuity.
|
|
- Assistant chat spends aiMessages; pure MCP `tools/call` bash does not.
|
|
|
|
## Gateway pattern (OpenAI-compat over the pool)
|
|
|
|
`gateway.py` (stdlib ThreadingHTTPServer): pool from `accounts.jsonl` hot-reloaded every 60s; models `honen-assistant` (Claude chat) and `honen-sandbox` (prompt = script, response = stdout/stderr). Rules that mattered:
|
|
- Accounts with `"pro": true` are picked FIRST and exempt from the 15-msg quarantine (`remaining` initialized from the account, default 15).
|
|
- Dead cookie → auto-relogin via stored email/password; quarantine only after relogin fails.
|
|
- Check the port is free before launch (other local rotators squat the 8600-range) and after launch verify EXACTLY ONE listener via `netstat -ano | grep :PORT` — Windows SO_REUSEADDR lets duplicate daemons co-bind and answer randomly.
|
|
|
|
## Repo publishing checklist (applies to any toolkit repo)
|
|
|
|
- Exclude: account banks, cookies, hit logs/state, card files, screenshots. Include an `accounts.jsonl.example` with fake values.
|
|
- Run the redact scanner (`tmp/scan_redact_providers.py`) over the copy dir, and grep for `pk_live|sk_live|eyJ|Bearer ` — both must be clean.
|
|
- Create repo via `POST /user/repos` with a token read AT RUNTIME from `tmp/pw_alive.json`; push with inline-token URL (leaves no token in `.git/config`); verify with `GET /repos/{owner}/{repo}/commits/main`, not by push exit code.
|
|
- Vlad's public-repo standard: self-contained + dashboard section ("paste your token") + `t.me/AlStack` link in README footer.
|