182 lines
10 KiB
Markdown
182 lines
10 KiB
Markdown
# SESSION-0009.0 — Real ecomm build: R01 + Auth + R02 + GraphQL/BFF + replan
|
|
|
|
**Date:** 2026-06-01
|
|
**Driver:** Ben (ben@wiggleverse.org)
|
|
**Repos touched:** `wiggleverse-ecomm` (impl, branch `r01-store-settings`),
|
|
`wiggleverse-ecomm-meta` (plan, branch `replan-v2-resequence`)
|
|
**Outcome:** First real releases shipped (code-complete, on a branch, unmerged);
|
|
GraphQL+REST-BFF architecture established; release plan reassessed.
|
|
|
|
Transcript-honest per the engineering guide — wrong turns included.
|
|
|
|
---
|
|
|
|
## What happened (in order)
|
|
|
|
1. **"Implement the first ecomm release per the BDD tool."** Investigated; the
|
|
throwaway prototype had R01/R04/R06. Asked which track. **Ben: "We didn't end up
|
|
needing the prototype. Build Real Build R01, based on the OHM concepts at
|
|
ohm.wiggleverse.org."** → Pivot: prototype **retired**, real product begins.
|
|
|
|
2. **R01 — Store profile & settings** (`13.06.0001-0010`). Wrote `SPEC.md` v0.1
|
|
first (binding), every mechanic citing the OHM concept it serves (§5 traceability
|
|
table = Transparency & Traceability applied to our own code). Read the live OHM
|
|
corpus via `https://ohm.wiggleverse.org/api/rfcs` (39 rows; 7 are known dash-less
|
|
dupes; only `human`/RFC-0001 is graduated, rest are super-draft pitches). Stack:
|
|
FastAPI + stdlib sqlite3 (WAL) + forward-only `.sql` migrations + Vite/React.
|
|
Grounded the model in Participants (Store controlled by a Merchant/Human-in-role),
|
|
No Retroactive Harm (units/currency/tz are display-only, stored canonically;
|
|
order numbers stamped-at-mint and immutable), Privacy & Data Minimization,
|
|
Agency & Anti-Manipulation (frictionless pause/reactivate). 11 tests + browser
|
|
verified. Commit `9f397b0`.
|
|
|
|
3. **"Block any user who hasn't been invited — logging in creates the user in an
|
|
Uninvited state, invite later, exactly like ohm-rfc-app."** Read rfc-app's
|
|
`auth.py`/`otc.py`/`invites.py` first, then mirrored its `permission_state`
|
|
model (`pending`=Uninvited / `granted` / `revoked`). Ben chose **OTC, email
|
|
stubbed**. A sign-in *provisions* rather than rejects; `require_granted` gates
|
|
writes; owner invites/grants/revokes. 11 tests + full browser flow. Commit
|
|
`9843e56`.
|
|
|
|
4. **Ben: "Is this R01 or R02?"** — a fair correction. I'd framed the auth gate as
|
|
"R01 substrate"; it's really **R02** (Staff & permissions). Honest answer given;
|
|
then **"Finish R2."**
|
|
|
|
5. **R02 — Staff & permissions** (`13.15.0001-0009`), full release on the auth
|
|
foundation: per-section permission scopes, invite-with-scopes → accept → Active,
|
|
section-limited access, revoke-preserving audit log, owner protection, store-wide
|
|
2FA mandate (gate real, second factor stubbed), ownership transfer, time-limited
|
|
collaborators, subset-rule on granting. 10 tests + browser. Commit `0bbe37b`.
|
|
|
|
6. **"Everything available via a GraphQL API (full surface + relationships); plus
|
|
REST BFFs for the UI."** Established the standing **two-layers-over-one-core**
|
|
architecture (SPEC §A). GraphQL (Strawberry) = canonical complete graph + all
|
|
mutations; REST = screen-shaped BFF; both share `store.py`/`staff.py` and the
|
|
factored `auth.assert_*` gates. Ben chose full read+write + "UI may also use
|
|
GraphQL" → the Team page loads via one GraphQL relationship query. 6 GraphQL
|
|
tests (38 total) + browser. Commit `16c3f1c`.
|
|
|
|
7. **"Reassess the releases and shuffle."** Replan v2 (see below). Meta branch
|
|
`replan-v2-resequence`, unpushed.
|
|
|
|
8. **Working mode set: "trust and verify."** Proceed autonomously; announce
|
|
what + why before each chunk; verify + commit to a branch; never merge/push.
|
|
**NO SECRETS** — never handle secret bytes; hand Ben the gesture.
|
|
|
|
## Wrong turns / gotchas (honest record)
|
|
|
|
- **Mis-labeled the auth gate as R01 substrate** — it's R02. Ben caught it.
|
|
- **OTC 60-second cooldown** makes rapid same-email re-login in the browser flaky
|
|
(silently no-ops, leaves the prior session — once made a GraphQL check *look*
|
|
like a bug when it was just the owner session lingering). Workaround: drive the
|
|
login via an in-page `.click()` + poll loop, or wait it out. pytest is unaffected
|
|
(fresh DB/email per test). Not a product bug.
|
|
- **First `mkdir` for the backend landed in the wrong dir** (cwd was the ecomm
|
|
working root, not the repo) — corrected.
|
|
- **One GraphQL test asserted the wrong seed name** ("Owner" vs the Merchant entity
|
|
"Store Owner") — fixed.
|
|
|
|
## Replan v2 — release reassessment
|
|
|
|
Two structural defects fixed in `roadmap/RELEASE-PLAN.md`:
|
|
|
|
1. **R03 Locations was un-buildable as sequenced** — 5/9 scenarios depend on
|
|
Inventory/Checkout/Orders/Fulfillment. Slimmed R03 to its dependency-free core
|
|
(`13.07.0001/0002/0003/0006`); moved `0008`→R07, `0007`→R13,
|
|
`0004/0005/0009`→R23.
|
|
2. **POS was gated behind the whole online stack** (R22→R15→R13→storefront…).
|
|
Re-rooted: the **Order is a shared spine** born from manual/draft creation (R25
|
|
pulled forward); online checkout (R13) and POS (R22) are two channels onto it;
|
|
R15/R16 re-root on R25; R22 depends R16, not the online stack → **Hasan's
|
|
in-person-payment MVP reachable without any storefront/theme/shipping**. Pulled
|
|
Customers + Taxes(R12) into the shared foundation. **Two MVP finish lines:
|
|
Hasan=R22, Connie=R14.** Authoritative build-order table added at the top of the
|
|
plan; R-codes kept stable (now non-monotonic). Validated: no id duped, counts match.
|
|
|
|
## Artifacts / state at end of session
|
|
|
|
- **Impl** `wiggleverse-ecomm`, branch `r01-store-settings`, **4 commits unmerged**:
|
|
`9f397b0` R01 · `9843e56` auth · `0bbe37b` R02 · `16c3f1c` GraphQL+BFF.
|
|
`SPEC.md` v0.4. **38 tests pass.** Working tree clean.
|
|
- **Plan** `wiggleverse-ecomm-meta`, branch `replan-v2-resequence`, replan commit
|
|
`6b785b8` (+ this transcript). Unpushed.
|
|
- **Operator follow-ups (Ben):** merge/push the impl branch; review + push the
|
|
replan branch (push re-ingests the live BDD app); optionally physically reorder
|
|
the plan's sections to match the build-order table. Still stubbed: real outbound
|
|
email, real TOTP.
|
|
|
|
---
|
|
|
|
## NEXT-SESSION RESUME PROMPT — R03 Locations (core)
|
|
|
|
> Paste the block below into a fresh session.
|
|
|
|
```
|
|
Build R03 — Locations (core) — the next release in the real wiggleverse-ecomm
|
|
product. Read your memory first ([[ecomm-real-build]], [[ecomm-bdd-release-planner]],
|
|
[[ecomm-business-context]]).
|
|
|
|
WORKING MODE — "trust and verify": proceed autonomously on the right things; tell me
|
|
what you'll do and why before each meaningful chunk, then go. Verify with tests + a
|
|
browser pass, and commit to the branch (do NOT merge or push — those are mine).
|
|
NO SECRETS, EVER — never type/paste/generate/echo a secret value; build around it and
|
|
hand me the gesture. Code reads secrets from env / Secret Manager only.
|
|
|
|
WHERE THINGS ARE:
|
|
- Impl repo: ~/projects/wiggleverse/ecomm/git/wiggleverse-ecomm (branch
|
|
r01-store-settings — keep working on it; it has R01 + auth + R02 + GraphQL/BFF,
|
|
unmerged). Backend: backend/app/{main,db,deps,store,staff,auth,units,graphql_api}.py,
|
|
backend/migrations/000X_*.sql, backend/tests/test_*.py. Frontend: frontend/src/.
|
|
venv at repo-root .venv/. Run backend: cd backend && ECOMM_DB=backend/var/ecomm.db
|
|
ECOMM_OWNER_EMAIL=owner@wiggleverse.test ../.venv/bin/python -m uvicorn app.main:app
|
|
--port 8000. Tests: cd backend && ../.venv/bin/python -m pytest -q. Frontend preview:
|
|
launch.json config "ecomm-frontend" (port 5173, proxies /api -> :8000).
|
|
- SPEC.md (binding, v0.4): read §A (GraphQL+BFF architecture), §1 (model), §5
|
|
(concept→mechanic traceability — ADD ROWS for R03), §7-§8 (auth/staff gates).
|
|
- Scenarios: wiggleverse-ecomm-meta/research/shopify/settings/locations.md (feature
|
|
13.07). Plan: wiggleverse-ecomm-meta/roadmap/RELEASE-PLAN.md (R03 was slimmed to
|
|
the core on branch replan-v2-resequence — build ONLY these 4):
|
|
13.07.0001 add a new location with fulfillment enabled
|
|
13.07.0002 edit an existing location's details
|
|
13.07.0003 set a location as the primary fulfillment location
|
|
13.07.0006 cannot delete the only remaining location
|
|
DO NOT build 0004/0005 (need inventory+orders → R23), 0007 (checkout → R13), 0008
|
|
(inventory → R07), 0009 (fulfillment → R23). They moved out by design.
|
|
|
|
GROUND IT IN OHM (the discipline): fetch the relevant concepts from
|
|
https://ohm.wiggleverse.org/api/rfcs/<slug> and cite each mechanic in SPEC §5.
|
|
Likely hooks: a Location is the embodied, physical venue of the Commercial
|
|
Relationship (commerce where humans actually meet); "can't delete the only location"
|
|
and "set primary" protect the merchant's operational integrity (Dignity in Commerce /
|
|
Duty of Care — never strand a store with nowhere to fulfill from). Decide and cite.
|
|
|
|
THE ARCHITECTURE TO FOLLOW (every release lands in BOTH layers on the shared core):
|
|
1. Domain: a Location entity, store-scoped (store_id). Fields: name, address_*,
|
|
fulfillment_enabled, local_pickup_enabled, is_primary, active. New module
|
|
app/locations.py (mirror staff.py shape: primitive params, raise HTTPException).
|
|
Invariants: setting primary unsets the others; cannot delete/deactivate the only
|
|
active location (0006). Migration 0004_locations.sql. Seed one primary location
|
|
for the store in db._seed so 0006 has something to protect.
|
|
2. Auth: gate location management under the 'settings' section
|
|
(require_section('settings')) — consistent with where Shopify files Locations.
|
|
(Or add a 'locations' section to staff.SECTIONS if you think it earns its keep —
|
|
your call; if you add it, update the staff scope UI + tests.)
|
|
3. GraphQL (canonical): add Location type + Store.locations relationship + mutations
|
|
(addLocation, updateLocation, setPrimaryLocation, deleteLocation) in
|
|
app/graphql_api.py. Reuse the _require_section/_run gate helpers.
|
|
4. REST BFF: screen-shaped endpoints under /api/stores/{sid}/locations.
|
|
5. Tests: backend/tests/test_r03.py — one test per scenario id (0001/0002/0003/0006),
|
|
plus a GraphQL test for the locations relationship + a mutation. Keep the full
|
|
suite green.
|
|
6. Frontend: a Locations admin section (list, add, edit, set-primary, delete-guarded).
|
|
Verify in the browser via the preview tool (sign in as owner@wiggleverse.test; OTC
|
|
code is returned in dev — watch the 60s cooldown; drive login via an in-page click
|
|
+ poll if it stalls).
|
|
|
|
DELIVERABLES: migration 0004, app/locations.py, GraphQL + REST + gate wiring, tests
|
|
(all green), frontend Locations UI, SPEC §5 rows + a short "## 9. Locations" section,
|
|
README "Shipped" bump, commit to r01-store-settings. Update memory. Then give the
|
|
resume prompt for the next release (R04 Product create & lifecycle) and a session
|
|
transcript.
|
|
```
|