S10 (a1): public ledger profiles v1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -206,3 +206,29 @@ The system's track record — settled grades vs real results. Written by
|
||||
`GET /api/snapshot/:sport` grades may carry `outcome: { result:'hit'|'miss'|
|
||||
'push', actual:number }` once the game is final. `AccuracyBadge` +
|
||||
`StatStrip.OutcomeChip` render these. Frontend proxy: `web/src/app/api/accuracy`.
|
||||
|
||||
## 8. Public ledger profiles (`src/routes/profiles.js`, A1 Session 10)
|
||||
|
||||
Strava-for-betting v1. Table `public_profiles` (migration 022 — apply
|
||||
before deploy). PRIVATE BY DEFAULT; one explicit publish toggle in Settings.
|
||||
|
||||
### `GET /api/profiles/:handle` (public, cached 60s)
|
||||
Published only. Unknown AND unpublished return the SAME 404 body
|
||||
(`{ error: 'Profile not found' }`) — no existence leak.
|
||||
```
|
||||
{
|
||||
handle: string,
|
||||
aggregate: <getModelAggregate shape, scoped to the user via userId>,
|
||||
entries: [<same columns as /api/ledger, SETTLED rows only, newest 50>],
|
||||
min_sample: 20 // below this, RECORD BUILDING — never a %
|
||||
}
|
||||
```
|
||||
|
||||
### `GET|POST /api/profiles/me` (requireAuth)
|
||||
GET → `{ profile: { handle, published, created_at } | null }`.
|
||||
POST `{ handle, published }` → upsert own row (service role). Handle must
|
||||
match `^[a-z0-9_]{3,20}$` (400); a handle owned by another user → 409.
|
||||
`published` flips ONLY on boolean `true`.
|
||||
|
||||
Frontend: `/u/[handle]` (OPEN route, server shell + client record + OG card,
|
||||
Node runtime) via proxies `web/src/app/api/profiles/me|[handle]`.
|
||||
|
||||
Reference in New Issue
Block a user