Skip to content

feat(survey+mqc+hardening): real Survey & MQC modules + helmet security + migration infra - #2

Draft
mcabico-blip wants to merge 68 commits into
mainfrom
claude/magical-darwin-dulx3f
Draft

feat(survey+mqc+hardening): real Survey & MQC modules + helmet security + migration infra#2
mcabico-blip wants to merge 68 commits into
mainfrom
claude/magical-darwin-dulx3f

Conversation

@mcabico-blip

Copy link
Copy Markdown
Owner

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

  • Helmetapp.use(helmet()) in main.ts; all responses now get standard security headers
  • TypeORM migration infraapps/api/src/data-source.ts for the CLI + migration:generate / migration:run / migration:revert scripts added to package.json. Operator must run migration:generate against the live DB then migration:run and set DB_SYNC=false before production.

Survey module (was stub, now real)

  • survey_measurement entity — station/chainage (STA 0+000 format), pay item, volume, type (cross-section / stakeout / original-ground / as-built), YYYY-MM period
  • survey_cross_section entity — area at station, interval, computed volume
  • survey.volumes read-model now aggregates real DB rows → feeds ManCom + Ask AI
  • REST: GET /survey/volumes, GET/POST /survey/projects/:id/measurements, GET/POST /survey/projects/:id/cross-sections
  • Web page /survey — volume trend chart (TrendChart), measurement table per project, measurement submit form
  • Demo seed: 8 measurements for PKG-02 (PCCP 311(1)c) and PKG-05 (subbase 200)

MQC module (was stub, now real)

  • DPWH minimum testing rules table for pay items 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 mm, air content %
  • mqc_material_cert entity — cert no, billing ref, StorageProvider file path
  • 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 lookup panel, test results tab (with Stamp), pour logs tab, submit forms for both
  • Demo seed: 5 test results + 2 pour logs for PKG-02 / PKG-05

Shell / routing

  • /survey and /mqc routes added to App.tsx
  • "Tools" group added to sidebar with Survey tools + MQC tools direct links
  • Tab-switcher, badge, and field label CSS added to styles.css

Test plan

  • npm run dev:api starts cleanly (helmet loaded, survey + mqc modules registered)
  • npm run dev:web builds with no TS errors
  • Login as ceo@ubi.ph → navigate to /survey → volume trend renders from seeded data
  • Submit a new measurement → appears in the table; /api/survey/volumes updates
  • Navigate to /mqc → DPWH rules for 311(1)c show (7 rules)
  • Test results tab shows 2 pending (badge) + 3 passed for PKG-02
  • Pour logs tab shows 2 pours; submit a new one → appears in table
  • AI Insights / Ask AI still work (read-models now DB-backed)
  • Check response headers include X-Content-Type-Options, X-Frame-Options (Helmet)

https://claude.ai/code/session_013K35zHH4mCqU8qHwN9Ypzg


Generated by Claude Code

claude added 30 commits June 11, 2026 16:03
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
…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
…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
…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 /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
- 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
claude added 30 commits June 15, 2026 00:45
…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
…(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
…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
…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
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants