# Progress — PEDW FrontEnd ## Completed / evidenced milestones - Bilingual routing structure is established with extensive Welsh rewrites and locale namespace mapping. - Next-auth + Prisma SQL Server persistence is integrated for user/session lifecycle. - Broad API surface exists for search, case, portal, admin, and file/document operations. - CRM/relay hash pattern is implemented across many endpoint handlers. - Recent shipped updates focused on: - search/case back-navigation and breadcrumb behavior, - DNS/view-all navigation logic, - preferred-language handling for notify template selection, - PDF formatting/hyperlink fixes, - upload validation character updates. ## Work in progress signals - Ongoing iterative fixes in breadcrumb/case-summary flows suggest navigation consistency is still being tuned. - Mixed proxy/non-proxy endpoint implementations continue to evolve in parallel. - Priority 1 refactor plan execution started for `actions/index.js` split (Phase 1 foundation complete). ## Planned / partially implemented (inferred from code state) - Partial migration or coexistence of deployment/runtime patterns (Next runtime plus custom server artifacts). - Continued refinement of document/email workflow behavior (template/language and formatting quality). - Prioritized structural refactor backlog documented in `memory-bank/refactor-backlog.md`. ## Known technical debt - `actions/services/legacyActionsService.js` still holds broad domain wrappers after Phase 1 extraction (core helpers now separated). - Significant duplication of token/hash/relay logic across endpoint files. - Inconsistent security/hash guard enforcement in some file routes. - Sparse automated test coverage (`tests/` currently empty). - Verbose logging in sensitive flows (auth/email/actions/file) increases privacy risk. ## Latest update (2026-03-12) - Branch `0000-update-actions-monolith` created from development branch for Priority 1 refactor implementation. - `actions/index.js` reduced to a compatibility barrel. - New core helper modules added under `actions/core/`: - `env.js` - `logger.js` - `hash.js` - `token.js` - `headers.js` - Existing action wrappers moved to `actions/services/legacyActionsService.js` and continue to be exported via the barrel for compatibility. - `actions/clients/` scaffolded for upcoming client extraction phase. - Phase 2 service grouping completed with dedicated service files and `actions/services/index.js` barrel. - Export parity check confirms grouped service modules cover all legacy exported action names. - Phase 3 migration started by moving selected high-churn consumers and representative endpoint handlers to direct `actions/services/*` and `actions/core/*` imports. - Phase 4 hardening baseline added with new guard helpers and redacted logging, adopted in selected notify/login/contact API handlers. - Additional Priority 1 consumer migration pass completed for high-use portal/form/representation helpers: - Updated direct service/core imports in: - `components/admin/tabs/documents.js` - `components/admin/tabs/storage.js` - `components/admin/utils/serverside.js` - `components/case/documents.js` - `components/case/representation/representationComplete.js` - `components/case/representation/representationElements.js` - `components/elements/index.js` - `components/myportal/awaitingsubmissionfromblob.js` - `components/myportal/topthree.js` - `components/myportal/topthree_reps.js` - `components/utils/index.js` - `lib/myportal/loadMyPortalAppealPage.js` - `lib/newappeal/loadNewAppealPage.js` - Additional Priority 1 consumer migration pass completed for view-all/search/unsubscribe flows: - Updated direct service/core imports in: - `components/myportal/viewall.js` - `components/search/addresssearchresults.js` - `pages/unsubscribe/[watchlistid].js` - `pages/unsubscribeall/[watchlistid].js` - Broad `actions` barrel import count reduced again; remaining non-comment usages are now concentrated in selected `pages/api/endpoint/*` and `pages/api/file/*` handlers. - Additional Priority 1 endpoint/file proxy migration chunk completed: - Updated imports in: - `pages/api/endpoint/getmylpacases_api.js` - `pages/api/endpoint/getbasicdnssearchpaged_api.js` - `pages/api/endpoint/getsearchdocumentdetailspaged_api.js` - `pages/api/endpoint/getbasicsearchpaged_api.js` - `pages/api/file/getawaitingsubmissionfromblobproxy.js` - `pages/api/file/getrepsblobproxy.js` - `pages/api/file/getbloblistproxy.js` - `pages/api/file/createappealcompletemessageproxy_api.js` - Migrated from broad `../../../actions` imports to focused `actions/core/*` + service imports. - Removed duplicated local hash helper in `getmylpacases_api.js` and reused `actions/core/hash`. - Broad `actions` import scan now reports only comment-only references (no active broad imports in `.js` files). - Lint check re-run outcome unchanged: `next lint` fails due legacy/unsupported ESLint options in repo tooling config (not introduced by this refactor pass). ## Handover update (2026-03-13) - Priority 1 import-migration wave has been checked in and completed via pull request. - Recent migration commits captured in this wave: - `f0202bb` - `fa98535` - `bef8f25` - Active broad `.../actions` imports are now eliminated from live `.js` code paths. - Next refactor phase will begin on a **new branch** and focus on splitting `actions/services/legacyActionsService.js` into smaller direct implementation modules. - Recommended decomposition order for the new branch: 1. reference/search extraction 2. portal/document extraction 3. compatibility layer slimming + dead wrapper removal ## Latest update (2026-03-13 — Phase 5 kickoff) - New branch created from `SIPS-Development`: `TASK21997-phase5-legacyactions-split`. - Completed first Phase 5 decomposition slice from `legacyActionsService`: - Added `actions/services/searchDirectService.js` - Added `actions/services/referenceDataDirectService.js` - Updated `actions/services/searchService.js` to source from `searchDirectService` - Updated `actions/services/referenceDataService.js` to source from `referenceDataDirectService` - Compatibility approach preserved: public grouped service exports and function signatures remain unchanged for callers. - Validation status unchanged: - `npm run lint` still fails due pre-existing Next/ESLint option incompatibility in repo tooling configuration. ## Latest update (2026-03-13 — Phase 5 document slice) - Continued on branch `TASK21997-phase5-legacyactions-split`. - Completed second decomposition slice from `legacyActionsService`: - Added `actions/services/documentDirectService.js` - Updated `actions/services/documentService.js` to source from `documentDirectService` - Compatibility approach preserved: - grouped service export names/signatures unchanged for consumers. - Verification: - service import scan now shows remaining legacy-backed grouped modules are: - `portalService`, `accountService`, `caseService`, `adminService`, `notifyService`, `integrationService` - `npm run lint` passes with warnings only (no blocking errors). ## Latest update (2026-03-13 — Phase 5 completion) - Continued decomposition and completed all remaining slices on `TASK21997-phase5-legacyactions-split`: - portal direct extraction - account + case direct extraction - admin + integration + notify direct extraction - legacy cleanup/removal - New direct modules now in place: - `portalDirectService.js` - `accountDirectService.js` - `caseDirectService.js` - `adminDirectService.js` - `integrationDirectService.js` - `notifyDirectService.js` - `actions/services/legacyActionsService.js` removed after import parity checks. - Validation evidence: - `actions/services` import scan: zero `./legacyActionsService` references - `npm run lint`: warnings only, no blocking errors - `npm run build`: successful production build ## Latest update (2026-03-13 — Phase 6 post-Phase-5 hardening, in progress) - Branch created from `SIPS-Development`: `TASK21998-phase6-postphase5-hardening`. - Added focused parity checks for grouped/direct service stability and service index barrel stability: - `tests/phase6/service-parity.test.cjs` - validates grouped service import/export parity across: - search, referenceData, document, portal, account, case, admin, integration, notify - validates `actions/services/index.js` export list stability/order. - Added shared service error helper: - `actions/services/httpServiceUtils.js` - centralizes common `consoleLogger + return error.response` and `ErrResponse` shape patterns. - Applied low-risk duplication reduction in direct services (no signature/shape changes intended): - `searchDirectService.js` - `referenceDataDirectService.js` - `caseDirectService.js` - `adminDirectService.js` - Logging cleanup/redaction-oriented hardening (sensitive-flow noisy logs removed): - removed debug `console.log` statements from: - `searchDirectService.js` - `documentDirectService.js` - `portalDirectService.js` - `caseDirectService.js` - `adminDirectService.js` ### Validation snapshot (Phase 6) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `npm run lint` -> **warnings only** (same pre-existing warnings) ### Decision captured (Phase 6) - Agreed approach: keep parity guard tests **and** add focused behavioural unit tests in the current refactor stream (instead of deferring all behavioural checks to long-term roadmap). - Implemented now: - `tests/phase6/service-behaviour.test.cjs` - mocked-axios behavioural checks for critical success/error contracts across search/reference/case/admin direct services. - Wider behavioural expansion remains on roadmap for additional domains/functions. ### Targeted smoke snapshot (local dev server) - Search flow: - `GET /searchresults` (EN/CY) -> **500** in local env due existing serialization issue (`initialState.search.searchString` undefined in SSR payload), observed in `/tmp/phase6-dev.log`. - `GET /advancedsearch` and `GET /cy/advancedsearch` -> **200** - Case flow: - `GET /case` and `GET /cy/case` -> **200** - My Portal flow (negative-path): - `GET /myportal` and `GET /cy/myportal` -> **307** redirect to `/auth/signin` (expected unauthenticated behavior) - Document flow (negative-path): - `GET /api/file/getbloblistproxy?container=test&casefolderID=test` -> **400** - Notify flow (negative-path): - `POST /api/email/notify` with `{}` -> **400** ## Latest update (2026-03-13 — Phase 8 hardening slice) - New branch created from `origin/SIPS-Development` with work item prefix: - `TASK22017-phase8-hardening-slice` - Hardened four sensitive API handlers with minimal reversible guards: - `pages/api/file/deleteblobcase.js` - `pages/api/file/deleteblobrep.js` - `pages/api/file/createappealcompletemessage_api.js` - `pages/api/endpoint/getportallogin_api.js` - Scope delivered: - re-enabled/enforced hash checks where bypassed/commented - standardized early 400 negative paths for missing/invalid required query inputs - reduced noisy sensitive-path logging and routed errors through `consoleLogger` - preserved function signatures and existing response-shape contracts - Consumer parity updates (required to preserve behaviour after hash enforcement): - `actions/services/documentDirectService.js` - append hash for delete-blob-case/delete-blob-rep calls - `actions/services/portalDirectService.js` - append hash for create-appeal-complete-message call (hash path preserved to existing API contract) - Added focused tests: - `tests/phase8/service-behaviour.test.cjs` - covers negative paths for all 4 handlers (missing/invalid hash and missing key params as applicable) - includes one happy-path check for `getportallogin_api` with valid hash via mocked dependencies ### Validation snapshot (Phase 8) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing react-hooks dependency warnings; no new lint errors) ### Manual HTTP checks (Phase 8) - Local dev server on `http://localhost:3001`. - Negative-path checks: - `GET /api/file/deleteblobcase?...` missing hash -> **400** - `GET /api/file/deleteblobcase?...&hash=bad` -> **400** - `GET /api/file/deleteblobrep?...` missing hash -> **400** - `GET /api/file/deleteblobrep?...&hash=bad` -> **400** - `GET /api/file/deleteblobrep?...` missing `repfile` -> **400** - `GET /api/file/createappealcompletemessage_api?...` missing hash -> **400** - `GET /api/file/createappealcompletemessage_api?...&hash=bad` -> **400** - `GET /api/file/createappealcompletemessage_api?...` missing `tempcaseref` -> **400** - `GET /api/endpoint/getportallogin_api?...` missing hash -> **400** - `GET /api/endpoint/getportallogin_api?...&hash=bad` -> **400** - `GET /api/endpoint/getportallogin_api?...` missing `emailAddress` -> **400** - Valid-hash spot-check: - `GET /api/endpoint/getportallogin_api?...&hash=` reached handler with valid hash but returned **400** from upstream relay/CRM call in local environment (expected environmental dependency risk, not hash-guard bypass). ## Latest update (2026-03-13 — Phase 9 hardening slice) - New branch created from `origin/SIPS-Development` with work item prefix: - `TASK22019-phase-9-hardening` - Hardened four additional sensitive file handlers with minimal reversible changes: - `pages/api/file/createrepcompletemessage_api.js` - `pages/api/file/upload.js` - `pages/api/file/uploadsinglefile.js` - `pages/api/file/setupcontainer.js` - Scope delivered: - re-enabled/enforced hash validation where bypassed/commented - added/standardized early 400 negative paths for missing/invalid hash and missing key parameters - reduced noisy logging in sensitive file-upload/message paths - preserved handler signatures and external response-shape contracts - Consumer parity updates: - `actions/services/portalDirectService.js` - append hash for `createrepcompletemessage_api` call - `actions/services/documentDirectService.js` - append hash for `upload` and `uploadsinglefile` calls - Added focused tests: - `tests/phase9/service-behaviour.test.cjs` - covers negative paths across all 4 phase-9 handlers ### Validation snapshot (Phase 9) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing react-hooks warnings; no new lint errors) ### Manual HTTP checks (Phase 9) - Negative-path checks on `localhost:3000`: - `GET /api/file/createrepcompletemessage_api?...` missing hash -> **400** - `GET /api/file/createrepcompletemessage_api?...&hash=bad` -> **400** - `POST /api/file/upload` missing hash -> **400** - `POST /api/file/upload?hash=bad` -> **400** - `POST /api/file/uploadsinglefile` missing hash -> **400** - `POST /api/file/uploadsinglefile?hash=bad` -> **400** - `GET /api/file/setupcontainer?ident=...` missing hash -> **400** - `GET /api/file/setupcontainer?ident=...&hash=bad` -> **400** - `GET /api/file/setupcontainer?hash=bad` (missing ident) -> **400** - Valid-hash happy-path spot-check: - Completed using `.env.local` runtime key: `POST /api/file/uploadsinglefile?hash=` -> **200** ### Rollback plan (Phase 9) 1. Revert the four hardened API handlers. 2. Revert direct-service hash append changes in `documentDirectService` and `portalDirectService`. 3. Remove `tests/phase9/service-behaviour.test.cjs` if full slice rollback required. 4. Re-run phase6/7/8/9 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 10 hardening slice) - Continued on branch: - `TASK22019-phase-9-hardening` - Hardened four additional sensitive file handlers with minimal reversible changes: - `pages/api/file/getawaitingsubmissionfromblob.js` - `pages/api/file/getprogressobjblob.js` - `pages/api/file/getbloblist.js` - `pages/api/file/getrepsblob.js` - Scope delivered: - added explicit early 400 handling for missing/empty required inputs (`container`, `casefolderID` where applicable, `hash`) - standardized hash-mismatch negative-path checks to early return 400 - removed legacy/noisy commented debug blocks from touched handlers - preserved existing handler signatures and response-shape contracts - Caller parity impact: - no new caller changes required in this slice because direct-service consumers already append hash for these APIs. - Added focused tests: - `tests/phase10/service-behaviour.test.cjs` - covers negative paths for all 4 selected phase-10 handlers - includes one valid-hash contract-preserving happy-path check (`getbloblist` via mocked dependencies) ### Validation snapshot (Phase 10) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing react-hooks warnings; no new lint errors) ### Manual HTTP checks (Phase 10) - Negative-path checks on `localhost:3000`: - `GET /api/file/getawaitingsubmissionfromblob?container=test` (missing hash) -> **400** - `GET /api/file/getprogressobjblob?container=test&casefolderID=case-1` (missing hash) -> **400** - `GET /api/file/getbloblist?container=test&casefolderID=case-1` (missing hash) -> **400** - `GET /api/file/getrepsblob?container=test&casefolderID=case-1` (missing hash) -> **400** - Valid-hash happy-path spot-check: - `GET /api/file/getbloblist?container=test&casefolderID=case-1&hash=` -> **500** - expected due local storage/upstream dependency constraints, while confirming hash gate is no longer the failing check. ### Rollback plan (Phase 10) 1. Revert the four hardened API handlers. 2. Remove `tests/phase10/service-behaviour.test.cjs` if full phase-10 rollback required. 3. Re-run phase6/7/8/9/10 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 11 hardening slice) - Continued on branch: - `TASK22019-phase-9-hardening` - Hardened three additional sensitive file handlers with minimal reversible changes: - `pages/api/file/getbloblist.js` - `pages/api/file/deleteblob.js` - `pages/api/file/deleteawaitingsubmissionfromblob.js` - Scope delivered: - added explicit early 400 handling for missing/empty required query inputs (`container`, `casefolderID`, `blobname`, `hash` as applicable) - standardized hash-mismatch negative-path checks to early return 400 - removed legacy/noisy commented debug traces in touched handlers - preserved existing handler signatures and response-shape contracts - Caller parity impact: - no new caller changes required in this slice; direct-service consumers already pass expected query/hash data. - Added focused tests: - `tests/phase11/service-behaviour.test.cjs` - covers negative paths for selected phase-11 handlers - includes one valid-hash contract-preserving happy-path check (`getbloblist` via mocked dependencies) ### Validation snapshot (Phase 11) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `npm run lint` -> **warnings only** (pre-existing react-hooks warnings; no new lint errors) ### Manual HTTP checks (Phase 11) - Negative-path checks on `localhost:3000`: - `GET /api/file/getbloblist?container=test&casefolderID=case-1` (missing hash) -> **400** - `GET /api/file/deleteblob?container=test&casefolderID=case-1&blobname=file.pdf` (missing hash) -> **400** - `GET /api/file/deleteawaitingsubmissionfromblob?container=test&casefolderID=case-1&blobname=file.pdf` (missing hash) -> **400** - `GET /api/file/deleteblob?container=test&casefolderID=case-1&hash=bad` (missing blobname/invalid hash) -> **400** - Valid-hash happy-path spot-check: - `GET /api/file/getbloblist?container=test&casefolderID=case-1&hash=` -> **500** - expected due local storage/upstream dependency constraints, while confirming hash gate is no longer the failing check. ### Rollback plan (Phase 11) 1. Revert the three hardened API handlers. 2. Remove `tests/phase11/service-behaviour.test.cjs` if full phase-11 rollback required. 3. Re-run phase6/7/8/9/10/11 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 12 hardening slice) - Continued on branch: - `TASK22019-phase-9-hardening` - Hardened four additional sensitive handlers with minimal reversible changes: - `pages/api/file/downloadblob.js` - `pages/api/file/getbloblistproxy.js` - `pages/api/file/getrepsblobproxy.js` - `pages/api/file/getawaitingsubmissionfromblobproxy.js` - Scope delivered: - added explicit early 400 handling for missing/empty required query inputs (`container`, `casefolderID`, `blobname`, `hash` as applicable) - standardized hash-mismatch negative-path checks for `downloadblob` - preserved existing function signatures and response-shape contracts - Added focused tests: - `tests/phase12/service-behaviour.test.cjs` - covers negative paths for selected phase-12 handlers - includes one valid-hash contract-preserving happy-path check (`downloadblob` via mocked dependencies) ### Validation snapshot (Phase 12) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `npm run lint` -> **warnings only** (pre-existing react-hooks warnings; no new lint errors) ### Manual HTTP checks (Phase 12) - Negative-path checks on `localhost:3000`: - `GET /api/file/downloadblob?container=test&casefolderID=case-1&blobname=file.pdf` (missing hash) -> **400** - `GET /api/file/downloadblob?container=test&casefolderID=case-1&blobname=file.pdf&hash=bad` -> **400** - `GET /api/file/getbloblistproxy?casefolderID=case-1` (missing container) -> **400** - `GET /api/file/getrepsblobproxy` (missing container) -> **400** - `GET /api/file/getawaitingsubmissionfromblobproxy` (missing container) -> **400** - Valid-hash happy-path spot-check: - `GET /api/file/downloadblob?container=test&casefolderID=case-1&blobname=file.pdf&hash=` -> **500** - expected due local storage/upstream dependency constraints, while confirming hash gate is no longer the failing check. ### Rollback plan (Phase 12) 1. Revert the four hardened API handlers. 2. Remove `tests/phase12/service-behaviour.test.cjs` if full phase-12 rollback required. 3. Re-run phase6/7/8/9/10/11/12 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 13 hardening slice) - Continued on branch: - `TASK22019-phase-9-hardening` - Hardened four additional sensitive handlers with minimal reversible changes: - `pages/api/file/deleteblobcase.js` - `pages/api/file/deleteblobrep.js` - `pages/api/file/createcaseinvolvement_api.js` - `pages/api/file/createrepinvolvement_api.js` - Scope delivered: - added explicit early 400 handling for missing/empty required query/body inputs (`hash`, `contactid`, `incidentid` as applicable) - standardized hash-mismatch negative-path checks for delete-blob handlers - removed noisy body/query logging in involvement handlers - preserved existing function signatures and response-shape contracts - Added focused tests: - `tests/phase13/service-behaviour.test.cjs` - covers negative paths for selected phase-13 handlers - includes valid-hash/valid-body contract-preserving happy-path checks via mocked dependencies ### Validation snapshot (Phase 13) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `npm run lint` -> **warnings only** (pre-existing react-hooks warnings; no new lint errors) ### Manual HTTP checks (Phase 13) - Negative-path checks on `localhost:3000`: - `GET /api/file/deleteblobcase?container=test&casefolderID=case-1` (missing hash) -> **400** - `GET /api/file/deleteblobcase?container=test&casefolderID=case-1&hash=bad` -> **400** - `GET /api/file/deleteblobrep?container=test&casefolderID=case-1&repfile=r.pdf` (missing hash) -> **400** - `POST /api/file/createcaseinvolvement_api` with `{}` -> **400** - `POST /api/file/createrepinvolvement_api` with `{}` -> **400** - Valid-hash happy-path spot-check: - `GET /api/file/deleteblobcase?container=test&casefolderID=case-1&hash=` -> **500** - expected due local storage/upstream dependency constraints, while confirming hash gate is no longer the failing check. ### Rollback plan (Phase 13) 1. Revert the four hardened API handlers. 2. Remove `tests/phase13/service-behaviour.test.cjs` if full phase-13 rollback required. 3. Re-run phase6/7/8/9/10/11/12/13 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 14 client-hash signing fix) - Continued on branch: - `TASK22019-phase-9-hardening` - Fixed authenticated user-journey runtime error during new appeal flow where client-side hashing tried to use server-only `HASHKEY`. - Added authenticated server-side hash signer endpoint: - `pages/api/endpoint/gethash_api.js` - requires session (`getSession`), allow-lists supported API paths, returns `{ hash }`. - Updated direct services to request hash from server signer for browser calls, with server-side fallback only when `HASHKEY` exists: - `actions/services/documentDirectService.js` - `actions/services/portalDirectService.js` - Preserved existing API contracts and response shapes in file handlers. - Added focused tests: - `tests/phase14/service-behaviour.test.cjs` - covers signer endpoint negative paths + authenticated happy path. ### Validation snapshot (Phase 14) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (4/4) - `npm run lint` -> **warnings only** (pre-existing hook dependency warnings) ### Rollback plan (Phase 14) 1. Revert `pages/api/endpoint/gethash_api.js`. 2. Revert direct-service hash signer usage in `documentDirectService.js` and `portalDirectService.js`. 3. Remove `tests/phase14/service-behaviour.test.cjs` if rolling back full phase-14 slice. 4. Re-run phase6–phase14 tests + lint. ## Latest update (2026-03-13 — Phase 14 closeout follow-up) - Continued on branch: - `TASK22019-phase-9-hardening` - Completed follow-up hardening and contract-alignment after runtime verification: - `actions/services/accountDirectService.js` - `getPortalLogin` now uses authenticated signer endpoint (`/api/endpoint/gethash_api`) for browser-safe hash generation - retains server-only fallback to local `hashAPIPath` when `HASHKEY` is available - `pages/api/endpoint/gethash_api.js` - allow-list expanded for `/api/endpoint/getportallogin_api` - `pages/api/file/getrepsblob.js` - removed enforced `casefolderID` guard and argument pass-through to align with route contract (`/api/file/getrepsblob?container=...`) - `components/elements/index.js` - added missing `updateLinks` import from `components/utils` to resolve Quill runtime error - Tests updated: - `tests/phase7/service-behaviour.test.cjs` - updated `getPortalLogin` expectations for signer endpoint behavior - `tests/phase14/service-behaviour.test.cjs` - added allow-list coverage for signer path `/api/endpoint/getportallogin_api` ### Validation snapshot (Phase 14 follow-up) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing hook dependency warnings) ### Risks + mitigations (follow-up) - Risk: signer endpoint over-expansion could broaden hash issuance. - Mitigation: strict allow-list retained; only required `getportallogin_api` path added. - Risk: tightened/changed guards could break existing caller contracts. - Mitigation: `getrepsblob` guard aligned back to actual route contract; response shape unchanged. - Risk: UI runtime dependency regressions during hardening verification. - Mitigation: missing `updateLinks` import restored with minimal diff. ### Rollback plan (follow-up) 1. Revert signer-path migration commit `6094874` (or files: `accountDirectService.js`, `gethash_api.js`, `tests/phase7`, `tests/phase14`). 2. Revert contract/import alignment commit `b8fa514` (or files: `getrepsblob.js`, `components/elements/index.js`). 3. Re-run phase6–phase14 tests and lint to confirm rollback parity. ### Rollback plan (Phase 8) 1. Revert the four hardened API handlers. 2. Revert direct-service hash append changes in `documentDirectService` and `portalDirectService`. 3. Remove `tests/phase8/service-behaviour.test.cjs` if full slice rollback required. 4. Re-run phase6/7 baseline tests + lint after rollback. ## Latest update (2026-03-13 — Phase 15 hardening slice) - New branch created from `origin/SIPS-Development` with confirmed work item prefix: - `TASK22028-phase15-hardening-slice` - Delivered a small consistency-only hardening slice across 4 additional sensitive file handlers: - `pages/api/file/upload.js` - `pages/api/file/uploadsinglefile.js` - `pages/api/file/createappealcompletemessage_api.js` - `pages/api/file/setupcontainer.js` - Scope delivered: - standardized explicit early 400 handling for missing hash in handlers where hash validation was present but missing-hash guard was inconsistent - standardized guard style in `setupcontainer` to early-return on hash mismatch (same status/contract) - standardized missing required hash handling in `createappealcompletemessage_api` - preserved response shapes and signatures (no contract changes) - Added focused phase-15 tests: - `tests/phase15/service-behaviour.test.cjs` - negative-path coverage for missing hash across all 4 handlers - additional required-input checks where applicable - one valid-hash happy-path contract check (`setupcontainer` -> 200 with existing response shape) ### Validation snapshot (Phase 15) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase15/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ## Latest update (2026-03-14 — Phase 19 endpoint consistency slice) - Continued on branch: - `TASK22057-phase17-hardening-closeout` - Delivered a small additional consistency-only endpoint slice across: - `pages/api/endpoint/createwatchedcases_api.js` - `pages/api/endpoint/getappealtypes_api.js` - `pages/api/endpoint/getdnslist_api.js` - Scope delivered: - added required early 400 handling for malformed/missing `@odata.bind` values in `createwatchedcases_api` - removed noisy query logging in `getappealtypes_api` and `getdnslist_api` - preserved response-shape/signature contracts - Added focused tests: - `tests/phase19/service-behaviour.test.cjs` (5/5 passing) ### Validation snapshot (Phase 19) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (12/12) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (9/9) - `node tests/phase15/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase16/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase17/service-behaviour.test.cjs` -> **pass** (6/6) - `node tests/phase18/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase19/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ## Latest update (2026-03-14 — Phase 20 endpoint consistency slice) - Continued on branch: - `TASK22057-phase17-hardening-closeout` - Delivered a small additional consistency-only endpoint slice across: - `pages/api/endpoint/getbasicdnssearch_api.js` - `pages/api/endpoint/getbasicdnsurlsearch_api.js` - `pages/api/endpoint/getbasicsearchdetailspaged_api.js` - Scope delivered: - removed noisy query logging in `getbasicdnssearch_api` - standardized missing/empty `searchString` handling in `getbasicdnsurlsearch_api` with early 400 - standardized missing required input handling in `getbasicsearchdetailspaged_api` (`appealTypeName`, `primaryIdAttribute`, `incidentID`) with early 400 - preserved response-shape/signature contracts - Added focused tests: - `tests/phase20/service-behaviour.test.cjs` (5/5 passing) ### Validation snapshot (Phase 20) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (12/12) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (9/9) - `node tests/phase15/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase16/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase17/service-behaviour.test.cjs` -> **pass** (6/6) - `node tests/phase18/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase19/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase20/service-behaviour.test.cjs` -> **pass** (5/5) - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ### Manual HTTP snapshot (Phase 15) - Dev server run on `http://localhost:3002`. - Negative-path checks: - `POST /api/file/upload` missing hash -> **400** - `POST /api/file/upload?hash=wrong` -> **400** - `POST /api/file/uploadsinglefile` missing hash -> **400** - `POST /api/file/uploadsinglefile?hash=wrong` -> **400** - `GET /api/file/createappealcompletemessage_api?container=c1&tempcaseref=t1` missing hash -> **400** - `GET /api/file/createappealcompletemessage_api?container=c1&tempcaseref=t1&hash=wrong` -> **400** - `GET /api/file/createappealcompletemessage_api?container=c1` missing required params/hash -> **400** - `GET /api/file/setupcontainer?ident=c1` missing hash -> **400** - `GET /api/file/setupcontainer?ident=c1&hash=wrong` -> **400** - `GET /api/file/setupcontainer?hash=` missing required `ident` -> **400** - Valid-hash spot-check: - `GET /api/file/setupcontainer?ident=c1&hash=` -> **200** ### Rollback plan (Phase 15) 1. Revert these files: - `pages/api/file/upload.js` - `pages/api/file/uploadsinglefile.js` - `pages/api/file/createappealcompletemessage_api.js` - `pages/api/file/setupcontainer.js` - `tests/phase15/service-behaviour.test.cjs` 2. Re-run phase6–phase15 tests and lint to confirm parity. ## Latest update (2026-03-13 — Phase 16 file-proxy consistency slice) - Continued on branch: - `TASK22028-phase15-hardening-slice` - Delivered a small consistency-only hardening slice across 3 sensitive file proxy handlers: - `pages/api/file/getbloblistproxy.js` - `pages/api/file/getrepsblobproxy.js` - `pages/api/file/getawaitingsubmissionfromblobproxy.js` - Scope delivered: - removed unused imports/constants in touched handlers to reduce noisy/unsafe dead code - standardized required input checks using shared local `hasValue` pattern - preserved response shape/signature/status behavior contracts - Added focused tests: - `tests/phase16/service-behaviour.test.cjs` - negative-path checks for missing required container/casefolder inputs - one valid-input happy-path contract check for `getbloblistproxy` (200 + passthrough shape) ### Validation snapshot (Phase 16) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `node tests/phase8/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase9/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase10/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase11/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase12/service-behaviour.test.cjs` -> **pass** (4/4) - `node tests/phase13/service-behaviour.test.cjs` -> **pass** (7/7) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase15/service-behaviour.test.cjs` -> **pass** (5/5) - `node tests/phase16/service-behaviour.test.cjs` -> **pass** (4/4) - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ## Latest update (2026-03-19 — TASK22168 endpoint account contract consistency slice) - New branch created from `origin/SIPS-Development` with required work item prefix: - `TASK22168-endpoint-account-contract-consistency` - Delivered next coherent low-risk `pages/api/endpoint/**` slice after TASK22109 across: - `pages/api/endpoint/getaccounts_api.js` - `pages/api/endpoint/getemailaccountcheck_api.js` - `pages/api/endpoint/getpreferredlanguage_api.js` - Scope delivered: - removed dead/noisy code in touched handlers (unused imports and commented debug remnants) - standardized structured negative-path handling for: - missing required `emailAddress` - catch/failure paths - preserved success response contracts by returning unchanged upstream `data` - Added focused phase21 endpoint contract coverage: - `tests/phase21/endpoint-handler-contract.test.cjs` - extended `tests/phase21/api-contract-slice1.test.cjs` runner ### Validation snapshot (TASK22168) - `node tests/phase21/api-contract-slice1.test.cjs` -> **pass** - helper: 4/4 - file-handler: 11/11 - email-handler: 12/12 - endpoint-handler: 7/7 - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ### Risks + mitigations (TASK22168) - Risk: endpoint contract drift in success payloads. - Mitigation: success responses kept as upstream `data` payload via `respondSuccess`. - Risk: over-broad behavior change in account/login adjacent APIs. - Mitigation: scoped to 3 low-risk handlers only; no auth/session/security flow changes. - Risk: regression in negative-path status/shape expectations. - Mitigation: added explicit phase21 missing-input and catch-path assertions for each touched endpoint. ### Rollback plan (TASK22168) 1. Revert endpoint files: - `pages/api/endpoint/getaccounts_api.js` - `pages/api/endpoint/getemailaccountcheck_api.js` - `pages/api/endpoint/getpreferredlanguage_api.js` 2. Revert phase21 test updates: - `tests/phase21/endpoint-handler-contract.test.cjs` - `tests/phase21/api-contract-slice1.test.cjs` 3. Re-run: - `node tests/phase21/api-contract-slice1.test.cjs` - `npm run lint` ## Latest update (2026-03-19 — TASK22168 Bundle C extension on same branch) - Continued same branch with user-approved larger bundle: - `TASK22168-endpoint-account-contract-consistency` - Added contract-consistency coverage for login/portal/account-adjacent endpoints: - `pages/api/endpoint/getlogin_api.js` - `pages/api/endpoint/getportallogin_api.js` - `pages/api/endpoint/getportalloginproxy_api.js` - `pages/api/endpoint/getpersonalaccount_api.js` - Scope delivered: - removed dead imports/commented debug/noisy logging remnants - standardized structured 400 errors for required-input negative paths and catch/failure paths - preserved success payload contracts via `respondSuccess` pass-through - Phase21 endpoint suite expanded in: - `tests/phase21/endpoint-handler-contract.test.cjs` - test count grew from 7 to 18 for endpoint handler coverage ### Validation snapshot (TASK22168 Bundle C) - `node tests/phase21/api-contract-slice1.test.cjs` -> **pass** - helper: 4/4 - file-handler: 11/11 - email-handler: 12/12 - endpoint-handler: 18/18 - `npm run lint` -> **warnings only** (pre-existing `react-hooks/exhaustive-deps` warnings) ### Risks + mitigations (TASK22168 Bundle C) - Risk: contract drift from broad endpoint touch surface. - Mitigation: constrained to login/account adjacency group only and preserved success pass-through behavior. - Risk: hash-path behavior regression in `getportallogin_api`. - Mitigation: explicit tests for missing hash, invalid hash, and catch path. - Risk: inconsistent required-input behavior across adjacent handlers. - Mitigation: standardized explicit required-input envelopes in all four newly touched handlers. ### Rollback plan (TASK22168 Bundle C) 1. Revert endpoint files: - `pages/api/endpoint/getlogin_api.js` - `pages/api/endpoint/getportallogin_api.js` - `pages/api/endpoint/getportalloginproxy_api.js` - `pages/api/endpoint/getpersonalaccount_api.js` 2. Revert endpoint contract test updates: - `tests/phase21/endpoint-handler-contract.test.cjs` 3. Re-run: - `node tests/phase21/api-contract-slice1.test.cjs` - `npm run lint` ### Manual HTTP checks (Phase 16) - Dev server on `http://localhost:3002`. - Negative-path checks: - `/api/file/getbloblistproxy?casefolderID=case-1` -> **400** - `/api/file/getbloblistproxy?container=c1` -> **400** - `/api/file/getrepsblobproxy` -> **400** - `/api/file/getawaitingsubmissionfromblobproxy` -> **400** - Feasible valid-input spot-check: - `/api/file/getbloblistproxy?container=c1&casefolderID=case-1` -> **400** (expected downstream/local dependency behavior; input guard passed) ### Rollback plan (Phase 16) 1. Revert commit `c196edb` or files: - `pages/api/file/getbloblistproxy.js` - `pages/api/file/getrepsblobproxy.js` - `pages/api/file/getawaitingsubmissionfromblobproxy.js` - `tests/phase16/service-behaviour.test.cjs` 2. Re-run phase6–phase16 tests and lint. ## Latest update (2026-03-13 — signer allow-list follow-up) - Branch: `TASK22028-phase15-hardening-slice` - Fix applied: - added `/api/file/deleteblobcase` to signer endpoint allow-list in `pages/api/endpoint/gethash_api.js` - Test update: - extended `tests/phase14/service-behaviour.test.cjs` with deleteblobcase allow-list coverage ### Validation snapshot (follow-up) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (6/6) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `npm run lint` -> **warnings only** (pre-existing) ## Latest update (2026-03-13 — signer delete-flow follow-up) - Branch: `TASK22028-phase15-hardening-slice` - Extended signer allow-list and browser signer usage for additional delete flows: - `deleteWatchedCases` - `deleteMyRepresentations` - `deleteAwaitingSubmissionsFromBlob` - `deleteMyRepresentationsFromBlob` ### Validation snapshot (delete-flow follow-up) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (12/12) - `node tests/phase14/service-behaviour.test.cjs` -> **pass** (9/9) - `npm run lint` -> **warnings only** (pre-existing) ## Latest update (2026-03-13 — myportal + i18n follow-up) - Branch: `TASK22028-phase15-hardening-slice` - Delivered follow-up fixes: - myportal representation delete calls now use `caseRef` in top-three and view-all flows - missing `myportal` namespace added for `/newappeal/[appealtypes]` in `i18n.js` ### Validation snapshot (myportal + i18n follow-up) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (12/12) - `npm run lint` -> **warnings only** (pre-existing) ## Outstanding risks / gaps - Navigation regressions across EN/CY + route query combinations. - Drift between rewrite config and component-level locale path logic. - Deployment ambiguity due to multiple CI/CD artifacts (Azure pipeline, Jenkins, Docker) with unclear active source of truth. - Security posture variability where hash checks are bypassed/commented in selected handlers. ## Latest update (2026-03-13 — Phase 7 post-Phase-6 hardening) - New branch created from `origin/SIPS-Development` with required work item prefix: - `TASK21988a-phase7-postphase6-hardening` - Fixed known pre-existing SSR serialization issue on search results route: - `pages/searchresults.js` - updated SSR dispatch fallback from `setSearch(query.q)` to `setSearch(query?.q || "")` - result: `/searchresults` and `/cy/searchresults` now return 200 in local smoke checks (no 500 observed in this run). - Added expanded behavioural coverage for remaining direct-service domains: - new test file: `tests/phase7/service-behaviour.test.cjs` - includes document, portal, account, notify, integration behavioural checks - includes negative-path assertions for relay/hash/token-sensitive behaviors where feasible: - hashed URL append checks (`hashAPIPath`) - error handling contracts (undefined/error string/rethrow depending on existing function contract) ### Validation snapshot (Phase 7) - `node tests/phase6/service-parity.test.cjs` -> **pass** - `node tests/phase6/service-behaviour.test.cjs` -> **pass** (8/8) - `node tests/phase7/service-behaviour.test.cjs` -> **pass** (10/10) - `npm run lint` -> **warnings only** (pre-existing hook dependency warnings; no new lint errors) ### Targeted smoke snapshot (local dev server) - Note: dev server auto-started on `http://localhost:3001` because port `3000` was in use. - Search flow: - `GET /searchresults` and `GET /cy/searchresults` -> **200** - Case flow: - `GET /case` and `GET /cy/case` -> **200** - My Portal flow (negative-path): - `GET /myportal` and `GET /cy/myportal` -> **307** redirect to `/auth/signin` - Document flow (negative-path): - `GET /api/file/getbloblistproxy?container=test&casefolderID=test` -> **400** - Notify flow (negative-path): - `POST /api/email/notify` with `{}` -> **400**