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

277 lines
14 KiB
Markdown
Raw Permalink 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.

# 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.