Files
pedwfrontend/memory-bank/change-log.md
T

105 KiB

Change Log (AI/Human Curated)

Entry Template

date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: change
rationale: <why change was made>
impact: <user/system/security/i18n/a11y>
status: completed|rolled-back|partial

Summary:
Validation:
Follow-ups:

CL-001: TASK22211 endpoint search-document contract consistency slice

date: 2026-03-23
author: Cline
scope: pages/api/endpoint/{getsearchdocumenthistory_api,getsearchdocumenthistorypaged_api,getsearchdocumentdetails_api,getsearchdocumentdetailspaged_api,getsearchdocumentTypes_api}.js, tests/phase21/endpoint-handler-contract.test.cjs
type: change
rationale: Continue the endpoint contract-consistency stream by normalizing a coherent search-document handler cluster that still used raw error passthrough and noisy legacy logging patterns.
impact: Improved negative-path consistency and safer error contract handling in search-document endpoints while preserving success payload behavior.
status: completed

Summary:

  • Branch created from SIPS-Development: TASK22211-endpoint-search-document-contract-consistency.
  • Standardized five search-document handlers to respondError/respondSuccess usage.
  • Added explicit required-input guards:
    • DOCUMENT_ID_REQUIRED for history/historypaged
    • INCIDENT_ID_REQUIRED for details/detailspaged/types
    • ORDER_BY_REQUIRED, FIELD_SORT_REQUIRED, SHOW_NUMBER_OF_RECORDS_REQUIRED for details-paged query requirements
  • Removed noisy direct logging in paged/details code paths.
  • Preserved success contract patterns (pass-through or transformed payloads where already established).
  • Expanded phase21 endpoint tests with missing-input, catch-path, and success parity assertions for this cluster.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 11/11
    • email-handler: 12/12
    • endpoint-handler: 53/53
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps warnings; no new lint errors)

Follow-ups:

  • Continue the next endpoint cluster using the same pattern (bounded slice + phase21 test expansion).
  • Keep response success payloads contract-stable and avoid broad relay/auth refactors in this stream.

CL-002: TASK22211 endpoint token handler contract consistency slice

date: 2026-03-23
author: Cline
scope: pages/api/endpoint/getToken.js, tests/phase21/endpoint-handler-contract.test.cjs
type: change
rationale: Close out remaining non-standard endpoint contract handling by normalizing the legacy token endpoint to shared API response helpers and explicit error coding.
impact: Improved endpoint error consistency and test coverage for token acquisition failures while preserving successful token payload passthrough.
status: completed

Summary:

  • Refactored getToken.js to use respondSuccess and respondError from pages/api/middleware/apiResponse.
  • Removed legacy raw res.status(...).json(...)/bare status assignment pattern and dead logging artifacts.
  • Added explicit catch-path contract: TOKEN_FETCH_FAILED with 400 status.
  • Added endpoint phase21 tests for:
    • success token payload passthrough
    • catch-path error contract assertion

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 11/11
    • email-handler: 12/12
    • endpoint-handler: 147/147
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps warnings; no new lint errors)

Follow-ups:

  • Remaining outlier API handler for this consistency stream is pages/api/file/generateappealpdfcopy.js (not yet on shared response helpers).

CL-003: TASK22211 endpoint contract-hardening stream backfill (all known slices)

