TASK22269: add signed request client and migrate portal deleteWatchedCases pilot

This commit is contained in:
2026-03-25 13:37:49 +00:00
parent 35ff16b2b2
commit 811655c8d2
6 changed files with 120 additions and 10 deletions
+1
View File
@@ -2,3 +2,4 @@ export * from "./relayClient";
export * from "./endpointClient";
export * from "./fileClient";
export * from "./fileRouteBuilder";
export * from "./signedRequestClient";
+38
View File
@@ -0,0 +1,38 @@
import { requestJson } from "./endpointClient";
import { buildHashedQueryUrl } from "./relayClient";
const signedRequestJson = async ({ method, queryUrl, data, config = {} }) => {
const signedUrl = await buildHashedQueryUrl(queryUrl);
return requestJson({
method,
url: signedUrl,
data,
...config
});
};
export const getSignedJson = (queryUrl, config = {}) => {
return signedRequestJson({
method: "get",
queryUrl,
config
});
};
export const postSignedJson = (queryUrl, data, config = {}) => {
return signedRequestJson({
method: "post",
queryUrl,
data,
config
});
};
export const deleteSignedJson = (queryUrl, config = {}) => {
return signedRequestJson({
method: "delete",
queryUrl,
config
});
};
+4 -10
View File
@@ -2,6 +2,7 @@ import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { buildHashedQueryUrl } from "../clients/relayClient";
import { getJson, requestJson } from "../clients/endpointClient";
import { deleteSignedJson } from "../clients/signedRequestClient";
import {
buildFileQuery,
withBaseUrl,
@@ -189,16 +190,9 @@ export const deleteWatchedCases = async (watchedCaseID) => {
watchedCaseID
});
return buildHashedQueryUrl(queryUrl)
.then((signedUrl) =>
requestJson({
method: "delete",
url: signedUrl
})
)
.catch((error) => {
consoleLogger(error);
});
return deleteSignedJson(queryUrl).catch((error) => {
consoleLogger(error);
});
};
export const sendCaseCompleteMessage = async (
+43
View File
@@ -2725,3 +2725,46 @@ Validation:
Follow-ups:
- Sequence A step3 targeted gaps are now covered; further test expansion should be treated as new scope (e.g., deeper end-to-end journey assertions).
---
### CL-076: TASK22269 Slice B1.1 — signed-request helper set + portal pilot signed-flow migration
date: 2026-03-25
author: Cline
scope: `actions/clients/{signedRequestClient,index}.js`, `actions/services/portalDirectService.js`, `tests/{serviceHarness,phase22/portal-service-behaviour}.cjs`
type: change
rationale: Execute Sequence B Workstream B1 pilot by introducing shared signed request helpers (GET/POST/DELETE) and migrating one bounded portal signed flow without broader module rollout.
impact: Reduces duplication and drift risk in hash-signing + method execution paths while preserving existing signed-flow behavior contracts.
status: completed
Summary:
- Added new shared signed-request client helper module:
- `actions/clients/signedRequestClient.js`
- exports:
- `getSignedJson(queryUrl, config?)`
- `postSignedJson(queryUrl, data, config?)`
- `deleteSignedJson(queryUrl, config?)`
- all helpers use existing `buildHashedQueryUrl(...)` + `requestJson(...)` composition to preserve signing semantics
- Exported new helper module via `actions/clients/index.js`.
- Migrated exactly one pilot signed flow in portal service:
- `deleteWatchedCases` in `actions/services/portalDirectService.js`
- from inline `buildHashedQueryUrl(...).then(requestJson(...))` to `deleteSignedJson(queryUrl)`
- preserved existing catch/log behavior (`consoleLogger` + `undefined` return on catch)
- Added test harness compatibility for VM import-stripping suites:
- `tests/serviceHarness.cjs` now injects default `deleteSignedJson` mock behavior.
- Expanded portal behavioral tests with explicit negative-path assertion:
- `tests/phase22/portal-service-behaviour.test.cjs`
- verifies `deleteWatchedCases` logs and safely returns `undefined` when signed delete fails.
Validation:
- `npm run lint` -> pass with warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
- `node tests/phase22/index.test.cjs` -> pass
- portal-service suite now 5/5 including signed-delete failure path
- `node tests/phase7/service-behaviour.test.cjs` -> pass (13/13)
Follow-ups:
- Continue Sequence B B1 in future bounded slices by migrating additional signed flows one module/function cluster at a time (outside this slice).
@@ -134,6 +134,27 @@ test("portal/sendRepCompleteMessage rejects when hash signing fails before reque
assert.strictEqual(logger.calls.length, 0);
});
test("portal/deleteWatchedCases logs and returns undefined when signed delete fails", async () => {
const axios = createAxiosMock();
const logger = createLoggerMock();
const error = createAxiosError(401, "Unauthorized");
const portal = loadServiceModule("portalDirectService.js", {
axios,
BASE_URL: "",
consoleLogger: logger.consoleLogger,
deleteSignedJson: async () => {
throw error;
}
});
const result = await portal.deleteWatchedCases("watch-2");
assert.strictEqual(result, undefined);
assert.strictEqual(logger.calls.length, 1);
assert.strictEqual(logger.calls[0], error);
});
const run = async () => {
let passed = 0;
+13
View File
@@ -126,6 +126,18 @@ const loadServiceModule = (fileName, injected = {}) => {
});
};
const defaultDeleteSignedJson = async (queryUrl, config = {}) => {
const hashedUrl = await (
injected.buildHashedQueryUrl || defaultBuildHashedQueryUrl
)(queryUrl);
return (injected.requestJson || defaultRequestJson)({
method: "delete",
url: hashedUrl,
...config
});
};
const defaultBuildFileQuery = (pathValue, params = {}, options = {}) => {
const { encode = false } = options;
const entries = Object.entries(params).filter(([, value]) => {
@@ -172,6 +184,7 @@ const loadServiceModule = (fileName, injected = {}) => {
getSignedFileJson:
injected.getSignedFileJson || defaultGetSignedFileJson,
downloadFileBlob: injected.downloadFileBlob || defaultDownloadFileBlob,
deleteSignedJson: injected.deleteSignedJson || defaultDeleteSignedJson,
buildHashedQueryUrl:
injected.buildHashedQueryUrl || defaultBuildHashedQueryUrl,
buildFileQuery: injected.buildFileQuery || defaultBuildFileQuery,