MEGAINFRA-WEBAPP/docs/minimax-multi-site-audit-prompt.md
DEls 08ed89d9c8 feat(dashboard): enhance operations dashboard with rain outlook and coordinate support
Updated the operations dashboard to include a rain outlook feature, providing users with a 7-day forecast based on site coordinates. Added latitude and longitude fields to the site form for better weather data integration. Enhanced the fuel log and site management functionalities to utilize dynamic fuel pricing based on historical data. Improved overall data handling and user experience across various dashboard components.
2026-09-06 19:59:52 +02:00

14 KiB
Raw Permalink Blame History

Prompt for MiniMax agent — Document the app + assess multi-site readiness

Paste everything below the line into the MiniMax agent. It assumes the agent has read/write access to this repository.


Role

You are a senior engineer joining the MEGA INFRASTRUCTURE codebase. Your job has two parts, in this order:

  1. Write the missing technical documentation for the app as it exists today.
  2. Deliver a multi-site readiness assessment: can this app genuinely run many construction sites at once right now, and what specifically has to change for it to do so reliably at scale?

You are producing documentation and analysis only. Do not change application code, schema, or config. The only files you create or modify are the deliverables listed at the bottom.


Ground rules

  • Evidence over assumption. Every factual claim you make must cite a real path/to/file.ts:line. If you cannot find evidence for something, write "unverified" and say what you looked at.
  • The README.md at the repo root is stale and actively wrong. It describes an earlier mock-data version. It references src/lib/fuel.ts, src/lib/types.ts, src/app/api/mcp/, src/app/api/upload/, and /dashboard/orders — none of these exist. Do not use it as a source. Treat the source code as the only truth.
  • Read AGENTS.md first. This is a modified build of Next.js 16; conventions may differ from what you expect. Authoritative docs live in node_modules/next/dist/docs/. Read the relevant guide there before making any claim about Next.js behaviour (caching, dynamic rendering, route handlers, server components).
  • Do not invent severity. Distinguish clearly between: (a) a bug that breaks correctness today, (b) a limit that will break at a known threshold, (c) a design choice that is fine now but will cost more to change later.
  • Verify claims by reading code. Where useful, run npm run typecheck and npm run test:run to confirm the suite's current state, and report the actual output.

What the app is

A Next.js 16 (App Router, React 19, Tailwind v4) operations dashboard for a South African civil construction company, backed by PocketBase. It tracks, per construction site: sites/contracts, employees & timesheets, vehicles (fuel and plant units), fuel logs, plant hour meters, fixed costs, income claims, purchase orders + line items, and delivery notes with OCR-driven receipting. There is also an LLM chat ("Ask") surface with a read-only tool layer over the same data, and an MCP server.

Key entry points to orient yourself:

Area Path
PocketBase clients (pb browser, pbAdmin superuser) src/lib/pb.ts
Full collection type definitions src/lib/pb-types.ts
Dashboard pages (server components) src/app/dashboard/**/page.tsx
Route handlers src/app/api/**/route.ts
Pure metric/calculation functions src/lib/metrics/
Import parsers (timesheets, fuel, plant hours, POs) src/lib/*-parse.ts, src/lib/*-import.ts
Chat/agent tool layer src/lib/agent/, src/lib/chat/
Auth (PIN gate) src/hooks/use-auth.tsx, src/components/auth-gate.tsx
Schema bootstrap / rules scripts scripts/pb-bootstrap-schema.py, scripts/pb-relax-rules.py
Existing design/plan docs docs/superpowers/specs/, docs/superpowers/plans/

Part 1 — Documentation to write

Write these as Markdown into docs/. Aim for documents a new engineer could use to become productive without reading every file, and that a non-technical owner could use to understand what the system does.

1. docs/architecture.md

  • Runtime topology: Next.js app → PocketBase → n8n webhooks (PO ingest, delivery-note OCR) → LLM providers. Draw it as a Mermaid diagram.
  • Rendering model: which pages are server components, what export const dynamic settings are in use, where data fetching happens, and what is client-side.
  • The two PocketBase clients and when each is used. Be explicit about the fact that server routes and pages authenticate as the PocketBase superuser via pbAdmin() (src/lib/pb.ts) and what that implies.
  • Auth model as it actually is today: a shared numeric PIN from NEXT_PUBLIC_APP_PIN (default 2468), held in sessionStorage, with a ?demo=1 query-string bypass (src/hooks/use-auth.tsx). State plainly that there is no per-user identity in the application.
  • Build/deploy: Dockerfile, docker-compose.yml, COOLIFY.md, the --webpack requirement for the PWA plugin, and the icon/OG-image prebuild scripts.

2. docs/data-model.md

  • Every PocketBase collection from src/lib/pb-types.ts: fields, types, relations, and which are optional/legacy.
  • An entity-relationship Mermaid diagram.
  • For each collection, state explicitly whether it carries a site relation, a project_code string, both, or neither. Flag the ones that carry neither and explain how those records are attributed to a site (if at all).
  • Document the project_code denormalisation: it is copied onto child records rather than read through the site relation. Describe the drift risk and where it is written.
  • Document known unique indexes and constraints you can find (e.g. the composite unique index on plant_hours_log referenced in src/app/api/plant-hours/import/route.ts), and what happens on collision.
  • Document PocketBase API rules as configured by scripts/pb-relax-rules.py (list/view/create = any authenticated user; update/delete = superuser only) and what that means for who can read what.

3. docs/modules.md

One section per dashboard module (Overview, Sites, Workforce, Plant & Equipment, Fleet & Fuel, Purchasing, Ask). For each: purpose, route, which collections it reads, which metric functions it uses, what the user can do there, and which API routes it calls.

4. docs/data-flows.md

Trace each ingestion pipeline end to end, with a sequence diagram:

  • Timesheet import (/api/timesheets/import) — including the auto-create-employees path.
  • Fuel log import (/api/fuel-logs/import).
  • Plant hours import (/api/plant-hours/import) + exception report.
  • Purchase order upload → n8n → /api/purchase-orders/ingest → process-batch.
  • Delivery note upload → OCR → /api/delivery-notes/[id]/ocr-result → received items.

For each pipeline, answer precisely: how is the target site determined for each imported row? Name the exact matching strategy and the failure behaviour when no match is found.

5. docs/api-reference.md

Every route under src/app/api/: method, path, auth/secret requirements, request shape, response shape, error cases. Note which are protected by N8N_INGEST_SECRET and which have no protection at all.

6. docs/operations.md

Environment variables (from .env.local.example), what each does, which are client-exposed (NEXT_PUBLIC_), the scripts in scripts/, how to run tests, and the existing feature flags (e.g. ENABLE_CHAT).


Part 2 — Multi-site readiness assessment

Write this as docs/multi-site-assessment.md. This is the deliverable that matters most.

The question to answer

Multiple construction sites — The Hills, Cosmo City, Castle Gate, Autumns Gate, Pitsana Mills, West Park, and more to come. This is not a question about multi-tenancy or serving multiple client companies. It is: does the existing per-site model actually hold up as the number of sites and the volume of historical data grows, and where does it break?

Structure your answer in three parts.

Part A — What works today

The data model is already site-aware. Verify and document this properly: which collections carry a site relation, which UI surfaces group or filter by site, how per-site financials are computed (src/lib/metrics/site-spend.ts, site-projection.ts, income-vs-expenses.ts), and how the chat tool layer resolves a site from free text (src/lib/agent/resolve.ts). Give a plain verdict: at what scale does the app work correctly as-is?

Part B — Where it breaks

Investigate each of the following. These are leads I have partially verified — confirm or refute each one yourself with file:line evidence, correct me where I am wrong, and add anything I missed. Do not simply restate this list; test each claim.

  1. Hard 50-site cap on the Overview page. src/app/dashboard/page.tsx:64 calls pb.collection("sites").getList<SiteRecord>(1, 50, { sort: "name" }). Determine what happens to site 51+ — does it silently vanish from KPI tiles and the "Attention required" rail? Search the whole codebase for other capped getList(page, perPage) calls and list every one with its cap and its blast radius. There is a related comment at src/app/dashboard/purchasing/page.tsx:29 about a previous cap that silently truncated data — treat that as evidence this class of bug has already bitten once.

  2. Load-everything-then-filter-in-memory. Most dashboard pages call getFullList() on entire collections and filter in JavaScript — e.g. src/app/dashboard/page.tsx, src/app/dashboard/sites/page.tsx, src/app/dashboard/purchasing/page.tsx, src/app/dashboard/fuel/page.tsx, src/app/dashboard/employees/page.tsx. Note especially src/app/dashboard/sites/[id]/page.tsx:50-56, which filters some collections by site='<id>' server-side but pulls all timesheets and all employees regardless. Quantify: with N sites × M months of fuel logs, timesheets, POs and received items, how does page cost grow? Estimate the row counts at which pages become slow, and identify which single page falls over first.

  3. No global site scope. The sidebar (src/components/layout/sidebar.tsx) has no site selector; each module handles site filtering independently, mostly client-side. Assess what this costs a user who works on one site: how many clicks/filters to see just their data, and which modules offer no site filter at all.

  4. Site resolution by name string. Importers match incoming rows to sites by case-insensitive sites.name comparison (see src/app/api/fuel-logs/import/route.ts around lines 214-224 and src/app/api/plant-hours/import/route.ts around lines 237-245), and PO matching goes through src/lib/purchase-order-schema.ts. Evaluate the failure modes as site count grows: near-identical names, renamed sites, whitespace/casing drift, two sites sharing a name, source spreadsheets using a different label than PocketBase. What happens to a row that matches nothing — is it dropped, orphaned, or rejected? Is project_code a more reliable key, and is it consistently present?

  5. Vehicles, plant and employees moving between sites. A vehicle or worker is bound to one site at a time. Determine what happens to historical records when that assignment changes: do past fuel logs and timesheets stay attributed to the old site, or do they follow the current assignment and silently rewrite history? Check whether logs snapshot the site at import time or read it through the relation. Note that plant_hours_log stores vehicle_unit_type_at_import, which suggests the codebase already understands point-in-time snapshotting — does the same discipline apply to site? Also check the (vehicle_qr, start_date) unique index for cross-site collisions.

  6. Access control per site. With a single shared PIN and no user records, no user can be restricted to their own site — everyone who knows the PIN sees every site's contract values, margins and payroll. Confirm this, and confirm that server-side data access runs as PocketBase superuser (pbAdmin()), meaning collection-level API rules do not constrain it. State whether per-site access control is achievable without introducing real user accounts.

  7. The chat/agent layer. Tools in src/lib/agent/tools.ts load portfolio-wide bundles (list_sites and friends). Assess: cost and latency growth as sites multiply, whether ambiguous site names are handled safely (src/lib/agent/resolve.ts), and whether the agent can leak one site's financials to a user who should only see another's. Note that .env.local.example already warns ENABLE_CHAT must stay off in production until real authentication exists — verify whether that warning is still accurate.

  8. Anything else you find. Cross-site data leakage, missing indexes, N+1 queries, unbounded getFullList() calls in route handlers, aggregates that double-count when a record has a stale project_code, and the $autoCancel: false workarounds in src/lib/pb.ts and the dashboard pages — do those indicate a concurrency problem that worsens with more sites?

For every finding, give: what breaks, at what threshold, what the user sees when it breaks, and the file:line evidence.

Part C — What to change

A prioritised remediation plan. For each item: the problem, the proposed change, the files affected, rough effort (S/M/L), the risk of doing it, and the risk of not doing it. Group into:

  • Tier 1 — Correctness. Things that silently produce wrong numbers or hide data today. These are not optional.
  • Tier 2 — Scale. Query patterns, pagination, indexes, and server-side filtering needed before the site count or data volume grows further. Say explicitly what the app should do instead of getFullList() and where PocketBase filters/indexes belong.
  • Tier 3 — Product. A global site scope/selector, per-site access control (and the user model it requires), site archiving for completed contracts, and point-in-time site attribution for moved assets.

End with a one-paragraph bottom line in plain English, written for the business owner, not an engineer: can this app run many sites today, how many, and what is the single most important thing to fix first.


Deliverables

Create exactly these files:

docs/architecture.md
docs/data-model.md
docs/modules.md
docs/data-flows.md
docs/api-reference.md
docs/operations.md
docs/multi-site-assessment.md

Then replace the stale root README.md with an accurate short overview that links to the documents above. Keep it under 100 lines; the detail belongs in docs/.

Do not modify any file under src/, scripts/, or any config file.

Finish with a short summary in chat covering: your multi-site verdict, the top three things that must be fixed, and any claim in this prompt that turned out to be wrong.