Commit graph

142 commits

Author SHA1 Message Date
dependabot[bot]
987f3314bd
build(deps): bump react-router-dom from 7.15.1 to 7.16.0 in /web (#78)
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 7.15.1 to 7.16.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.16.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-version: 7.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:34:00 +00:00
dependabot[bot]
ba1b6bc22b
build(deps): update boto3 requirement in /lambdas/pdf-generate (#76)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.14...1.43.18)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.18
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:57 +00:00
dependabot[bot]
a9b0df54da
build(deps): update boto3 requirement in /lambdas/pdf-extract (#73)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.14...1.43.18)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.18
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:50 +00:00
dependabot[bot]
4f724531bf
build(deps): bump react-native-app-auth from 8.3.0 to 8.4.0 in /mobile (#79)
Bumps [react-native-app-auth](https://github.com/FormidableLabs/react-native-app-auth) from 8.3.0 to 8.4.0.
- [Release notes](https://github.com/FormidableLabs/react-native-app-auth/releases)
- [Commits](https://github.com/FormidableLabs/react-native-app-auth/compare/react-native-app-auth@8.3.0...react-native-app-auth@8.4.0)

---
updated-dependencies:
- dependency-name: react-native-app-auth
  dependency-version: 8.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:42 +00:00
dependabot[bot]
a71b07db4d
build(deps): update boto3 requirement in /lambdas/library-ingest (#77)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.14...1.43.18)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.18
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:40 +00:00
dependabot[bot]
a330eb39c2
build(deps): update boto3 requirement in /lambdas/suggestions (#74)
Updates the requirements on [boto3](https://github.com/boto/boto3) to permit the latest version.
- [Release notes](https://github.com/boto/boto3/releases)
- [Commits](https://github.com/boto/boto3/compare/1.43.14...1.43.18)

---
updated-dependencies:
- dependency-name: boto3
  dependency-version: 1.43.18
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:37 +00:00
dependabot[bot]
57cd85e4c2
build(deps): bump fastlane from 2.234.0 to 2.235.0 in /mobile (#75)
Bumps [fastlane](https://github.com/fastlane/fastlane) from 2.234.0 to 2.235.0.
- [Release notes](https://github.com/fastlane/fastlane/releases)
- [Changelog](https://github.com/fastlane/fastlane/blob/master/CHANGELOG.latest.md)
- [Commits](https://github.com/fastlane/fastlane/compare/fastlane/2.234.0...fastlane/2.235.0)

---
updated-dependencies:
- dependency-name: fastlane
  dependency-version: 2.235.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:34 +00:00
dependabot[bot]
d3347333b2
build(deps-dev): bump @types/react from 19.2.14 to 19.2.15 in /web (#72)
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 19.2.14 to 19.2.15.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-version: 19.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:29 +00:00
dependabot[bot]
8691c8a205
build(deps-dev): bump aws-cdk from 2.1124.1 to 2.1125.0 in /infra (#71)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1124.1 to 2.1125.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1125.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1125.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:26 +00:00
dependabot[bot]
b23c4be81c
build(deps): bump react-native-paper from 5.15.2 to 5.15.3 in /mobile (#70)
Bumps [react-native-paper](https://github.com/callstack/react-native-paper) from 5.15.2 to 5.15.3.
- [Release notes](https://github.com/callstack/react-native-paper/releases)
- [Commits](https://github.com/callstack/react-native-paper/compare/v5.15.2...v5.15.3)

---
updated-dependencies:
- dependency-name: react-native-paper
  dependency-version: 5.15.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-30 04:33:20 +00:00
Adam Moussa
ae3ad9d823 fix: CORS, JWT auth, useBlocker crash, and auto-migration for production deploy
Some checks failed
Deploy / Deploy to AWS (push) Has been cancelled
- Add CloudFront origin to API Gateway CORS preflight and .NET CORS policy
- Replace HttpMethod.ANY with explicit methods so OPTIONS preflight doesn't
  hit the JWT authorizer (was causing 403 on all API calls)
- Return Cognito ID token instead of access token from auth callback
  (access tokens lack the aud claim required by API Gateway JWT authorizer)
- Add CloudFront callback URI to allowed redirect list
- Remove identity_provider=Google from login URL to show Cognito hosted UI
- Replace useBlocker (requires data router) with state-based navigation guard
  to fix crash on AdminWorkspace with BrowserRouter
- Add auto-migration on Lambda cold start
- Enable Swagger in production
2026-05-27 19:20:29 -04:00
Adam Moussa
da783d48cd fix(web): restore WEB-C1/M4 fixes reverted by rebase conflict resolution
Some checks failed
Deploy / Deploy to AWS (push) Waiting to run
Deploy Mobile (iOS) / Build & Upload to TestFlight (push) Has been cancelled
- client.ts: localStorage → sessionStorage (WEB-C1 critical fix)
- proposals.ts: re-add 'Other' to ServiceCategory (WEB-M4)
- ProposalListPage.tsx: STATUS_COLORS → STATUS_CHIP_STYLES (visual design)
2026-05-27 18:21:03 -04:00
Adam Moussa
f9081fabf4 docs: Phase 6 cleanup — update AUDIT-REPORT, README, remove stale docs
- AUDIT-REPORT.md: mark all Phase 6 findings fixed (API-M2/M5/M7/M9/M10/M12/M13,
  WEB-M3/M4/M8/M9/M11, LAM-M2/M3/M6/M9, INF-M1/M2/M9), update test count to 149
- README.md: Function URL NONE→AWS_IAM, add Testing and Security sections,
  expand CI table with test jobs, note SQS encryption/OpenSearch VPC/access logging
- Remove stale session docs (AUDIT-2026-05-20, HANDOFF, RETROSPECTIVE, CHATGPT prompt)
- Add .claude/agents/ to .gitignore
- Remove empty-state placeholder from SimilarProposalsPanel
2026-05-27 18:18:44 -04:00
Adam Moussa
ab9569d7a9 test: add ProposalNumberGenerator, LineItemService state guard, and API client interceptor tests
- ProposalNumberGenerator tests (8 tests): format validation (SHI-YYYY-NNNN),
  sequence incrementing, revision skipping, year boundary isolation, uniqueness,
  zero-padding, high sequence rollover. Uses SQLite in-memory with Postgres
  function stubs to support ExecuteSqlRawAsync.

- LineItemService state guard tests (18 tests): verifies line items cannot be
  created/bulk-updated/deleted on Approved or Sent proposals (QA-C2), confirms
  operations succeed on InReview and Revised statuses, validates
  KeyNotFoundException on missing proposals, verifies audit logging.

- API client interceptor tests (14 tests): request interceptor attaches Bearer
  token from sessionStorage (WEB-C1), handles missing/malformed token data,
  response interceptor dispatches Redux logout on 401 (WEB-M2), returns friendly
  messages for 403/404, extracts server error details, handles network errors.

- DbContextFactory updated to suppress InMemoryEventId.TransactionIgnoredWarning
  so BulkUpdateAsync tests work with in-memory provider.

- Added SqliteDbContextFactory for tests requiring relational features.

- Added Microsoft.EntityFrameworkCore.Sqlite to test project dependencies.

Total: 104 .NET tests (was 77), 26 web tests (was 12). CI already wired.
2026-05-27 18:18:44 -04:00
Adam Moussa
8d73e66a17 fix(api): API-M2, M5, M7, M9, M10, M12, M13 — Medium audit findings
- API-M2: Add comment for fail-loud auth config guard (already implemented)
- API-M5: Add FluentValidation validators for VendorProposal, GeneratedPdf,
  and SimilarReference DTOs; move request records to Application DTOs
- API-M7: Add AsNoTracking() to all read-only queries in ProposalService,
  LineItemService, AdminController, UsersController, FilesController
- API-M9: Log stderr from dev PDF generation instead of returning to client
- API-M10: Return generic "Authentication service unavailable" in auth
  callbacks instead of leaking Cognito/DevMode configuration state
- API-M12: Enrich audit logging with before/after values for status changes,
  proposal edits, and line item operations using structured JSON
- API-M13: Log previous role alongside new role on user role changes in
  both UsersController and Cognito-synced role updates in AuthController
2026-05-27 18:18:44 -04:00
Adam Moussa
15570d24db docs: update AUDIT-REPORT.md for WEB-M3, M4, M8, M9, M11 fixes 2026-05-27 18:18:44 -04:00
Adam Moussa
51ca6df403 fix(web): WEB-M3, M4, M8, M9, M11 — scope validation, category alignment, dashboard errors, line item skeleton, return-to-review
- WEB-M3: Add minimum length validation (10 chars) on scope of work field
  with inline MUI error message
- WEB-M4: Add 'Other' to shared ServiceCategory contract to align with
  API enum (already present in frontend and backend)
- WEB-M8: Show error alert with retry button instead of misleading zeros
  when dashboard stats fetch fails (both dispatcher and admin dashboards)
- WEB-M9: Add MUI Skeleton loading state for line items in admin workspace
- WEB-M11: Wire 'Return to Review' button on approved proposals — backend
  supports Approved->InReview transition, API client already had the method
2026-05-27 18:18:44 -04:00
Adam Moussa
669e9c0e43 fix(lambdas): LAM-M2, M3, M6, M9 — prompt injection, PDF size check, numeric validation, API key TTL
LAM-M2: Add sanitize_user_text() to suggestions Lambda that strips common
prompt injection patterns (blocklist + delimiter neutralisation) before
including user-supplied text in Bedrock prompts.

LAM-M3: Add file size check in pdf-extract before downloading — rejects
PDFs over 50 MB with a logged warning and ValueError.

LAM-M6: Add validate_line_item_numerics() to suggestions Lambda that
rejects Bedrock-generated line items with negative values, NaN/Inf, or
amounts exceeding $10M ceiling.

LAM-M9: Replace indefinite API key cache with 5-minute TTL in all four
Lambdas (suggestions, pdf-extract, pdf-generate, library-ingest) so
rotated Secrets Manager values take effect promptly.
2026-05-27 18:18:44 -04:00
Adam Moussa
8da87e9301 fix(infra): scope Bedrock model ARN, AOSS permissions, require deploy approval (INF-M1, M2, M9)
INF-M1: Replace wildcard anthropic.claude-* foundation-model ARN with the
specific cross-region inference profile ARN and its backing foundation model.
Both suggestions and pdf-extract Lambdas use us.anthropic.claude-sonnet-4-5-20250929-v1:0.

INF-M2: Replace aoss:* data access policy permissions with scoped actions.
KB role gets DescribeCollectionItems/CreateCollectionItems/UpdateCollectionItems
on collection and DescribeIndex/ReadDocument/WriteDocument on indexes.
Index creator gets CreateIndex/DescribeIndex/WriteDocument plus collection describe/create.

INF-M9: Change --require-approval never to --require-approval broadening in
infra/package.json deploy script so IAM/security changes require manual
confirmation during local development.
2026-05-27 18:18:44 -04:00
Adam Moussa
8212c48d1e docs: update CLAUDE.md audit status for Phase 5 2026-05-27 18:18:44 -04:00
Adam Moussa
af4ba1bfb7 docs: update AUDIT-REPORT.md for Phase 5 Medium fixes
17 Medium findings fixed across API, Web, Lambda, and Infra:
- API: M3, M4, M6, M8, M11, M14
- Web: M2, M5, M6, M7, M10, M13
- Lambda: M1, M5, M8
- Infra: M5, M8
CI pipeline now runs all 108 tests (dotnet, vitest, pytest)
2026-05-27 18:18:44 -04:00
Adam Moussa
71a5b56ee9 fix: Lambda medium findings (LAM-M1, M5, M8)
LAM-M1: Add event/record validation at handler entry for all 4 SQS-triggered
Lambdas. Validates Records key exists and is a non-empty list, checks each
record has a body key, and catches malformed JSON separately to add to
batchItemFailures.

LAM-M5: Change logger.error() to logger.exception() inside all except blocks
across pdf-extract, pdf-generate, suggestions, and library-ingest handlers
so stack traces are included in CloudWatch logs for debugging.

LAM-M8: Add _validate_s3_key() to pdf-extract, pdf-generate, and
library-ingest that strips path traversal sequences (../, ..\), collapses
double slashes, and rejects keys with disallowed characters via regex.
2026-05-27 18:18:44 -04:00
Adam Moussa
57122ee702 fix: web medium findings (WEB-M2, M5, M6, M7, M10, M13)
WEB-M2: 401 interceptor now dispatches Redux logout action to clear
auth state, not just localStorage.

WEB-M5: CreateProposalRequest uses typed ServiceCategory and Priority
unions aligned with shared/api-contracts contract.

WEB-M6: Vendor PDF upload validates MIME type (application/pdf),
file extension (.pdf), and max size (25 MB) before accepting.

WEB-M7: AdminWorkspace shows error Alert with retry button when
proposal fetch fails, instead of rendering empty workspace.

WEB-M10: State transition buttons (Approve, Send, Revise) are
disabled with explanatory tooltips when proposal is not in the
correct state for that transition.

WEB-M13: ToastContainer moved inside BrowserRouter so toasts
render in the correct React tree context.
2026-05-27 18:18:44 -04:00
Adam Moussa
42fe0823b0 fix: API medium findings (API-M3, M4, M6, M8, M11, M14)
- API-M3: Add dispatcher ownership check on line item reads
- API-M4: Add dispatcher ownership check on PDF endpoints
- API-M6: Add 25 MB file size validation on presigned upload URLs
- API-M8: Wrap BulkUpdate delete-all/insert-all in explicit transaction
- API-M11: Replace silent catch blocks with logged exceptions in
  LineItemService and ProposalService
- API-M14: Validate dev signing key is present (from user-secrets or
  env vars) instead of using null-forgiving operator
2026-05-27 18:18:44 -04:00
Adam Moussa
fcdc46c136 fix: infra medium findings (INF-M5, INF-M8)
INF-M5: Add enforceSSL: true to all S3 buckets (uploads, generated,
library, web site) to require HTTPS-only access via bucket policy.

INF-M8: Pin all reusable GitHub Actions workflow references from @main
to commit SHA c040bfaa for supply chain security.
2026-05-27 18:18:44 -04:00
Adam Moussa
01fe003a6d fix: wire test suites into CI, fix stale tests from Phase 1-2 fixes
- Add web-test job (vitest) and python-test job (pytest) to CI workflow
- dotnet reusable workflow already runs tests by default
- Update InternalApiKeyMiddleware tests for API-C1/API-H1 fixes:
  invalid key now returns 401 (not pass-through), valid key on
  disallowed path returns 403
- Fix suggestions test: include status field for LAM-H4 idempotency guard
- Total: 108 tests (77 .NET, 12 web, 19 Python) all passing
2026-05-27 18:18:44 -04:00
Adam Moussa
9c04ba4756 fix: resolve test compile errors from merge, update AUDIT-REPORT.md
Fix CreateProposalRequest constructor calls (missing PoNumber param)
and ProposalService constructor (missing ILogger param) that diverged
when test-bootstrap and api-hardening worktrees merged.

Mark all Critical and High findings as fixed in AUDIT-REPORT.md with
remediation status for each phase.
2026-05-27 18:18:44 -04:00
Adam Moussa
d21b1c5edb test: bootstrap test infrastructure with critical coverage (QA-C1 through QA-C6)
QA-C1: Create xUnit test project, add to solution, wire dependencies
- api/tests/ProposalSystem.Tests with xUnit + FluentAssertions + NSubstitute
- InMemory EF Core provider for isolated DB tests

QA-C2: Proposal state machine transition tests (16 tests)
- Valid: InReview->Approved, Approved->Sent, Sent->Revised
- Invalid: InReview->Sent, Approved->Revised, Draft->Approved, etc.
- Edge cases: idempotency, missing line items, revision line item copying
- Audit and job publisher verification

QA-C3: Authorization attribute tests (16 tests)
- Controller-level [Authorize] on all controllers except AuthController
- Role requirements: admins/sysadmins on admin actions
- Dispatcher exclusion from admin/sysadmin routes
- SysAdmin-only user management enforcement

QA-C4: InternalApiKeyMiddleware tests (8 tests)
- Valid key sets claims and calls next
- Invalid key passes through to JWT (no 401/403)
- Missing key/empty config disables middleware
- Documents API-C1 vulnerability (key works on any path)

QA-C5: ProtectedRoute and RoleGuard tests (12 tests, vitest)
- ProtectedRoute: renders children when authenticated, redirects when not
- RoleGuard: role-based access, dispatcher/admin/sysadmin enforcement
- authSlice: setUser, logout, expired token handling

QA-C6: Lambda SQS handler tests (19 tests, pytest)
- pdf-generate: batch processing, failure reporting, malformed body
- suggestions: batch processing, proposal-not-found skip, AI item preservation
- API key caching, retry helpers

Total: 107 tests (76 .NET + 12 web + 19 Python), all passing.
2026-05-27 18:18:44 -04:00
Adam Moussa
2017c0379e fix: API-H2 validate redirectUri, API-H6 add structured logging to services
API-H2: Validate redirectUri against an allowlist before exchanging the
authorization code with Cognito. Production URI is always allowed;
localhost is only allowed when Auth:DevMode is true.

API-H6: Inject ILogger<T> into ProposalService and LineItemService.
Log state transitions (approve, send, revise) at Information level,
invalid state transition attempts at Warning level, and caught
exceptions (audit/job publisher failures) at Error level.
2026-05-27 18:18:44 -04:00
Adam Moussa
a74ac4945f fix: LAM-C1/INF-H1 require IAM auth on Function URL, INF-H3 restrict OpenSearch to VPC
LAM-C1/INF-H1: Change Function URL authType from NONE to AWS_IAM and
grant invokeUrl permission to all four caller Lambdas (suggestions,
pdf-extract, pdf-generate, library-ingest). Lambda HTTP clients will
need SigV4 signing as a follow-up.

INF-H3: Create OpenSearch Serverless VPC endpoint in private subnets
and update network policy from AllowFromPublic to SourceVPCEs, removing
public internet access to the vector search collection.
2026-05-27 18:18:44 -04:00
Adam Moussa
67b4732395 fix: WEB-C1 move JWT to sessionStorage, complete mutation error handling
- WEB-C1 (Critical): Replace all localStorage token operations with
  sessionStorage in authSlice.ts and client.ts. Tokens now clear when
  the browser tab closes, reducing the XSS token-theft window.
  httpOnly cookie migration documented as follow-up.
- WEB-M2: 401 interceptor now dispatches Redux logout() before
  redirect so auth state stays consistent with cleared storage.
- WEB-H5/H6: Add onError toast handlers to sendMutation,
  reviseMutation, and regenerateMutation in AdminWorkspace.
2026-05-27 18:18:44 -04:00
Adam Moussa
4f1271eb50 audit: fix all Critical and High security/reliability issues across monorepo
6-domain audit (API, web, mobile, lambdas, infra, QA) with fixes:

API security: scope internal API key middleware to allowed paths only,
return 401 on invalid key instead of falling through, remove unvalidated
JWT code path, sanitize error messages, add UpdateProposal validator,
remove status field from UpdateProposalRequest to prevent over-posting,
log swallowed exceptions in ProposalService.

Infrastructure: enforce SSL on all S3 buckets, encrypt SQS queues,
enable optional MFA on Cognito, add API Gateway access logging.

Lambdas: fix _retry_request undefined variable across all 4 Lambdas,
re-raise exceptions in pdf-extract/pdf-generate instead of swallowing,
add idempotency guard to suggestions Lambda.

Web: add ErrorBoundary, add auth loading state to ProtectedRoute,
add mutation error toasts in AdminWorkspace, fix dead Cognito link.

Mobile: add mutex to offline queue processing, distinguish permanent
vs retryable failures, register all screens for both roles, log sync
errors.

Swagger/OpenAPI: add Swashbuckle with JWT bearer security definition,
add ProducesResponseType attributes to key endpoints.

Includes AUDIT-REPORT.md with complete findings and CLAUDE.md project
instructions.
2026-05-27 18:18:44 -04:00
Adam Moussa
d15f6bfb95 workspace: sticky panels, action bar polish, breadcrumb nav, line item UX improvements 2026-05-27 18:18:44 -04:00
Adam Moussa
0c8ab31282 pages: users empty state card, form max-width, table display improvements 2026-05-27 18:18:44 -04:00
Adam Moussa
cfee6690c0 login: audit styling — gradient, card, button colors, descriptions 2026-05-27 18:18:39 -04:00
Adam Moussa
a6091344da dashboard: audit KPI styling, secondary context lines, page title consistency 2026-05-27 18:18:35 -04:00
Adam Moussa
2e20e7ad99 sidebar: audit styling updates, responsive collapse at 1200px/900px 2026-05-27 18:18:30 -04:00
Adam Moussa
f7b4ab6f93 theme: apply full UX audit token pass (palette, typography, shapes, component overrides) 2026-05-27 18:18:27 -04:00
Adam Moussa
d27cc2e528 style: switch to subtle tinted chips with borders, reduce urgent row prominence 2026-05-27 18:18:27 -04:00
Adam Moussa
cef0b611ba topbar: update avatar color, add DEV environment indicator pill 2026-05-27 18:18:24 -04:00
Adam Moussa
b21e5db08a Update login page colors to match refined app palette 2026-05-27 18:18:24 -04:00
Adam Moussa
3e131dbd00 Add worktrees to gitignore 2026-05-27 18:18:24 -04:00
Adam Moussa
b507bb0c28 Replace MUI semantic chip colors with custom status/priority palette 2026-05-27 18:18:24 -04:00
Adam Moussa
83e1a7948e Fix nested tbody in proposal tables: use Fragment instead of Box component="tbody" 2026-05-27 18:18:12 -04:00
Adam Moussa
b43bb64fff Consolidate hardcoded colors in Topbar and Sidebar to match refined palette 2026-05-27 18:18:12 -04:00
Adam Moussa
837aaa3db3 Update theme: Inter font, flat AppBar, refined palette, 6px radius, polished component defaults 2026-05-27 18:17:48 -04:00
Adam Moussa
594d3395c6 Add UX improvements: clickable KPIs, status tabs, revision grouping, workspace restructure, form sections
Medium-effort improvements:
- Shrink KPI cards and make each clickable (navigates to filtered list)
- Role-specific KPI labels (admin: All Proposals/Pending Review; dispatcher: Total Submitted/In Review)
- Reorder sidebar nav per role (admins see Admin section first)
- Add WO# and Priority columns to Dashboard recent proposals table
- Replace "View All" with "View All Proposals" button with arrow icon
- Add Age column to admin queue with color-coded staleness (>2d orange, >5d red)

Heavy-lift improvements:
- Status tabs on All Proposals page (replace status dropdown with All/In Review/Approved/Sent/Revised tabs)
- Group proposal revisions in tables (expand/collapse, latest shown by default)
- Collapsible left panel in admin workspace (chevron toggle, center panel expands to fill)
- Sticky action bar with total display, item count, vendor cost, compact unsaved-changes chip
- Restructure proposal form into 3 card sections (Job Details, Site & Location, Work Details)
- Disabled-submit helper text showing missing required fields
- Compact status timeline with timestamps under completed steps
- Status explanation below timeline (e.g., "Awaiting admin pricing and approval")
2026-05-27 18:17:48 -04:00
Adam Moussa
d583f99f5b Update session handoff with current state and remaining tasks
Consolidates all 7 commits (4 prior + 3 this session), organizes
remaining UX review items by effort level, and documents outstanding
infrastructure and mobile tasks.
2026-05-27 18:17:48 -04:00
Adam Moussa
85bed9a161 Apply UX quick wins from external review
- Replace $0.00 with "Not priced" via formatBidAmount helper
- Consistent login buttons with role descriptions
- Context-aware empty states (filter mismatch vs no data)
- Clear Filters button on proposal list and admin dashboard
- Rename "Regenerate" to "Regenerate Suggested Line Items"
- Add tooltips explaining disabled Save/Approve buttons
- Replace "RAG engine" jargon with plain language
- Improve User Management placeholder with Cognito guidance
- Add Puppeteer screenshot script for all roles/pages
2026-05-27 18:17:48 -04:00
Adam Moussa
ef052a81ac Add role-aware dashboard stats and recent proposals
GetStatsAsync now returns global counts for admins/sysadmins instead of
filtering by submitter. Dashboard recent proposals query uses mine=false
for admins so they see all proposals, not just their own.
2026-05-27 18:17:48 -04:00