mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-09-30 04:13:13 +00:00
docs: SHOC-alignment Phase 1 — ADRs, governance files, doc corrections (#220)
- Add ADR 0002 (SHOC merge boundary: separate backend services, shared conventions) and ADR 0003 (adopt SHOC design system + UI/UX layout) - Add CODEOWNERS (internal-dev) and PR template (Summary/Test plan/Jira/ docs-current checklist + contract-table convention) - Fix stale facts in README/CLAUDE.md: MUI v7→v9, RN 0.85→0.86, OpenSearch Serverless/oss-index-creator → Aurora pgvector/ aurora-pgvector-init (ADR 0001), test counts 149→186 (123 xUnit / 26 vitest / 37 pytest), deploy triggers are workflow_dispatch-only, reusable workflow refs float on @main, aws-cdk-lib version claim replaced with Dependabot-maintained note
This commit is contained in:
parent
536d440282
commit
a4b09eb0ad
6 changed files with 167 additions and 29 deletions
2
.github/CODEOWNERS
vendored
Normal file
2
.github/CODEOWNERS
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
# Default: all changes require internal-dev review
|
||||
* @Sea-Haven-Industries/internal-dev
|
||||
21
.github/pull_request_template.md
vendored
Normal file
21
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
## Summary
|
||||
|
||||
<!-- What changed and why. Reference finding IDs (API-C1, WEB-M5, ...) where applicable. -->
|
||||
|
||||
## Test plan
|
||||
|
||||
<!-- How this was verified: commands run, tests added, manual checks. -->
|
||||
|
||||
## Jira / tracking
|
||||
|
||||
<!-- Ticket ID(s), or "n/a". -->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Docs current — README / CLAUDE.md / ADRs / Confluence updated if this changes architecture, endpoints, or behavior
|
||||
- [ ] If an endpoint shape changed: contract table included below and `shared/api-contracts` updated
|
||||
|
||||
<!-- Contract table (only when an endpoint shape changes):
|
||||
| Endpoint | Method | Request change | Response change |
|
||||
|---|---|---|---|
|
||||
-->
|
||||
18
CLAUDE.md
18
CLAUDE.md
|
|
@ -6,10 +6,10 @@ Proposal management platform for Sea Haven Industries. Dispatchers submit servic
|
|||
|
||||
## Architecture
|
||||
|
||||
- **api/**: .NET 8 API, EF Core, PostgreSQL, Cognito JWT auth
|
||||
- **web/**: React 19 + MUI v7 SPA, Vite, CloudFront + S3
|
||||
- **mobile/**: React Native 0.85 iOS app, offline-capable, Hermes
|
||||
- **lambdas/**: Python 3.12 Lambdas (ARM64): pdf-extract, pdf-generate, library-ingest, suggestions, oss-index-creator
|
||||
- **api/**: .NET 8 API, EF Core, PostgreSQL (Aurora Serverless v2), Cognito JWT auth
|
||||
- **web/**: React 19 + MUI v9 SPA, Vite, CloudFront + S3
|
||||
- **mobile/**: React Native 0.86 iOS app, offline-capable, Hermes
|
||||
- **lambdas/**: Python 3.12 Lambdas (ARM64): pdf-extract, pdf-generate, library-ingest, suggestions, aurora-pgvector-init
|
||||
- **infra/**: CDK TypeScript (foundation-stack, compute-stack, frontend-stack)
|
||||
- **shared/**: Shared TypeScript API contracts
|
||||
- **scripts/**: Local dev helpers
|
||||
|
|
@ -19,6 +19,12 @@ Proposal management platform for Sea Haven Industries. Dispatchers submit servic
|
|||
External: Cognito JWT via API Gateway (web + mobile client IDs, groups: dispatchers/admins/sysadmins)
|
||||
Internal: Lambdas → .NET Function URL with Secrets Manager API key via custom middleware
|
||||
|
||||
## Key Decisions (ADRs in docs/adr/)
|
||||
|
||||
- **ADR 0001**: Bedrock KB vector store is Aurora PostgreSQL + pgvector (replaced OpenSearch Serverless; `oss-index-creator` Lambda replaced by `aurora-pgvector-init`)
|
||||
- **ADR 0002**: SHOC merge boundary — backends stay separate services permanently (PostgreSQL + Cognito here; SQL Server + ASP.NET Identity in SHOC); consolidation converges on conventions/layers/service patterns, never on platform
|
||||
- **ADR 0003**: SHOC dev's design system + UI/UX layout is canonical (Montserrat/DM Sans, primary #1c75bc, 244px sidebar, CSS-variable single-token-source consumed by MUI via getCssVar); the old Nunito/#0c4f6f canon and the interim "Sea Haven Ops" Inter/#2563EB theme are superseded
|
||||
|
||||
## Request Flow
|
||||
|
||||
1. Dispatcher submits proposal (web/mobile) → InReview (no Draft stage)
|
||||
|
|
@ -29,7 +35,7 @@ Internal: Lambdas → .NET Function URL with Secrets Manager API key via custom
|
|||
|
||||
## Infrastructure
|
||||
|
||||
AWS us-east-1, RDS PostgreSQL 15, S3, SQS+DLQ, Cognito+Google OAuth, OpenSearch Serverless, Bedrock KB, GitHub Actions OIDC, CloudFront+S3 OAC
|
||||
AWS us-east-1, Aurora PostgreSQL 15 Serverless v2 (RDS Data API + pgvector), S3, SQS+DLQ, Cognito+Google OAuth, Bedrock KB (Aurora pgvector store — ADR 0001), GitHub Actions OIDC, CloudFront+S3 OAC
|
||||
|
||||
## Agent Delegation Rules
|
||||
|
||||
|
|
@ -58,7 +64,7 @@ AWS us-east-1, RDS PostgreSQL 15, S3, SQS+DLQ, Cognito+Google OAuth, OpenSearch
|
|||
|
||||
## Audit Status
|
||||
|
||||
AUDIT-REPORT.md completed 2026-05-27. 5 Critical, 36 High, 75+ Medium, 60+ Low findings. Phase 1-5 complete: all Critical/High fixed, 17 Medium fixed, CI runs 108 tests.
|
||||
AUDIT-REPORT.md completed 2026-05-27. 5 Critical, 36 High, 75+ Medium, 60+ Low findings. Phase 1-5 complete: all Critical/High fixed, 17 Medium fixed, CI runs 186 tests (123 xUnit, 26 vitest, 37 pytest).
|
||||
|
||||
### Critical Findings (fix first)
|
||||
|
||||
|
|
|
|||
44
README.md
44
README.md
|
|
@ -13,9 +13,9 @@ Internal proposal management platform for Sea Haven Industries. Dispatchers subm
|
|||
Monorepo with five primary services:
|
||||
|
||||
- **.NET 8 API** -- Clean Architecture REST API hosted on Lambda behind API Gateway (JWT-authorized) with Function URL (AWS_IAM) for internal access
|
||||
- **React 19 Web** -- MUI v7 admin/dispatcher workspace served via CloudFront + S3
|
||||
- **React 19 Web** -- MUI v9 admin/dispatcher workspace served via CloudFront + S3
|
||||
- **React Native Mobile** -- iOS-first field app for dispatchers (offline-capable)
|
||||
- **Python Lambdas** -- PDF extraction, PDF generation, library ingestion, AI suggestions, AOSS index provisioning
|
||||
- **Python Lambdas** -- PDF extraction, PDF generation, library ingestion, AI suggestions, Aurora pgvector bootstrap
|
||||
- **CDK Infrastructure** -- Three TypeScript stacks managing all AWS resources
|
||||
|
||||
## Repository Structure
|
||||
|
|
@ -23,8 +23,8 @@ Monorepo with five primary services:
|
|||
```
|
||||
proposal-system/
|
||||
├── api/ .NET 8 Web API (Lambda-hosted, EF Core + PostgreSQL)
|
||||
├── web/ React 19 + MUI v7 + Vite frontend
|
||||
├── mobile/ React Native 0.85 iOS app
|
||||
├── web/ React 19 + MUI v9 + Vite frontend
|
||||
├── mobile/ React Native 0.86 iOS app
|
||||
├── lambdas/ Python 3.12 processing functions (arm64)
|
||||
├── infra/ CDK TypeScript (3 stacks)
|
||||
├── shared/ TypeScript API contracts (shared between web + mobile)
|
||||
|
|
@ -38,11 +38,11 @@ proposal-system/
|
|||
| Component | Technologies |
|
||||
|---|---|
|
||||
| API | .NET 8, ASP.NET Core, EF Core + Npgsql, FluentValidation, Cognito JWT, Amazon.Lambda.AspNetCoreServer |
|
||||
| Web | React 19, TypeScript, MUI v7, Vite, Redux Toolkit, TanStack Query, axios |
|
||||
| Mobile | React Native CLI 0.85, React 19, React Native Paper, React Navigation, react-native-app-auth (PKCE), amazon-cognito-identity-js (SRP), Keychain, offline draft queue |
|
||||
| Web | React 19, TypeScript, MUI v9, Vite, Redux Toolkit, TanStack Query, axios |
|
||||
| Mobile | React Native CLI 0.86, React 19, React Native Paper, React Navigation, react-native-app-auth (PKCE), amazon-cognito-identity-js (SRP), Keychain, offline draft queue |
|
||||
| Lambdas | Python 3.12, arm64, pdfplumber, reportlab, httpx, boto3 |
|
||||
| Infrastructure | CDK TypeScript (aws-cdk-lib 2.253.1) |
|
||||
| AI/RAG | Bedrock Knowledge Base (Titan Embeddings v2), OpenSearch Serverless (VPC-only), Claude Sonnet via Bedrock cross-region inference |
|
||||
| Infrastructure | CDK TypeScript (aws-cdk-lib pinned exact, kept current by Dependabot) |
|
||||
| AI/RAG | Bedrock Knowledge Base (Titan Embeddings v2), Aurora PostgreSQL + pgvector vector store (see ADR 0001), Claude Sonnet via Bedrock cross-region inference |
|
||||
| Auth | Cognito User Pool + Google OAuth IdP (groups: dispatchers, admins, sysadmins) |
|
||||
|
||||
## AWS Resources
|
||||
|
|
@ -51,8 +51,8 @@ All resources are in **us-east-1** (account 328440206208).
|
|||
|
||||
| CDK Stack | Key Resources |
|
||||
|---|---|
|
||||
| `proposal-system-foundation` | RDS PostgreSQL 15 (t4g.small), S3 buckets, SQS queue + DLQ, Cognito user pool, Secrets Manager |
|
||||
| `proposal-system-compute` | API Gateway HTTP API (JWT authorizer + access logging), .NET 8 API Lambda + Function URL (AWS_IAM), Python Lambdas (pdf-extract, pdf-generate, library-ingest, suggestions, oss-index-creator), OpenSearch Serverless collection (VPC endpoint), Bedrock KB |
|
||||
| `proposal-system-foundation` | Aurora PostgreSQL 15 Serverless v2 (RDS Data API, pgvector), S3 buckets, SQS queue + DLQ, Cognito user pool, Secrets Manager |
|
||||
| `proposal-system-compute` | API Gateway HTTP API (JWT authorizer + access logging), .NET 8 API Lambda + Function URL (AWS_IAM), Python Lambdas (pdf-extract, pdf-generate, library-ingest, suggestions, aurora-pgvector-init bootstrap), Bedrock KB (Aurora pgvector store) |
|
||||
| `proposal-system-frontend` | CloudFront distribution (S3 OAC) |
|
||||
|
||||
| Resource Type | Names |
|
||||
|
|
@ -118,17 +118,17 @@ Seven parallel jobs calling org reusable workflows:
|
|||
|
||||
| Job | Workflow | What it checks |
|
||||
|---|---|---|
|
||||
| .NET Build & Test | `ci-dotnet.yaml` | Restore, build, test the API solution (104 xUnit tests) |
|
||||
| .NET Build & Test | `ci-dotnet.yaml` | Restore, build, test the API solution (123 xUnit tests) |
|
||||
| Web Frontend Check | `ci-typescript-cdk.yaml` | TypeScript typecheck for web |
|
||||
| Web Tests | `ci-typescript-cdk.yaml` | vitest suite (26 tests — auth, interceptors, components) |
|
||||
| Web Tests | inline job | vitest suite (26 tests — auth, interceptors, components) |
|
||||
| Mobile Typecheck | `ci-typescript-cdk.yaml` | TypeScript typecheck for mobile |
|
||||
| Python Lint | `ci-python-sam.yaml` | ruff check + format on lambdas/ |
|
||||
| Python Tests | `ci-python-sam.yaml` | pytest suite (19 tests — pdf-generate, suggestions handlers) |
|
||||
| Python Tests | inline job | pytest suite (37 tests — pdf-generate, suggestions, library-ingest, internal API signing) |
|
||||
| CDK Synth | `ci-typescript-cdk.yaml` | Synthesize CDK stacks (includes .NET publish) |
|
||||
|
||||
### Deploy (on push to main)
|
||||
### Deploy (manual)
|
||||
|
||||
Calls `cd-cdk.yaml` reusable workflow:
|
||||
Auto-deploy on push to main is currently disabled (PR #167) — both deploy workflows run via `workflow_dispatch` from the Actions tab. `deploy.yaml` calls the `cd-cdk.yaml` reusable workflow:
|
||||
1. Publishes .NET 8 API and Python Lambdas
|
||||
2. Runs `cdk deploy --all`
|
||||
3. Executes `scripts/post-deploy.sh` (builds web, syncs to S3, invalidates CloudFront)
|
||||
|
|
@ -139,9 +139,7 @@ Deploy uses OIDC role `githubdeploy-proposal-system`. Concurrency group prevents
|
|||
|
||||
Workflow: `deploy-mobile.yaml` -- builds and uploads to TestFlight via `cd-mobile-ios.yaml` reusable workflow on `macos-26`.
|
||||
|
||||
Triggers:
|
||||
- **Automatic**: push to `main` with changes in `mobile/**`
|
||||
- **Manual**: `workflow_dispatch` for on-demand builds
|
||||
Trigger: **manual only** (`workflow_dispatch`) while the app is pre-V1, to save macOS runner cost.
|
||||
|
||||
## Mobile iOS
|
||||
|
||||
|
|
@ -186,13 +184,13 @@ Failed SQS messages are reported via `batchItemFailures` and retried up to 3 tim
|
|||
|
||||
## Testing
|
||||
|
||||
149 tests across three stacks, all run in CI on every PR:
|
||||
186 tests across three stacks, all run in CI on every PR:
|
||||
|
||||
| Suite | Framework | Count | Coverage |
|
||||
|---|---|---|---|
|
||||
| .NET API | xUnit | 104 | State machine transitions, authorization attributes, middleware, validators, ProposalNumberGenerator, LineItemService state guards |
|
||||
| .NET API | xUnit | 123 | State machine transitions, authorization attributes, middleware, validators, ProposalNumberGenerator, LineItemService state guards |
|
||||
| Web | vitest | 26 | ProtectedRoute, RoleGuard, API client interceptor (401 logout, token attachment) |
|
||||
| Python Lambdas | pytest | 19 | pdf-generate and suggestions handler contracts |
|
||||
| Python Lambdas | pytest | 37 | pdf-generate, suggestions, library-ingest handler contracts, internal API signing |
|
||||
|
||||
```bash
|
||||
cd api && dotnet test # .NET tests
|
||||
|
|
@ -207,7 +205,7 @@ Hardening applied across all layers (see AUDIT-REPORT.md for full details):
|
|||
- **Auth:** Cognito JWT validation with audience check, startup fails if auth not configured, DevMode gated to `IsDevelopment()`
|
||||
- **API:** FluentValidation on all DTOs, generic error responses (no stack traces or config leaks), structured audit logging with before/after diffs
|
||||
- **Function URL:** AWS_IAM auth + internal API key (two-layer defense)
|
||||
- **Infrastructure:** S3 `enforceSSL` + `BLOCK_ALL`, SQS managed encryption, OpenSearch VPC-only, Cognito optional TOTP MFA, API Gateway access logging
|
||||
- **Infrastructure:** S3 `enforceSSL` + `BLOCK_ALL`, SQS managed encryption, Aurora in private subnets, Cognito optional TOTP MFA, API Gateway access logging
|
||||
- **Lambdas:** Prompt injection sanitization, PDF size limits, numeric validation on AI suggestions, S3 key sanitization, idempotent SQS processing
|
||||
- **CI/CD:** OIDC (no long-lived credentials), SHA-pinned workflow refs, `--require-approval broadening` on local deploys
|
||||
- **CI/CD:** OIDC (no long-lived credentials), org reusable workflows (`@main`), `--require-approval broadening` on local deploys
|
||||
- **Web:** sessionStorage for tokens (not localStorage), error boundaries, role guards on all admin routes, 401 interceptor clears auth state
|
||||
|
|
|
|||
62
docs/adr/0002-shoc-merge-boundary.md
Normal file
62
docs/adr/0002-shoc-merge-boundary.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# ADR 0002 — SHOC merge boundary: separate backend services, shared conventions
|
||||
|
||||
- **Status:** Accepted (2026-07-13)
|
||||
- **Decision owner:** Adam Moussa
|
||||
- **Scope:** `proposal-system` ↔ SHOC (`shoc-backend` / `shoc-frontend-new`) consolidation strategy
|
||||
|
||||
## Context
|
||||
|
||||
proposal-system was built as a standalone service deliberately mirroring SHOC's
|
||||
architecture for a clean future merge. As of 2026-07-13 the two projects diverge on
|
||||
platform fundamentals:
|
||||
|
||||
| Axis | proposal-system | SHOC |
|
||||
|---|---|---|
|
||||
| Database | Aurora PostgreSQL (pgvector) via EF Core/Npgsql | SQL Server via EF Core |
|
||||
| Identity | Cognito (hosted UI, groups, web + mobile clients) | ASP.NET Identity + custom JWT issuance |
|
||||
| API layout | 4-project Clean Architecture (Api/Application/Infrastructure/Domain) | Single API project, services injecting DbContext |
|
||||
| Error contract | RFC 7807 ProblemDetails, string enums | Typed-exception codes per controller, numeric enums |
|
||||
| Hosting | Lambda behind API Gateway (CDK) | Elastic Beanstalk (external-dev account) |
|
||||
|
||||
A full platform alignment (engine migration, auth migration, rehosting) would cost
|
||||
weeks, carry data-migration risk, and deliver no user value.
|
||||
|
||||
## Decision
|
||||
|
||||
**The backends remain separate services permanently. Consolidation converges on
|
||||
conventions, layers, and service patterns — never on platform.**
|
||||
|
||||
Concretely:
|
||||
|
||||
1. **No database engine migration** in either direction. PostgreSQL stays here;
|
||||
SQL Server stays in SHOC.
|
||||
2. **No identity migration now.** Cognito stays here. At consolidation time, identity
|
||||
converges on Cognito (or a federation layer in front of both) — not on
|
||||
ASP.NET Identity, which would regress to self-managed credentials and reintroduce
|
||||
the remediated WEB-C1 token-theft class (SHOC currently stores JWTs in
|
||||
localStorage).
|
||||
3. **Conventions converge** (tracked by the 2026-07 SHOC-alignment plan):
|
||||
- Frontend: SHOC's design system + UI/UX layout (ADR 0003), domain layering
|
||||
(`src/domain/<entity>/{api,schemas,mappers,types,use-cases}`), TanStack Query,
|
||||
zod, react-hook-form.
|
||||
- API contracts: shared TypeScript contracts package + zod schemas; ProblemDetails
|
||||
with machine-readable business `code` extensions (SHOC's error-code vocabulary,
|
||||
proposal-system's envelope).
|
||||
- Mutation semantics: optimistic concurrency with SHOC's 409-plus-currentState
|
||||
response shape; staged audit-trail entries persisted at one SaveChanges boundary.
|
||||
- Process: org reusable CI callers, CODEOWNERS, PR template, conventional commits.
|
||||
4. **Layering stays Clean Architecture here.** SHOC's flatter service style is not
|
||||
adopted; if SHOC restructures at consolidation, this repo's 4-project layout is the
|
||||
reference shape.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The eventual "merge" is a monorepo consolidation of independently deployable
|
||||
services sharing a frontend architecture and wire conventions — not a single
|
||||
backend.
|
||||
- A merged frontend can treat both APIs identically for errors (ProblemDetails +
|
||||
`code`) and conflicts (409 + currentState) once alignment phases 3/6 land.
|
||||
- Anything requiring one database across both domains (cross-domain reporting,
|
||||
shared entities) must go through APIs, not shared tables.
|
||||
- SHOC's localStorage JWT + CORS `*` are flagged to the SHOC team as findings; they
|
||||
are not constraints on this repo.
|
||||
49
docs/adr/0003-shoc-design-system-adoption.md
Normal file
49
docs/adr/0003-shoc-design-system-adoption.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# ADR 0003 — Adopt the SHOC design system and UI/UX layout
|
||||
|
||||
- **Status:** Accepted (2026-07-13)
|
||||
- **Decision owner:** Adam Moussa
|
||||
- **Scope:** `web/` theming, layout shell, and all future proposal-system UI work
|
||||
|
||||
## Context
|
||||
|
||||
Three design-token sets existed across Sea Haven web apps as of 2026-07-13:
|
||||
|
||||
1. **Old canon** — Nunito, primary `#0c4f6f`, 220px sidebar, `#f4f6f7` background
|
||||
(what SHOC's stale `docs/DESIGN_SYSTEM.md` still describes).
|
||||
2. **SHOC dev's new system** (shoc-frontend-new PR #17) — Montserrat (display) /
|
||||
DM Sans (body) / JetBrains Mono, primary `#1c75bc`, navy `#262262`, page background
|
||||
`#f9fafb`, 244px sidebar (76px collapsed), 64px gradient topbar
|
||||
(`#1b1f52 → #1c4f8f → #1c75bc`), defined in a single CSS-variable token file
|
||||
(`src/styles/theme.css`) consumed by both MUI (`getCssVar` → `createTheme`) and
|
||||
Tailwind v4.
|
||||
3. **proposal-system's "Sea Haven Ops" theme** — Inter, accent `#2563EB`,
|
||||
navy-900 AppBar, 216px drawer (`web/src/theme.ts`).
|
||||
|
||||
## Decision
|
||||
|
||||
**SHOC dev's new design system and UI/UX layout (set 2) is the canonical Sea Haven
|
||||
standard.** proposal-system adopts it fully:
|
||||
|
||||
- **Tokens:** mirror shoc-frontend-new dev's `theme.css` values and structure
|
||||
(fonts, palette, radii, spacing, shadows).
|
||||
- **Mechanism:** single CSS-variable token file is the one source of truth;
|
||||
`web/src/theme.ts` becomes a thin `getCssVar` → MUI `createTheme` adapter matching
|
||||
SHOC's `mui-theme.ts`. Token changes are values-only edits, never theme rewrites.
|
||||
- **Layout shell:** SHOC's admin shell dimensions and treatment — 244px/76px-collapse
|
||||
sidebar, 64px gradient topbar, avatar initials.
|
||||
- **Component library:** MUI only. Tailwind (SHOC runs a MUI + Tailwind v4 hybrid off
|
||||
the same CSS variables) is **not** adopted here pre-consolidation; the shared
|
||||
CSS-variable source keeps that door open.
|
||||
|
||||
The reference is shoc-frontend-new's **`dev` branch** at adoption time; subsequent
|
||||
SHOC token changes should be ported as values-only updates.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The "Sea Haven Ops" theme (Inter/#2563EB) is retired; alignment plan Phase 2
|
||||
implements the port.
|
||||
- Visual verification for Phase 2 compares proposal-system screens side-by-side with
|
||||
SHOC dev screens, not with the old canon.
|
||||
- The superseded Nunito/`#0c4f6f` tokens must not be reintroduced anywhere.
|
||||
- At monorepo consolidation, both frontends already share token structure, so a
|
||||
single `theme.css` can serve both.
|
||||
Loading…
Add table
Reference in a new issue