This manifest maps the components of the Metaval project. It documents file boundaries, routing paths, and architectural vulnerabilities to enforce strict developer safeguards and eliminate technical clutter.
The frontend is a styled dashboard tracking real-time layout telemetry data and streaming administrative requests to the local server gateway.
- Primary Functionality: Core state lifecycle manager for the user interface. Coordinates modal toggles, table selection switches, background data extraction alerts, and global clock intervals.
- Behavioral Rules: Runs synchronous
useEffectintervals to handle background layout metrics checks. - [cite_start]π¨ Safety Safeguard Alert: When validating query dispatch updates via
handleQuerySubmit, it must map to the original user input structure parameters (queryData.name,queryData.email,queryData.message)[cite: 71, 72]. Changing these fields without syncing your inline form properties (QueryForm.jsx) will throw layout blocking dialogues.
- Primary Functionality: Central HTTP client instantiation. Employs a flat connection base URL targeting the local server port.
- Network Mapping Mapping Rules: ```javascript
baseURL: "http://localhost:5000"
- π¨ Safety Safeguard Alert: Do NOT append path folders like
/apior/api/datainside this baseline client configuration file. Doing so while passing manual paths from your files will cause route duplications and trigger immediate404 Not Foundnetwork crashes.
- Primary Functionality: High-performance tabular datagrid ledger viewer. Renders column variables dynamically based on table catalogs polled directly from the live database schema.
- Primary Functionality: Dropdown interactive UI alert manager. Listens for incoming system admin tickets and handles real-time response inputs.
The application engine exposes endpoints that match front-end requests, discover database shapes dynamically, and call parsing binaries.
- Primary Functionality: Primary server entry point configuration loader. Initializes global CORS permissions, activates JSON serialization hooks, and mounts your primary application route modules under a unified folder prefix.
- Middleware Route Map Rule:
app.use('/api/data', dataRoutes);
- Primary Functionality: Centralized route mapper. Matches frontend Axios client calls directly to your
dataControllermethods using clean endpoints. - Active Route Maps:
GET /dashboardβgetDashboardDataPOST /uploadβuploadPDFGET /workbook/:tableNameβgetWorkbookTableDataPOST /queryβsubmitQueryPOST /replyβreplyQueryGET /exportβexportExcel
- Primary Functionality: Core execution logic hub. Reads incoming payloads, inspects active database constraints dynamically, and commits parameters safely to your relational ledger tables.
- π¨ Safety Safeguard Alert (Response Duplication Bug): If you execute local sub-process routines inside your controllers (like spawning background scripts), you must explicitly run single
return res.json(...)blocks inside your callbacks. Attempting to pass error text blocks followed by trailing fallback streams will throw an unhandledERR_HTTP_HEADERS_SENTserver crash.
- Primary Functionality: PostgreSQL client connection allocator. Pools credentials and manages high-concurrency transactional pipelines.
Isolated procedural utilities that handle file conversion, file writing, and string positioning matching scripts.
- Primary Functionality: Primary document text ingestion. Leverages layout parsers (
pdf-parse) to convert selectable digital character strings into readable text vectors.
- Primary Functionality: Heuristic structural position layout matching. Maps loose text elements into correct database cells based on row index coordinates.
- Primary Functionality: Data download generation layer. Converts raw arrays straight into structured Excel sheets, avoiding unstable CSV modifications.
- [cite_start]Never Hard-Bind Database Schemas: Your worksheets are highly dynamic (over 129 columns for tables like
ofa_upload)[cite: 462]. Your code must always run dynamic lookups againstinformation_schema.columnsto find active layout shapes rather than using static indices or hard-coded insertion strings[cite: 466]. - [cite_start]Protect the Event Loop on Large Files: In the future, as you scale toward processing 500-page logistics sheets, processing heavy visual calculations synchronously inside the main API execution thread will freeze your server[cite: 796]. [cite_start]Long-running document processes should be handled asynchronously via a background task framework[cite: 855].
- Validate Data Types Prior to Query Execution: If a string parser pulls text context (like
"To be confirmed by vendor data") and tries to push it into a strict PostgreSQLNUMERICtable cell, the engine will drop the query. Enforce string filtering layers in your controller to keep your columns safe.
problems
Here's a full risk map and a fix order that won't leave you rebuilding the same thing twice. I've grouped issues by what breaks first if ignored, then sequenced the phases so each one is a stable foundation for the next.
If you jump straight to "add tests" or "make it scale" while buildWorkbookSearchQuery is undefined and half the routes have no auth, you'll be debugging phantom failures that have nothing to do with what you're actually working on. The sequence below is: make it run correctly β make it safe β make it reliable β make it observable β make it fast/scalable β make it maintainable. Each phase assumes the previous one is done.
Fix these before touching anything else β they'll sabotage your testing of every later phase.
| Issue | Where | Fix |
|---|---|---|
buildWorkbookSearchQuery is called but never defined |
dataController.js (exportExcel, getWorkbookTableData) |
Write it: build a parameterized WHERE clause from req.query against the known column list. Until this exists, /export and /workbook/:tableName throw. |
pool used without import |
dataRoutes.js (/job-status/:jobId), emailStats.js |
Import pool from config/db, or move the logic into dataController.js where pool already exists. |
strategy_core.py source is missing |
server/workers/pipeline_runner.py |
Recover it from wherever it was authored, or rewrite NumericField/DropdownField/StandardTextField from scratch β the pipeline cannot run without it. |
aiController.js doesn't exist |
routes/airoutes.js |
Either implement it or delete the route file β a route pointing at nothing is a landmine for whoever touches it next. |
| Case-sensitive import mismatches | deltaPoller.js β ./deltaService vs DeltaService.js; uislice.ts vs uiSlice import |
Rename files or fix imports to match exactly. This works today only because your OS filesystem is case-insensitive β it will break the moment you deploy to Linux/CI. |
| Two dashboard-fetch paths, two query clients | features/dashboard/services/* (mocked) vs services/dashboardService.ts (real); app/queryClient.ts vs lib/queryClient.ts |
Delete the unused one of each pair now, before more code starts depending on the wrong one. |
How to know you're done: every route in api-contracts.md marked π΄ is either fixed or deliberately removed, and npm run dev at the root runs both apps with zero console errors on a cold start.
This is an enterprise project handling customer RFQs and email content β treat auth and injection risk as blocking, not "nice to have."
- Apply
authenticate(andallowRoleswhere relevant) to every route that isn't public. Right now only/api/documents/*is protected./api/data/*(including file upload!) and/api/review/*(approve/reject!) are wide open. Anyone who can reach port 5000 can upload arbitrary files or approve fabricated engineering specs intoofa_upload. - Lock down CORS for real environments.
app.jshard-codeslocalhost:5173/5174. Move this into an env-driven allowlist before you have a staging/prod domain. - Re-audit the dynamic-table pattern.
verifyTableExistsDynamicallyis a genuinely good idea β keep it β but double-check every place a table/column name gets string-interpolated after validation. Values must always go through$1, $2...; only validated identifiers get interpolated. - Secrets hygiene.
JWT_SECRET,GRAPH_CLIENT_SECRET, DB creds all live in.envfiles that are.gitignore'd β good. But confirm none of them were ever committed in an earlier commit (git log -p -- server/.env), and rotate anything that was. - File-upload hardening.
uploadMiddleware.jsaccepts any file type/size via Multer with no filter or size limit. Add MIME/extension whitelisting (.pdf,.ziponly) and alimits: { fileSize }cap β otherwise/api/data/uploadis an open door to disk-fill or malicious file attacks. - Remove debug logging of secrets.
config/msal.tslogsVITE_CLIENT_ID/VITE_TENANT_IDto the console β low risk but sloppy; strip before shipping. - Rate-limit public-ish endpoints (
/auth/login,/api/data/upload) β nothing currently stops a brute-force or flood.
How to know you're done: run through api-contracts.md and mark which endpoints require auth vs. are intentionally public β nothing should be "open" by accident.
This is where "enterprise-grade" actually gets tested β money/engineering decisions depend on this data being correct.
- Consolidate the schema into migrations. Right now schema lives ad hoc:
sql/ofa_upload.sql(drops and recreates!), an emptymodels/schema.sql, and several tables (document_jobs,review_queue,system_state,users,queries,status_ledger) that are only ever implied by query code, never defined anywhere. Introduce a migration tool (node-pg-migrate, Knex, or Prisma migrate) and check every table into version control.DROP TABLE ... CASCADEin a script that could run against a live DB is a production incident waiting to happen β remove that from any script that isn't explicitly a "reset dev DB" tool. - Wrap multi-step DB writes in transactions.
approveReview()does anINSERTintoofa_uploadfollowed by anUPDATEonreview_queueas two separate queries β if the second fails, you've committed a spec row with no corresponding review record. Wrap inBEGIN/COMMIT/ROLLBACK. - Make the mail-delta polling idempotent and crash-safe.
deltaPoller.jsruns an infinitewhile(true)loop with no process supervision. If the Node process dies mid-cycle, you rely entirely on the saved Graph cursor to avoid re-processing β verifysaveCursoronly happens after a batch is fully queued, not before, or you can lose documents on a crash between "cursor saved" and "job queued." - Add retry/dead-letter handling to the BullMQ worker. Currently a failed job just throws and BullMQ's defaults apply. For an enterprise pipeline, configure explicit
attempts, backoff, and a dead-letter queue/alert so a permanently-failing PDF doesn't silently vanish fromdocument_jobsasFAILEDwith nobody watching. - Extend
approveReview's column list. It only inserts 19 ofofa_upload's ~129 columns β confirm this is intentional (partial approval flow) or a gap that's silently dropping extracted data. - Handle the Python service being down.
documentQueue.js's worker POSTs toPYTHON_API_URLwith no visible timeout/circuit-breaker β a hung external service will hang worker slots. Add a request timeout and treat timeout as a retryable failure, not a silent hang.
How to know you're done: you can kill the server mid-poll, mid-upload, and mid-review-approve, restart it, and nothing is duplicated, lost, or left in an inconsistent state.
Do this before scaling, because scaling problems are invisible without it.
- Structured logging. Replace the emoji
console.logs with a real logger (pinoorwinston) that outputs JSON, includes request IDs, and can be shipped to a log aggregator (Datadog, ELK, CloudWatch). Keep the operational clarity the current logs have β just make it machine-parseable too. - Health/readiness endpoints.
GET /exists as a liveness check; add a real readiness check that verifies DB, Redis, and (optionally) the Python service are reachable β this is what a load balancer/orchestrator (k8s, ECS) needs to route traffic correctly. - Metrics. Track: queue depth/age (
document_jobsstuck inPROCESSINGtoo long), Graph API error rates per mailbox, upload volume, review-queue backlog. Even a simple/metricsPrometheus endpoint pays off fast. - Alerting on the failure modes you just made visible in Phase 2 β a mailbox whose cursor keeps expiring, a worker that's failing every job, a review queue that's not being cleared.
There is currently no test suite and no CI in either package.json. For an enterprise system this is the single biggest thing standing between you and confident deploys.
- Unit tests first, on the highest-risk logic:
verifyTableExistsDynamically,buildWorkbookSearchQuery(once written),hasKeyword, the review approve/reject flow,normalizeValue. - Integration tests for the mail pipeline against a mocked Graph client β this is the part most likely to silently regress since it only runs in a loop with no direct test coverage.
- API contract tests for every route in
api-contracts.mdβ you already have the contract documented, turn it intosupertestassertions. - CI pipeline (GitHub Actions or similar): lint (frontend already has ESLint configured β wire it into CI), run tests, build both apps, and β importantly β run
npm audit/pnpm auditfor dependency vulnerabilities on every PR. - Only after tests exist, start doing the case-sensitivity/dead-code/duplicate-module cleanup from Phase 0/coding-guidelines β tests are what let you refactor without fear.
Now that it's correct, observable, and tested, make it handle real load.
- Horizontal scaling of the BullMQ worker.
concurrency: 2is hard-coded for one process β plan for running multiple worker instances/pods pointed at the same Redis, and make sure DB row locking (FOR UPDATEwhere needed) prevents two workers racing on the same job. - Connection pool sizing.
max: 20on the Postgres pool is a reasonable default for one instance β revisit once you have multiple app instances, since pools multiply per instance. - Machine-2 dependency.
checkMachine2()pinging a hard-coded IP (192.168.11.239) is not production infra β replace with a proper service discovery mechanism or at minimum an env var, and add retry/backoff instead of a one-shot boot-time check. - Pagination everywhere.
GET /api/data/alland others return unbounded result sets β addLIMIT/OFFSETor cursor pagination before a table grows large enough to make that endpoint a liability. - Frontend production build config β env-driven API base URL (already scaffolded via
ENV.API_BASE_URL, just make sure it's actually set per environment), code-splitting for the feature folders as they get built out, and a CDN for static assets.
- PII/data retention policy for email content and customer data flowing through
document_jobs/ofa_uploadβ decide how long raw PDFs and email metadata are retained, and automate cleanup. - Audit trail for review approve/reject actions β you're currently storing
reviewer_nameas a free-text field the client sends; derive it from the authenticated JWT (req.user) instead, so it can't be spoofed, and log every state transition. - Backup/DR plan for Postgres β nothing in the repo currently addresses this; it needs to exist before this holds real customer commitments.
- Role model completion.
middleware/authenticate.jsalready sketches future roles (SUPER_ADMIN,AUDITOR, etc.) in a comment β formalize this into an actual permissions table/matrix rather than the current three flat roles, especially since approve/reject on customer specs is a sensitive action.
Do this last, or continuously in small batches β it's important but non-blocking, and premature cleanup on code you haven't stabilized yet just creates merge conflicts with the phases above.
- Normalize CRLFβLF line endings across
server/. - Standardize the
errorvsmessageresponse key. - Delete the large commented-out code blocks (
app.js,App.tsx,DashboardPage.tsx, etc.) β trust Git history instead. - Finish or delete the empty scaffolded files (
authMiddleware.js,permissionService.js, moststore/slices/*,theme/mui/palette.ts, etc.) so it's clear what's "not built yet" vs. "abandoned."
Fix what's broken β lock down who can do what β make writes correct and crash-safe β make failures visible β prove it with tests/CI β then and only then optimize for scale β clean up debt continuously in the gaps.
If you want, I can turn this into a tracked checklist (e.g. a markdown file or a project board format) you can check off as you go, or go deep on any one phase β Phase 1 (security) and Phase 2 (data integrity) are the two I'd start on literally today given this handles real customer RFQ data.