docs: Phase 2 accounts & roles — roadmap, README, session log

This commit is contained in:
Bas van Rossem
2026-06-17 18:04:19 +02:00
parent 7d200eb8fc
commit 3d8524c827
5 changed files with 903 additions and 39 deletions

View File

@@ -1,7 +1,7 @@
# Insole Production Time Tracker — Rebuild Roadmap & Project Overview
- **Created:** 2026-06-17
- **Status:** Approved — living project doc; Phase 0 plan written (`docs/plans/phase-0-foundation.md`)
- **Status:** Approved — living project doc; Phases 02 implemented (`docs/plans/phase-2-accounts-roles.md`)
- **Type:** Greenfield rebuild of an inherited app
- **Tracked in git** under `docs/` (the project's documentation source of truth).
@@ -9,7 +9,7 @@
> (`apps/mobile`, `apps/web`, `publisher/`) was deleted in a full cleanup. The repo is now
> a single-service backend (`apps/api`) plus `packages/shared`. Reference for the old code
> is preserved in `docs/reference/` and in git history. The sections below describe the
> codebase *as inherited* and the rebuild plan; treat references to the legacy apps as
> codebase _as inherited_ and the rebuild plan; treat references to the legacy apps as
> historical.
---
@@ -32,7 +32,7 @@ Reverse-engineering established:
cookies for web), but the core flow does not actually require login.
- **The data and accounts are not ours.** Users, password hashes, and all task/time
data live in the platform's managed Neon Postgres, bound to the friend's Create
account/organization. This repo contains only the *code* and an
account/organization. This repo contains only the _code_ and an
`ANYTHING_PROJECT_TOKEN` — no database credentials. Nothing runs locally and no
database is reachable from this code.
@@ -61,21 +61,21 @@ it is saved → repeats. Because the **backend is the source of truth**:
- An **admin panel** shows live who-is-working-on-what, generates reports, and manages
users and activities.
Goals: it must **genuinely work in the workshop** (reliability, no data loss) *and* serve
Goals: it must **genuinely work in the workshop** (reliability, no data loss) _and_ serve
as a **learning vehicle** the owner extends himself.
## 3. Decisions (resolved during brainstorming)
| # | Decision | Choice |
|---|---|---|
| 1 | Purpose | Real workshop tool **and** a learning vehicle |
| 2 | Platform relationship | **Clean break** from Create/Anything |
| 3 | Hosting | **Dockerized** stack; runs locally now, portable to any cloud later |
| 4 | Build strategy | **Greenfield rebuild**, porting only the good parts |
| 5 | Backend topology | **Dedicated backend service** (Option A): single owner of auth + DB; UIs are interchangeable clients |
| 6 | Auth | **better-auth** (don't hand-roll security for real use) |
| 7 | Database | **SQLite** (small userbase; one file, easy backup/Docker) |
| 8 | Language | **TypeScript everywhere** so types flow end-to-end |
| # | Decision | Choice |
| --- | --------------------- | ---------------------------------------------------------------------------------------------------- |
| 1 | Purpose | Real workshop tool **and** a learning vehicle |
| 2 | Platform relationship | **Clean break** from Create/Anything |
| 3 | Hosting | **Dockerized** stack; runs locally now, portable to any cloud later |
| 4 | Build strategy | **Greenfield rebuild**, porting only the good parts |
| 5 | Backend topology | **Dedicated backend service** (Option A): single owner of auth + DB; UIs are interchangeable clients |
| 6 | Auth | **better-auth** (don't hand-roll security for real use) |
| 7 | Database | **SQLite** (small userbase; one file, easy backup/Docker) |
| 8 | Language | **TypeScript everywhere** so types flow end-to-end |
## 4. Architecture
@@ -99,6 +99,7 @@ as a **learning vehicle** the owner extends himself.
```
**Auth flow**
- **Mobile** — native email+password screen → `POST /api/auth/sign-in/email` → backend
returns a bearer **token** → stored in Expo SecureStore → sent as
`Authorization: Bearer <token>` on every request. (Drops the current app's embedded
@@ -108,15 +109,15 @@ as a **learning vehicle** the owner extends himself.
## 5. Tech stack (recommended picks, approved)
| Layer | Pick | Notable alternative |
|---|---|---|
| Backend framework | **Hono** | Fastify |
| Auth | **better-auth** | — |
| DB access + migrations | **Drizzle ORM** | Kysely / Prisma |
| Database | **SQLite** | libsql/Turso (if cloud later) |
| Admin UI | **Vite + React** (SPA) | Next.js (if SSR wanted) |
| Mobile | **Expo / React Native** | — |
| Shared contracts | **`packages/shared`** (TS types + zod) | — |
| Layer | Pick | Notable alternative |
| ---------------------- | -------------------------------------- | ----------------------------- |
| Backend framework | **Hono** | Fastify |
| Auth | **better-auth** | — |
| DB access + migrations | **Drizzle ORM** | Kysely / Prisma |
| Database | **SQLite** | libsql/Turso (if cloud later) |
| Admin UI | **Vite + React** (SPA) | Next.js (if SSR wanted) |
| Mobile | **Expo / React Native** | — |
| Shared contracts | **`packages/shared`** (TS types + zod) | — |
## 6. Monorepo shape
@@ -161,27 +162,30 @@ maps, 3D, audio, calendar, contacts, sensors, …).
Each phase keeps the system working and is its own spec → plan → build cycle.
- **Phase 0 — Foundation.** Greenfield monorepo; dockerized Hono backend with better-auth
+ Drizzle + SQLite; `docker compose up` brings it up; health check + one auth
round-trip proven end-to-end. *Done when:* a client can sign in against the
containerised backend and the token authorises a protected call.
- Drizzle + SQLite; `docker compose up` brings it up; health check + one auth
round-trip proven end-to-end. _Done when:_ a client can sign in against the
containerised backend and the token authorises a protected call.
- **Phase 1 — Worker timing.** Activities + server-authoritative work-sessions
(open/close) + history + CSV export in the backend; mobile app rebuilt to use it.
*Done when:* a worker can pick an activity, start/stop a server-side session, and see
_Done when:_ a worker can pick an activity, start/stop a server-side session, and see
history; CSV exports.
- **Phase 2 — Accounts & roles.** Worker/admin roles, admin-creates-users, per-user data
scoping. *Done when:* workers see only their own sessions; an admin account exists.
- **Phase 2 — Accounts & roles.** **Implemented.** Worker/admin roles (better-auth `admin`
plugin), admin-creates-users, per-user data scoping. Workers are scoped to their own sessions;
an admin account exists; admin manages users via `/api/auth/admin/*` and sees all sessions via
`/api/admin/sessions`. Public sign-up is closed; activity writes are admin-only.
_Done when:_ workers see only their own sessions; an admin account exists.
- **Phase 3 — Admin panel.** The React admin app: live active-work view, reports/export,
user management, **manual entry/edit (the fallback)**. *Done when:* an admin can see
user management, **manual entry/edit (the fallback)**. _Done when:_ an admin can see
who's working now, manage users, and hand-correct a session.
- **Phase 4 — Workbench scanning.** QR at the bench → select workbench/activity, with
manual selection fallback. *Done when:* scanning a bench QR pre-fills the session.
manual selection fallback. _Done when:_ scanning a bench QR pre-fills the session.
- **Phase 5 — Polish & deploy.** Reporting niceties, dependency slimming, push the
container to a chosen cloud host.
## 10. Open questions & assumptions (confirm as we go)
- **Scanning = QR codes** on benches, read by the phone camera (no special hardware),
always with manual fallback. *(Assumption.)*
always with manual fallback. _(Assumption.)_
- **Start fresh, no data migration.** Assumes no live workshop data/users worth
preserving in the friend's platform instance. If there are, they must be **exported
from the friend's Create account** — unreachable from this repo.
@@ -189,7 +193,7 @@ Each phase keeps the system working and is its own spec → plan → build cycle
friend.
- **Deployment host** is deferred (Phase 5); the dockerized stack keeps options open.
- **Domain term:** "insole" / orthotic; Dutch UI (`Type zool`, `handeling`, `aantal
zolen`, etc.).
zolen`, etc.).
## 11. Risks