Skip to content

Enterprise-readiness follow-ups (from ground-up review) #139

Description

@capnbigal

Tracking issue for the prioritized follow-ups from the ground-up review (docs/GROUND_UP_APP_REVIEW.md). Findings were verified against source; severities below are post-verification. The full refactor/feature/long-term roadmap lives in the review doc and docs/IMPLEMENTATION_PLAN_ENTERPRISE_APP.md.

Already shipped in #138: critical seed-user gate · admin password reset (/admin/users + API) · dead-code removal · doc-accuracy fixes.


P0 — do first

  • Rotate the live admin@email.com password (operational — code doesn't reset existing users). Use the new /admin/users reset after Enterprise review + seed-user security gate + admin password reset #138 deploys, or the SQL stopgap now.
  • CI runs the test suite. build.yml is build-only; ~340 NUnit cases (incl. auth/SSR-form regression guards) gate nothing. Add an mssql service container + ConnectionStrings__DefaultConnection env override + dotnet test --logger trx --collect "XPlat Code Coverage".
  • Enable account lockout. Login.razor calls PasswordSignInAsync(..., lockoutOnFailure: false), so the configured 5-attempt lockout never fires. One-line fix.

P1 — security / auth

  • Wire the "api" rate limiter. Registered (100/min) but attached to zero endpoints → the whole /api surface is unthrottled. Add .RequireRateLimiting("api") to the /api group.
  • Partition the "auth" limiter per-IP. Currently a single global fixed-window bucket → one client can DoS login/logout for everyone.
  • Authorization fallback policy + narrow the Employee floor. No FallbackPolicy; every Employee gets a Read floor on all areas (Sales/HR/Person incl. credit-card tables). Reconcile the endpoint-RequireRole vs AreaPermissionMiddleware models so they can't drift.
  • Finish API-key hash migration, then drop the indefinite plaintext fallback; use FixedTimeEquals.
  • Remove hardcoded p@55wOrd from the Demo:AutofillLogin path in Login.razor.

P1 — API contract / error handling

  • Global AddProblemDetails() + IExceptionHandler → RFC-7807 JSON for /api/* (today unhandled API exceptions render the HTML /Error page). Map DbUpdateException (unique/FK) → 409.
  • Document the X-Api-Key scheme in OpenAPI (AddSecurityDefinition + requirement); enable XML-comment ingestion.
  • Convert the ~10 untyped-Results endpoints (e.g. ShopFloorEndpoints) to TypedResults.

P1 — observability

  • Write SecurityAuditLog events (login/lockout/password/role/API-key). The entity is read by the failed-login alert but never written, so the alert is permanently 0.
  • Per-request correlation/trace ID threaded through RequestLogsAuditLog ↔ errors (can't join them today).
  • OpenTelemetry (ASP.NET/EF/SqlClient auto-instrumentation + exporter) — none today.
  • Job-health watchdog (Hangfire failures are silent) · Docker HEALTHCHECK/healthz · Serilog rolling-file fallback.

P1 — data correctness / performance

  • InventoryBalance lost-update race — read-modify-write with no concurrency token. Use an atomic UPDATE ... SET Quantity = Quantity + {delta} or a rowversion + retry.
  • Global soft-delete query filters (HasQueryFilter) — DeletedDate is enforced ad hoc per query today.
  • EnableRetryOnFailure on the SqlServer DbContext (verify inline-transaction endpoints tolerate the execution strategy).
  • Fix the ~5 over-fetching *ExpandedRow loaders (Customer/Product/Vendor/SalesTerritory/SalesPerson) that materialize an entity's entire transaction history per row-expand → aggregate projections + Take(10).

P1 — consistency / UX foundation

  • Revive PageHeader (title as <h1> → fixes the silent FocusOnNavigate a11y defect) and route CrudPage through it; default EmptyState/loading skeletons. Then migrate hand-rolled Index pages in batches.
  • First validator unit-test layer (TestValidate) — 250 validators currently have 0 direct tests; runs without SQL Server.

Discovery (the product thesis — see the review for sequencing)

  • Federated record search — wire GlobalSearch to the existing LookupService record searches (+ /api/search).
  • Per-record detail pages / ?id= filters for /aw + Enterprise-core (template already exists in newer modules) so cross-entity links land on the actual record.
  • Data catalog (/catalog) + schema relationship map + native AdventureWorks activity timelines (the Process Timeline is empty for all historical data today).

Generated from the multi-agent review on 2026-06-17. See docs/GROUND_UP_APP_REVIEW.md for the full findings, enterprise-readiness checklist, and roadmaps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions