# Conflicts: # src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-controller.ts |
||
|---|---|---|
| .cursor/rules | ||
| .github | ||
| .husky | ||
| config | ||
| docs | ||
| e2e | ||
| eslint-rules | ||
| public | ||
| scripts | ||
| src | ||
| terraform | ||
| tmp/pr-descriptions | ||
| .env | ||
| .env.development | ||
| .env.example | ||
| .env.production | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| ARCHITECTURE_AND_CODE_QUALITY.md | ||
| commitlint.config.js | ||
| eslint.config.js | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| playwright.visual.config.ts | ||
| QUALITY_GATES.md | ||
| README.md | ||
| REVIEW_AND_PR_FRAMEWORK.md | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| vite.config.ts | ||
| vitest.config.ts | ||
SHOC Frontend (shoc-frontend-new)
Vite + React SPA for Sea Haven facility management (SHOC): work orders, vendor
portal, uplifts, and related admin features. This is the selective rebuild of
the legacy SHOC frontend — new code follows the IrisLoan.Admin conventions
documented in docs/ARCHITECTURE_PLAN.md.
- GitHub:
Sea-Haven-Industries/shoc-frontend-new - Hosted at: https://dev.seahaven.com (dev environment; the only environment today)
- Backend API:
https://api.dev.seahaven.com/api(called directly, cross-origin) — source:Sea-Haven-Industries/shoc-backend
Architecture
Static SPA hosting on AWS, owned by HCP Terraform
(terraform/README.md). CloudFront serves the built
dist/ from a private S3 bucket using a current/previous origin group;
the SPA calls the backend directly over HTTPS at VITE_API_URL (no /api
proxy at the CDN — the backend allows CORS).
graph LR
U[Browser] -->|HTTPS dev.seahaven.com| CF[CloudFront]
CF -->|origin group OAC| S3[S3 seahaven-shoc-frontend-dev]
CF -.->|viewer-request fn| FN[SPA rewrite → /index.html]
U -->|HTTPS api.dev.seahaven.com/api CORS| API[SHOC backend API]
GH[GitHub Actions] -->|OIDC upload releases/*| S3
TF[HCP Terraform shoc-frontend-new-dev] -->|pointer origin_path invalidation| CF
Dev hosting and content CD are owned by HCP Terraform (SH-300). Staging still
uses CloudFormation outputs and scripts/deploy-web.sh (SH-287).
Frontend stack: React 19, TypeScript, Vite, Tailwind CSS 4 + MUI, TanStack
Query, React Router (via @generouted/react-router), React Hook Form + Zod,
Ky HTTP client. Source layout: src/api/, src/domain/, src/app/ (see the
architecture plan for the keep/discard migration matrix).
AWS Resources
HCP workspace shoc-frontend-new-dev — account 396287094661, region
us-east-1. Defined in terraform/live/dev.
| Resource | Name | Purpose |
|---|---|---|
| S3 bucket | seahaven-shoc-frontend-dev |
Private origin (BLOCK_ALL, SSE, versioned; OAC-only reads) |
| CloudFront distribution | (stack output DistributionId) |
HTTPS static hosting on dev.seahaven.com, ACM *.seahaven.com |
| CloudFront Function | SpaRewrite |
Viewer-request rewrite of extensionless paths to /index.html (deep links) |
| IAM role | githubdeploy-shoc-frontend-new-dev |
GitHub Actions OIDC deploy role, trust scoped to repo:Sea-Haven-Industries/shoc-frontend-new:ref:refs/heads/dev |
| Route 53 records | A/AAAA apex alias in zone dev.seahaven.com (Z07671212N75U4YLPWZR8) |
Points the custom domain at CloudFront |
No Lambdas, queues, or databases — this stack is static hosting only.
Configuration
Secrets
No Secrets Manager or SSM parameters. AWS access is OIDC only; the deploy role ARNs are deterministic and pinned in the workflows. The one GitHub Actions repo secret is:
| Secret | Purpose |
|---|---|
SENTRY_AUTH_TOKEN |
Source-map upload by scripts/upload-sourcemaps.sh after a deploy |
Environment variables (build-time, VITE_*)
| Variable | Description | Dev value |
|---|---|---|
VITE_API_URL |
Ky API base prefix, baked into the build at vite build |
/api (dev server) / https://api.dev.seahaven.com/api (production build) |
VITE_API_TARGET |
Dev-proxy target for /api (Vite dev server only) |
http://localhost:5141 |
VITE_API_URL supplies the full API prefix — route paths in API_PATHS do
not include /api. Absolute values must end with /api;
vite.config.ts enforces this via config/api-url-contract.ts and fails the
build otherwise. See .env.example,
.env.development, and .env.production.
Pinned hosting constants (domain, certificate ARN, hosted zone) live in
terraform/live/dev/main.tf.
Local Development
Requirements: Node.js ≥ 22.22.1 (CI/CD run Node 24), npm 11.16.0 (pinned via
packageManager).
npm ci
cp .env.example .env # then set VITE_API_URL=/api for local dev
npm run dev # Vite dev server on port 3000, proxies /api → VITE_API_TARGET
The dev proxy expects the shoc-backend API at http://localhost:5141;
override with VITE_API_TARGET (e.g. https://api.dev.seahaven.com to use
the deployed dev API).
| Command | Description |
|---|---|
npm run dev |
Start Vite dev server on port 3000 |
npm run build |
Type-check (tsc -b) and production build to dist/ |
npm run preview |
Preview the production build locally |
npm test / npm run test:watch |
Vitest unit tests (once / watch) |
npm run test:e2e / npm run test:e2e:ui |
Playwright e2e tests (headless / UI mode) |
npm run lint / npm run lint:fix |
ESLint (check / auto-fix) |
npm run format / npm run format:check |
Prettier (write / check) |
npm run governance |
Governance checks (godfile, maintainability, Terraform, CD guards) |
npm run verify |
All gates: format + lint + build + test + governance |
npm run governance needs terraform and python3 on PATH for the
Terraform and content-CD gates.
Husky + lint-staged run ESLint and Prettier on staged files at commit;
commitlint enforces conventional commit messages. Run npx tsc --noEmit (or
npm run build) before pushing to catch type errors early.
Contributing
- Branch from
devwith a kebab-case description and a prefix matching the work:feature/,bug/,hotfix/,chore/,docs/, orrefactor/(e.g.feature/vendor-portal-filters,chore/sea-haven-branding). - Commit messages follow Conventional Commits — commitlint rejects anything else at commit time.
- Open PRs against
dev. Bothdevandmainare protected: every PR needs a green CI run and an approving review from a code owner (@Sea-Haven-Industries/internal-dev); new pushes dismiss stale approvals. Merged branches are deleted automatically. - A PR that changes
terraform/**may not also change application code (theterraform-isolationCI job); ship Terraform in its own PR. - Promotion flow:
feature/* → dev(deployed todev.seahaven.comthrough Terraform content CD onceTERRAFORM_CONTENT_CD_ENABLED=true)→ main(production promotion — no prod environment exists yet).
Deployment
No stored AWS keys — OIDC only. Infrastructure and content deploy separately:
- CI (
.github/workflows/ci.yaml) — on push and PRs tomain/dev/staging, callsSea-Haven-Industries/.github→ci-typescript-frontend.yaml(Node 24): format check, lint, build, tests; and runs a repo-ownedgovernancejob that callsnpm run verifyso every gate (including the maintainability ratchets inscripts/governance-check.mjs, the Terraform gates, and the content-CD guards) is guaranteed from this repository. Conventions and gates are documented underAGENTS.md,QUALITY_GATES.md,ARCHITECTURE_AND_CODE_QUALITY.md, andREVIEW_AND_PR_FRAMEWORK.md. - Terraform isolation
(
.github/workflows/terraform-isolation.yaml) — fails a PR that mixesterraform/**with application code, so a Terraform merge never races a content release for the HCP workspace. - Dev content (
.github/workflows/deploy.yml) —workflow_dispatchondev, and push-to-devwhenvars.TERRAFORM_CONTENT_CD_ENABLEDistrue(paths-ignore: terraform/**). GitHub uploadsreleases/<sha>-<run>-<attempt>/only. Terraform updates.release/current, both origin paths, and the invalidation action. Verify and rollback sharescripts/verify-cloudfront-release.sh. Every run prints a live-state summary. - Staging content
(
.github/workflows/deploy-staging.yml) — on push tostaging, unchanged. - Infrastructure — administrator-run HCP Terraform workspace
shoc-frontend-new-dev(terraform/README.md). Staging hosting stays on the existing CloudFormation stack until SH-287.
Do not run scripts/deploy-web.sh against dev. That script remains the staging
content publisher only.
Operations
- Verify: open https://dev.seahaven.com after a green Deploy dev content run in the Actions tab; confirm a deep link (e.g. a work-orders route) loads directly and API calls succeed.
- Logs: deploy logs live in GitHub Actions (CI + Deploy workflows). There are no CloudWatch application logs — the stack is static hosting; runtime errors surface in the browser and on the backend API's side.
- Common failure modes:
- Stale content after deploy — CloudFront is still
InProgressor an edge still serves the previousindex.htmlhash. Read the live-state summary before assuming the site is down. - OIDC
AssumeRoleerrors — the trust policy is scoped to thedevref on this repo; dispatching the workflow from another branch is rejected by design. - Broken API requests after a build —
VITE_API_URLmissing the/apisuffix or carrying the wrong environment's host (it is baked in at build time). - CORS errors — the backend must allow the frontend origin; CloudFront does
not proxy
/api.
- Stale content after deploy — CloudFront is still
- Push-to-
devis gated. Merging todevpublishes only whenTERRAFORM_CONTENT_CD_ENABLED=true. Merging aterraform/**change queues an HCP Terraform run that a human confirms or discards before the next content release (see the operational rules interraform/README.md).
Documentation
- Dev Terraform runbook:
terraform/README.md - Rebuild strategy and conventions:
docs/ARCHITECTURE_PLAN.md; design system and UI docs underdocs/