# EHS: Project folder structure

Onboarding guide to the **EHS monorepo** layout: where each app lives, how folders relate, and where to look when changing a feature.

For ports, npm scripts, and API prefixes, see **`APPS-AND-API-BOUNDARIES.md`**. For JWT and auth, see **`AUTH-AND-JWT-REFERENCE.md`**. For performance and repo hygiene, see **`EHS-PROJECT-OPTIMIZATION-GUIDE.md`**.

---

## Overview

The repo is a **multi-app monorepo** for an Environmental, Health & Safety (EHS) platform:

| Layer | Count | Role |
|-------|-------|------|
| Frontends | 5 packages | Master login shell, SAT portal, ORAC risk assessment, SWI documents, PTW permits |
| Backends | 5 packages | Master auth, SAT, ORAC, SWI, PTW API implementations |
| Unified server | 1 file at repo root | `combined-server.mjs` — one Node process, one port |

```
┌──────────────────────────────────────────────────────────────────────────┐
│  Frontends (separate dev servers)                                      │
│  Master_Dashboard_Frontend :5174 │ SAT_Frontend :3000                    │
│  Risk_Assessment_Frontend :5173  │ swi_frontend :5175 │ ptw_frontend :5176│
└────────────────────────────┬─────────────────────────────────────────────┘
                             │ HTTP (proxied in dev)
┌────────────────────────────▼─────────────────────────────────────────────┐
│  combined-server.mjs  (default port 5012)                                │
│  ├── /api/sat/*    → SAT_backend/src/routes/*                             │
│  ├── /api/orac/*   → Risk_assessment_backend/src/routes/*                 │
│  ├── /api/swi/*    → swi_backend/src/routes/*                             │
│  ├── /api/ptw/*    → ptw_backend/src/routes/*                             │
│  ├── /api/master/* → master_dashboard_backend/src/routes/*                │
│  └── /uploads      → Risk_assessment_backend/uploads/                     │
└──────────────────────────────────────────────────────────────────────────┘
```

**Run everything locally:** from repo root, `npm run install-all` then `npm run dev`.

---

## Repo root

```
EHS/
├── combined-server.mjs      ← Canonical API entry (all backends)
├── package.json             ← Root orchestrator scripts
├── .env                     ← Shared env (also loads per-app .env files)
│
├── docs/                    ← Architecture & reference documentation
├── archive/legacy-servers/  ← Archived root server stubs (not runnable)
│
├── Master_Dashboard_Frontend/ ← HSE login shell + project launcher (:5174)
├── master_dashboard_backend/  ← Master auth API (/api/master/*)
├── SAT_Frontend/            ← Main HSE portal UI (:3000)
├── SAT_backend/             ← SAT API (mounted at /api/sat/*)
├── Risk_Assessment_Frontend/← ORAC UI (:5173)
├── Risk_assessment_backend/ ← ORAC API (mounted at /api/*, /api/orac/*)
├── swi_frontend/            ← SWI UI (:5175)
├── swi_backend/             ← SWI API (mounted at /api/swi/*)
├── ptw_frontend/            ← PTW admin UI (:5176)
└── ptw_backend/             ← PTW API (mounted at /api/ptw/*)
```

### Legacy root entry files (archived)

Former repo-root server stubs (`app.js`, `server.js`, `index1.js`, `index2.js`) are **removed from the root**. Historical copies live under **`archive/legacy-servers/`** — do not run them.

| Use instead | Purpose |
|-------------|---------|
| `combined-server.mjs` | Unified SAT + ORAC + SWI + PTW + Master API (`npm start`, `npm run dev-api`) |
| `Risk_assessment_backend/src/server.js` | Standalone ORAC API only |
| `SAT_backend/src/index.js` | Standalone SAT API only |

---

## Naming: ORAC folder casing

The ORAC stack uses two top-level folders that differ only in **`assessment` casing**. Copy paths **verbatim** in scripts and imports.

| Role | Folder (exact spelling) | `package.json` name |
|------|-------------------------|---------------------|
| Master auth API | `master_dashboard_backend/` | (see package.json) |
| Master login UI | `Master_Dashboard_Frontend/` | (see package.json) |
| ORAC API | `Risk_assessment_backend/` | `orac-risk-assessments-api` |
| ORAC UI | `Risk_Assessment_Frontend/` | `orac-risk-assessment-ui` |
| SWI API | `swi_backend/` | `swi-api` |
| SWI UI | `swi_frontend/` | `swi-frontend` |
| PTW API | `ptw_backend/` | (see package.json) |
| PTW UI | `ptw_frontend/` | (see package.json) |
| SAT API | `SAT_backend/` | (see package.json) |
| SAT UI | `SAT_Frontend/` | `sat-portal-react` |

