Files
solelog/docs/roadmap.md
2026-06-17 19:17:20 +02:00

226 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Insole Production Time Tracker — Rebuild Roadmap & Project Overview
- **Created:** 2026-06-17
- **Status:** Approved — living project doc; Phases 02 implemented + Phase **3a** implemented (`docs/superpowers/plans/2026-06-17-phase-3a-admin-panel.md`)
- **Type:** Greenfield rebuild of an inherited app
- **Tracked in git** under `docs/` (the project's documentation source of truth).
> **2026-06-17 — Legacy code removed.** The inherited Create/Anything export
> (`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
> historical.
---
## 1. Context
The codebase was inherited as an export from the **Create / Anything AI** platform — a
working time-tracking app for **insole (orthotic) production**, originally built by a
friend through a chat-driven workflow. It arrived with no history, no documentation, and
no clarity on what was complete or where the backend/data lived.
Reverse-engineering established:
- It is a **two-app monorepo**: `apps/mobile` (Expo/React Native) + `apps/web`
(Next.js 16 backend on Neon Postgres). Plus `publisher/` (deploy tooling).
- It is **heavily coupled to the Create platform**: "do-not-edit" platform files,
patched dependencies, a web-sandbox iframe layer, and ~80 dependencies for what is
functionally a stopwatch.
- **Auth** is `better-auth` (email+password, argon2 hashes, bearer tokens for mobile,
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
`ANYTHING_PROJECT_TOKEN` — no database credentials. Nothing runs locally and no
database is reachable from this code.
Work already done this session (committed):
- Git repository initialised; baseline + doc corrections committed.
- Found and fixed `/api/logs` — it was both git-ignored (an over-broad `logs` rule) and
broken at runtime (missing its `import sql`). That route is History + Stop&Save.
- Wrote a reverse-engineered `schema.sql` (no migration shipped).
- Installed dependencies (~1.7 GiB) and confirmed Docker is available.
> The existing code is treated as a **working reference / seed**, not the foundation.
## 2. Vision
A **multi-user, backend-driven shop-floor time-tracking system**. The phone is one of
several clients, not the source of truth.
A worker, on **their own phone with their own account**, logs in → goes to a workbench →
**scans it (QR) or selects manually** → picks the activity → times the work → ends it →
it is saved → repeats. Because the **backend is the source of truth**:
- An active session lives **server-side**, so if the phone dies the worker can **end or
log the work from a computer** instead.
- There is a **manual-entry fallback** wherever something can fail.
- 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
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 |
## 4. Architecture
```
┌─────────────┐ ┌─────────────┐
│ Mobile app │ │ Admin web │ clients — UI only, no DB access
│ (Expo/RN) │ │ (React SPA) │
└──────┬──────┘ └──────┬──────┘
│ HTTP (Bearer) │ HTTP (cookie/Bearer)
└─────────┬─────────┘
┌──────────────────┐
│ Backend service │ the ONLY thing that touches auth + DB
│ better-auth + │
│ business logic │
└────────┬─────────┘
┌─────────┐
│ SQLite │ single file on a Docker volume
└─────────┘
```
**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
login WebView.)
- **Admin** — standard better-auth **session cookies**.
- **Backend** — mounts better-auth, owns all DB access, enforces roles.
## 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) | — |
## 6. Monorepo shape
```
apps/
mobile/ Expo worker app (client)
admin/ Vite + React panel (client)
api/ Hono + better-auth + Drizzle + SQLite (backend service)
packages/
shared/ TS types + zod schemas (API contracts)
docker-compose.yml + Dockerfiles
```
## 7. Data model
Server-authoritative; an open session (`end_time` null) is "active work".
- **users** — id, email, name, password hash (better-auth managed), **role** (`worker` | `admin`)
- **workbenches** — id, name, `qr_code` (seeded / hardcoded for now)
- **activities** — id, name, `insole_types[]` (subset of `Kurk` | `Berk` | `3D`)
- **sessions** — id, `user_id`, `activity_id`, `workbench_id`, `insole_type`,
`pair_count`, `start_time`, `end_time` (null = running),
`status` (`active` | `completed` | `discarded`),
`source` (`app` | `manual`), `notes`, `created_at`
(better-auth also creates its own `session`/`account`/`verification` tables; those are
distinct from the domain `sessions` table above — naming to be disambiguated in Phase 0,
e.g. `work_sessions`.)
## 8. Port vs. leave behind
**Port (the good parts):** the data model, the API route logic, the screen flows/UX, the
CSV export logic, the Dutch UI strings, and the lessons captured in the current code's
comments (Android font/freeze fixes, SecureStore quirks).
**Leave behind:** the `__create` plumbing, the web-sandbox iframe layer, analytics /
Sentry / anything-menu, the patched dependencies, and the ~60 unused libraries (ads, IAP,
maps, 3D, audio, calendar, contacts, sensors, …).
## 9. Phased roadmap
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.
- **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
history; CSV exports.
- **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 (`apps/admin`, Vite + React, dev port
5174): live active-work view, reports/export, user management, **activity management**,
**manual entry/edit (the fallback)**.
**3a implemented** (`apps/admin`; plan `docs/superpowers/plans/2026-06-17-phase-3a-admin-panel.md`):
admin-only login (rejects non-admins via `role` on `/api/me`), the sidebar shell, the live
active-work view (`/api/admin/sessions/active`, 5 s auto-refresh, read-only), and activity
management (handelingen CRUD on `/api/activities`). **3b remaining:** reports/export
(all-users filtered CSV — current `/api/export` is self-scoped), user management
(better-auth `/api/auth/admin/*`), and manual entry/edit + admin stop/fix of a running
session (needs new backend endpoints).
Activity management (add/edit/delete handelingen + their `insole_types`) was removed from the
worker client in the Phase 2 follow-up because it is admin-only; it must be **ported here**. The
backend already exists (`/api/activities` writes are admin-gated; `useActivities`/the legacy
worker `Settings.tsx` at git `decb158`/`1631c16` are the UI reference), so this is a UI-only port.
User management likewise consumes the existing better-auth `/api/auth/admin/*` endpoints, and the
live view + reports consume `/api/admin/sessions[/active]`. _Done when:_ an admin can see who's
working now, manage users **and activities**, 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.
- **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.)_
- **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.
- **Workbench↔activity mapping** is hardcoded/seeded for now; real mapping TBD with the
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.).
## 11. Risks
- **Greenfield is more work than evolving in place** — mitigated by porting proven logic
and keeping the old code as a running reference.
- **SQLite is single-writer / single-instance** — fine at this scale; swap to
Postgres/libsql is a config change via Drizzle/better-auth if ever needed.
- **Offline on the shop floor** — the friend hit connectivity issues. Backend-as-source-
of-truth assumes reachable network; true offline-first is explicitly out of scope for
now (revisit if it bites).
## 12. Next step
Brainstorm **Phase 0** in detail, then hand it to the writing-plans skill for an
implementation plan. No code before that plan exists.