# M1 Delivery Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Deliver `laundry-desk` M1 as a working Electron Windows NSIS app with receive, pickup, order list/detail, customer de-duplication, automatic/manual backup, type/lint/test gates, and CI artifact generation. **Architecture:** Keep the approved Electron split: main owns SQLite and services, preload exposes a narrow typed API, renderer uses IPC only. Replace the current prototype DB/bootstrap with focused service modules, explicit Zod IPC schemas, Drizzle relations, and deterministic tests using in-memory SQLite. M2-M4 placeholders are removed or hidden unless needed by M1. **Tech Stack:** Electron 41, React 19, TypeScript strict, Vite/electron-vite, better-sqlite3, Drizzle ORM, Zod, Vitest, Tailwind CSS, Playwright, electron-builder NSIS. **Status 2026-04-23:** M1 local delivery completed by Codex. Windows x64 NSIS artifact generated at `dist/laundry-desk Setup 0.1.0.exe`; SHA256 stored next to it. Final gates passed: `npm run lint`, `npm run typecheck`, `npm test -- --run`, `npm run test:e2e`, `npm run build:win`, and `npm audit --omit=dev --audit-level=high` with no high-severity production findings. Remaining audit item is moderate `uuid` via `exceljs` / Tencent Cloud SDK; npm's automatic fix is breaking, so it is intentionally not applied for M1. --- ### Task 1: Build And Tooling Baseline **Files:** - Modify: `package.json` - Modify: `tsconfig.node.json` - Modify: `tsconfig.web.json` - Modify: `electron.vite.config.ts` - Create: `eslint.config.js` - Modify: `vitest.config.ts` - [ ] **Step 1: Run current failing gates** Run: `npm run typecheck`, `npm run lint`, `npm test -- --run` Expected: failures document the current baseline. - [ ] **Step 2: Fix TypeScript project boundaries** Set `rootDir` to `src` or use `rootDirs` so `src/shared` compiles for node and web. Keep `strict` inherited from electron-toolkit. - [ ] **Step 3: Add working ESLint flat config** Use TypeScript parser/config compatible with ESLint 8 and React JSX. Make the lint script run without "config not found". - [ ] **Step 4: Rebuild native dependencies for local Node if needed** Run: `npm rebuild better-sqlite3`. Expected: Vitest can import `better-sqlite3`. - [ ] **Step 5: Re-run gates** Run: `npm run typecheck`, `npm run lint`, `npm test -- --run` Expected: tooling errors are resolved or narrowed to real implementation failures. ### Task 2: Database And Service Core **Files:** - Modify: `src/main/db/schema.ts` - Modify: `src/main/db/index.ts` - Create: `src/main/db/migrate.ts` - Create: `src/main/db/client.ts` - Modify: `src/main/services/customerService.ts` - Modify: `src/main/services/orderService.ts` - Modify: `src/main/services/pickupCodeService.ts` - Modify: `src/main/services/auditService.ts` - Modify: `tests/unit/services.test.ts` - [ ] **Step 1: Write service tests for M1 behavior** Cover customer upsert by phone, order creation transaction, integer cents validation, order number sequencing, pickup code format, pickup search by code/phone/order number, pickup balance settlement, and audit log creation. - [ ] **Step 2: Verify tests fail for missing/incorrect behavior** Run: `npm test -- --run tests/unit/services.test.ts` Expected: failures for missing search, transaction/audit, validation, or schema gaps. - [ ] **Step 3: Implement DB initialization** Expose a `createDbClient(sqlite)` helper for tests and `getDb()` for app runtime. Enable WAL and foreign keys. Run idempotent SQL migrations for all M1 tables and indexes from one source. - [ ] **Step 4: Implement service behavior** Use transactions for create order and pickup. Generate `order_no` and `pickup_code` inside the transaction with unique-conflict retry. Recompute totals from item rows, require integer cents, require `paidAmount <= totalAmount`, and write audit rows through the same transaction. - [ ] **Step 5: Re-run unit tests** Run: `npm test -- --run tests/unit/services.test.ts` Expected: service tests pass. ### Task 3: IPC Contract And Preload API **Files:** - Modify: `src/shared/index.ts` - Modify: `src/shared/schemas.ts` - Modify: `src/preload/index.ts` - Modify: `src/main/ipc/orders.ts` - Modify: `src/main/ipc/customers.ts` - Modify: `src/main/ipc/settings.ts` - Create: `src/main/ipc/backup.ts` - Modify: `src/main/index.ts` - [ ] **Step 1: Write IPC schema tests where practical** Cover invalid order id, invalid search query, invalid settings key, and invalid backup action schemas. - [ ] **Step 2: Implement uniform IPC helpers** Every handler returns `{ ok: true, data } | { ok: false, error }`, logs detailed errors in main, and returns user-safe messages. - [ ] **Step 3: Narrow preload exposure** Expose only `window.api`; remove default `window.electron`; use typed request/response signatures instead of `any`. - [ ] **Step 4: Add CSP and production-safe window behavior** Remove debug background, `alwaysOnTop`, devtools auto-open, and fixed startup delay. Add CSP to renderer HTML. - [ ] **Step 5: Re-run typecheck/lint** Run: `npm run typecheck && npm run lint` Expected: zero errors. ### Task 4: Renderer M1 Flows **Files:** - Modify: `src/renderer/index.html` - Modify: `src/renderer/src/assets/main.css` - Modify: `src/renderer/src/env.d.ts` - Modify: `src/renderer/src/routes/index.tsx` - Modify: `src/renderer/src/components/Layout.tsx` - Modify: `src/renderer/src/routes/Home.tsx` - Modify: `src/renderer/src/routes/Receive.tsx` - Modify: `src/renderer/src/routes/Pickup.tsx` - Modify: `src/renderer/src/routes/Orders.tsx` - Modify: `src/renderer/src/routes/OrderDetail.tsx` - Modify: `src/renderer/src/routes/Customers.tsx` - Modify: `src/renderer/src/routes/Settings.tsx` - [ ] **Step 1: Add focused renderer tests if test harness exists, otherwise rely on typecheck and manual/E2E smoke** Validate route imports compile and typed IPC calls are correct. - [ ] **Step 2: Restore usable styling** Either configure Tailwind correctly or replace with a compact CSS utility layer sufficient for the current class usage. Preserve Apple HIG-inspired layout and responsive behavior. - [ ] **Step 3: Complete receive flow** Phone lookup, customer upsert, item rows with cents conversion, partial payment selection, validation messages, success reset, and navigation to order detail. - [ ] **Step 4: Complete pickup flow** Search by pickup code, phone, order number, or customer name; render results; support balance settlement and picked-up transition. - [ ] **Step 5: Complete list/detail/settings M1 routes** Order list pagination basics, order detail with print button hidden/disabled until M3, customers list/search, settings shop name, manual backup, and backup list/restore placeholder only if clearly marked out-of-scope. ### Task 5: Backup And Delivery Verification **Files:** - Modify: `src/main/services/backupService.ts` - Modify: `src/main/ipc/backup.ts` - Modify: `tests/unit/services.test.ts` - Modify: `.github/workflows/build.yml` - Modify: `README.md` - Create: `docs/CHANGELOG.md` - [ ] **Step 1: Add backup tests** Use a temp directory and a test database. Verify backup zip is created atomically, contains `laundry.db`, and rotate keeps 30 newest files. - [ ] **Step 2: Implement backup service** Checkpoint WAL, write to temp zip, finalize, rename atomically, rotate after success, and expose manual backup IPC. - [ ] **Step 3: Add CI gates** Run install, typecheck, lint, test, build, and `build:win`. Upload NSIS artifact and SHA256. - [ ] **Step 4: Run local verification** Run: `npm run typecheck`, `npm run lint`, `npm test -- --run`, `npm run build` Expected: all pass locally. - [ ] **Step 5: Attempt package verification** On macOS run `npm run build:unpack` if supported. Final `.exe` must be generated by GitHub Actions `windows-latest`.