**Mnemonic:** backend = lowercase `assessment`; frontend = uppercase `Assessment`.

---

## Documentation (`docs/`)

| File | Purpose |
|------|---------|
| `APPS-AND-API-BOUNDARIES.md` | Apps, ports, npm scripts, API prefixes, master dashboard source of truth |
| `AUTH-AND-JWT-REFERENCE.md` | JWT secrets, roles, auth flows across SAT/ORAC/SWI |
| `RPN-HOW-IT-WORKS.md` | Risk Priority Number calculation and usage |
| `COMBINED-QUESTIONS-EXPLAIN-PROMPT.md` | ORAC combined-question behavior |
| `EHS-PROJECT-OPTIMIZATION-GUIDE.md` | Dev workflow, bundle size, CSS, backend, deployment |
| `EHS-SSO-ACCESS-AND-ENTRY-POINT-GUIDE.md` | SSO, JWT entry points, reverse proxy |
| `PROJECT-FOLDER-STRUCTURE.md` | This document |

---

## Backend packages

All five backends follow a similar **Express layered layout**:

```
src/
├── app.js / server.js / index.js   ← Standalone entry (when not using combined-server)
├── config/                         ← db.js, passport, jwtSecret, loadEnv
├── constants/                      ← hseRoles, status enums
├── controllers/                    ← Request handlers
├── middlewares/                    ← auth, asyncHandler, errorHandler
├── repositories/                   ← Database access
├── routes/                         ← Express routers
├── services/                       ← Business logic (email, AI, SWI forms)
├── utils/                          ← ApiError, domain helpers
└── sql/ or migrations/             ← Schema and migrations
```

### `SAT_backend/`

**Domain:** Audits, dynamic forms, questions, submissions, users, roles, ticketing, dashboards, RPN, activity logs, Google OAuth, AI-assisted form fill.

```
SAT_backend/
├── src/
│   ├── index.js
│   ├── config/
│   │   ├── db.js
│   │   ├── passport.js
│   │   └── jwtSecret.js
│   ├── controllers/
│   │   ├── auditsController.js
│   │   ├── formsController.js
│   │   ├── submissionsController.js
│   │   ├── ticketsController.js
│   │   ├── dashboardController.js
│   │   ├── usersController.js
│   │   ├── aiController.js
│   │   └── …
│   ├── repositories/              ← One repo per entity (~20 files)
│   ├── routes/
│   │   ├── loginRoutes.js
│   │   ├── auditsRoutes.js
│   │   ├── formsRoutes.js
│   │   ├── submissionsRoutes.js
│   │   ├── ticketsRoutes.js
│   │   ├── dashboardRoutes.js
│   │   ├── questionsRoutes.js
│   │   ├── dynamicFormRoutes.js
│   │   ├── activityLogRoutes.js
│   │   ├── auditSchedulesRoutes.js
│   │   └── … (24 route modules total)
│   ├── services/
│   │   ├── emailService.js
│   │   └── ollamaService.js
│   ├── middlewares/
│   │   ├── verifyAdmin.js
│   │   ├── verifyAdminOrAuditor.js
│   │   └── errorHandler.js
│   └── sql/
│       ├── db_schema.sql
│       └── migrations/            ← ~25 incremental SQL files
├── scripts/                       ← One-off DB fix / migration helpers
└── .env.example
```

**Mounted at:** `/api/sat/*` by `combined-server.mjs`.

---

### `Risk_assessment_backend/`

**Domain:** ORAC risk assessments — forms, sections, questions, snaps, verification flow, participants, archive, submissions, RPN, shared ticketing.

