refactor(actions): include residual axios-risk slices in branch

This commit is contained in:
2026-03-25 09:43:40 +00:00
parent 94e2ed5831
commit ba7d94d83d
4 changed files with 251 additions and 202 deletions
+2 -9
View File
@@ -1,4 +1,3 @@
import axios from "axios";
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { buildHashedQueryUrl } from "../clients/relayClient";
@@ -129,7 +128,7 @@ export const deleteMyRepresentations = (myRepresentationsID) => {
return buildHashedQueryUrl(queryUrl)
.then((signedUrl) =>
axios({
requestJson({
method: "delete",
url: signedUrl,
headers: {
@@ -142,9 +141,6 @@ export const deleteMyRepresentations = (myRepresentationsID) => {
}
})
)
.then((res) => {
return res.data;
})
.catch((error) => {
consoleLogger(error);
});
@@ -170,14 +166,11 @@ export const deleteWatchedCases = async (watchedCaseID) => {
return buildHashedQueryUrl(queryUrl)
.then((signedUrl) =>
axios({
requestJson({
method: "delete",
url: signedUrl
})
)
.then((res) => {
return res.data;
})
.catch((error) => {
consoleLogger(error);
});
+128 -193
View File
@@ -1,35 +1,25 @@
import axios from "axios";
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { getJson } from "../clients/endpointClient";
import {
logAndReturnResponse,
logAndReturnEmptyValueErrorResponse
} from "./httpServiceUtils";
export const getBasicSearch = (searchString) => {
return axios
.get(
BASE_URL +
"/api/endpoint/getbasicsearch_api?searchString=" +
searchString
)
.then((res) => {
return res.data;
})
.catch(logAndReturnResponse);
return getJson(
BASE_URL +
"/api/endpoint/getbasicsearch_api?searchString=" +
searchString
).catch(logAndReturnResponse);
};
export const getBasicDNSURLSearch = (searchString) => {
return axios
.get(
BASE_URL +
"/api/endpoint/getbasicdnsurlsearch_api?searchString=" +
searchString
)
.then((res) => {
return res.data;
})
.catch(logAndReturnResponse);
return getJson(
BASE_URL +
"/api/endpoint/getbasicdnsurlsearch_api?searchString=" +
searchString
).catch(logAndReturnResponse);
};
export const getAddressSearchPaged = (
@@ -39,23 +29,18 @@ export const getAddressSearchPaged = (
fieldSort,
showNumberOfRecords
) => {
return axios
.get(
"/api/endpoint/getbasicsearch_by_address_paged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
)
.then((res) => {
return res.data;
})
.catch(logAndReturnResponse);
return getJson(
"/api/endpoint/getbasicsearch_by_address_paged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getBasicSearchPaged = (
@@ -65,46 +50,36 @@ export const getBasicSearchPaged = (
fieldSort,
showNumberOfRecords
) => {
return axios
.get(
"/api/endpoint/getbasicsearchpaged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
)
.then((res) => {
return res.data;
})
.catch(logAndReturnResponse);
return getJson(
"/api/endpoint/getbasicsearchpaged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getDNSCoords = () => {
return axios
.get(BASE_URL + "/api/endpoint/getdnscoords_api")
.then((res) => {
return res.data;
})
.catch(logAndReturnEmptyValueErrorResponse);
return getJson(BASE_URL + "/api/endpoint/getdnscoords_api").catch(
logAndReturnEmptyValueErrorResponse
);
};
export const getDNSList = (searchString) => {
return axios
.get(BASE_URL + "/api/endpoint/getdnslist_api")
.then((res) => res.data)
.catch(logAndReturnResponse);
return getJson(BASE_URL + "/api/endpoint/getdnslist_api").catch(
logAndReturnResponse
);
};
export const getBasicDNSSearch = (searchString) => {
return axios
.get(BASE_URL + "/api/endpoint/getbasicdnssearch_api")
.then((res) => res.data)
.catch(logAndReturnResponse);
return getJson(BASE_URL + "/api/endpoint/getbasicdnssearch_api").catch(
logAndReturnResponse
);
};
export const getBasicDNSSearchPaged = (
@@ -113,30 +88,24 @@ export const getBasicDNSSearchPaged = (
fieldSort,
showNumberOfRecords
) => {
return axios
.get(
"/api/endpoint/getbasicdnssearchpaged_api?pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
)
.then((res) => res.data)
.catch(logAndReturnResponse);
return getJson(
"/api/endpoint/getbasicdnssearchpaged_api?pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getAdvancedSearch = (searchString) => {
return axios
.get(
BASE_URL +
"/api/endpoint/getadvancedsearch_api?searchstring=" +
JSON.stringify(searchString)
)
.then((res) => res.data)
.catch(logAndReturnEmptyValueErrorResponse);
return getJson(
BASE_URL +
"/api/endpoint/getadvancedsearch_api?searchstring=" +
JSON.stringify(searchString)
).catch(logAndReturnEmptyValueErrorResponse);
};
export const getAdvancedSearchPaged = (
@@ -146,21 +115,18 @@ export const getAdvancedSearchPaged = (
fieldSort,
showNumberOfRecords
) => {
return axios
.get(
"/api/endpoint/getadvancedsearchpaged_api?searchstring=" +
JSON.stringify(searchString) +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
)
.then((res) => res.data)
.catch(logAndReturnEmptyValueErrorResponse);
return getJson(
"/api/endpoint/getadvancedsearchpaged_api?searchstring=" +
JSON.stringify(searchString) +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnEmptyValueErrorResponse);
};
export const getBasicSearchDetails = async (
@@ -169,20 +135,17 @@ export const getBasicSearchDetails = async (
primaryIdAttribute,
incidentID
) => {
return axios
.get(
BASE_URL +
"/api/endpoint/getbasicsearchdetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
)
.then((res) => res.data)
.catch((error) => {
consoleLogger(error);
});
return getJson(
BASE_URL +
"/api/endpoint/getbasicsearchdetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getBasicPartSavedDetails = (
@@ -191,20 +154,17 @@ export const getBasicPartSavedDetails = (
primaryIdAttribute,
incidentID
) => {
return axios
.get(
BASE_URL +
"/api/endpoint/getbasicpartsaveddetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
)
.then((res) => res.data)
.catch((error) => {
consoleLogger(error);
});
return getJson(
BASE_URL +
"/api/endpoint/getbasicpartsaveddetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getBasicSearchDetailsPaged = async (
@@ -231,8 +191,8 @@ export const getBasicSearchDetailsPaged = async (
)}`;
try {
const res = await axios.get(url);
return res.data.value || [];
const data = await getJson(url);
return data.value || [];
} catch (error) {
consoleLogger(error);
return [];
@@ -240,27 +200,20 @@ export const getBasicSearchDetailsPaged = async (
};
export const getSearchDocumentDetails = (incidentID) => {
return axios
.get(
"/api/endpoint/getsearchdocumentdetails_api?incidentid=" +
incidentID
)
.then((res) => res.data)
.catch((error) => {
consoleLogger(error);
throw error;
});
return getJson(
"/api/endpoint/getsearchdocumentdetails_api?incidentid=" + incidentID
).catch((error) => {
consoleLogger(error);
throw error;
});
};
export const getSearchDocumentTypes = (incidentID) => {
return axios
.get(
"/api/endpoint/getsearchdocumentTypes_api?incidentid=" + incidentID
)
.then((res) => res.data)
.catch((error) => {
consoleLogger(error);
});
return getJson(
"/api/endpoint/getsearchdocumentTypes_api?incidentid=" + incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getSearchDocumentDetailsPaged = (
@@ -271,39 +224,30 @@ export const getSearchDocumentDetailsPaged = (
showNumberOfRecords,
documentType
) => {
return axios
.get(
"/api/endpoint/getsearchdocumentdetailspaged_api?incidentid=" +
incidentID +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords +
"&documentType=" +
documentType
)
.then((res) => res.data)
.catch((error) => {
consoleLogger(error);
});
return getJson(
"/api/endpoint/getsearchdocumentdetailspaged_api?incidentid=" +
incidentID +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords +
"&documentType=" +
documentType
).catch((error) => {
consoleLogger(error);
});
};
export const getLinkedCases = (parentIncidentid) => {
return axios
.get(
"/api/endpoint/getlinkedcases_api?parentincidentid=" +
parentIncidentid
)
.then((res) => {
return res.data;
})
.catch((error) => {
consoleLogger(error);
});
return getJson(
"/api/endpoint/getlinkedcases_api?parentincidentid=" + parentIncidentid
).catch((error) => {
consoleLogger(error);
});
};
export const getAddressSearch = async (searchString) => {
@@ -313,14 +257,5 @@ export const getAddressSearch = async (searchString) => {
var queryUrl =
BASE_URL + "/api/endpoint/getbasicsearch_by_address_api?" + str;
var config = {
method: "get",
url: queryUrl
};
return axios(config)
.then((res) => {
return res.data;
})
.catch(logAndReturnEmptyValueErrorResponse);
return getJson(queryUrl).catch(logAndReturnEmptyValueErrorResponse);
};
+55
View File
@@ -75,3 +75,58 @@ Guidance:
- Do not treat these files as active runtime architecture unless explicitly reactivated.
- If reactivation is proposed, document rationale and rollout/rollback in `memory-bank/change-log.md` and `context/runbook.md`.
## Current State Assessment and Prioritised Next Steps (2026-03-25)
### Assessment summary
The platform has moved into a stronger operational and architectural posture through sustained bounded refactor slices and contract hardening.
Strengths:
1. **Governance maturity is high**
- Guardrails are explicit for auth/session integrity, CSP/security headers, Prisma source-of-truth, relay hash integrity, and EN/CY parity.
2. **API reliability posture has improved materially**
- Endpoint contract hardening and phase21 contract test expansion have reduced inconsistency in negative-path handling.
3. **Relay operations are significantly more robust**
- Shared relay forwarding now includes bounded retry/timeout policy, structured redacted lifecycle logging, and documented rollout/rollback controls.
4. **Façade decomposition is delivering low-risk progress**
- `actions` layer migration to shared clients (`relayClient`, `endpointClient`) is reducing duplicated request boilerplate and lowering drift risk.
Primary residual risks/gaps:
1. **Remaining direct-service inconsistency**
- Some direct services still contain legacy axios/request patterns and bespoke signed-request blocks.
2. **Coverage concentration**
- Contract tests are strong in targeted slices, but end-to-end/high-value journey coverage in sensitive flows remains comparatively sparse.
3. **Logging hygiene variance**
- Structured redaction exists in relay paths, but broader codebase logging still has uneven consistency.
4. **i18n parity assurance remains process-heavy**
- EN/CY parity relies heavily on manual discipline rather than automated parity checks.
### Prioritised next steps
1. **Complete direct-service consistency sweep (low risk, high maintainability)**
- Prioritise `actions/services/searchDirectService.js` for `getJson`/`requestJson` adoption in bounded slices.
- Preserve existing error-return behavior contracts per function.
2. **Consolidate signed-request patterns (medium risk, high security clarity)**
- Introduce a focused signed-request helper for hash-based/signed delete/get pathways currently repeated in service modules.
- Keep existing hash/header semantics unchanged while reducing duplication.
3. **Add high-value regression automation (high value)**
- Add focused automated checks for:
- auth callback/redirect safety
- one signed-delete negative path
- one upload/document authorization negative path
- one EN/CY route parity check
4. **Perform targeted logging hardening in sensitive paths**
- Continue replacing direct/verbose logging in `auth`, `file`, `email`, and account-sensitive endpoint paths with redacted structured logging patterns.
5. **Introduce EN/CY parity CI checks**
- Add automated checks for route rewrite parity and locale key alignment to reduce drift and manual burden.
6. **Continue endpoint sprawl reduction**
- Keep collapsing duplicated proxy/request patterns behind shared helpers in bounded route clusters while preserving public response contracts.
### Recommended execution sequence
- **Sequence A (immediate):** Step 1 + Step 3 (fastest risk reduction per effort)
- **Sequence B (next):** Step 2 + Step 4 (security/logging consistency consolidation)
- **Sequence C (after):** Step 5 + Step 6 (institutionalise parity and reduce long-tail maintenance cost)
+66
View File
@@ -1892,3 +1892,69 @@ Validation:
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.