Internal Tool / Dashboard Template - Chronological Implementation TODO Plan (Template repo: ai-eng-template-internal-tool-dashboard) ============================================================================== INTENT ============================================================================== A starting point for the studio's internal-tool and operations-dashboard engagements: small teams that need a role-aware web app to manage records, review approvals, monitor KPIs, and export operational reports. The template ships with auth, role-based access, a CRUD scaffolding generator, a chart toolkit, an audit log, and a CSV export pipeline. It is the default repo for "operations dashboard", "back-office app", and "ops console" engagements. OUT OF SCOPE: anything that should be the customer-facing product (use the founder SaaS template), e-commerce, booking, or mobile-first surfaces. High-level summary - Goal: a forkable, opinionated internal-tool starter that ships with auth, role-based access, an audit log, a CRUD scaffolding generator, charts, and a CSV export pipeline. - Platform target: Next.js App Router, Firebase Auth + Firestore + Cloud Functions + Storage, Recharts (or Visx) for charts, Tailwind + design tokens. - Performance/security target: tight role separation, App Check enforced on every callable, immutable audit log, encrypted-at-rest secrets. - Rough delivery estimate: 3-8 weeks per customer customization. Phase 0 - Scope freeze, product definitions, and delivery guardrails (Effort: Medium) Dependencies: customer discovery workshop output. [ ] Freeze template scope: - [ ] confirm the template ships with: sign-in (password + Google), 3 role templates (admin, operator, viewer), a record-management CRUD shell, a KPI dashboard with 4 example cards, an approvals queue, an audit log, a CSV export pipeline, and an admin shell for user management. - [ ] confirm explicit OUT-OF-SCOPE: customer-facing pages, public sign-up, marketing surfaces, or any flow that needs anonymous access. [ ] Define delivery guardrails: - [ ] every privileged mutation writes an audit entry. - [ ] every Firestore mutation goes through a Cloud Function. - [ ] every role boundary has a Firestore Security Rules test. Potential gotchas: - [ ] customers will request "just one public form"; reroute that to the small-business website template. Phase 1 - Repository skeleton, tooling, and CI (Effort: Small) Dependencies: scope freeze. [ ] Repository scaffolding and CI mirroring the SaaS MVP template, plus: - [ ] CODEOWNERS file with a default operator/reviewer pair. - [ ] `scripts/scaffold-crud.mjs` - CLI that generates a new CRUD resource (list, create, edit, detail) from a single zod schema. Phase 2 - Design system and token foundation (Effort: Small) Dependencies: Phase 1. [ ] Tokens and primitives mirror the SaaS template, plus operator-style density: - [ ] DataTable (sticky header, sortable columns, column visibility menu, pagination, CSV export button). - [ ] FilterBar (date range, status, owner). - [ ] KPI card, Trend card, Spark line. Phase 3 - Authentication and role model (Effort: Large) Dependencies: Phase 1. [ ] Firebase Auth: - [ ] only invite-based onboarding; no public sign-up. - [ ] sign-in providers: email/password and Google (configurable). [ ] Role model: - [ ] custom claim `role` per user: `admin` | `operator` | `viewer`. - [ ] additional `team` claim if the customer requires team scoping. - [ ] `setUserRole` Cloud Function callable, restricted to admins, audit- logged. [ ] Session: - [ ] server-side session cookie set via a Cloud Function so SSR pages can guard before first paint. Potential gotchas: - [ ] long-lived sessions and stale custom claims are a real problem in ops tooling; rotate the session cookie after a role change. Phase 4 - Data model and persistence (Effort: Large) Dependencies: Phase 3. [ ] Default Firestore collections: - [ ] `records/{recordId}` - the placeholder CRUD entity. - [ ] `approvals/{approvalId}` - pending approval entries with `status`, `requestedBy`, `requestedAt`, `decidedBy`, `decidedAt`. - [ ] `auditLogs/{logId}` - immutable audit entries (`kind`, `actor`, `subject`, `timestamp`, `metadata`). - [ ] `exports/{exportId}` - CSV export jobs. [ ] Security rules: - [ ] viewers can read but never write. - [ ] operators can read and write `records` and `approvals` but not roles or audit logs. - [ ] admins can read everything; audit logs are append-only for everyone, including admins. Potential gotchas: - [ ] audit logs that admins can rewrite are not audit logs; enforce append-only via rules AND deny `update`/`delete` in code. Phase 5 - Dashboard and KPI surface (Effort: Medium) Dependencies: Phase 4. [ ] `/dashboard` shows 4 example KPI cards (total records, pending approvals, last-7-days throughput, error rate). [ ] Cards are computed from a denormalized `dashboardSnapshots/{date}` document written by a scheduled Cloud Function (every 15 minutes) so the dashboard is cheap to read. [ ] Charts: - [ ] line chart for daily throughput. - [ ] stacked bar for status mix. - [ ] include a "Stale data" indicator if the snapshot is older than the refresh interval. Potential gotchas: - [ ] computing KPIs on the fly from raw Firestore reads will get expensive fast; always go through a snapshot. Phase 6 - CRUD scaffolding generator (Effort: Medium) Dependencies: Phase 4. [ ] `pnpm scaffold:crud --schema ` generates: - [ ] list/detail/edit/new routes under `(app)/[resource]/...`. - [ ] a Firestore collection + composite indexes derived from the schema. - [ ] Cloud Function callables for `create`, `update`, `archive`, with audit-log writes baked in. - [ ] a Vitest unit test stub and a Firestore Security Rules test stub. [ ] Convention: every CRUD resource is governed by a zod schema in `packages/schemas/src/`. Potential gotchas: - [ ] generators that drift from the zod schema cause silent runtime errors; regenerate from the schema, never edit the generated CRUD by hand for structural changes. Phase 7 - Approvals queue (Effort: Medium) Dependencies: Phases 4, 6. [ ] `/approvals` lists pending approvals scoped to the operator's `team`. [ ] Bulk approve/reject with optional reason; every decision writes to `auditLogs/{logId}` with `kind: 'approval.decided'`. [ ] Email digest (configurable, opt-in per operator) summarizing the queue. Potential gotchas: - [ ] approvers and requesters should never overlap; enforce in the rules and in the UI. Phase 8 - Audit log and exports (Effort: Medium) Dependencies: Phase 4. [ ] `/audit` is admin-only, with filters by actor, kind, date range, subject. [ ] CSV export: - [ ] `createExport` Cloud Function builds the CSV in Cloud Storage and returns a signed URL valid for 15 minutes. - [ ] export job writes an audit entry with the filter parameters. Potential gotchas: - [ ] never expose raw Firestore IDs in CSVs without redaction; document this in `docs/customization.md`. Phase 9 - Observability, security, accessibility (Effort: Medium) Dependencies: Phases 5-8. [ ] App Check enforced on every callable and HTTP function. [ ] Cloud Logging structured logs with `requestId` and `actor` per call. [ ] CSP, HSTS, frame headers configured; `/dashboard` and `/admin` blocked from indexing. [ ] Lighthouse a11y >= 95 on every internal route. Potential gotchas: - [ ] internal tools are notoriously inaccessible; do not skip the audit just because the audience is small. Phase 10 - Testing strategy (Effort: Medium) Dependencies: Phases 3-9. [ ] Firestore Security Rules tests for every collection and every role. [ ] Vitest unit tests on every Cloud Function and every generated CRUD module. [ ] Playwright smoke per release: sign in as operator, create a record, request approval, switch session to admin, approve, export CSV, verify audit row. Potential gotchas: - [ ] role switching in Playwright requires custom-claim refresh; use Admin SDK against the emulator to set claims. Phase 11 - Customization handbook (Effort: Small per customer) Dependencies: Phases 0-10. [ ] `docs/customization.md` records, per customer: - [ ] real resource names that replace the `record` placeholder. - [ ] role names and the permissions matrix. - [ ] integrations (HR system import, accounting export, Slack alerts). - [ ] approval policies (single approver, dual approver, threshold-based). - [ ] retention policy for audit logs and exports. - [ ] which KPIs replace the example cards. Potential gotchas: - [ ] resource renames break URLs; do not rename in production after launch. Document the rename window in the launch checklist. Phase 12 - Public showcase integration (Effort: Small) Dependencies: this plan, ecosystem Phase 26. [ ] Showcase metadata: - [ ] register this template in `apps/web/src/lib/showcase.ts` with id `internal-tool-dashboard`, hero, feature list, "what you get", and a CTA. [ ] Live preview: - [ ] a public staging instance with synthetic seed data is deployed and embedded as a sandboxed iframe on `/showcase/internal-tool-dashboard`. - [ ] preview is reseeded every 12 hours by a scheduled Cloud Function. - [ ] the preview shows a permanent "Template preview - synthetic data" banner. [ ] Documentation surfaced on the detail page: - [ ] template README, architecture diagram, role permissions matrix. Potential gotchas: - [ ] never reuse real customer audit data for the showcase; the seeder must generate synthetic records only.