```
Risk_assessment_backend/
├── src/
│   ├── app.js
│   ├── server.js                  ← Standalone ORAC-only server
│   ├── routes/
│   │   ├── index.js               ← Mounts /health, auth, /orac/*
│   │   ├── authRoutes.js
│   │   ├── oracAssessmentsRoutes.js
│   │   ├── oracSnapsRoutes.js
│   │   ├── oracVerificationFlowRoutes.js
│   │   ├── oracFormDetailsRoutes.js
│   │   ├── oracSubmissionsRoutes.js
│   │   ├── oracCombinedQuestionRoutes.js
│   │   ├── oracArchiveFormRoutes.js
│   │   ├── oracArchiveSectionRoutes.js
│   │   ├── ticketsRoutes.js
│   │   ├── rpnRoutes.js
│   │   └── … (~35 route files)
│   ├── controllers/
│   ├── middlewares/
│   │   ├── authMiddleware.js      ← requireAuth, requireAdmin
│   │   └── errorHandler.js
│   ├── repositories/
│   ├── utils/
│   │   ├── oracFormVersioning.js
│   │   ├── oracAssessmentRoleRules.js
│   │   └── oracCombinedQuestionEnrichment.js
│   └── config/db.js
├── migrations/                    ← Numbered SQL (001–006+)
├── scripts/                       ← loginHttp, e2eExecuterLogin, FK fixes
├── uploads/                       ← Static files → served at /uploads
├── API_DOCUMENTATION.md
└── POSTMAN_ORAC_FULL.md
```

**Mounted at:** `/api/*` (health, auth) and `/api/orac/*` (JWT-protected ORAC APIs).

---

### `swi_backend/`

**Domain:** Standard Work Instruction (SWI) documents, page content, assignments, tickets, shared auth/admin tables.

```
swi_backend/
├── src/
│   ├── app.js
│   ├── server.js
│   ├── routes/
│   │   ├── index.js
│   │   ├── swiDocumentRoutes.js
│   │   ├── swiAssignmentRoutes.js
│   │   ├── swiTablesRoutes.js
│   │   ├── sharedAuthTablesRoutes.js
│   │   ├── sharedAdminTablesRoutes.js
│   │   ├── authRoutes.js
│   │   └── ticketsRoutes.js
│   ├── controllers/
│   │   ├── swiDocumentController.js
│   │   ├── swiAssignmentController.js
│   │   ├── authController.js
│   │   └── ticketsController.js
│   ├── services/
│   │   ├── swiFormService.js
│   │   └── swiPageContentService.js
│   ├── repositories/
│   │   └── ticketsRepository.js
│   ├── constants/
│   │   ├── swiDocumentStatus.js
│   │   └── ticketStatus.js
│   └── middlewares/
├── sql/
│   ├── swi.sql
│   └── migrations/
├── API_DOCUMENTATION.md
└── API_ROUTES.md
```

**Mounted at:** `/api/swi/*`.

---

### `master_dashboard_backend/`

**Domain:** HSE login shell — password login, JWT issuance, Google OAuth hooks used by `Master_Dashboard_Frontend`.

```
master_dashboard_backend/
├── src/
│   ├── server.js                  ← Standalone master auth server
│   ├── routes/
│   │   ├── index.js               ← /health, /auth/*
│   │   └── authRoutes.js
│   ├── controllers/
│   │   └── authController.js
│   ├── config/
│   │   ├── db.js
│   │   └── passport.js
│   └── middlewares/
└── .env.example
```

**Mounted at:** `/api/master/*` (health + auth). SAT/ORAC/SWI/PTW apps consume tokens issued here.

---

### `ptw_backend/`

**Domain:** Permit-to-Work (PTW) — forms, sections, questions, permits, lifecycle, tickets, job types, handover notifications.

```
ptw_backend/
├── src/
│   ├── server.js
│   ├── routes/
│   │   ├── index.js               ← /health, /ptw/* (admin-only)
│   │   ├── formRoutes.js
│   │   ├── permitRoutes.js
│   │   ├── masterRoutes.js
│   │   ├── locationRoutes.js
│   │   ├── userRoutes.js
│   │   └── ticketRoutes.js
│   ├── controllers/
│   ├── services/
│   ├── middlewares/
│   │   └── authMiddleware.js
│   └── utils/
├── sql/
│   ├── ptw.sql
│   └── migrations/
└── docs/api-pages/
```

**Mounted at:** `/api/ptw/*` (admin JWT required).

---

## Frontend packages

### `Master_Dashboard_Frontend/` — HSE login shell

**Stack:** Vite, React. **Dev URL:** `http://localhost:5174`

Entry point for HSE users: login, project launcher, SSO handoff to SAT/ORAC/SWI/PTW satellite apps. Wired into root `npm run dev` as `dev-master-ui`.

```
Master_Dashboard_Frontend/
├── src/
│   ├── App.jsx
│   ├── routes/AppRoutes.jsx
│   ├── components/auth/         Login, AuthCallback, ProtectedRoute
│   └── components/features/master-dashboard/
└── vite.config.js                 ← Proxies /api → unified API
```

