Merge pull request #161 from Sea-Haven-Industries/chore/repo-docs-and-template

chore(repo): add PR template and README, retire stale root files
This commit is contained in:
Adam Moussa 2026-09-18 23:18:09 +00:00 • committed by GitHub
commit ae35f10921
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 148 additions and 228 deletions

View file

@ -1,11 +1,11 @@
# Sea Haven Industries ÔÇö shoc-backend required configuration
# Sea Haven Industries — shoc-backend required configuration
#
# This file documents the secrets that used to be hardcoded in appsettings*.json
# and source files. Copy the values into one of the supported configuration sources;
# do NOT commit real values.
#
# .NET resolves configuration in this order (later wins):
# 1. appsettings.json / appsettings.{Environment}.json (committed ÔÇö placeholders only)
# 1. appsettings.json / appsettings.{Environment}.json (committed — placeholders only)
# 2. User Secrets (local dev): dotnet user-secrets set "Key:Sub" "value"
# 3. Environment variables (use "__" as the section separator)
#

63
.gitattributes vendored
View file

@ -1,63 +1,2 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
# Normalize line endings on checkout and checkin.
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

22
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,22 @@
<!--
Title: type(scope): description (SH-123)
type is one of feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert, release.
Product work carries its SH key at the end of the title. Platform or security work carries PLAT or SEC.
Docs-only and configuration-only chores may omit the key.
Branch: feature/, fix/, hotfix/, chore/, docs/, refactor/, release/ plus a kebab-case description. No Jira keys in branch names.
Scope: one logical change per PR. If the title needs "and", split it.
Body: verifiable facts about the change. No validation transcripts, no deployment notes, no AI attribution footers.
The layout below is this repository's contract (REVIEW_AND_PR_FRAMEWORK.md, section 8). Keep the three headings.
-->
## Summary
<!-- What changed and why, in plain language. Two to four sentences. -->
## Changes and value
<!-- Grouped by area, each with the value it delivers. Bullets, bold lead-in per bullet. -->
## Ticket
<!-- The board key(s) this PR delivers, one per line. "None" when nothing applies. -->

View file

@ -6,9 +6,7 @@ may add stricter backend rules but may never weaken the workspace baseline.
## Canonical governance documents (precedence)
1. `ARCHITECTURE_AND_CODE_QUALITY.md` — *what* the rules mean (canonical;
supersedes the older `BACKEND_ARCHITECTURE.md`, which is retained only as
historical reference).
1. `ARCHITECTURE_AND_CODE_QUALITY.md` — *what* the rules mean (canonical).
2. `QUALITY_GATES.md` — *how* rules are enforced (commands + CI mapping).
3. `REVIEW_AND_PR_FRAMEWORK.md` — *who* reviews, in what order, with what
evidence.

View file

@ -1,9 +1,8 @@
# Architecture and Code Quality (canonical)
> **Status: canonical.** This document owns the *meaning* of the backend's
> architecture and code-quality rules. On any conflict with the older
> `BACKEND_ARCHITECTURE.md`, **this document governs**; that file is retained
> only as historical reference pending removal.
> architecture and code-quality rules. It replaced the earlier
> `BACKEND_ARCHITECTURE.md`, which now lives only in git history.
>
> Companion documents:
> - `QUALITY_GATES.md` — *how* each rule is enforced (commands + CI mapping).

View file

@ -1,106 +0,0 @@
# Backend Architecture and Quality Rules
This repository uses a feature-oriented service boundary over Entity Framework Core:
```text
HTTP controller -> I{Feature}Service -> I{Feature}DataService -> ApplicationDbContext
```
The interfaces are architectural seams, not a requirement to wrap every class or every
EF method. Add an interface when it separates HTTP, business, persistence, or external
I/O responsibilities and enables behavior-focused testing.
## Layer responsibilities
### API controllers
- Parse HTTP input, authorize the caller, invoke a business-service interface, and map
the result to the established HTTP contract.
- Do not inject `ApplicationDbContext`, concrete service implementations, or concrete
data-service implementations.
- Do not contain persistence queries or business workflows.
- Do not expose exception messages to clients. Map known failures explicitly and let the
centralized exception boundary handle unexpected failures.
### Business services
- Own validation, business decisions, orchestration, and transaction intent.
- Depend on interfaces for persistence and external I/O.
- Use `IOptions<T>` for typed configuration. Do not inject `IConfiguration`.
- Keep feature responsibilities cohesive. Split a service when it has independently
changing business reasons, not because it crossed an arbitrary line count.
- Preserve existing API and board-backed behavior unless the accepted requirement
explicitly changes it.
### Data services
- Own EF Core query shape, persistence, batching, and transaction implementation.
- Accept cancellation tokens on new I/O methods and pass them to EF Core.
- Use `AsNoTracking()` for read-only queries.
- Project only required columns for list/read models; include full graphs only when the
caller needs them.
- Page unbounded collections at the database.
- Avoid query-in-loop and save-in-loop patterns. Prefer set-based reads and batched writes
while preserving the workflow's failure and transaction semantics.
- Do not introduce a generic repository over EF Core. Feature data services should expose
intent-revealing operations.
## Performance review
For each changed hot path, document and test:
- input size variables;
- CPU and memory complexity;
- database round trips;
- whether filtering, ordering, and paging execute in SQL;
- whether tracking is necessary;
- whether repeated work can be hoisted out of loops;
- the partial-failure and transaction behavior.
Prefer dictionary or hash-set reconstruction when database results must follow caller
order. A query followed by dictionary reconstruction is normally `O(n)` CPU and memory;
repeated `First`/`Single` scans over the result are `O(n²)`.
Do not optimize by weakening correctness. In particular, batching all writes into one
final save can change partial-success behavior, and adding a transaction can change
locking and retry semantics. Those are business decisions, not mechanical cleanup.
## Configuration
Configuration is bound once during composition in
`SeaHaven.Services/DependencyInjection/ServicesModule.cs`. Business services receive
typed options such as `FrontendOptions`, `JwtOptions`, `ApprovalsOptions`, and
`VendorPortalOptions`.
Defaults must preserve current behavior. Startup validation should be introduced only
when every deployed environment is known to provide the required value.
## Enforcement
`ArchitectureTests` enforces mechanical dependency rules:
- controllers cannot inject EF contexts or concrete service/data-service classes;
- business services cannot inject EF contexts or raw `IConfiguration`.
The pull-request quality workflow runs those tests and verifies formatting for changed
C# files. The normal CI workflow builds the solution and runs the full test suite.
Architecture tests are appropriate for dependency direction. Behavior belongs in tests
through public interfaces. Do not add tests merely to prove a linter or analyzer itself
works; test the product behavior the rule protects.
## Review checklist
- Controller depends only on service abstractions.
- Business logic is in a cohesive feature service.
- EF operations are behind a feature data-service abstraction.
- No raw `IConfiguration` in a business service.
- No unbounded load followed by in-memory filtering.
- No query/save loop where a set-based operation preserves semantics.
- Read-only EF queries use no tracking.
- New async I/O accepts and propagates cancellation where the public contract permits.
- Errors do not leak internal exception details.
- Tests cover behavior, authorization, data contracts, ordering, duplicates, missing
records, and relevant failure boundaries.
- Changed behavior has been checked against the authoritative ticket board. Missing board
access blocks readiness and merge claims.

115
README.md Normal file
View file

@ -0,0 +1,115 @@
# SHOC Backend (`shoc-backend`)
[![CI](https://github.com/Sea-Haven-Industries/shoc-backend/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Sea-Haven-Industries/shoc-backend/actions/workflows/ci.yml)
[![Deploy](https://github.com/Sea-Haven-Industries/shoc-backend/actions/workflows/deploy.yaml/badge.svg)](https://github.com/Sea-Haven-Industries/shoc-backend/actions/workflows/deploy.yaml)
![.NET 8](https://img.shields.io/badge/.NET-8.0-512BD4?logo=dotnet&logoColor=white)
![SQL Server](https://img.shields.io/badge/SQL%20Server-CC2927?logo=microsoftsqlserver&logoColor=white)
![Terraform](https://img.shields.io/badge/Terraform-844FBA?logo=terraform&logoColor=white)
ASP.NET Core 8 API for Sea Haven facility management (SHOC): work orders, the
work-order board, dispatches and the vendor portal, uplift approvals,
notifications, and the dashboard. It is the backend for
[`shoc-frontend-new`](https://github.com/Sea-Haven-Industries/shoc-frontend-new),
which calls it directly over HTTPS.
| Environment | API | Elastic Beanstalk environment | Deployed by |
|---|---|---|---|
| dev | `https://api.dev.seahaven.com` | `shoc-backend-dev` | every push to `main` |
| staging | `https://api.staging.seahaven.com` | `shoc-backend-staging` | a `vX.Y.Z-staging` tag cut with `release.yaml` |
Both run in `us-east-1` on the .NET 8 Amazon Linux 2023 platform. Terraform in
`terraform/live/` owns the environments; GitHub Actions owns the application
versions. There is no production environment yet.
## Architecture
```text
Controller -> I{Feature}Service -> I{Feature}DataService -> ApplicationDbContext
```
Controllers depend on feature service interfaces only. Business services depend
on feature data-service interfaces, never on `DbContext`. Data services own
Entity Framework Core and are the atomic commit boundary. Tenant scope is
derived on the server from claims, and authorization is enforced at service
entry. The rules and their reasons are in
[`ARCHITECTURE_AND_CODE_QUALITY.md`](ARCHITECTURE_AND_CODE_QUALITY.md).
| Project | Role |
|---|---|
| `Api.SeaHavenIndustries` | The deployed API: controllers, hosted services, infrastructure adapters, `Program.cs` |
| `SeaHaven.Services` | Business services, DTOs, validation, helpers |
| `SeaHaven.DataServices` | Feature data services over EF Core |
| `Data.SeaHavenIndustries` | Entities, `ApplicationDbContext`, Identity, migrations |
| `SeaHavenIndustries` | Legacy Blazor Server app sharing the data layer; not part of the API deployment |
| `Api.SeaHavenIndustries.Tests`, `SeaHaven.Services.Tests`, `SeaHavenIndustries.Tests` | xunit test projects |
## Local development
Requires the .NET 8 SDK and a reachable SQL Server. Configuration comes from
`appsettings*.json` placeholders, then user secrets, then environment
variables. `.env.example` lists every key, including the connection string, JWT
secret, SendGrid key and Sentry DSN. Do not commit real values.
```bash
dotnet restore SeaHavenIndustries.sln
dotnet build SeaHavenIndustries.sln --configuration Release
dotnet test SeaHavenIndustries.sln --configuration Release
dotnet run --project Api.SeaHavenIndustries
```
The full repository gate that CI runs, including architecture discovery, the
changed-file maintainability check, Terraform checks and app/Terraform
isolation:
```bash
BASE_REF=origin/main bash scripts/governance-check.sh
```
Migrations live in `Data.SeaHavenIndustries/Migrations` and are applied at
deploy time from a bundle the packaging script builds with `dotnet-ef`. Adding
one follows the G6 rules in [`QUALITY_GATES.md`](QUALITY_GATES.md).
## Contributing
- Branch from `main` with a `feature/`, `fix/`, `chore/`, `docs/` or
`refactor/` prefix and a kebab-case description.
- Commit subjects follow Conventional Commits. PR titles end with the Jira
key for product work.
- The PR body uses the three-section layout the template pre-fills: Summary,
Changes and value, Ticket. The reasoning is in
[`REVIEW_AND_PR_FRAMEWORK.md`](REVIEW_AND_PR_FRAMEWORK.md).
- `main` requires a code-owner review and the `Build and test`,
`architecture` and `review / dependency-review` checks. PRs merge through the
merge queue, so a branch does not need to be updated with `main` before it
merges.
- Application code and `terraform/` do not change in the same PR (G13).
## Deployment
`deploy.yaml` packages the API with `scripts/package-elastic-beanstalk.sh`,
uploads the bundle to the Elastic Beanstalk bucket, updates the environment,
verifies the exact version is active, and smoke-tests it. The bundle carries a
self-contained EF Core migrations bundle that Elastic Beanstalk runs on the
leader instance before the new version starts
(`.ebextensions/01_migrations.config`). A push to `main` targets dev.
`release.yaml` cuts a SemVer tag from `main` and calls the same workflow for
staging. Both are described in the workflow headers and in
[`terraform/live/README.md`](terraform/live/README.md).
Renovate opens dependency PRs on the schedule in `.github/renovate.json`;
majors wait for approval on the Dependency Dashboard issue.
## Documentation
- [`AGENTS.md`](AGENTS.md): repo-specific rules for coding agents and the order
of precedence between the governance documents.
- [`ARCHITECTURE_AND_CODE_QUALITY.md`](ARCHITECTURE_AND_CODE_QUALITY.md): what
the architecture rules mean.
- [`QUALITY_GATES.md`](QUALITY_GATES.md): every gate, the command that runs it
locally, and where CI runs it.
- [`REVIEW_AND_PR_FRAMEWORK.md`](REVIEW_AND_PR_FRAMEWORK.md): review order,
evidence, and the PR description contract.
- [`docs/adr/`](docs/adr/): architecture decision records.
- [`docs/work-orders/`](docs/work-orders/): work-order board phase notes.
- [`postman/`](postman/): generated Postman collection and dev environment.
- [`terraform/README.md`](terraform/README.md): infrastructure runbook.

View file

@ -130,6 +130,11 @@ Avoid boilerplate: no deployment notes, no validation transcripts, no
"residual-risk" theatre, no AI signatures. The validation story lives in the
check run results and the close-out, not in the PR body.
`.github/PULL_REQUEST_TEMPLATE.md` pre-fills this layout and overrides the org
template, whose Summary / Validation / Tests / Notes headings this repository
does not use. The org `callable-pr-policy` workflow hard-codes those four
headings; it is not wired into this repository, and this layout is the reason.
## 9. Merge readiness
Merge requires: exact-head review done; board-backed regression check pass (or

52
TODO.md
View file

@ -1,52 +0,0 @@
# SHOC — TODO
## Vendor Portal (Next Priority)
- [ ] Change dispatch email Accept button to "View Work Order" linking to vendor portal
- [ ] Vendor web portal — public pages authenticated by dispatch token
- [ ] Vendor can view their dispatches, accept, update status, complete sign-offs, fill checklists
- [ ] No login required — token-based access from email link
- [ ] Per-WO template selection in multi-WO dispatch
## Dispatch & Vendor Communication
- [x] Dispatch detail modal — view/edit status, dates, NTE, description
- [x] Dispatch number — auto-generated DSP-00001
- [x] DispatchId on Comments — tie vendor comments to specific dispatches
- [x] Vendor activity feed per dispatch
- [x] Internal user → vendor email
- [x] Cancel dispatch button
- [x] Checklist items with template support
- [x] Two-party sign-offs (Customer + Vendor)
- [x] Dispatcher verification gate
- [x] Vendor accept via email link
- [x] Time tracking / wait indicators
- [x] Multi-WO dispatch
- [ ] **Front API integration** — replace SendGrid/SES with Front inbox (vendors@seahaven.com)
- [ ] Add ability for dispatcher to assign a template checklist after initial dispatch
- [ ] Resend dispatch email button
## Work Order List
- [ ] Pinned Actions column — CSS grid doesn't support sticky horizontal scroll, revisit
## Pages Not Yet Built
- [ ] `/profile` — My Profile page (linked from user dropdown)
- [ ] `/settings` — Account Settings page (linked from user dropdown)
- [ ] `/change-password` — Change Password page (linked from user dropdown)
## Controllers Not Yet Built
- [ ] `CalendarController` — backend CRUD for calendar/events (frontend pages exist)
## Dashboard
- [ ] Priority Analysis table — needs backend endpoint to calculate age buckets by severity
- [ ] Invoice Analysis table — placeholder data, no backend yet
## Data & Integration
- [ ] Customer NTE — wire to PO database (placeholder on WO view page)
- [ ] Vendor PO detailed format — line items, billing address, payment terms, expiration, T&C
- [ ] PDF generation for Vendor PO — QuestPDF or similar
- [ ] Address-based distance calculation — upgrade from zip-to-zip to geocoded addresses
- [ ] Backfill location zip codes from address strings during sync
## Deployment
- [ ] When SHOC deploys, switch workorder-ingest Lambda from DynamoDB to direct SHOC API calls
- [ ] Retire DynamoDB sync bridge
- [ ] GitHub branch protection — requires paid plan for private repos