date: 2026-03-23
author: Cline
scope: pages/api/endpoint/*_api.js, pages/api/endpoint/getToken.js, tests/phase21/endpoint-handler-contract.test.cjs
type: change
rationale: Backfill memory-bank traceability so the complete known TASK22211 contract-consistency stream is documented in one place now that memory-bank is being versioned.
impact: Improves governance/auditability of API contract hardening, makes rollout and rollback analysis easier, and records exactly which endpoint clusters were normalized.
status: completed

Summary:

  • Backfilled all known TASK22211 slices currently on branch (in commit order):
    • b57f3de search-document endpoint contracts + phase21 coverage
    • 9af541a my-portal retrieval endpoint contracts
    • b880364 basic search endpoint contracts
    • a106dea DNS basic search endpoint contracts
    • b5a3a62 portal module + LPA case endpoint contracts
    • 4601d7c case detail endpoint contracts
    • 2959c7d delete/watched-case endpoint contracts
    • b59f13a metadata + linked-case endpoint contracts
    • bcf03a6 form + publication endpoint contracts
    • e0e91c8 DNS + representation endpoint contracts
    • 98e159d case creation + media endpoint contracts
    • 88e4586 advanced-search-paged endpoint contract
    • cb69bbe case update + CRM task endpoint contracts
    • 722ef98 hash + metadata endpoint contracts
    • 134f99c address-search endpoint contract
    • 8b6ed73 new-appeal appeal-types endpoint contract
    • eec59e8 token endpoint contract handling
  • Across the stream, handlers were standardized toward respondSuccess/respondError, required-input guards, and explicit negative-path error codes while preserving success payload compatibility.
  • Phase21 endpoint contract suite was expanded incrementally alongside each slice.

Validation:

  • Stream validation baseline (latest known run):
    • node tests/phase21/api-contract-slice1.test.cjs -> pass (endpoint-handler 147/147)
    • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue with remaining non-standard API outlier(s), notably pages/api/file/generateappealpdfcopy.js.
  • Keep future slices logged in this file at commit-time now that memory-bank is versioned.

CL-004: TASK22224 file + static endpoint contract hardening bundle (phase21)

date: 2026-03-23
author: Cline
scope: pages/api/file/{downloadblob,generateappealpdfcopy}.js, pages/api/endpoint/{getsipsmedia_api,getappealtypesfornewappeal_api}.js, tests/phase21/{file-handler-contract,endpoint-handler-contract}.test.cjs
type: change
rationale: Deliver the agreed larger bounded slice for remaining non-standard file/static handlers, improving negative-path consistency while preserving current success payload behavior.
impact: Standardized error envelopes/codes for download and generated PDF copy flows, method guard parity for static endpoints, and expanded phase21 contract coverage for both file and endpoint handlers.
status: completed

Summary:

  • downloadblob.js:
    • added explicit catch-path response via respondError with DOWNLOAD_BLOB_FAILED
    • kept success behavior intact (attachment header + raw file body)
    • removed dead internal helper (streamToBuffer) and tightened local declarations
  • generateappealpdfcopy.js:
    • removed unused imports/noisy console warnings
    • standardized required-input and negative-path contracts:
      • INCIDENT_ID_REQUIRED (400)
      • CASE_NOT_FOUND (404)
      • FORM_COLLECTION_NOT_FOUND (400)
      • APPEAL_PDF_COPY_GENERATION_FAILED (400)
    • preserved success output contract (PDF content headers + buffer body)
  • getsipsmedia_api.js and getappealtypesfornewappeal_api.js:
    • added method guard for non-GET requests using METHOD_NOT_ALLOWED (405)
    • preserved existing GET success payloads
  • Expanded phase21 tests:
    • file-handler-contract.test.cjs: added coverage for download failure + full generated PDF copy contract/negative paths
    • endpoint-handler-contract.test.cjs: added method guard tests for both static endpoints

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 17/17
    • email-handler: 12/12
    • endpoint-handler: 149/149
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • If desired, next slice can target remaining file-route parity candidates outside this bundle, but this closes the planned TASK22224 scope.

CL-005: TASK22224 downloadblob hotfix closure (path normalization + hash compatibility)

date: 2026-03-23
author: Cline
scope: pages/api/file/downloadblob.js
type: change
rationale: Close post-merge runtime regressions reported on live links where download URLs alternated between filename-only/full-path blob names and mixed encoded/raw hash input variants.
impact: Restored reliable blob downloads without relaxing hash security guarantees (still HMAC validated), and preserved existing caller compatibility across legacy/new URL encodings.
status: completed

Summary:

  • Hotfix 1 (f09f3b7): normalized blob path resolution
    • accepts both forms of blobname input:
      • filename only (legacy)
      • full prefixed path (already includes casefolderID/...)
    • prevents double-prefix lookup failures
    • sets attachment filename from final path segment only
  • Hotfix 2 (bd3bf68): hash compatibility validation
    • validates against a bounded set of canonical query-path variants (raw/encoded combinations for casefolderID and blobname)
    • fixes INVALID_HASH false negatives for legitimate caller-generated links
    • keeps strict HMAC requirement in place (no unauthenticated bypass)

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (17/17)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 17/17
    • email-handler: 12/12
    • endpoint-handler: 149/149
  • User confirmation: "downloadblob now works"

Follow-ups:

  • Next recommended slice on this branch: complete file-route guard parity for deleteblob.js, deleteblobcase.js, and deleteblobrep.js by aligning hash validation canonicalization and explicit respondError contracts (MISSING_REQUIRED_QUERY, INVALID_HASH, operation-specific *_FAILED).
  • Extend tests/phase21/file-handler-contract.test.cjs for the above routes with mixed encoded/raw hash cases to lock compatibility.

CL-006: TASK22224 file delete-route guard parity slice

date: 2026-03-23
author: Cline
scope: pages/api/file/{deleteblob,deleteblobcase,deleteblobrep}.js, tests/phase21/file-handler-contract.test.cjs
type: change
rationale: Execute the next planned slice to align hash/canonicalization behavior and negative-path contracts across high-risk file delete routes, matching the compatibility posture established for downloadblob.
impact: Reduces false INVALID_HASH failures for legitimate encoded/raw caller variants while preserving strict hash enforcement and improving resilience via explicit catch-path contracts.
status: completed

Summary:

  • deleteblob.js
    • added bounded hash candidate validation for encoded/raw combinations of casefolderID and blobname
    • normalized delete path handling for both filename-only and already-prefixed blob paths
    • added explicit catch-path contract: DELETE_BLOB_FAILED
  • deleteblobcase.js
    • added hash candidate validation for raw/encoded casefolderID
    • added explicit catch-path contract: DELETE_BLOB_CASE_FAILED
  • deleteblobrep.js
    • added hash candidate validation for encoded/raw casefolderID + repfile
    • added explicit catch-path contract: DELETE_BLOB_REP_FAILED
  • Phase21 tests expanded (file-handler-contract.test.cjs):
    • encoded hash-variant acceptance cases for all three delete routes
    • explicit dependency-failure contract assertions for all three delete routes

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (23/23)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 23/23
    • email-handler: 12/12
    • endpoint-handler: 149/149

Follow-ups:

  • Optional next slice: apply same bounded hash-canonicalization parity to remaining high-sensitivity file routes where mixed encoded/raw callers may exist (getbloblist, getprogressobjblob) and add regression cases to phase21.

CL-007: TASK22224 getrepsblob stability hotfix after delete representation flow

date: 2026-03-23
author: Cline
scope: actions/azurestorage.js (getRepsBlobs), tests/phase21/file-handler-contract.test.cjs
type: change
rationale: Resolve reported runtime 400 (GET_REPS_BLOB_FAILED) after delete representation actions, caused by stale soft-deleted blob tag hits during representation blob enumeration.
impact: Prevents transient/stale Azure tag index entries from breaking representation retrieval, improving reliability of post-delete refresh without relaxing route security contracts.
status: completed

Summary:

  • Hardened getRepsBlobs(containerName) in actions/azurestorage.js:
    • fixed async misuse (blobClient.getProperties().contentLength without await)
    • added existence/property guard with explicit await blobClient.getProperties()
    • skips 404s (soft-deleted/stale tag index results) instead of throwing
    • preserves behavior for non-404 failures (rethrow for proper error visibility)
    • kept existing _rep.json/undefined name filtering intact
  • Added phase21 contract coverage for getrepsblob route:
    • success payload contract test
    • dependency failure contract test (GET_REPS_BLOB_FAILED)

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (25/25)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 25/25
    • email-handler: 12/12
    • endpoint-handler: 149/149

Follow-ups:

  • Optional: add the same stale-tag existence guard pattern to any remaining Azure tag-list readers that still consume findBlobsByTags results without property existence verification.

CL-008: TASK22224 awaiting-submission route resilience parity hardening

date: 2026-03-23
author: Cline
scope: pages/api/file/getawaitingsubmissionfromblob.js, tests/phase21/file-handler-contract.test.cjs
type: change
rationale: Add explicit catch-path contract parity for awaiting-submission blob retrieval route so unexpected dependency failures return consistent, actionable error envelopes.
impact: Improves reliability/diagnostics for post-delete case refresh and aligns file-route error handling style without changing success payload contract or hash verification behavior.
status: completed

Summary:

  • Refactored getawaitingsubmissionfromblob handler to structured try/catch flow.
  • Preserved existing guard behavior:
    • MISSING_REQUIRED_QUERY for missing container/hash
    • INVALID_HASH for signature mismatch
  • Added explicit dependency failure contract:
    • GET_AWAITING_SUBMISSION_BLOB_FAILED (400)
    • message: Failed to retrieve awaiting submission blobs
  • Added phase21 coverage for this route:
    • success payload pass-through contract
    • dependency failure contract assertion

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (27/27)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 27/27
    • email-handler: 12/12
    • endpoint-handler: 149/149

Follow-ups:

  • Optional parity sweep: apply the same explicit catch-path contract pattern to remaining file routes that still rely on implicit promise-chain errors.

CL-009: TASK22224 proxy-route resilience and encoding parity bundle

date: 2026-03-23 author: Cline scope: pages/api/file/{getbloblistproxy,getrepsblobproxy,getawaitingsubmissionfromblobproxy,createappealcompletemessageproxy_api}.js, tests/phase21/file-handler-contract.test.cjs type: change rationale: Continue larger-slice hardening by aligning proxy handlers with explicit async error handling and safer encoded upstream query forwarding for hash-based downstream calls. impact: Improves proxy reliability and compatibility for encoded query values while preserving existing proxy error contracts and response behavior. status: completed

Summary:

  • getbloblistproxy.js
    • converted .then/.catch chain to explicit try/catch
    • encoded forwarded container and casefolderID query values
    • preserved error contract: GET_BLOB_LIST_PROXY_FAILED
  • getrepsblobproxy.js
    • converted .then/.catch chain to explicit try/catch
    • encoded forwarded container
    • preserved error contract: GET_REPS_BLOB_PROXY_FAILED
  • getawaitingsubmissionfromblobproxy.js
    • converted .then/.catch chain to explicit try/catch
    • preserved error contract: GET_AWAITING_SUBMISSION_PROXY_FAILED
  • createappealcompletemessageproxy_api.js
    • converted .then/.catch chain to explicit try/catch
    • encoded forwarded container and tempcaseref
    • preserved error contract: CREATE_APPEAL_COMPLETE_MESSAGE_PROXY_FAILED
  • Phase21 tests expanded for proxy paths:
    • getbloblistproxy success + dependency failure
    • getrepsblobproxy success
    • getawaitingsubmissionfromblobproxy dependency failure
    • createappealcompletemessageproxy dependency failure

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (46/46)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 46/46
    • email-handler: 12/12
    • endpoint-handler: 149/149

Follow-ups:

  • Optional next big slice: bring remaining proxy/message routes using raw axios promise chains (createcaseinvolvement_api.js, createrepinvolvement_api.js, updatecase_api.js) onto the same async/await + explicit contract pattern.

CL-010: TASK22224 involvement/update route async contract hardening bundle

date: 2026-03-23 author: Cline scope: pages/api/file/{createcaseinvolvement_api,createrepinvolvement_api,updatecase_api}.js, tests/phase21/file-handler-contract.test.cjs type: change rationale: Execute the next requested slice by modernizing remaining relay-backed involvement/update handlers that still used axios promise chains and legacy dead imports. impact: Improves reliability/readability and preserves existing response contracts, including 412 "record exists" semantics for involvement creation flows. status: completed

Summary:

  • createcaseinvolvement_api.js
    • removed unused CryptoJS import
    • refactored axios .then/.catch to explicit try/catch
    • preserved conflict behavior: status 412 -> success { record: "exists" }
    • preserved failure contract: CREATE_CASE_INVOLVEMENT_FAILED
  • createrepinvolvement_api.js
    • removed unused CryptoJS import
    • refactored axios .then/.catch to explicit try/catch
    • preserved conflict behavior: status 412 -> success { record: "exists" }
    • preserved failure contract: CREATE_REP_INVOLVEMENT_FAILED
  • updatecase_api.js
    • removed unused CryptoJS import
    • refactored axios .then/.catch to explicit try/catch
    • preserved failure contract: UPDATE_CASE_FAILED
  • Phase21 tests expanded:
    • createcaseinvolvement 412 conflict success contract
    • createrepinvolvement dependency failure contract
    • updatecase dependency failure contract

Validation:

  • node tests/phase21/file-handler-contract.test.cjs -> pass (49/49)
  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 49/49
    • email-handler: 12/12
    • endpoint-handler: 149/149

Follow-ups:

  • Optional: apply equivalent modernization to any remaining relay-backed handlers outside pages/api/file/ that still use raw axios promise chains and have no explicit phase21 contract assertions.

CL-011: TASK22224 aggressive non-file bundle (email/admin/endpoint parity)

date: 2026-03-23 author: Cline scope: pages/api/email/{getmailinglist,getcaseref,notify}.js, pages/api/admin/{getnewappeals_api,getlatestdocuments_api}.js, pages/api/endpoint/getportallogin_api.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Execute requested aggressive bundling for remaining non-file modernization/parity candidates: remove legacy promise chains and improve hash compatibility on login endpoint while preserving existing contracts. impact: Improves consistency and resilience across email/admin/endpoint routes with no contract regressions; adds encoded hash-variant compatibility for portal login hash checks. status: completed

Summary:

  • pages/api/email/getmailinglist.js
    • converted axios .then/.catch to try/catch
    • preserved flattening behavior and error contract MAILING_LIST_FETCH_FAILED
  • pages/api/email/getcaseref.js
    • converted axios .then/.catch to try/catch
    • preserved flattening behavior and error contract CASE_REF_FETCH_FAILED
  • pages/api/email/notify.js
    • converted notify client .then/.catch to try/catch
    • preserved success payload and error contract EMAIL_NOTIFY_FAILED
  • pages/api/admin/getnewappeals_api.js
    • removed unused CryptoJS import
    • converted axios .then/.catch to try/catch
    • preserved @odata.nextLink normalization and error contract ADMIN_NEW_APPEALS_FETCH_FAILED
  • pages/api/admin/getlatestdocuments_api.js
    • converted axios .then/.catch to try/catch
    • preserved flatten/enrich behavior and error contract ADMIN_LATEST_DOCS_FETCH_FAILED
  • pages/api/endpoint/getportallogin_api.js
    • retained required query/hash guards
    • expanded hash validation to accept raw + encoded emailAddress query-path candidates
    • preserved error contract PORTAL_LOGIN_FETCH_FAILED
  • phase21 endpoint tests expanded:
    • getportallogin encoded hash variant success path
    • getnewappeals_api catch contract
    • getlatestdocuments_api catch contract

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 49/49
    • email-handler: 12/12
    • endpoint-handler: 152/152

Follow-ups:

  • Remaining major modernization candidate is pages/api/file/generateappealpdf.js (+ optional pages/api/file/generatepdf.js) if we continue final closure slices.

CL-012: TASK22224 generatepdf/generateappealpdf async hardening slice

date: 2026-03-23 author: Cline scope: pages/api/file/{generateappealpdf,generatepdf}.js, tests/phase21/file-handler-contract.test.cjs type: change rationale: Execute next requested slice to modernize remaining file PDF-generation handlers still using promise chains, while preserving existing hash/response behavior. impact: Improves maintainability and error-path consistency for PDF generation routes; phase21 coverage now includes explicit failure contracts for both handlers. status: completed

Summary:

  • pages/api/file/generateappealpdf.js
    • converted mixed promise-chain flow to async/await + try/catch
    • preserved existing guard contracts: MISSING_REQUIRED_QUERY, INVALID_HASH
    • preserved generation failure contract: GENERATE_APPEAL_PDF_FAILED
    • replaced JSX render call with React.createElement(...) compatibility form used by test loader
  • pages/api/file/generatepdf.js
    • converted create/upload promise-chain to async/await + try/catch
    • preserved existing guard contracts: HASH_REQUIRED, INVALID_HASH
    • preserved generation failure contract: GENERATE_PDF_FAILED
    • replaced JSX render call with React.createElement(...) compatibility form used by test loader
  • phase21 file tests expanded:
    • generatepdf catch-path contract (GENERATE_PDF_FAILED)
    • generateappealpdf catch-path contract (GENERATE_APPEAL_PDF_FAILED)

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 51/51
    • email-handler: 12/12
    • endpoint-handler: 152/152

Follow-ups:

  • Remaining optional cleanup in these handlers is dead import/unused local pruning (non-behavioral) if we want a final low-risk tidy pass.

CL-013: TASK22224 completion-message route parity closure slice

date: 2026-03-24 author: Cline scope: pages/api/file/createappealcompletemessage_api.js, tests/phase21/file-handler-contract.test.cjs type: change rationale: Continue next requested slice by closing the final promise-chain parity outlier in file completion-message flow and strengthening phase21 contract coverage. impact: Improves maintainability and async error hygiene while preserving route behavior and existing error contracts. status: completed

Summary:

  • pages/api/file/createappealcompletemessage_api.js
    • replaced inline .catch(...) on fire-and-forget updateAccount(...) with explicit async IIFE + try/catch and void invocation
    • preserved non-blocking behavior and logging semantics for account-update failure path
    • preserved primary route contracts and success payload ({ status: "success" })
  • phase21 file contract tests expanded:
    • success path for encoded hash candidate on createappealcompletemessage_api
    • dependency-failure contract assertion for CREATE_APPEAL_COMPLETE_MESSAGE_FAILED

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152

Follow-ups:

  • Optional final low-risk tidy sweep: remove dead imports/unused locals in legacy file handlers now that contract hardening stream is functionally complete.

CL-014: TASK22224 pdf render compatibility tidy slice

date: 2026-03-24 author: Cline scope: pages/api/file/{generatepdf,generateappealpdf}.js, tests/phase21/file-handler-contract.test.cjs type: change rationale: Apply a low-risk compatibility tidy so PDF render invocation remains stable across runtime and contract-test VM contexts. impact: Keeps functional behavior unchanged while reducing test/runtime mismatch risk in render path setup. status: completed

Summary:

  • pages/api/file/generatepdf.js
    • switched render call input from React.createElement(MyDocument, ...) to direct MyDocument(...) invocation in ReactPDF.renderToStream(...)
  • pages/api/file/generateappealpdf.js
    • switched render call input from React.createElement(MyDocument, ...) to direct MyDocument(...) invocation in ReactPDF.renderToStream(...)
  • tests/phase21/file-handler-contract.test.cjs
    • added Buffer injection for generatepdf catch-path test harness to align VM context expectations

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152

Follow-ups:

  • Optional: dead import cleanup (Document/Page/Text/View/StyleSheet/PDFViewer, middleware, nextConnect, fs, etc.) can be done in a dedicated non-behavioral hygiene PR.

CL-015: TASK22224 pdf handler dead-code hygiene slice

date: 2026-03-24 author: Cline scope: pages/api/file/{generatepdf,generateappealpdf}.js type: change rationale: Execute the requested next low-risk slice by removing dead imports and unused locals in recently hardened PDF handlers. impact: Non-behavioral maintainability cleanup; reduces lint noise and future edit risk while preserving existing contracts. status: completed

Summary:

  • pages/api/file/generatepdf.js
    • pruned unused Azure storage imports, leaving only createRepPDFBlob
    • pruned unused @react-pdf/renderer named imports
    • removed unused imports (middleware, nextConnect, fs)
    • removed unused locals (casefolderID, representationType, repRaiser, localeSelect, repCapacity, repType)
  • pages/api/file/generateappealpdf.js
    • pruned unused Azure storage imports to only required functions
    • pruned unused @react-pdf/renderer named imports
    • removed unused imports (middleware, nextConnect, fs, path, unused pdf templates)
    • removed unused local (caseRef)

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152

Follow-ups:

  • Optional: run full repo lint in a separate pass for broader non-slice hygiene now that targeted contract suite is stable.

CL-016: TASK22224 documents download contract slice

date: 2026-03-24 author: Cline scope: pages/api/documents/download/[id].js, tests/phase21/{documents-handler-contract,api-contract-slice1}.test.cjs type: change rationale: Execute next aggressive slice by standardizing document download guard behavior and bringing the route under phase21 contract coverage. impact: Improves reliability on invalid input and relay-failure paths while preserving existing user-visible fallback behavior (/filenotavailable) for download failures. status: completed

Summary:

  • pages/api/documents/download/[id].js
    • added explicit required-query guard for id and hash
    • unified fallback redirect path via constant (/filenotavailable)
    • preserved streaming download behavior and retry flow
  • added tests/phase21/documents-handler-contract.test.cjs covering:
    • missing query -> redirect contract
    • success -> attachment/content-type headers + stream pipe contract
    • relay failure -> redirect contract
  • updated combined runner (tests/phase21/api-contract-slice1.test.cjs) to include documents handler contract suite

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Optional future hardening: migrate documents route onto shared respondError/respondSuccess envelope if product requirements allow replacing redirect-style fallback.

CL-017: TASK22224 endpoint legacy-comment hygiene slice

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{createwatchedcases_api,getadvancedsearchpaged_api}.js type: change rationale: Complete second requested slice with low-risk maintainability cleanup by removing large obsolete commented legacy handler blocks. impact: Non-behavioral cleanup only; improves readability and reduces maintenance noise with no runtime contract changes. status: completed

Summary:

  • createwatchedcases_api.js
    • removed obsolete commented promise-chain implementation block
  • getadvancedsearchpaged_api.js
    • removed obsolete commented legacy implementation block retained below active handler

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Optional further hygiene pass can target remaining oversized commented historical sections in non-sensitive handlers.

CL-018: TASK22224 nextauth notify micro-refactor

date: 2026-03-24 author: Cline scope: pages/api/auth/[...nextauth].js type: change rationale: Execute the explicitly approved auth micro-slice by replacing inline promise .catch(...) with explicit try/catch while preserving existing auth behavior. impact: Auth-sensitive non-functional refactor only; keeps current sign-in flow, template/locale routing, and error-handling semantics unchanged. status: completed

Summary:

  • pages/api/auth/[...nextauth].js
    • replaced:
      • await notifyClient.sendEmail(...).catch((error) => consoleLogger(error))
    • with explicit:
      • try { await notifyClient.sendEmail(...) } catch (error) { consoleLogger(error) }
  • preserved behavior contracts:
    • Notify failures are still logged and do not throw through auth handler
    • no changes to callback URL construction, locale/template selection, NextAuth options, session/cookies/pages config

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Optional future auth hygiene (separate guarded slice): replace verbose auth console.log diagnostics with structured logger usage once production logging requirements are confirmed.

CL-019: TASK22229 P2-S1 relay forwarding pilot (proxy endpoint cluster)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, pages/api/endpoint/{getwatchedcasesproxy_api,getmyrepresentationsproxy_api,getrepresentationsproxy_api,getawaitingsubmissionproxy_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Start Priority-2 by piloting a shared relay forwarding helper on a bounded proxy endpoint cluster to reduce duplicated token/hash/header/axios boilerplate while preserving endpoint contracts. impact: Maintainability and consistency improvement with no intended behavioral contract changes; error code/status/message and success payload contracts remain unchanged for migrated endpoints. status: completed

Summary:

  • Added shared relay helper:
    • pages/api/middleware/relayForwarding.js
    • exports relayGet({ queryUrl, res, errorResponse, transformData })
    • centralizes token fetch, relay URL + hash composition, azureHeaders, GET execution, success/error response handling, and logging
  • Migrated pilot endpoint cluster to relayGet:
    • getwatchedcasesproxy_api.js (with existing payload transform preserved)
    • getmyrepresentationsproxy_api.js
    • getrepresentationsproxy_api.js
    • getawaitingsubmissionproxy_api.js (with existing payload transform preserved)
  • Updated endpoint contract tests to mock relayGet for migrated routes while preserving existing assertions.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • P2-S2 rollout: migrate the next relay-heavy endpoint batch onto relayGet/shared forwarding utility pattern.
  • P2-S3 hardening: add shared timeout/retry config and redacted structured relay error logging policy.

CL-020: TASK22229 P2-S2 Batch 1 (account/login relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, pages/api/endpoint/{getaccounts_api,getemailaccountcheck_api,getpreferredlanguage_api,getlogin_api,getpersonalaccount_api,getportalloginproxy_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Deliver first P2-S2 batch as a dedicated commit by migrating a bounded account/login endpoint cluster onto shared relayGet while preserving response contracts. impact: Reduced relay boilerplate and improved consistency with no intended endpoint contract changes. status: completed

Summary:

  • Extended relayGet to support optional requestOptionsBuilder for handlers requiring paged header variants.
  • Migrated Batch 1 endpoints to relayGet:
    • getaccounts_api.js
    • getemailaccountcheck_api.js
    • getpreferredlanguage_api.js
    • getlogin_api.js (uses azureHeadersPaged via requestOptionsBuilder)
    • getpersonalaccount_api.js
    • getportalloginproxy_api.js (uses azureHeadersPaged via requestOptionsBuilder)
  • Updated phase21 endpoint contract tests to mock relayGet for migrated handlers, preserving existing guard/catch/success assertions.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Continue P2-S2 with Batch 2 as next dedicated commit on this same branch.

CL-021: TASK22229 P2-S2 Batch 2 (my-portal + representation relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getmycases_api,getmyrepresentations_api,getwatchedcases_api,getawaitingsubmission_api,getrepresentations_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Deliver second P2-S2 commit by migrating the next bounded portal/representation GET endpoint cluster onto shared relayGet while preserving route contracts. impact: Reduced duplicated relay boilerplate and aligned forwarding behavior with no intended response contract changes. status: completed

Summary:

  • Migrated Batch 2 endpoints to relayGet:
    • getmycases_api.js (preserved title mapping transform)
    • getmyrepresentations_api.js
    • getwatchedcases_api.js (preserved watched-case projection transform)
    • getawaitingsubmission_api.js (preserved title mapping transform)
    • getrepresentations_api.js
  • Updated phase21 endpoint contract tests for migrated handlers by mocking relayGet in guard/catch test paths.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Continue P2-S2 with Batch 3 as the next dedicated commit on this branch.

CL-022: TASK22229 P2-S2 Batch 3 (case/event relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getcase_api,getcasebyid_api,getincidentbyid_api,getsipsevents_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Deliver third P2-S2 commit by migrating an additional bounded case/event endpoint cluster onto shared relayGet while preserving route contracts. impact: Further relay boilerplate reduction and consistent forwarding behavior with no intended contract changes. status: completed

Summary:

  • Migrated Batch 3 endpoints to relayGet:
    • getcase_api.js (preserved @odata.nextLink normalization)
    • getcasebyid_api.js (preserved @odata.nextLink normalization and array-wrapped success payload)
    • getincidentbyid_api.js
    • getsipsevents_api.js
  • Updated phase21 endpoint contract tests to mock relayGet for migrated handlers in guard/catch paths.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 152/152
    • documents-handler: 3/3

Follow-ups:

  • Continue P2-S2 with next bounded batch (e.g. search/listing cluster) as a separate commit if required.

CL-023: TASK22229 P2-S2 Batch 6 (profile/form/document-history/portal-module relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getpersonalaccount_api,getformdata_api,getsearchdocumenthistory_api,getsearchdocumenthistorypaged_api,getportalmoduledetails_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Execute requested Batch 6 by migrating the next bounded set of read-only endpoint handlers to shared relayGet while preserving existing request validation and response/error contracts. impact: Reduced endpoint relay boilerplate and improved consistency; no intended behavior contract changes. status: completed

Summary:

  • Migrated Batch 6 endpoints to shared relayGet:
    • getpersonalaccount_api.js
    • getformdata_api.js
    • getsearchdocumenthistory_api.js (uses requestOptionsBuilder with azureHeadersPaged)
    • getsearchdocumenthistorypaged_api.js (uses requestOptionsBuilder with azureHeadersPaged)
    • getportalmoduledetails_api.js
  • Preserved all existing required-query validation guards and existing error codes/messages.
  • Updated Phase 21 endpoint contract tests to inject relayGet mocks for migrated handlers (validation path, catch path, and success path where applicable).

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded batch: migrate remaining legacy relay GET handlers in advanced/basic search-document/detail clusters that still use direct axios relay patterns.

CL-024: TASK22229 P2-S2 Batch 7 (search-document + portal-proxy relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getportalmoduledetailsproxy_api,getsearchdocumentTypes_api,getsearchdocumentdetails_api,getsearchdocumentdetailspaged_api,getappealpdfdocuments_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue P2-S2 in bounded commits by migrating a coherent search-document/portal-proxy GET cluster onto shared relay forwarding while preserving existing validation, transforms, and error contracts. impact: Reduced duplicate relay plumbing and improved consistency in search-document handlers; no intended API contract changes. status: completed

Summary:

  • Migrated Batch 7 endpoints to shared relayGet:
    • getportalmoduledetailsproxy_api.js
    • getsearchdocumentTypes_api.js
    • getsearchdocumentdetails_api.js
    • getsearchdocumentdetailspaged_api.js
    • getappealpdfdocuments_api.js
  • Preserved existing guard behavior and error response contracts.
  • Preserved endpoint-specific transform behavior via transformData, including:
    • grouped search-document type payloads
    • document hashlink enrichment and published-date normalization
    • @odata.nextLink normalization where present
    • appeal PDF document name projection
  • Updated phase21 endpoint tests to mock relayGet for migrated handlers in validation/catch/success paths as applicable.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue with next bounded P2-S2 batch from remaining legacy GET endpoints (e.g., advanced/basic paged search-detail clusters and related non-migrated proxies).

CL-025: TASK22229 P2-S2 Batch 8 (basic search details + DNS details relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getbasicsearchpaged_api,getbasicsearchdetails_api,getbasicsearchdetailspaged_api,getbasicdnssearchdetails_api,getbasicdnssearchdetailspaged_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue the P2-S2 relay migration using bounded commits by moving the remaining basic-search-details and DNS-details GET handlers to shared relayGet, preserving existing guards and response contracts. impact: Reduced duplicated relay plumbing and more consistent forwarding behavior across search-detail handlers; no intended API contract changes. status: completed

Summary:

  • Migrated Batch 8 endpoints to shared relayGet:
    • getbasicsearchpaged_api.js
    • getbasicsearchdetails_api.js
    • getbasicsearchdetailspaged_api.js
    • getbasicdnssearchdetails_api.js
    • getbasicdnssearchdetailspaged_api.js
  • Preserved existing validation guards and error contracts.
  • Preserved existing endpoint-specific transforms:
    • @odata.nextLink normalization in paged responses
    • flattened ticketnumber enrichment for search detail handlers
  • Updated phase21 endpoint contract tests to inject relayGet mocks for migrated handlers in validation and catch-path tests.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue P2-S2 with next bounded batch from remaining legacy GET endpoints (currently: createwatchedcases_api, deletewatchedcasesproxy_api, getadvancedsearch_api, getadvancedsearchpaged_api, getappealid_api, getbasicdnssearchpaged_api, getbasicpartsaveddetails_api, getbasicsearch_by_address_api, getbasicsearch_by_lparref_api, getdnscoords_api, getdnslist_api, getmylpacases_api, getportallogin_api).

CL-026: TASK22229 P2-S2 Batch 9 (appeal-id + DNS list/paged + part-saved relay GET cluster)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getappealid_api,getbasicdnssearchpaged_api,getbasicpartsaveddetails_api,getdnslist_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue bounded P2-S2 relay migration by moving another coherent set of read-only handlers to shared relayGet, preserving existing guards, transforms, and error contracts. impact: Reduced duplicated relay plumbing and improved consistency for DNS list/paged and appeal detail lookup endpoints; no intended API contract changes. status: completed

Summary:

  • Migrated Batch 9 endpoints to shared relayGet:
    • getappealid_api.js
    • getbasicdnssearchpaged_api.js
    • getbasicpartsaveddetails_api.js
    • getdnslist_api.js
  • Preserved existing input validation guards and endpoint-specific error contracts.
  • Preserved endpoint-specific transform behavior (@odata.nextLink normalization in DNS list/paged handlers).
  • Updated phase21 endpoint contract tests to inject relayGet mocks for these migrated handlers in guard and catch-path assertions.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue P2-S2 with next bounded batch from remaining legacy relay GET endpoints (createwatchedcases_api, deletewatchedcasesproxy_api, getadvancedsearch_api, getadvancedsearchpaged_api, getbasicsearch_by_address_api, getbasicsearch_by_lparref_api, getdnscoords_api, getmylpacases_api, getportallogin_api).

CL-027: TASK22229 P2-S2 Batch 10 (portal login + my LPA cases relay GET pair)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getportallogin_api,getmylpacases_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue bounded relay migration by moving two remaining high-use portal retrieval endpoints to shared relayGet while preserving existing hash/lookup guards and response contracts. impact: Further relay boilerplate reduction and consistent forwarding behavior in portal login/LPA case retrieval flows; no intended API contract changes. status: completed

Summary:

  • Migrated Batch 10 endpoints to shared relayGet:
    • getportallogin_api.js (preserved hash validation guard and error contract)
    • getmylpacases_api.js (preserved LPA lookup/404 guard and title transform)
  • Preserved endpoint-specific behavior:
    • getportallogin_api: raw + encoded hash candidate validation before relay call
    • getmylpacases_api: JSONPath LPA lookup with LPA_NOT_FOUND handling and pinswg_title enrichment transform
  • Updated phase21 endpoint contract tests to inject relayGet mocks for migrated handlers in validation/catch/success paths.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue P2-S2 with the remaining legacy relay GET candidates (createwatchedcases_api, deletewatchedcasesproxy_api, getadvancedsearch_api, getadvancedsearchpaged_api, getbasicsearch_by_address_api, getbasicsearch_by_lparref_api, getdnscoords_api).

CL-028: TASK22229 P2-S2 Batch 11 (advanced-search-paged relay GET)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/getadvancedsearchpaged_api.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue bounded relay migration by moving the remaining advanced-search paged GET handler to shared relayGet while preserving query validation and response contracts. impact: Reduced duplicated relay plumbing and aligned advanced paged search route with shared forwarding; no intended API contract changes. status: completed

Summary:

  • Migrated getadvancedsearchpaged_api.js to shared relayGet.
  • Preserved existing guard behavior and error contracts:
    • SEARCH_STRING_REQUIRED
    • ORDER_BY_REQUIRED
    • FIELD_SORT_REQUIRED
    • SHOW_NUMBER_OF_RECORDS_REQUIRED
    • INVALID_SEARCH_STRING
    • ADVANCED_SEARCH_PAGED_FETCH_FAILED
  • Preserved endpoint-specific transform behavior (@odata.nextLink normalization via transformData).
  • Updated phase21 endpoint contract tests to inject relayGet mocks for getadvancedsearchpaged_api guard/catch assertions.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Continue P2-S2 with remaining legacy relay GET candidates (createwatchedcases_api, deletewatchedcasesproxy_api, getadvancedsearch_api, getbasicsearch_by_address_api, getbasicsearch_by_lparref_api, getdnscoords_api).

CL-029: TASK22229 P2-S2 Batch 12 (remaining relay GET candidates)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, pages/api/endpoint/{createwatchedcases_api,deletewatchedcasesproxy_api,getadvancedsearch_api,getbasicsearch_by_address_api,getbasicsearch_by_lparref_api,getdnscoords_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Complete Batch 12 by migrating the remaining listed legacy relay GET candidates to shared forwarding helpers while preserving endpoint-specific validation, transforms, and error contracts. impact: Consolidated relay GET behavior and reduced endpoint-level relay boilerplate; no intended API contract changes. status: completed

Summary:

  • Extended relay middleware with reusable helpers:
    • relayGetData now supports token reuse via transformData path
    • Added forwardGetData to support custom base URLs (used by proxy-to-local endpoint) while preserving hash behavior
  • Migrated remaining Batch 12 candidates:
    • getadvancedsearch_api.js -> relayGet + relayGetData for project-type enrichment loop
    • getdnscoords_api.js -> relayGetData for both DNS + SIPS source pulls
    • getbasicsearch_by_lparref_api.js -> relayGetData
    • getbasicsearch_by_address_api.js -> relayGetData for appeal-type and incident fetches
    • deletewatchedcasesproxy_api.js -> forwardGetData with BASE_URL
    • createwatchedcases_api.js -> relayGetData for record-exists pre-check (POST/PATCH upsert flow preserved)
  • Preserved endpoint-specific guard and error contracts (including status codes such as 500 for BASIC_SEARCH_BY_ADDRESS_FETCH_FAILED).
  • Updated phase21 endpoint contract tests for migrated handlers to mock relayGetData / forwardGetData where appropriate.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Batch 12 completes the previously listed remaining P2-S2 relay GET candidates.

CL-030: TASK22236 P2-S3 relay forwarding hardening (timeouts, retries, structured redacted logs)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, tests/phase21/relay-forwarding-hardening.test.cjs type: change rationale: Begin P2-S3 by hardening shared relay forwarding behavior with bounded timeout/retry controls and structured redacted operational logging, reducing transient failure impact while preserving endpoint contracts. impact: Improves resilience/observability for relay GET traffic; endpoint success/error contracts remain unchanged because caller handlers still manage response envelopes. status: completed

Summary:

  • Hardened forwardGetData in relayForwarding.js with:
    • configurable timeout (RELAY_TIMEOUT_MS, default 8000ms)
    • bounded retries (RELAY_RETRY_MAX, default 2)
    • exponential backoff with cap (RELAY_RETRY_BASE_DELAY_MS, RELAY_RETRY_MAX_DELAY_MS)
    • retry eligibility for transient statuses/codes (408/429/5xx, selected network timeout/reset codes)
  • Added structured, redacted operational relay logs:
    • relay_request_retrying
    • relay_request_failed
  • Preserved compatibility behaviors:
    • existing token/header/hash handling
    • optional appendHash and custom requestOptionsBuilder
    • endpoint-level relayGet error response semantics
  • Added focused Phase 21 hardening tests:
    • retries on retryable status and succeeds
    • does not retry non-retryable status
    • applies timeout and respects appendHash=false

Validation:

  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (3/3)
  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next hardening increment: introduce endpoint-specific retry overrides for write paths (if future non-GET use is introduced) to keep retry policy conservative by operation type.

CL-031: TASK22236 P2-S3 Batch 2A policy tightening (retry classification, config clamping, log de-dup)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, tests/phase21/relay-forwarding-hardening.test.cjs type: change rationale: Execute P2-S3 Batch 2A by tightening relay retry policy and operational safety bounds while preventing duplicate error noise between relay-layer and endpoint-layer logging. impact: Stronger resilience and cleaner observability with no endpoint contract changes; retry behavior is now explicitly conservative for deterministic client/auth failures. status: completed

Summary:

  • Updated relay retry policy:
    • explicitly non-retryable statuses: 400, 401, 403, 404, 422
    • retries still allowed for transient classes (408, 429, 5xx) and selected transport error codes
    • any other explicit numeric HTTP status now treated as non-retryable by default
  • Added runtime-safe config clamping for relay knobs:
    • timeout clamped to 100..30000ms
    • retries clamped to 0..4
    • retry delays clamped to 0..5000ms
    • both env-derived and per-call numeric overrides are sanitized
  • Reduced duplicate logging noise:
    • non-retry terminal relay failures are marked as already logged in middleware
    • relayGet catch now skips consoleLogger when relay layer has already emitted a structured log
  • Expanded relay hardening tests:
    • no retry on 401
    • duplicate logging suppression path through relayGet
    • env-value clamping behavior for timeout bounds

Validation:

  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (6/6)
  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Batch 2B: update memory/context docs with canonical relay hardening policy, env knobs, and rollback/tuning guidance.

CL-032: TASK22239 governance + operational rollout playbook bundle (relay hardening)

date: 2026-03-24 author: Cline scope: context/runbook.md, context/integration-map.md, memory-bank/{change-log,decisions,patterns}.md type: change rationale: Deliver a combined governance and operational rollout slice after P2-S3 code hardening so relay policy changes have explicit merge gates, smoke matrix coverage, and rollback/monitoring discipline. impact: Improves release safety and auditability for relay policy updates without changing runtime endpoint behavior. status: completed

Summary:

  • Added a dedicated Relay Hardening Rollout Playbook section to context/runbook.md covering:
    • pre-merge governance gate checklist
    • non-prod smoke matrix for deterministic and transient failure classes
    • progressive rollout guidance
    • Day 1/Day 3 monitoring checks
    • fast mitigation/rollback sequence
  • Added relay policy governance references in architecture/integration context docs to make rollout checks discoverable for future contributors.
  • Recorded governance baseline updates in memory-bank:
    • decision entry for relay policy-change governance gate
    • reusable pattern entry for required rollout/smoke/rollback workflow

Validation:

  • Documentation consistency review across context/runbook.md, context/integration-map.md, and memory-bank entries.

Follow-ups:

  • Optional next iteration: add a PR template block in Azure DevOps mirroring the runbook governance gate checklist.

CL-033: TASK22242 relay telemetry enrichment (lifecycle events + correlation fields)

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, tests/phase21/relay-forwarding-hardening.test.cjs type: change rationale: Add richer relay observability so operations can correlate retries and outcomes per request and track latency/status patterns without changing endpoint contracts. impact: Improves operational diagnostics and trend analysis for relay traffic while preserving existing API behavior. status: completed

Summary:

  • Enriched relay middleware telemetry with request lifecycle events:
    • relay_request_started
    • relay_request_retrying
    • relay_request_succeeded
    • relay_request_failed
  • Added shared telemetry fields for correlation and analysis:
    • relayRequestId (per request correlation id)
    • attemptsMade, retryCountUsed, remainingRetries
    • elapsedMs
    • statusClass (2xx/4xx/5xx style buckets)
    • resolved runtime knobs included at start event
  • Kept existing retry policy and endpoint response contracts unchanged.
  • Expanded phase21 relay hardening tests to assert telemetry behavior:
    • started/retrying/succeeded event presence
    • failed event telemetry fields
    • stable relayRequestId across lifecycle events for one request

Validation:

  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (7/7)
  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next step: map these lifecycle fields into central dashboards/alerts (retry rate, status-class distribution, p95 elapsedMs).

CL-034: TASK22242 per-endpoint relay overrides + idempotency-aware retry gating

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayForwarding.js, tests/phase21/relay-forwarding-hardening.test.cjs type: change rationale: Deliver the next functional relay enhancement by enabling route-level retry tuning while adding safe-by-default retry gating for non-idempotent methods. impact: Improves control and safety of relay retries without breaking existing endpoint contracts. status: completed

Summary:

  • Added relay policy override support (relayPolicy) to shared relay helpers (relayGet, relayGetData, forwardGetData):
    • per-call override of timeoutMs, maxRetries, retryBaseDelayMs, retryMaxDelayMs
    • optional method override via relayPolicy.method
  • Added idempotency-aware retry gating scaffolding:
    • retries allowed by default only for idempotent methods (GET, HEAD, OPTIONS)
    • non-idempotent retry behavior controlled by:
      • env flag RELAY_ALLOW_NON_IDEMPOTENT_RETRIES (default false)
      • per-call override relayPolicy.allowNonIdempotentRetries
  • Extended relay telemetry fields to include method and non-idempotent policy posture in start/failure/retry events.
  • Preserved existing route behavior:
    • existing GET endpoint flows continue to use retries per configured bounds
    • no endpoint response contract changes

Validation:

  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (10/10)
  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (152/152)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Future non-GET relay adoption should explicitly opt in/out per route using relayPolicy and include targeted negative-path tests.

CL-035: TASK22242 apply relayPolicy overrides across broader endpoint cluster

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getaccounts_api,getemailaccountcheck_api,getpreferredlanguage_api,getpersonalaccount_api,getlogin_api,getbasicsearch_api,getbasicsearchpaged_api,getadvancedsearch_api,getadvancedsearchpaged_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Expand practical adoption of per-endpoint relay policy tuning so high-traffic account/login/search handlers explicitly declare timeout/retry posture rather than relying only on global defaults. impact: Better operational control and predictable retry behavior per endpoint cluster, with no API contract changes. status: completed

Summary:

  • Added explicit relayPolicy usage to a broader endpoint set:
    • account/login: getaccounts, getemailaccountcheck, getpreferredlanguage, getpersonalaccount, getlogin
    • search: getbasicsearch, getbasicsearchpaged, getadvancedsearch, getadvancedsearchpaged
  • Applied conservative policy profiles by flow:
    • login endpoint (getlogin): no retries (maxRetries: 0) and tighter timeout
    • account lookup endpoints: low retry posture (maxRetries: 1)
    • search endpoints: bounded retry posture (maxRetries: 2) for transient resilience
  • Kept method explicit as GET in policy for clarity and future-proofing.
  • Extended phase21 endpoint tests with relayPolicy propagation assertions:
    • getaccounts relayPolicy pass-through
    • getlogin strict relayPolicy pass-through
    • getbasicsearchpaged relayPolicy pass-through

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (155/155)
  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (10/10)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next slice: apply relayPolicy declarations to remaining relayGet endpoints in coherent batches (portal module/documents/DNS groups) and standardize policy presets in one shared constants module.

CL-036: TASK22242 portal-facing relayPolicy parity (login + module endpoints)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getportallogin_api,getportalloginproxy_api,getportalmoduledetails_api,getportalmoduledetailsproxy_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Complete the next practical relay policy rollout slice by bringing portal-facing login/module endpoints onto explicit per-endpoint timeout/retry posture. impact: Improves predictability and operational tuning for portal-facing relay GET flows without changing API contracts. status: completed

Summary:

  • Added explicit relayPolicy for four portal-facing endpoints:
    • getportallogin_api -> strict/no-retry profile (maxRetries: 0, tighter timeout)
    • getportalloginproxy_api -> low-retry account lookup profile (maxRetries: 1)
    • getportalmoduledetails_api -> bounded read profile (maxRetries: 2)
    • getportalmoduledetailsproxy_api -> bounded read profile (maxRetries: 2)
  • Kept method explicit (GET) in each endpoint policy object.
  • Extended phase21 endpoint tests with relayPolicy propagation assertions for all four endpoints.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (159/159)
  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (10/10)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next slice: extract shared relay policy presets into constants to reduce duplication and enforce profile consistency across remaining relayGet endpoints.

CL-037: TASK22242 portal/my-cases relayPolicy parity (my portal + representations)

date: 2026-03-24 author: Cline scope: pages/api/endpoint/{getmycases_api,getmyrepresentations_api,getwatchedcases_api,getawaitingsubmission_api,getrepresentations_api}.js, tests/phase21/endpoint-handler-contract.test.cjs type: change rationale: Continue the branch-by-branch relay policy rollout by applying explicit policy posture to core my-portal retrieval endpoints. impact: Improves consistency and operational predictability of relay behavior for portal case/representation listing flows without changing endpoint contracts. status: completed

Summary:

  • Added explicit relayPolicy declarations to:
    • getmycases_api
    • getmyrepresentations_api
    • getwatchedcases_api
    • getawaitingsubmission_api
    • getrepresentations_api
  • Applied bounded read profile across the batch:
    • method: "GET"
    • timeoutMs: 8000
    • maxRetries: 2
    • retryBaseDelayMs: 150
    • retryMaxDelayMs: 800
  • Extended phase21 endpoint contract tests with relayPolicy pass-through assertions for each endpoint.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (164/164)
  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (10/10)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next slice: extract shared relay policy presets into a constants module and reference them from all relayGet endpoints to reduce duplication.

CL-038: TASK22242 P2-S3 closure slice — shared relay policy presets extraction

date: 2026-03-24 author: Cline scope: pages/api/middleware/relayPolicyPresets.js, pages/api/endpoint/{getaccounts_api,getemailaccountcheck_api,getpreferredlanguage_api,getpersonalaccount_api,getlogin_api,getportallogin_api,getportalloginproxy_api,getbasicsearch_api,getbasicsearchpaged_api,getadvancedsearch_api,getadvancedsearchpaged_api,getportalmoduledetails_api,getportalmoduledetailsproxy_api,getmycases_api,getmyrepresentations_api,getawaitingsubmission_api,getrepresentations_api,getwatchedcases_api}.js, tests/phase21/_shared.cjs type: change rationale: Complete the planned P2-S3 final maintainability slice by centralizing repeated relay timeout/retry policy objects into shared presets used consistently across all targeted relayGet endpoints. impact: Eliminates duplicated policy literals, reduces drift risk, and preserves endpoint contracts/behavior by reusing equivalent policy values. status: completed

Summary:

  • Added new middleware constants module:
    • pages/api/middleware/relayPolicyPresets.js
    • RELAY_POLICY_STRICT_LOGIN
    • RELAY_POLICY_LOOKUP
    • RELAY_POLICY_BOUNDED_READ
    • RELAY_POLICY_SEARCH_PAGED
  • Refactored 18 relayGet endpoints to import and use shared presets instead of inline relayPolicy object literals:
    • lookup profile: getaccounts, getemailaccountcheck, getpreferredlanguage, getpersonalaccount, getportalloginproxy
    • strict login profile: getlogin, getportallogin
    • bounded read profile: getbasicsearch, getportalmoduledetails, getportalmoduledetailsproxy, getmycases, getmyrepresentations, getawaitingsubmission, getrepresentations, getwatchedcases
    • search paged profile: getbasicsearchpaged, getadvancedsearch, getadvancedsearchpaged
  • Updated phase21 VM test harness (tests/phase21/_shared.cjs) to inject preset constants so endpoint contract tests continue to execute with import-stripped modules.

Validation:

  • node tests/phase21/endpoint-handler-contract.test.cjs -> pass (164/164)
  • node tests/phase21/relay-forwarding-hardening.test.cjs -> pass (10/10)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • P2-S3 planned slices are now complete; no further mandatory relay policy rollout slices remain for this stream.

CL-039: TASK22260 actions façade increment — shared relay client extraction

date: 2026-03-25 author: Cline scope: actions/clients/{relayClient,index}.js, actions/services/{accountDirectService,portalDirectService,documentDirectService}.js, actions/index.js, actions/clients/README.md type: change rationale: Continue Priority 1 façade decomposition by extracting duplicated hash-signing relay helper logic into a dedicated client module while preserving existing service/public export contracts. impact: Reduces duplication and drift risk in security-sensitive relay signing helper logic without changing call-site behavior. status: completed

Summary:

  • Added a new shared client wrapper:
    • actions/clients/relayClient.js exporting buildHashedQueryUrl
  • Added actions/clients/index.js barrel and exposed client exports via actions/index.js.
  • Updated direct services to consume shared relay client helper instead of duplicating local helper implementations:
    • actions/services/accountDirectService.js
    • actions/services/portalDirectService.js
    • actions/services/documentDirectService.js
  • Updated actions/clients/README.md to reflect the now-implemented relay client extraction and future incremental client split path.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)
  • Verified no remaining duplicated local buildHashedQueryUrl definitions across actions/services/*DirectService.js

Follow-ups:

  • Optional next TASK22260 increment: extract common axios invocation helpers into dedicated clients (endpointClient, fileClient, notifyClient) while keeping actions/index.js API stable.

Addendum (same TASK22260 slice):

  • Added shared endpointClient with getJson and requestJson helpers (actions/clients/endpointClient.js) and exported it via actions/clients/index.js.
  • Migrated additional direct services to consume shared endpoint client helpers:
    • actions/services/notifyDirectService.js (POST via requestJson)
    • actions/services/integrationDirectService.js (POST via requestJson)
    • actions/services/adminDirectService.js (GET flows via getJson)
  • Updated actions/clients/README.md to include endpointClient in current extracted clients.

CL-040: TASK22260 next slice — reference-data direct service endpointClient adoption

date: 2026-03-25 author: Cline scope: actions/services/referenceDataDirectService.js, actions/clients/README.md type: change rationale: Continue the incremental façade/client adoption stream by migrating another bounded direct-service module to shared endpoint request helpers. impact: Reduces axios boilerplate and centralizes JSON extraction behavior for reference-data requests without changing public call signatures. status: completed

Summary:

  • Migrated actions/services/referenceDataDirectService.js from direct axios.get(...).then(res => res.data) patterns to shared getJson(...) helper from actions/clients/endpointClient.
  • Preserved existing error behavior:
    • logAndReturnEmptyValueErrorResponse for appeals/project/LPA fetches
    • consoleLogger catch handling for form/mandatory/picklist/notice fetches
  • Updated actions/clients/README.md usage notes to include reference-data service reuse.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Next optional bounded slice: adopt getJson/requestJson for selected low-risk read paths in searchDirectService or caseDirectService while preserving per-function error semantics.

CL-041: TASK22260 next slice — account direct service endpointClient adoption

date: 2026-03-25 author: Cline scope: actions/services/accountDirectService.js type: change rationale: Continue incremental façade migration by moving account direct-service request plumbing onto shared endpoint client helpers while preserving existing error-return behavior contracts. impact: Reduces duplicated axios response extraction boilerplate and aligns account service request handling with the emerging client-layer pattern. status: completed

Summary:

  • Refactored actions/services/accountDirectService.js to consume shared endpoint client helpers:
    • getJson(...) for GET requests
    • requestJson(...) for config-based POST requests
  • Kept existing relay hash-signing behavior unchanged via buildHashedQueryUrl from relayClient.
  • Preserved existing catch-path semantics, including:
    • logging with consoleLogger
    • returning JSON.stringify(error) in portal login functions
    • returning error.response in preferred-language failure path

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: adopt endpoint client helpers in selected portalDirectService GET/POST helper paths while preserving delete/hash flow semantics.

CL-042: TASK22260 next slice — portal direct service partial endpointClient adoption

date: 2026-03-25 author: Cline scope: actions/services/portalDirectService.js type: change rationale: Continue phased client-layer adoption by migrating low-risk portal direct-service read/create paths to shared endpoint request helpers while leaving hash-sensitive delete/message flows unchanged. impact: Reduces duplicated axios response extraction on high-traffic portal retrieval paths and keeps hashed delete/message semantics stable. status: completed

Summary:

  • Refactored selected portalDirectService functions to use shared endpoint client helpers:
    • getJson(...) for read/listing routes (getMyCases, getMyInvolvements, getMyLPACases, representations, watched, awaiting submission variants)
    • requestJson(...) for createWatchedCases
  • Preserved existing hash/delete/message flow implementations (deleteMyRepresentations, deleteWatchedCases, completion message functions) using existing axios + relay signing behavior.
  • Preserved existing catch-path logging behavior for all migrated functions.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: migrate remaining non-hash POST helpers in portalDirectService (setRepInvolvment, setCaseInvolvment) to requestJson for full internal consistency.

CL-043: TASK22260 next slice — portal involvement helper endpointClient completion

date: 2026-03-25 author: Cline scope: actions/services/portalDirectService.js type: change rationale: Complete the next bounded internal-consistency slice by migrating remaining non-hash portal involvement POST helpers to shared endpoint client request plumbing. impact: Aligns portal service POST helper internals with established requestJson usage while preserving route semantics and error handling. status: completed

Summary:

  • Migrated remaining portal involvement helper POST functions to shared endpoint client:
    • setRepInvolvment
    • setCaseInvolvment
  • Both now use requestJson(config) while preserving existing payload shape, endpoint URLs, and catch-path logging behavior.
  • No changes made to hash-sensitive delete/message pathways.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: begin selective requestJson adoption for remaining config-based calls in documentDirectService where hash flow is already centralized.

CL-044: TASK22260 next slice — document direct service low-risk getJson adoption

date: 2026-03-25 author: Cline scope: actions/services/documentDirectService.js type: change rationale: Continue incremental façade/client rollout by migrating low-risk document service GET wrappers that already return JSON and do not alter hash-signing semantics. impact: Reduces duplicated axios .get(...).then(res => res.data) boilerplate and aligns document retrieval helpers with shared endpoint client usage. status: completed

Summary:

  • Added getJson usage in selected document service helpers:
    • getRepsFromBlobProxy
    • getAwaitingSubmissionFromBlobProxy
    • getFilesFromBlobproxy
    • getFilesFromBlobHashed
    • getProgressFromBlob
    • createContainerProxy
  • Preserved existing behavior contracts:
    • same query composition and hash query fragments
    • same catch-path logging and return conventions (including JSON string return in createContainerProxy error path)
  • Left hash-sensitive delete/upload/generation flows unchanged in this slice.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: migrate selected requestJson-eligible upload/generation helpers in documentDirectService (non-download paths) while preserving multipart/blob behavior.

CL-045: TASK22260 next slice — document direct service requestJson adoption (uploads + PDF generation)

date: 2026-03-25 author: Cline scope: actions/services/documentDirectService.js type: change rationale: Continue bounded client migration by moving config-based multipart/PDF POST helpers in document service to shared requestJson while preserving hashed URL generation and responseType behavior. impact: Reduces repeated axios config execution boilerplate and aligns document POST helper internals with shared endpoint client conventions. status: completed

Summary:

  • Migrated selected config-based document helper flows from axios(config) + res.data to requestJson(config):
    • uploadFiles
    • uploadSingleFile
    • uploadRepFiles
    • generateRepPDF
    • generateAppealPDF
  • Preserved behavior-critical aspects:
    • hashed URL creation via buildHashedQueryUrl(...)
    • multipart headers for upload flows
    • conditional responseType: "blob" for download PDF option paths
    • existing catch-path logging semantics
  • Left delete/download/hash-sensitive GET helpers unchanged in this slice.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: evaluate remaining legacy direct axios.get(...).then(res.data) helpers in documentDirectService (getAwaitingSubmissionFromBlob, getRepsFromBlob, getFilesFromBlob) for safe migration while preserving signed hash path behavior.

CL-046: TASK22260 next slice — document direct service remaining signed GET helper migration

date: 2026-03-25 author: Cline scope: actions/services/documentDirectService.js type: change rationale: Complete the remaining low-risk read helper migration in document service by replacing final direct axios.get(...).then(res.data) patterns with shared getJson while retaining hash/signature query construction. impact: Finishes consistency pass for JSON-returning document read helpers and reduces duplicated response extraction logic. status: completed

Summary:

  • Migrated the remaining signed document read helpers to getJson(...):
    • getAwaitingSubmissionFromBlob
    • getRepsFromBlob
    • getFilesFromBlob
  • Preserved existing behavior:
    • same BASE_URL and hash query composition via hashAPIPath(...)
    • same catch-path logging behavior (consoleLogger)
    • no changes to delete/download flows or hash-signing helper usage in mutation paths

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: targeted hygiene in documentDirectService to isolate remaining non-migrated special-case flows (downloadBlob, delete helpers) and assess if any shared client abstraction is beneficial without altering behavior.

CL-047: TASK22260 next slice — case direct service low-risk getJson adoption

date: 2026-03-25 author: Cline scope: actions/services/caseDirectService.js type: change rationale: Continue incremental endpoint client rollout with a bounded low-risk set of case service GET helpers that already return direct JSON payloads and have simple logging-only catch paths. impact: Reduces repeated axios GET/response extraction boilerplate and aligns additional case retrieval helpers with shared client conventions. status: completed

Summary:

  • Added getJson usage in selected caseDirectService helper functions:
    • getAppealPDFDocs
    • getPortalModuleDetails
    • getPortalModuleDetailsProxy
  • Preserved existing behavior contracts:
    • same request URL/query construction
    • same catch-path logging via consoleLogger
    • no change to handlers with bespoke error-return contracts (getAppealPDFDocument) or other non-targeted flows.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: migrate additional safe case service GET helpers that currently use axios.get(...).then(res.data) to getJson where custom catch behavior is compatible.

CL-048: TASK22260 next slice — case direct service GET cluster expansion

date: 2026-03-25 author: Cline scope: actions/services/caseDirectService.js type: change rationale: Continue phased endpoint client adoption by migrating another bounded set of case service GET helpers that already use shared catch handling (logAndReturnResponse). impact: Further reduces duplicated axios GET/response extraction boilerplate while preserving existing error-handling contracts for migrated paths. status: completed

Summary:

  • Migrated additional case retrieval helpers from axios.get(...).then(res.data) to getJson(...):
    • getCaseMessage
    • getIncidentbyID
    • getIsPublishedbyID
    • getPartSavedAppeal
    • getSIPSEvents
    • getSIPSMedia
  • Preserved behavior contracts:
    • unchanged URLs/query parameter composition
    • unchanged catch behavior via logAndReturnResponse
    • left non-targeted/bespoke flows untouched (getAppealID, create/update/patch operations, and error-response-specialized helpers)

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: evaluate remaining GET helpers in caseDirectService with custom catches (getCase, getCaseByID, getAppealPDFDocument) for selective migration where return-shape contracts remain stable.

CL-049: TASK22260 next slice — case direct service remaining GET helper migration

date: 2026-03-25 author: Cline scope: actions/services/caseDirectService.js type: change rationale: Complete the remaining safe GET-helper client migration in case service by moving custom-catch read functions to getJson while preserving their existing return-shape/error handling behavior. impact: Removes remaining direct axios GET response-extraction boilerplate in case read helpers and completes endpointClient read-path consistency for this service subset. status: completed

Summary:

  • Migrated remaining targeted case read helpers from direct axios.get(...).then(res.data) to getJson(...):
    • getCase
    • getCaseByID
    • getAppealPDFDocument
  • Preserved behavior contracts:
    • unchanged request URL/query construction
    • unchanged catch semantics:
      • getCase / getCaseByID still log via consoleLogger
      • getAppealPDFDocument still logs and returns error.response on failure
    • left non-targeted POST/update/create/patch flows unchanged.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: evaluate config-based POST helpers in caseDirectService (createNewCase, createNewCaseBlob, updateCase, updateCaseBlob) for selective requestJson(...) adoption while preserving existing side effects and error contracts.

CL-050: TASK22260 next slice — case direct service POST helper requestJson adoption

date: 2026-03-25 author: Cline scope: actions/services/caseDirectService.js type: change rationale: Continue bounded client-layer migration by moving config-based case service POST helpers from direct axios(config) usage to shared requestJson(...) while preserving current behavior and error semantics. impact: Reduces duplicated config-execution/response-extraction boilerplate and aligns case service write-helper internals with existing endpoint client conventions. status: completed

Summary:

  • Migrated selected case service POST helpers to requestJson(config):
    • createNewCase
    • createNewCaseBlob
    • updateCase
    • updateCaseBlob
  • Preserved behavior contracts:
    • unchanged payload/query construction and URLs
    • unchanged catch-path logging via consoleLogger
    • no changes to non-targeted helper logic (getAppealID, patchCase, and already-migrated GET helpers)

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: assess patchCase and getAppealID for migration opportunities (if/when preserving their specific behavior contracts remains straightforward).

CL-051: TASK22260 next slice — case direct service final axios dependency removal

date: 2026-03-25 author: Cline scope: actions/services/caseDirectService.js type: change rationale: Complete the bounded case service migration by replacing the remaining direct axios usage (getAppealID, patchCase) with shared endpoint client reads, enabling removal of the direct axios import. impact: Finalizes endpoint client consistency in case service and removes remaining direct axios dependency from this module without changing helper contracts. status: completed

Summary:

  • Migrated remaining direct axios-based read helpers to getJson(...):
    • getAppealID
    • patchCase
  • Preserved behavior contracts:
    • getAppealID still extracts first non-underscore key value from returned entity and logs on failure
    • patchCase still swallows failure (no explicit returned error contract introduced)
  • Removed now-unused axios import from caseDirectService.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: review other direct service modules for any remaining legacy axios import usage now that case service migration is complete.

CL-052: TASK22260 next slice — portal direct service requestJson parity for config-based reads/deletes

date: 2026-03-25 author: Cline scope: actions/services/portalDirectService.js type: change rationale: Continue bounded direct-service consistency by migrating remaining config-based portal helper calls from axios(config) to shared requestJson(...) where no signed-delete/header-specific behavior is required. impact: Reduces repeated config execution/response extraction boilerplate and improves request helper consistency in portal service while preserving behavior. status: completed

Summary:

  • Migrated selected config-based helpers to requestJson(config):
    • deleteAwaitingSubmissions
    • sendCaseCompleteMessage
    • sendCaseCompleteMessageProxy
    • sendRepCompleteMessage
  • Preserved behavior contracts:
    • unchanged query/hash composition and request methods
    • unchanged catch-path logging via consoleLogger
    • left signed delete helpers with bespoke axios/header behavior unchanged (deleteMyRepresentations, deleteWatchedCases)

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: assess whether signed-delete helpers in portalDirectService should remain explicit axios calls (for clarity on headers/hash semantics) or move to a dedicated signed-request client helper.

CL-053: Architecture documentation update — current-state assessment + prioritised roadmap

date: 2026-03-25 author: Cline scope: context/architecture.md type: change rationale: User requested the architectural assessment be documented in-project so current state, residual risks, and recommended sequencing are explicitly captured for team planning. impact: Improves documentation clarity and planning alignment; no runtime behavior changes. status: completed

Summary:

  • Added a new section to context/architecture.md:
    • Current State Assessment and Prioritised Next Steps (2026-03-25)
  • Documented:
    • strengths (governance maturity, API/relay hardening progress, façade decomposition progress)
    • residual risks/gaps (remaining direct-service inconsistency, coverage concentration, logging variance, i18n parity automation gap)
    • prioritised next steps with rationale
    • recommended execution sequencing (immediate/next/after)

Validation:

  • Manual coherence check against existing guardrails/runbook/integration-map and memory-bank context.

Follow-ups:

  • Optional: convert the prioritised steps into a sprint-ready plan (tasks, acceptance criteria, validation matrix, rollback notes).

CL-054: Branch correction — include residual duplication/axios risk slices (search + signed-delete portal flows)

date: 2026-03-25 author: Cline scope: actions/services/{portalDirectService,searchDirectService}.js, context/architecture.md type: change rationale: User requested the previously identified primary remaining technical risk slices be explicitly included on this branch, specifically residual axios/duplication in search direct service and signed-delete portal helper flows. impact: Further reduces direct-service axios boilerplate/duplication and aligns additional high-use service paths to shared endpoint client patterns while preserving existing behavior contracts. status: completed

Summary:

  • Implemented the requested risk slices on branch:
    1. Portal signed-delete flow parity (portalDirectService)
      • migrated signed delete helpers from direct axios({...}).then(res.data) to requestJson({...}):
        • deleteMyRepresentations
        • deleteWatchedCases
      • removed now-unused axios import from module
      • preserved hash-signing flow and custom headers semantics
    2. Search direct service axios reduction (searchDirectService)
      • migrated service GET helpers from direct axios.get(...).then(res.data) and axios(config) to getJson(...)
      • preserved existing catch semantics (logAndReturnResponse, logAndReturnEmptyValueErrorResponse, and explicit throw path in getSearchDocumentDetails)
      • removed direct axios import from module
  • Documentation alignment:
    • retained architecture assessment section in context/architecture.md that calls out these residual-risk slices and prioritisation.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: assess whether a dedicated signed-request client helper should encapsulate hash + headers + method conventions to prevent future drift in remaining signed flows.

CL-055: TASK22260 next slice — document direct service signed/delete axios reduction

date: 2026-03-25 author: Cline scope: actions/services/documentDirectService.js type: change rationale: Execute next bounded risk-reduction slice by migrating remaining non-download document-service delete and signed-get helper calls away from direct axios response extraction to shared endpoint clients. impact: Further reduces duplicated axios boilerplate and aligns document service internals with shared request-client conventions while preserving existing hash/query and catch-path behavior. status: completed

Summary:

  • Migrated signed hashed delete-helper flows from direct axios({...}).then(res.data) to requestJson({...}):
    • deleteAwaitingSubmissionsFromBlob
    • deleteMyRepresentationsFromBlob
  • Migrated delete helper GET calls from axios.get(...).then(res.data) to getJson(...):
    • deleteBlob
    • deleteRepBlob
  • Preserved behavior contracts:
    • unchanged query/hash composition and endpoint URLs
    • unchanged catch-path logging with consoleLogger
  • Left downloadBlob unchanged in this slice (special-case behavior path retained for separate focused handling).

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: isolate and correct downloadBlob behavior in documentDirectService (including legacy res usage) behind an explicit, tested contract.

CL-056: TASK22260 next slice — document direct service download helper contract fix

date: 2026-03-25 author: Cline scope: actions/services/documentDirectService.js type: change rationale: Execute the next bounded follow-up by correcting the legacy downloadBlob service helper path that still relied on invalid res references and direct axios usage, aligning it to shared request client behavior. impact: Fixes a service-layer contract defect risk in document download helper and improves consistency by using shared request client patterns; no endpoint contract change. status: completed

Summary:

  • Refactored downloadBlob(containerName, blobName) in documentDirectService:
    • removed legacy direct axios.get(...).then(response => res.status(...)) pattern that referenced undefined res in service layer
    • now returns blob response data via requestJson({ method: "get", url, responseType: "blob" })
    • preserved catch-path logging (consoleLogger)
  • Removed now-unused module-level axios import from documentDirectService.

Validation:

  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: add a focused test (or integration harness assertion) around downloadBlob service return contract to prevent regression to response-object assumptions.

CL-057: TASK22260 next slice — phase7 behavioural harness compatibility update

date: 2026-03-25 author: Cline scope: tests/phase7/service-behaviour.test.cjs type: change rationale: After service-layer client migration (getJson/requestJson/buildHashedQueryUrl), phase7 behavioural harness still assumed direct axios imports only; update harness defaults so legacy behavior assertions remain executable. impact: Restores service behavioural regression coverage (12/12) without changing production runtime code. status: completed

Summary:

  • Enhanced phase7 VM loader default injections for migrated service helpers:
    • added default getJson(...) mock delegating to axios.get(...).then(res.data)
    • added default requestJson(...) mock delegating to axios(config).then(res.data)
    • added default buildHashedQueryUrl(...) mock resolving hash via /api/endpoint/gethash_api compatibility path
  • Updated notify behavior assertions to align with shared request client usage (requestJson invokes axios config-style call):
    • switched notify test handlers from axios.postHandler to axios.requestHandler
    • assertions now inspect axios.calls[0].config.{url,method,data}

Validation:

  • node tests/phase7/service-behaviour.test.cjs -> pass (12/12)

Follow-ups:

  • Optional next bounded slice: add a small shared test utility for service harness client mocks to reduce future per-file drift as façade migration continues.

CL-058: TASK22260 next slice — phase6 behavioural harness compatibility parity

date: 2026-03-25 author: Cline scope: tests/phase6/service-behaviour.test.cjs type: change rationale: Keep older phase6 behavioural harness aligned with service client-wrapper migration by adding default helper injections required by getJson/requestJson-based direct services. impact: Restores phase6 behavioural regression execution parity (8/8) with no runtime code changes. status: completed

Summary:

  • Updated loadServiceModule default context in tests/phase6/service-behaviour.test.cjs:
    • added default getJson(...) mock backed by axios.get(...).then(res.data)
    • added default requestJson(...) mock backed by axios(config).then(res.data)
  • Preserved existing test assertions and behavior semantics; this is harness-compatibility only.

Validation:

  • node tests/phase6/service-behaviour.test.cjs -> pass (8/8)

Follow-ups:

  • Optional consolidation: extract shared phase6/phase7 VM loader helpers into a single test utility to reduce duplication.

CL-059: TASK22260 next slice — shared service harness extraction (continued bounded risk-reduction)

date: 2026-03-25 author: Cline scope: tests/{serviceHarness,phase6/service-behaviour,phase7/service-behaviour}.cjs type: change rationale: Continue the bounded risk-reduction stream by removing duplicated test harness infrastructure across phase6/phase7 service behavioural suites and centralizing client-wrapper-compatible mocks. impact: Reduces test harness drift risk and keeps client-wrapper migration verification stable across multiple suites, without runtime code changes. status: completed

Summary:

  • Added shared helper module tests/serviceHarness.cjs with reusable:
    • createAxiosMock
    • createLoggerMock
    • createAxiosError
    • loadServiceModule (with default getJson/requestJson/buildHashedQueryUrl injections)
    • normalize
  • Refactored tests/phase6/service-behaviour.test.cjs to import shared harness utilities and remove duplicated local harness implementation.
  • Refactored tests/phase7/service-behaviour.test.cjs to import shared harness utilities and remove duplicated local harness implementation.

Validation:

  • node tests/phase6/service-behaviour.test.cjs -> pass (8/8)
  • node tests/phase7/service-behaviour.test.cjs -> pass (12/12)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded risk-reduction slice: evaluate whether other legacy service test suites can adopt tests/serviceHarness.cjs to standardize migration-era service mocking behavior.

CL-060: TASK22260 next slice — core token helper client-wrapper migration (continued bounded risk-reduction)

date: 2026-03-25 author: Cline scope: actions/core/token.js type: change rationale: Include the identified remaining candidate outside actions/services and continue the bounded risk-reduction stream by removing direct axios response extraction from core token retrieval. impact: Aligns token helper request execution with shared endpoint client conventions while preserving existing token caching and error-return behavior. status: completed

Summary:

  • Refactored getToken in actions/core/token.js:
    • replaced direct axios.post(...).then(res => res.data) chain with shared requestJson({...})
    • migrated function to async/await with equivalent try/catch behavior
    • retained existing semantics:
      • successful token payload cached in cache.tokenResponse
      • failures logged via consoleLogger and returned to caller
  • Removed direct axios dependency from actions/core/token.js in favor of actions/clients/endpointClient.

Validation:

  • node tests/phase21/api-contract-slice1.test.cjs -> pass
    • helper: 4/4
    • file-handler: 53/53
    • email-handler: 12/12
    • endpoint-handler: 164/164
    • documents-handler: 3/3
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded risk-reduction slice: assess whether any remaining non-service utility modules still use promise-chain axios extraction patterns and migrate them to shared clients where behavior contracts remain unchanged.

CL-061: TASK22260 next slice — core token regression coverage addition (bounded hardening)

date: 2026-03-25 author: Cline scope: tests/phase22/core-token-behaviour.test.cjs type: change rationale: Follow the previous core token migration with a bounded verification slice to lock the request-client contract and prevent regression to direct axios extraction patterns. impact: Improves confidence in actions/core/token.js behavior (success + failure semantics) without runtime code changes. status: completed

Summary:

  • Added new focused Phase 22 behavioural test suite:
    • tests/phase22/core-token-behaviour.test.cjs
  • Coverage asserts:
    • getToken success path returns token payload and calls requestJson with expected URL/method/body/headers
    • failure path logs via consoleLogger and returns the original error object
  • Test harness uses VM import stripping consistent with existing phase behavioural suites.

Validation:

  • node tests/phase22/core-token-behaviour.test.cjs -> pass (2/2)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: add this phase22 suite to any aggregate test runner used in CI if/when phase-level suites are centrally orchestrated.

CL-062: TASK22260 next slice — phase22 runner export guard parity (bounded test-harness consistency)

date: 2026-03-25 author: Cline scope: tests/phase22/core-token-behaviour.test.cjs type: change rationale: Continue bounded test-hardening by aligning phase22 test entry behavior with established suite conventions so it can be executed both directly and from aggregate runners. impact: Improves test harness composability and reduces accidental double-execution risk when importing phase22 test suites. status: completed

Summary:

  • Updated tests/phase22/core-token-behaviour.test.cjs to export run and add require.main === module guard.
  • Preserved direct CLI execution behavior while enabling safe module import by aggregate runners.

Validation:

  • node tests/phase22/core-token-behaviour.test.cjs -> pass (2/2)
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: add a dedicated tests/phase22/index.test.cjs aggregate entrypoint if additional phase22 suites are introduced.

CL-063: TASK22260 next slice — phase22 aggregate runner entrypoint (bounded test-runner hardening)

date: 2026-03-25 author: Cline scope: tests/phase22/index.test.cjs type: change rationale: Continue the bounded test-harness stream by introducing a phase-level aggregate runner for phase22, matching established conventions used in other phase suites. impact: Improves consistency and future scalability of phase22 tests by enabling a single entry command as additional phase22 suites are added. status: completed

Summary:

  • Added tests/phase22/index.test.cjs aggregate runner.
  • Runner currently executes core-token-behaviour.test.cjs and prints a phase-level completion line.
  • Exported run and kept direct CLI execution guard parity (require.main === module).

Validation:

  • node tests/phase22/index.test.cjs -> pass
    • core-token: 2/2
    • phase22 combined: pass
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: add additional phase22 suites (e.g., shared-client utility behaviour tests) under this aggregate runner as migration coverage expands.

CL-064: TASK22260 next slice — phase22 client utility behaviour coverage expansion

date: 2026-03-25 author: Cline scope: tests/phase22/{client-utils-behaviour,index}.test.cjs type: change rationale: Execute the next bounded phase22 slice by adding focused behavioural coverage for shared client utilities to reduce regression risk as direct-service/client-wrapper migration continues. impact: Improves confidence in shared client helper contracts (endpointClient, relayClient) and keeps phase22 aggregate suite aligned with new coverage. status: completed

Summary:

  • Added new suite: tests/phase22/client-utils-behaviour.test.cjs.
  • Added assertions for shared client utility behavior:
    • endpointClient.getJson returns axios.get(...).data
    • endpointClient.requestJson returns axios(config).data
    • relayClient.buildHashedQueryUrl appends browser hash-service response
    • server fallback path uses hashAPIPath when HASHKEY is present
    • browser/no-HASHKEY failure path rethrows hash-service error
  • Updated tests/phase22/index.test.cjs to include the new client-utils suite in the phase aggregate runner.

Validation:

  • node tests/phase22/client-utils-behaviour.test.cjs -> pass (5/5)
  • node tests/phase22/index.test.cjs -> pass
    • core-token: 2/2
    • client-utils: 5/5
    • phase22 combined: pass
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: add focused phase22 behavioural coverage for any future shared client wrappers introduced beyond endpointClient/relayClient.

CL-065: TASK22260 next slice — fileClient extraction + phase22 behavioural coverage

date: 2026-03-25 author: Cline scope: actions/clients/{fileClient,index}.js, actions/services/documentDirectService.js, tests/phase22/{file-client-behaviour,index}.test.cjs type: change rationale: Continue bounded shared-client decomposition by extracting repeated file-route request patterns into fileClient and hardening behaviour with dedicated phase22 tests. impact: Reduces request-boilerplate duplication in document service and increases regression confidence for extracted file client helper contracts. status: completed

Summary:

  • Added new shared client wrapper: actions/clients/fileClient.js:
    • getFileJson(url)
    • getSignedFileJson(queryUrl)
    • downloadFileBlob(url)
  • Exported fileClient from actions/clients/index.js (and therefore via actions/index.js barrel path).
  • Migrated a bounded subset of actions/services/documentDirectService.js call sites to fileClient while preserving catch-path logging behavior:
    • getFilesFromBlobproxy -> getFileJson
    • deleteAwaitingSubmissionsFromBlob -> getSignedFileJson
    • deleteMyRepresentationsFromBlob -> getSignedFileJson
    • deleteBlob -> getFileJson
    • deleteRepBlob -> getFileJson
    • downloadBlob -> downloadFileBlob
  • Added tests/phase22/file-client-behaviour.test.cjs covering:
    • delegation to getJson
    • signed URL generation + requestJson invocation
    • blob download config contract (responseType: "blob")
  • Updated aggregate runner tests/phase22/index.test.cjs to include file-client suite.

Validation:

  • node tests/phase22/file-client-behaviour.test.cjs -> pass (3/3)
  • node tests/phase22/index.test.cjs -> pass
    • core-token: 2/2
    • client-utils: 5/5
    • file-client: 3/3
    • phase22 combined: pass
  • npm run lint -> warnings only (pre-existing react-hooks/exhaustive-deps; no new lint errors)

Follow-ups:

  • Optional next bounded slice: evaluate whether additional documentDirectService file-route call sites can adopt fileClient without altering current behavior contracts.