Dashboard widgets for analytics also exist in `SAT_Frontend/src/components/features/master-dashboard/` for users who land in the SAT shell after SSO. See `Master_Dashboard_Frontend/README.md` for the split.

---

### `SAT_Frontend/` — primary production shell

**Stack:** Create React App (`react-scripts`), React 18, React Router 6, Recharts, Google OAuth.

**Dev URL:** `http://localhost:3000`

```
SAT_Frontend/
├── public/
├── src/
│   ├── index.js
│   ├── App.js
│   ├── setupProxy.js              ← Dev proxy → unified API
│   ├── routes/
│   │   └── AppRoutes.jsx          ← Composes feature route modules
│   ├── components/
│   │   ├── auth/                  Login, ProtectedRoute
│   │   ├── common/                Button, Pagination, popups, LazyRoute
│   │   ├── layouts/               Navbar, TabNavigation
│   │   └── features/              ← Feature-sliced modules (see below)
│   ├── pages/                     AddSite, AddWorkarea, UserCreate, routes.jsx
│   ├── utils/                     authUtils, config, axiosConfig, dashboard helpers
│   ├── hooks/
│   └── styles/
└── README.md
```

#### SAT feature modules (`src/components/features/`)

Each feature owns a `routes.jsx` file. `AppRoutes.jsx` spreads these into React Router `<Routes>`.

| Feature folder | Responsibility |
|----------------|----------------|
| `master-dashboard/` | **Master & personalized dashboards** (production source of truth) |
| `dashboard/` | Analytics charts, RPN widgets, RA embeds, SWI personal-dashboard widgets |
| `audit-management/` | Create/update audits, scheduling, submissions, observations |
| `form/` | Form builder, preview, update flows |
| `questions-management/` | Question CRUD and table views |
| `user-management/` | Users, roles, profiles, access control |
| `ticketing/` | Raise/close tickets, progress, logs |
| `activitylog/` | Activity log views |
| `theme-management/` | Theme configuration |

**Key routes:** `/` → Master Dashboard, `/personalized-dashboard` → Personalized Dashboard.

---

### `Risk_Assessment_Frontend/` — ORAC UI

**Stack:** Vite, React 19, ESLint flat config.

**Dev URL:** `http://localhost:5173`

```
Risk_Assessment_Frontend/
├── public/
├── html_files/                    ← Legacy static HTML prototypes (outside src/)
├── src/
│   ├── App.jsx
│   ├── api.js, apiConfig.js
│   ├── authRoles.js
│   ├── assignmentRoutes.js
│   ├── components/
│   │   ├── admin/                 Form builder, sections, videos, pending actions
│   │   ├── executor/              Assignments, snaps, verifier, video assessment
│   │   ├── user/                  User dashboard, my videos, risk reports
│   │   └── common/                AppShell, Login, Navbar, Sidebar
│   └── utils/                     ORAC form/section/RPN helpers
└── vite.config.js
```

**Role-based UI areas:**

| Folder | Users | Purpose |
|--------|-------|---------|
| `admin/` | Admins | Form composition, sections, questions, video assignment |
| `executor/` | Field executors | Assessments, snaps, verification documents |
| `user/` | End users | Dashboard, assigned videos, risk reduction reports |
| `common/` | All | Shell, login, navigation |

---

### `swi_frontend/` — SWI UI

**Stack:** Vite, React 18, Axios, Fabric.js + Cropperjs (document/image editing).

**Dev URL:** `http://localhost:5175`

```
swi_frontend/
├── src/
│   ├── App.jsx, main.jsx
│   ├── pages/
│   │   ├── admin/                 Overview, documents, assign, users, tickets
│   │   └── user/                  Home, my SWIs, document form, assignments
│   ├── components/
│   │   ├── admin/                 Charts, modals, ticket UI
│   │   ├── swi/                   Document builder, approvals, assignments
│   │   ├── user/                  Stats, charts, personalized catalog
│   │   ├── layout/                PortalShell, PortalSidebar
│   │   └── common/
│   ├── config/                    adminNav, userNav, hseAuth, satPortal
│   ├── context/                   AuthContext, ThemeContext
│   ├── services/                  api.js, swiApi.js, ticketsApi.js
│   ├── hooks/
│   └── utils/
└── vite.config.js
```

**Dev note:** `npm run dev` waits for `http://127.0.0.1:5012/api/swi/health` before starting Vite.

---

### `ptw_frontend/` — PTW admin UI

