feat(survey+mqc+hardening): real Survey & MQC modules + helmet security + migration infra - #2
Draft
mcabico-blip wants to merge 68 commits into
Draft
feat(survey+mqc+hardening): real Survey & MQC modules + helmet security + migration infra#2mcabico-blip wants to merge 68 commits into
mcabico-blip wants to merge 68 commits into
Conversation
Seed the repo with the kickoff context: master context (stack, hard rules, three pillars, 14 module specs, git strategy), branching quick reference, functional & DFD diagram set, and Node/TS monorepo ignores. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
Annotated design frames for the suite's primary output, per scope decision (CEO deep-dive first, brand light UI, static annotated frames): - ManCom live dashboard: KPI band, accomplishment-vs-plan and survey volume charts, flagged projects, department report feed, AI rail - Trend-projection toggle shown OFF vs ON (solid=actual, dashed= projected, grey=plan convention) - AI Insights register: grounded, severity-ranked, actions route into VPO inbox / Audit exceptions - Ask AI conversational view with per-claim source citations - Agentic-view sandboxed host shell (host contract visible) - Mobile ManCom (PWA) - Widget -> Pillar-3 read-model contract table Verified in headless Chromium (Playwright): no console errors, no horizontal overflow at 1280px. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ity-scoped base entity, health https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…le offline grace, Google stub https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…t/receive, where-is + full movement history https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…cketing/notifications/expiry engines https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…er + dept read-model stubs + CEO ManCom consolidation + seeds All 14 departments expose Pillar-3 read surfaces; ManCom snapshot verified end-to-end against live Postgres (RBAC 401/403 checked). https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
… auth session, chart components https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…provals, engineering + dept read-surface pages Implements the approved mockup design against live API data; verified end-to-end in headless Chromium (CEO journey + PE→PM→VPO chain). https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…, sheet cards w/ crop marks, title blocks, stamps, chainage rulers, hazard stripes; Space Grotesk + IBM Plex Mono bundled https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…rs, stamped severities/approvals, billing chainage, survey-flag chart marker, drafting-sheet login https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…sessions (branches, run, prod env, next work) https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ET in production, pin CORS via CORS_ORIGIN, throttle /auth/login (10/min/IP) Verified: 11th bad login returns 429; boot fails on dev JWT default when NODE_ENV=production. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ile server-side verify (enforced when TURNSTILE_SECRET_KEY set), 5/min/IP spam throttle https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…get slot, TICKET LOGGED stamp, IT helpdesk queue card, nav + login links https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ch loaders across pages; proper inline input style on doc transmit https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
- GET /api/dept/:slug/dashboard — uniform shape for all 13 departments: 4 standard KPIs, dept-specific field monitoring (Pillar-3 read-model), CCTV camera meta (live snapshot when CCTV_BASE_URL set) - departments registry (head, read-model, camera id per dept) - seed head-<dept>@ubi.ph accounts (role:manager + dept:<slug>) - RBAC: dept head sees only their dept; CEO/VPO/admin cross-cutting https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…oring, CCTV thumbnail; dept heads land on their dashboard - DeptDashboard renders uniform KPI band + monitoring table + CctvThumb - CctvThumb: NVR snapshot when online, else NO-SIGNAL drafting placeholder - homeFor() routes dept heads to /dept/<slug>; Engineering tools at /engineering https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…-update, history; feeds IT PMS https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ss-gated physical-location index https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ty assets, DeskGuard v2 + consent, env monitoring https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
- Property: scan/re-custody/attest + movement history - Records: expiry, add vehicle doc, access-gated physical index - IT control room: devices, PMS, DeskGuard (consent banner), environmental https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…OAEC API, simulated ref when OAEC_BASE_URL unset); read-models https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…chedules surface as ready-to-buy https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…curement intake page; Engineering + dept links https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ceive only) — POST /docs then opens it ready to transmit https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…AC-scoped); ManCom/Insights remain exec-only https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
… every page (popover chat, typewriter + sources, RBAC-scoped) https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…x+rollback), wake trigger (timer + webhook), status-markdown handshake, tool allowlist Server Claude (claude -p on the box) deploys the production branch and fixes issues itself; status flows back via committed ops/DEPLOY_STATUS.md. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…property/etc data now backfills onto an existing demo DB after a deploy (was skipped by early return when pay_items already existed) Verified: on a DB with projects but no quantity rows + zeroed in-house, reboot restores in-house amounts + weekly entries without dropping the DB. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…t to ubi-edge, capture nginx PWA hardening Closes the loop on DEPLOY_STATUS for_cloud_claude: - Login demo chips gated on import.meta.env.DEV / VITE_SHOW_DEMO_LOGINS (prod login page no longer advertises working creds; verified absent from bundle) - DEPLOY.md §4 + allowlist use 'systemctl restart ubi-edge' (binds :8091) - ops/nginx.sample.conf documents the immutable-assets / no-cache-shell hardening https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…backstop), with security hardening + end-to-end verify https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…NGINE warning flagged by deploy) https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…(deploy) status commit; run triggers from /opt to survive git reset (folds server's box-side fix upstream) Without this, each deploy's status-commit push re-fires the webhook/timer → redeploy → push → infinite loop. Guard runs for both triggers. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…p off with VITE_HIDE_DEMO_LOGINS=true at real launch) https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…(build) + X-Robots-Tag note for nginx https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…de demo login chips in prod; ensureUser force-rotates on boot Plaintexts not committed (hashes only). Demo tap-to-login is off on the live login page now that real data is in. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…no env override) — box VITE_SHOW_DEMO_LOGINS could re-enable them https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…icle list, trips/events/geofences/drivers/fuel/maintenance proxy + read-models Env-driven Basic auth (CARTRACK_REGION/USER/PASS); demo fleet when unset. Verified live against PH account: 56 vehicles located, nested location.* parsed. https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…iver events, alerts, geofences, maintenance; per-vehicle locate; enriched live (odometer/fuel/driver); ManCom live-fleet card All verified against the live PH account: 56 vehicles, 10 trips, driver-events, 10 alerts, 10 geofences, maintenance/licence list. Correct paths/params (events end<=midnight, notifications bracket-keys). https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ized pilot creds; rotate after) https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…sswords, migrations, backups…); CLAUDE.md §0 points to it https://claude.ai/code/session_01SmE5jXnu5J2Di7wG6po7yM
…ation infra **Production hardening** - Add helmet to main.ts — security headers on every response - Add apps/api/src/data-source.ts for TypeORM CLI migrations - Add migration:generate / migration:run / migration:revert scripts to package.json **Survey module** (was stub, now real DB-backed) - `survey_measurement` entity — station/chainage (STA 0+000), pay item, volume, type (cross-section/stakeout/original-ground/as-built), period - `survey_cross_section` entity — area at station, interval, computed volume - `survey.volumes` read-model now aggregates real DB rows → feeds ManCom - REST: GET /survey/volumes, GET/POST /survey/projects/:id/measurements, GET/POST /survey/projects/:id/cross-sections - Web page /survey — volume trend chart, measurement table by project, submit form - Demo seed: 8 measurements for PKG-02 (PCCP) and PKG-05 (subbase) **MQC module** (was stub, now real DB-backed) - DPWH minimum testing rules table (311(1)a/b/c, 200, 201, 301) → GET /mqc/rules/:payItemNo - `mqc_test` entity — test type, result, cert ID, lab ref, billing ref - `mqc_pour_log` entity — station, date, mix design, volume, slump, air content - `mqc_material_cert` entity — cert no, billing ref, file path (StorageProvider) - `mqc.certs` read-model now pulls pending tests from DB → blocking-billing KPI - REST: GET/POST /mqc/projects/:id/tests|pours|certs, GET /mqc/rules/:item - Web page /mqc — DPWH rules panel, test results tab, pour logs tab, submit forms - Demo seed: 5 test results + 2 pour logs for PKG-02 / PKG-05 **Shell / routing** - Added /survey and /mqc routes in App.tsx - Added "Tools" group in sidebar with Survey tools + MQC tools links - Added tab-btn / badge-warn / .field CSS to styles.css https://claude.ai/code/session_013K35zHH4mCqU8qHwN9Ypzg
…B + equipment register **Replaces FleetModule with OmegaModule** (fleet is a sub-module of Omega Asia). Fleet API paths unchanged (/api/fleet/...) for web compat; equipment register at /api/omega/... **Server-side polling (no more on-demand Cartrack calls per request):** - 10s: pull /vehicles/status → FleetCache (in-memory); live map reads from cache - 60s: save position snapshot → fleet_position_log (analytics / history replay) - 10min: pull /vehicles/events + /alerts/notifications → fleet_driver_event + fleet_alert - FleetPoller implements OnModuleDestroy — clears intervals cleanly on shutdown - Falls back to direct Cartrack call only if cache is stale (>30s, e.g. poller restart) - Demo fleet served when CARTRACK_USER/PASS not set **New DB entities:** - fleet_position_log — lat/lng/speed/ignition/odometer/fuel per vehicle per minute; auto-purges >30d - fleet_driver_event — harsh braking/speeding events from 10min poll (raw JSONB preserved) - fleet_alert — geofence/ignition/panic alerts; acknowledgement endpoint POST /fleet/notifications/:id/ack - omega_equipment — OAEC equipment register (unit no, plate, type, cartrack_id, status, project) **New API endpoints:** - GET /fleet/vehicles/:id/history?hours=24 — position replay from DB - GET /fleet/events?hours=24 — driver events from DB (not live Cartrack) - GET /fleet/notifications?unack=true — alerts from DB - POST /fleet/notifications/:id/ack — acknowledge alert - GET /omega/equipment — equipment register - POST /omega/equipment — upsert equipment record **Read-models registered:** fleet.live, fleet.summary, fleet.events, fleet.alerts, omega.equipment **Web:** - Client poll: 20s → 5s (feels real-time since server caches at 10s) - Equipment tab added (reads from /omega/equipment) - Events/alerts columns updated to DB field names - Sheet bar rebranded to "Omega Asia — Fleet & Equipment" - Sidebar: "Fleet" → "Omega / Fleet" - Seed: 6 OAEC equipment units (entity=OMEGA) https://claude.ai/code/session_013K35zHH4mCqU8qHwN9Ypzg
… trend endpoint - Live map popup: shows fuel %, driver name, low-fuel⚠️ warning when <20% - Vehicle list: Fuel column with st-ok (≥40%) / st-warn (<40%) / st-bad (<20%) chips - GET /fleet/fuel/trend?hours=8 — fuel% over time per vehicle from fleet_position_log - fleet.fuel read-model registered → CEO Ask AI / ManCom can report low-fuel vehicles - FleetService.fuelTrend() aggregates stored position snapshots by vehicle https://claude.ai/code/session_013K35zHH4mCqU8qHwN9Ypzg
…erver Claude polls it
… deploy in progress, DNS issue noted
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Continues the UBI Construction Suite breadth-first build (PR #1). This session promotes Survey and MQC from stubs to real DB-backed modules, adds Helmet security headers, and wires the TypeORM migration infrastructure.
Production hardening
app.use(helmet())inmain.ts; all responses now get standard security headersapps/api/src/data-source.tsfor the CLI +migration:generate / migration:run / migration:revertscripts added topackage.json. Operator must runmigration:generateagainst the live DB thenmigration:runand setDB_SYNC=falsebefore production.Survey module (was stub, now real)
survey_measuremententity — station/chainage (STA 0+000 format), pay item, volume, type (cross-section / stakeout / original-ground / as-built), YYYY-MM periodsurvey_cross_sectionentity — area at station, interval, computed volumesurvey.volumesread-model now aggregates real DB rows → feeds ManCom + Ask AIGET /survey/volumes,GET/POST /survey/projects/:id/measurements,GET/POST /survey/projects/:id/cross-sections/survey— volume trend chart (TrendChart), measurement table per project, measurement submit formMQC module (was stub, now real)
GET /mqc/rules/:payItemNomqc_testentity — test type, result, cert ID, lab ref, billing refmqc_pour_logentity — station, date, mix design, volume, slump mm, air content %mqc_material_certentity — cert no, billing ref, StorageProvider file pathmqc.certsread-model now pulls pending tests from DB → "blocking billing" KPIGET/POST /mqc/projects/:id/tests|pours|certs,GET /mqc/rules/:item/mqc— DPWH rules lookup panel, test results tab (with Stamp), pour logs tab, submit forms for bothShell / routing
/surveyand/mqcroutes added toApp.tsxstyles.cssTest plan
npm run dev:apistarts cleanly (helmet loaded, survey + mqc modules registered)npm run dev:webbuilds with no TS errorsceo@ubi.ph→ navigate to/survey→ volume trend renders from seeded data/api/survey/volumesupdates/mqc→ DPWH rules for 311(1)c show (7 rules)X-Content-Type-Options,X-Frame-Options(Helmet)https://claude.ai/code/session_013K35zHH4mCqU8qHwN9Ypzg
Generated by Claude Code