218 lines
12 KiB
Markdown
218 lines
12 KiB
Markdown
# Insole Production Time Tracker — Rebuild Roadmap & Project Overview
|
||
|
||
- **Created:** 2026-06-17
|
||
- **Status:** Approved — living project doc; Phases 0–2 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).
|
||
|
||
> **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: live active-work view, reports/export,
|
||
user management, **activity management**, **manual entry/edit (the fallback)**.
|
||
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.
|