**Stack:** Vite, React, ExcelJS (export), signature and media upload components.

**Dev URL:** `http://localhost:5176`

```
ptw_frontend/
├── src/
│   ├── main.jsx
│   ├── pages/admin/               AdminApp, permits, forms, sections, lifecycle
│   ├── components/
│   │   ├── form/                  Document sections, risk table, audit blocks
│   │   ├── dashboard/             Permit charts and activity
│   │   ├── layout/                PortalShell, PortalSidebar
│   │   └── common/
│   ├── services/                  permitsApi, formsApi, dashboardApi, …
│   ├── styles/                    ptw-form-fill-hub.css (hub layout)
│   ├── ptw.css                    Main PTW styles
│   └── utils/                     question types, Excel export, permit helpers
├── public/templates/              generalptwformat.xlsx
└── vite.config.js                 ← Proxies /api/ptw → unified API
```

**Dev note:** Root script `npm run dev-ptw-ui` waits for `/api/ptw/health` before starting Vite.

---

## Tests

Automated tests are **optional** in this repo. Some packages may still contain `*.test.js` files from earlier work; there is no root `npm test` integration suite at present.

When reintroducing tests, prefer:

| Location | Suggested runner | Scope |
|----------|------------------|-------|
| `tests/integration/` (if added) | Vitest + supertest | Unified API smoke tests |
| `*/src/**/*.test.js` | Vitest (Vite apps) or Jest (CRA SAT) | Per-package unit tests |

See **`EHS-PROJECT-OPTIMIZATION-GUIDE.md`** § Phase D.

---

## Quick lookup: “Where do I change X?”

| Task | Location |
|------|----------|
| Run full local stack | Repo root → `npm run dev` |
| HSE login / SSO launcher | `Master_Dashboard_Frontend/` |
| Add or change a SAT API route | `SAT_backend/src/routes/`, mount in `combined-server.mjs` |
| Add or change an ORAC API route | `Risk_assessment_backend/src/routes/`, registered in `routes/index.js` |
| Add or change a SWI API route | `swi_backend/src/routes/` |
| Add or change a PTW API route | `ptw_backend/src/routes/` |
| Change master auth / login API | `master_dashboard_backend/src/routes/` |
| Change master / personalized dashboard widgets in SAT | `SAT_Frontend/src/components/features/master-dashboard/` |
| Change SAT audit flows | `SAT_Frontend/src/components/features/audit-management/` |
| Change ORAC executor / snap flow | `Risk_Assessment_Frontend/src/components/executor/` |
| Change SWI document builder | `swi_frontend/src/pages/`, `swi_frontend/src/components/swi/` |
| Change PTW permit form / lifecycle | `ptw_frontend/src/pages/admin/`, `ptw_frontend/src/components/form/` |
| Change shared auth behavior | `docs/AUTH-AND-JWT-REFERENCE.md` + per-app `authMiddleware.js` |
| Add a new frontend env variable | SAT: `REACT_APP_*` in `SAT_Frontend/`; Vite apps: `VITE_*` |

---

## Known structural notes

1. **Unified API is canonical** — Always develop against `combined-server.mjs`, not archived root entry files.
2. **Dashboard duplication** — Login shell is `Master_Dashboard_Frontend/`; analytics widgets also live in `SAT_Frontend/src/components/features/master-dashboard/`. SWI widgets are embedded in SAT's dashboard feature.
3. **Mixed frontend tooling** — SAT uses CRA; ORAC, SWI, PTW, and Master Dashboard use Vite. Env prefixes and dev proxies differ (`REACT_APP_*` vs `VITE_*`, `setupProxy.js` vs `vite.config.js` proxy).
4. **Shared database concepts** — Users, roles, and some admin tables are shared across apps; SWI exposes `sharedAuthTablesRoutes` and `sharedAdminTablesRoutes`.
5. **Build artifacts** — `dist/`, `.cache/`, and `.eslintcache` are gitignored; run `npm run build` per app for production bundles. Prototype HTML mock folders (`ptw form design/`, `swi_DocTestingPages`) have been removed from the tree.

---

## Related reading

- **`APPS-AND-API-BOUNDARIES.md`** — Ports, scripts, env files, master dashboard rules
- **`AUTH-AND-JWT-REFERENCE.md`** — Token secrets, role guards, login endpoints
- **`Master_Dashboard_Frontend/README.md`** — Why the standalone dashboard folder exists
- **`swi_backend/API_DOCUMENTATION.md`** — SWI REST API reference
