Files
open-safetylog-ehs/docs/ROADMAP.md
T
jayjennings 61c876edec
CI / Lint, typecheck, test, build (push) Canceled after 0s
CI / End-to-end tests (push) Canceled after 0s
Add OSHA Form 301 and Osha page components
- Implemented Form301 component for displaying OSHA Form 301 equivalent, including employee and case information.
- Created Osha component to manage OSHA recordkeeping, including tabs for 300 Log, 300A Summary, Hours & rates, and Submit to OSHA.
- Added functionality for printing and downloading CSV files for OSHA submissions.
- Integrated loading and error handling states for data fetching.
2026-10-06 13:09:57 -07:00

109 lines
8.7 KiB
Markdown
Raw 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.
# Open SafetyLog EHS Roadmap
A free, open-source (AGPL-3.0) accident and safety tracking system for manufacturing.
This is a living document. Update it as decisions are made or scope changes.
## Decisions
| Topic | Decision | Status |
| --- | --- | --- |
| License | AGPL-3.0-only | Decided |
| Frontend | React + Vite + TypeScript, Tailwind CSS v4 | Decided |
| Backend | Node + Hono, PostgreSQL via Drizzle ORM, Zod schemas shared with the web app (`shared/`). Node runs the TypeScript directly (no build step for the server) | Decided |
| Database | PostgreSQL in production; embedded PGlite for local development, tests and very small installs | Decided |
| Auth | Email + password (scrypt), server-side sessions in an http-only cookie, four roles: reporter < supervisor < safety manager < admin | Decided |
| Deployment | Self-hosted, single `docker compose up` (app + Postgres); file storage added with photo upload | Decided |
| Compliance scope | US OSHA first; data model kept extensible for other regions (e.g. RIDDOR) | Proposed |
| Incident PDFs | Browser print-to-PDF from a print stylesheet; server-side PDF deferred (see TODO) | Decided |
| Email | SMTP via `SMTP_URL`; without it, logged in development and dropped in production. Delivery setup deferred (see TODO) | Decided |
| Reporting without accounts | "Reporting links": revocable, rate-limited tokens that can only file reports; used for kiosk tablets and QR codes | Decided |
| Languages | English + Spanish with typed message files; worker-facing screens first, manager screens later (see TODO) | Decided |
| Offline | Installable PWA; reports queued in IndexedDB and retried with a client-generated id so retries never duplicate | Decided |
| OSHA rules | One shared rules module (`shared/osha.ts`) used by API and UI; printable forms are OSHA-permitted equivalents (1904.29(b)(4)); ITA exports follow OSHA's published CSV specs | Decided |
| Medical privacy | Injured-person and medical details visible to safety managers and admins only; timeline and case CSV carry no names | Decided |
| Charts | Hand-built SVG components (no chart library) following the dataviz method: validated color slots, one axis, hairline grid, hover tooltips, a table view on every chart | Decided |
| CI | Gitea Actions (`.gitea/workflows`): lint, typecheck, unit tests, build, e2e | Decided |
| Product name | Open SafetyLog EHS (replaced placeholder "IA Tracker" and the prototype's "Safesite" branding) | Decided |
## Phase 0: Foundation
- [x] AGPL-3.0 LICENSE
- [x] Convert to TypeScript
- [x] Split `App.jsx` into `pages/`, `components/`, `lib/`
- [x] Convert styling to Tailwind (remove hand-written `App.css`)
- [x] Remove unused template files
- [x] Bundle fonts locally (no Google Fonts dependency for offline/locked-down plant networks)
- [x] CI: lint, typecheck, unit tests (Vitest), build, e2e (Playwright)
- [x] Replace template README
- [x] CONTRIBUTING.md and CODE_OF_CONDUCT.md
- [x] About page with source-code link (AGPL section 13)
- [ ] Remaining setup items (name, CoC contact, final source URL, CI runner): see [TODO.md](TODO.md)
## Phase 1: Backend and data model
- [x] Database schema and first migration for all entities: Organization, Site → Area (location tree), User, Session, Incident, InjuredPerson, Attachment, Investigation, RootCause, CorrectiveAction, Comment, AuditLog, HoursWorked
- [x] First-run setup (creates the organization and first admin)
- [x] Email/password sign-in, sessions, change password, login rate limiting
- [x] Role-based permissions (reporters see only their own reports)
- [x] REST API: users, sites/areas, incidents with pagination, search, filters and gap-free sequential numbers (`INC-0001`); see [API.md](API.md)
- [x] Audit log of every change
- [x] Server tests (Vitest + in-memory PostgreSQL), demo seed data
- [x] Dockerfile and `docker-compose.yml`
- Moved to Phase 2: magic-link sign-in and password reset by email (both need the email sending built for notifications). SSO/OIDC stays "later".
## Phase 2: Core workflow (MVP)
- [x] Web app connected to the API: sign-in, first-run setup, every page on live data (demo data removed from the frontend)
- [x] Photo and PDF upload, checked by file content (not name), size-limited, served with a sandboxing security policy
- [x] Magic-link sign-in, password reset by email, email invitations for new users (admins can also set passwords when there's no email)
- [x] Incident detail page: details editing, activity log (comments + audit trail), investigation with 5 Whys and fishbone (6M) views, corrective actions (CAPA)
- [x] Status workflow Reported → Triage → Investigation → Corrective actions → Verification → Closed, with role rules and guards (e.g. high severity can't skip investigation; closing needs every action verified), shared between API and UI
- [x] "My actions" and "All actions" lists with overdue tracking; assignees can update progress on their own actions
- [x] Email notifications: high/critical alerts to safety managers, action assignment, daily due/overdue digest
- [x] CSV export of the filtered register (protected against spreadsheet formula injection); print-friendly incident page for PDF via the browser
- [x] Overview dashboard and Analytics computed from real data; Locations and Settings (people, roles, passwords) pages
- [x] End-to-end tests run against the real server: full three-role lifecycle, sign-in, visibility rules, mobile reporting
## Phase 3: Shop-floor reporting
- [x] Installable app (web manifest, icons, service worker caching the app shell plus who-am-I and site lists)
- [x] Offline outbox: reports and photos saved on the device, sent automatically on reconnect; duplicate-proof retries via a client-generated id; reports only sent for the user who made them; warning on sign-out with unsent reports
- [x] Reporting links (managed in Settings): revocable tokens, optionally limited to one site, 30 reports per 10 minutes, photos included; kiosk page for shared tablets with large touch targets and auto-reset
- [x] Printable QR code sheets per site/area, for signed-in users or through a reporting link, with bilingual captions; scanning pre-fills the location
- [x] Anonymous reporting from the app, the kiosk and QR codes
- [x] English/Spanish: sign-in pages, navigation, report form, kiosk, My actions, offline messages; language toggle remembered per device; follows the browser language by default
- [x] Tests: outbox (IndexedDB), translations complete, reporting links and duplicate-proof retries on the server, browser tests for offline sync, Spanish kiosk via QR, QR pre-fill and installability
## Phase 4: Compliance (US OSHA)
- [x] Injured/ill people per incident with a live recordability check (1904.4–1904.11): covered worker, work-related, new case, general criteria, special cases; most-serious-outcome classification; 14-item first-aid list and privacy-case rules shown in context
- [x] Day counts with the 180-day cap; days only counted when the matching outcome applies
- [x] Severe injury reporting (1904.39): 8-hour/24-hour deadline banner, email alert to safety managers, "reported to OSHA at" record
- [x] Form 300 Log (landscape print), Form 300A Summary with establishment details and certification block, printable Form 301 per case
- [x] Establishment details per site (address, NAICS, EIN, type) with validation
- [x] Monthly hours worked and headcount; TRIR, DART and LTIR
- [x] ITA CSV exports for the 300A summary and 300/301 case data (no names), plus OSHA's own upload checks run in the app
- [x] Tests: rules module unit tests, API tests incl. exact CSV output, browser test of the full recordkeeping flow
## Phase 5: Analytics
- [x] One filter row (date range presets or custom, site, incident type) scoping every number and chart on the page
- [x] Leading indicators: hazards & near misses reported, near misses per injury, triaged within 24 hours, actions completed on time; each compared with the previous period
- [x] Lagging indicators: injuries, OSHA-recordable cases, rolling 12-month TRIR/DART, average days to close; OSHA rates by calendar year
- [x] Charts: reports per week/month by kind, rolling OSHA rates, locations (sites, or areas within a site), root causes, weekday × hour heatmap, actions completed on time vs late
- [x] Saved views (private, or shared by supervisors and above) on Analytics and the Incidents list
- [x] Demo seed with a year of realistic history (deterministic)
- [x] Tests: analytics computations (periods, groupings, rates, scoping), saved views, chart scale helper, browser tests
## Phase 6: Release v1.0
- Docker images, backup and restore
- Demo instance with seed data
- Documentation site and upgrade guide
## Later
Inspections and audit checklists, job safety analysis (JSA), training and certification records, management of change, SDS links, public API and webhooks.