Files
pedwfrontend/context/portal-api-platform-assessment.md
Robert Bond 27fceffbc9 Merged PR 2413: updated docs
updated docs

Related work items: #23754
2026-06-22 05:36:30 +00:00

90 KiB
Raw Permalink Blame History

Portal API Platform Assessment

Status

Assessment-only.

First bounded slice complete:

  • Slice A — API Family Classification Sample

No refactor, implementation, or runtime behaviour change was performed.

Required context read

The following files were read before this assessment slice:

  • context/architecture.md
  • context/portal-api-security-boundary-assessment.md
  • context/integration-map.md
  • memory-bank/debt-list.md
  • memory-bank/change-log.md

Sample scope

This slice intentionally inspected only the following API areas:

  • pages/api/endpoint
  • pages/api/file
  • pages/api/email
  • pages/api/documents
  • pages/api/auth

This is not a full route catalogue.

Representative sample files reviewed directly:

  • pages/api/endpoint/getbasicsearch_api.js
  • pages/api/endpoint/getmycases_api.js
  • pages/api/endpoint/createcase_api.js
  • pages/api/file/getbloblist.js
  • pages/api/file/upload.js
  • pages/api/file/createappealcompletemessage_api.js
  • pages/api/email/notify.js
  • pages/api/email/getall.js
  • pages/api/documents/download/[id].js
  • pages/api/auth/[...nextauth].js
  • pages/api/auth/resolve-locale.js

Supporting bounded inspection also covered:

  • top-level file listings for each sampled folder
  • pages/api/middleware/*
  • targeted pattern searches inside the sampled folders only

Findings

The sampled API surface already shows a clear split between:

  1. newer helper-oriented relay handlers
    • typically using relayGet(...)
    • standard respondError(...)
    • explicit required-query validation
  2. older direct integration/orchestration handlers
    • typically using axios(...) directly
    • constructing CRM relay URLs manually
    • invoking hashAPIPath(...) inline
    • mixing multiple responsibilities in a single route

The sample suggests the platform is not one uniform API layer, but a mixed platform of:

  • CRM relay facades
  • Azure Storage facades
  • queue/finalisation orchestration routes
  • GOV.UK Notify routes
  • NextAuth/session routes
  • a small number of utility/meta helpers

API family classification

1. CRM relay read

Observed sample indicators:

  • pages/api/endpoint/getbasicsearch_api.js
  • pages/api/endpoint/getmycases_api.js

Characteristics:

  • reads CRM data through relay-backed query URLs
  • often uses relayGet(...)
  • usually validates required query fields first
  • may lightly transform CRM results before returning

Assessment classification:

  • endpoint/ is primarily CRM relay read plus some write variants

2. CRM relay write

Observed sample indicators:

  • pages/api/endpoint/createcase_api.js

Characteristics:

  • uses direct axios(...) with bearer token
  • constructs CRM URL as WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)
  • forwards create/update/patch/delete actions into CRM

Assessment classification:

  • part of endpoint/ is CRM relay write

3. storage/blob read

Observed sample indicators:

  • pages/api/file/getbloblist.js

Characteristics:

  • validates container, casefolderID, hash
  • verifies request integrity with candidate-path hash comparison
  • calls Azure storage helpers such as getBlobs(...)

Assessment classification:

  • part of file/ is storage/blob read

4. storage/blob write

Observed sample indicators:

  • pages/api/file/upload.js

Characteristics:

  • validates upload/body fields and hash
  • uses multipart middleware
  • writes through Azure storage helpers such as createBlob(...) / createRepBlob(...)

Assessment classification:

  • part of file/ is storage/blob write

5. queue/finalisation

Observed sample indicators:

  • pages/api/file/createappealcompletemessage_api.js

Characteristics:

  • reads and rewrites draft/progress blob state
  • updates completion markers
  • writes case blobs
  • triggers completion/finalisation helper createCaseCompleteMessage(...)
  • may also trigger secondary account side effects

Assessment classification:

  • part of file/ is queue/finalisation and mixed orchestration

6. email/notification

Observed sample indicators:

  • pages/api/email/notify.js
  • pages/api/email/getall.js

Characteristics:

  • GOV.UK Notify send operations
  • some routes also fetch CRM/watchlist/document/event data before building email payloads
  • bilingual template selection appears embedded in route logic

Assessment classification:

  • email/ is primarily email/notification
  • some routes are simple send helpers, others are broader orchestration/batch workflows

7. document download

Observed sample indicators:

  • pages/api/documents/download/[id].js

Characteristics:

  • streams a relay-backed document response
  • passes through id + hash
  • sets download headers
  • redirects to /filenotavailable on failure

Assessment classification:

  • documents/ is document download

8. auth/session

Observed sample indicators:

  • pages/api/auth/[...nextauth].js
  • pages/api/auth/resolve-locale.js

Characteristics:

  • NextAuth session establishment and callback handling
  • verification email send
  • locale-aware redirect handling
  • CRM-backed preferred-language resolution

Assessment classification:

  • auth/ is primarily auth/session

9. local utility/meta

Observed sample indicators:

  • pages/api/auth/resolve-locale.js

Characteristics:

  • small helper-style route
  • returns locale metadata rather than handling a full business operation

Assessment classification:

  • some sampled routes behave as local utility/meta, even when they consult CRM

10. middleware/helper

Observed sampled middleware area:

  • pages/api/middleware/apiResponse.js
  • pages/api/middleware/middleware.js
  • pages/api/middleware/relayForwarding.js
  • pages/api/middleware/relayPolicyPresets.js

Characteristics:

  • response envelope helper
  • multipart parsing helper
  • shared relay forwarding helper
  • relay policy presets

Assessment classification:

  • pages/api/middleware/* is clearly middleware/helper

Integration responsibility map

Sampled family Primary responsibility Backing integration classification
pages/api/endpoint read sample (getbasicsearch_api, getmycases_api) CRM query relay CRM relay-backed
pages/api/endpoint write sample (createcase_api) CRM create/write CRM relay-backed
pages/api/file read sample (getbloblist) blob listing/read Azure Storage SDK-backed
pages/api/file write sample (upload) blob upload/write Azure Storage SDK-backed
pages/api/file finalisation sample (createappealcompletemessage_api) draft/blob + completion + account side effects mixed/orchestration
pages/api/email/notify outbound transactional email GOV.UK Notify-backed
pages/api/email/getall CRM/watchlist/document/event aggregation + notify send mixed/orchestration
pages/api/documents/download/[id] streamed document retrieval via relay CRM relay-backed
pages/api/auth/[...nextauth] session/auth + verification email NextAuth-backed with GOV.UK Notify-backed email send and CRM locale lookup
pages/api/auth/resolve-locale locale helper mixed/orchestration leaning local-only utility with CRM lookup
pages/api/middleware/* shared route support local-only

Responsibility notes from the sample

  • endpoint/ is mostly a CRM relay platform family.
  • file/ is mostly an Azure Storage platform family, but includes finalisation/orchestration routes that cross into CRM/account workflows.
  • email/ is not just a thin Notify wrapper; at least one sampled route is an orchestration layer over CRM + Notify.
  • auth/ is centered on NextAuth, but locale and sign-in email behavior pull in CRM and Notify responsibilities.

Repeated patterns observed

Observed only from the bounded sample and targeted searches within sampled folders.

hash validation

Clearly repeated in sampled file/ routes and visible more broadly in sampled-folder searches.

Observed forms:

  • candidate path arrays
  • raw/encoded path variants
  • compare hashAPIPath(candidatePath) against &hash= or ?hash= + provided hash

Examples:

  • pages/api/file/getbloblist.js
  • pages/api/file/upload.js
  • pages/api/file/createappealcompletemessage_api.js

signed request helper usage

Observed in the newer relay family through shared helpers rather than inline hash construction.

Examples:

  • relayGet(...) in getbasicsearch_api.js
  • relayGet(...) in getmycases_api.js

Assessment note:

  • helper usage is present, but not yet universal across sampled families

relay forwarding

Observed strongly in the newer endpoint/ read family.

Characteristics:

  • relayGet(...)
  • relay policy preset import
  • optional transform step
  • structured error envelope

required query validation

Strongly repeated across all sampled families.

Examples:

  • searchString required
  • loggedInUserId required
  • container, casefolderID, hash required
  • id/hash required in download flow

response envelope style

Repeated modern pattern:

  • respondSuccess(...)
  • respondError(...)

Observed across sampled endpoint/file/email routes.

Assessment note:

  • response helpers are widespread in the sample even when integration patterns differ underneath

raw CRM URL building

Repeated in older direct-write/orchestration routes.

Examples:

  • WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)
  • direct axios config objects with bearer headers

Observed in:

  • pages/api/endpoint/createcase_api.js
  • pages/api/email/getall.js
  • visible across targeted searches in multiple sampled folders

Azure blob path construction

Repeated in sampled file/ routes.

Examples:

  • container + casefolderID
  • tempCaseRef + "/" + tempCaseRef + "_case.json"
  • split path handling for representation files using /

logging style

Mixed styles observed:

  • structured-ish redacted console.info(...) in email/notify.js and auth/[...nextauth].js
  • plain console.log(...) in createcase_api.js and documents/download/[id].js
  • consoleLogger(...) used for error logging in many routes

Assessment note:

  • logging style is visibly inconsistent within the sample

Obvious duplication candidates

These are sample-based family-level observations only. No consolidation is recommended yet.

paged / unpaged endpoint variants

Observed from folder listing and targeted search patterns:

  • getbasicsearch_api / getbasicsearchpaged_api
  • getbasicsearchdetails_api / getbasicsearchdetailspaged_api
  • getadvancedsearch_api / getadvancedsearchpaged_api
  • document detail/history paged variants

Classification:

  • likely intentional

Reason:

  • naming and existing contract-hardening history suggest explicit contract variants rather than accidental duplicates

search / detail / history variants

Observed from endpoint/ sample family:

  • search results
  • detail retrieval
  • history retrieval
  • document-type retrieval

Classification:

  • likely intentional

blob list / download / delete variants

Observed from file/ sample family and listings:

  • getbloblist
  • downloadblob
  • deleteblob
  • deleteblobcase
  • deleteblobrep
  • proxy variants

Classification:

  • likely historical

Reason:

  • the split between case/rep/proxy variants and repeated hash-validation shapes suggests growth by accretion

create / update / patch CRM wrappers

Observed from endpoint/ and file/ folder listings plus sample:

  • createcase_api
  • updatecase_api
  • patchcase_api
  • updateaccount_api
  • createaccount_api

Classification:

  • likely historical

Reason:

  • similar direct axios + token + hash + relay URL patterns recur across wrappers

email batch / send helpers

Observed from email/ sample:

  • notify.js as a focused send route
  • getall.js as a broad gather-and-send batch route
  • related support routes getdocuments.js, getevents.js, getmailinglist.js, getcaseref.js

Classification:

  • unclear

Reason:

  • some separation may reflect legitimate batch assembly boundaries, but the family also shows orchestration overlap

Contract-critical families

From the sample, the following families appear contract-critical.

Yes.

Evidence:

  • getbasicsearch_api.js
  • search/detail/history family naming in endpoint/

Why critical:

  • public-facing query/filter/result contracts likely feed core search UI behavior

myportal / dashboard

Yes.

Evidence:

  • getmycases_api.js

Why critical:

  • dashboard and authenticated case-list flows depend on these payloads and identifiers

submission / finalisation

Yes.

Evidence:

  • createappealcompletemessage_api.js

Why critical:

  • this looks like a transition point from draft/blob state into completion/finalisation processing

file upload / download

Yes.

Evidence:

  • upload.js
  • getbloblist.js
  • broader file folder sample

Why critical:

  • these routes underpin draft persistence and user document handling

document download

Yes.

Evidence:

  • documents/download/[id].js

Why critical:

  • direct binary/document delivery contract with failure redirect behavior

auth / session

Yes.

Evidence:

  • auth/[...nextauth].js

Why critical:

  • session establishment, callback routing, verification email, and locale-aware redirects are central platform contracts

email / notification

Yes.

Evidence:

  • email/notify.js
  • email/getall.js

Why critical:

  • user communications, watchlist notifications, and sign-in email flows depend on these contracts

Risks / cautions

This slice is intentionally high-level and sample-based.

Key cautions:

  1. Do not over-generalise from one sample per family
    • especially in endpoint/, where newer helper-based routes and older direct axios routes coexist
  2. Integration responsibility is not always single-system
    • some routes are clearly orchestration routes rather than thin adapters
  3. Naming can conceal contract differences
    • proxy, paged, history, detail, and case/rep variants may preserve subtle caller expectations
  4. The sample confirms structural inconsistency, not implementation priority
    • this assessment does not yet decide what should be consolidated
  5. Auth/email boundaries are cross-cutting
    • auth/[...nextauth].js is not just auth/session; it also includes Notify and CRM locale lookups

Validation performed

Manual inspection and small targeted searches only.

Performed:

  • direct reading of required context files
  • small directory listings for:
    • pages/api/endpoint
    • pages/api/file
    • pages/api/email
    • pages/api/documents
    • pages/api/auth
    • pages/api/middleware
  • direct bounded file inspection of representative samples only
  • targeted pattern searches limited to sampled folders for:
    • relayGet
    • respondError / respondSuccess
    • hashAPIPath
    • axios
    • NotifyClient
    • getPortalLogin
    • locale/redirect handling

Not performed:

  • no repo-wide automated analysis
  • no bulk inventory generation
  • no Python
  • no runtime code changes
  • no lint/tests, because this slice is documentation-only

Recommendation

Next bounded slice only:

Slice B — Endpoint CRM Relay Shape Sample

Inspect a small representative subset within pages/api/endpoint only, split into:

  • public search/read routes
  • authenticated myportal read routes
  • CRM mutation/write routes
  • proxy variants

Goal of Slice B:

  • distinguish newer relayGet(...) handler families from older direct axios + hashAPIPath relay wrappers
  • identify the main contract shapes and the most common wrapper patterns inside endpoint/
  • remain classification-only, with no consolidation proposal yet

Slice B — Endpoint CRM Relay Contract Shape Sample

Required context read

The following files were re-read before Slice B:

  • context/portal-api-platform-assessment.md
  • context/portal-api-security-boundary-assessment.md
  • context/architecture.md
  • memory-bank/change-log.md

Sample scope

Slice B intentionally focused only on:

  • pages/api/endpoint

This remained a representative subset only, not a folder-wide route inventory.

Representative routes reviewed directly:

1. Public read/search

  • getbasicsearch_api.js
  • getbasicsearchpaged_api.js
  • getadvancedsearch_api.js
  • getsearchdocumentdetails_api.js
  • getsearchdocumenthistory_api.js

2. Authenticated/myportal read

  • getmycases_api.js
  • getmyrepresentations_api.js
  • getwatchedcases_api.js
  • getawaitingsubmission_api.js
  • getpersonalaccount_api.js

3. CRM create/write

  • createcase_api.js
  • createaccount_api.js
  • createwatchedcases_api.js

4. CRM update/patch/delete

  • updateaccount_api.js
  • patchcase_api.js
  • deletewatchedcases_api.js
  • deletemyrepresentations_api.js

5. Proxy/pass-through or legacy variants

  • getwatchedcasesproxy_api.js

Supporting bounded inspection also included targeted endpoint-only searches for:

  • relayGet(...)
  • relayGetData(...)
  • axios(...)
  • hashAPIPath(...)
  • respondError(...) / respondSuccess(...)
  • transformData
  • @odata.nextLink
  • common explicit status codes

Findings

The sampled pages/api/endpoint family appears to collapse into a modest number of repeated contract shapes even though the implementation layer is mixed.

The clearest split is:

  1. newer helper-oriented relay read contracts
    • structured request guards
    • relayGet(...)
    • shared response helper usage
    • optional transformData
    • optional relay policy presets
  2. older direct-wrapper mutation contracts
    • getToken()
    • manual queryUrl
    • direct axios(config)
    • WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)
    • explicit method-specific config for create/update/delete

The sample suggests the endpoint layer is not dominated by many bespoke business contracts.

Instead, it looks like a relatively small set of repeated relay contract shapes with route-by-route variations in:

  • validation breadth
  • transforms
  • pagination options
  • identifier type
  • whether the route is read vs write vs delete

Endpoint contract shapes

A. Public CRM read

Observed sample routes:

  • getbasicsearch_api.js
  • getbasicsearchpaged_api.js
  • getadvancedsearch_api.js
  • getsearchdocumentdetails_api.js
  • getsearchdocumenthistory_api.js

Observed shape:

query params
→ CRM relay read
→ optional transform / pagination normalization
→ response

Characteristics:

  • public-style filter or lookup params
  • no route-local session enforcement visible
  • usually relayGet(...)
  • often optional transform stage
  • often @odata.nextLink normalization for paged families

B. User-owned CRM read

Observed sample routes:

  • getmycases_api.js
  • getmyrepresentations_api.js
  • getwatchedcases_api.js
  • getawaitingsubmission_api.js
  • getpersonalaccount_api.js

Observed shape:

contact/user identifier
→ CRM relay read
→ optional transform
→ response

Characteristics:

  • caller supplies loggedInUserId or contactid
  • route validates identifier presence
  • route forwards CRM query via relayGet(...)
  • some routes enrich/flatten CRM response before return

C. CRM create

Observed sample routes:

  • createcase_api.js
  • createaccount_api.js

Observed shape:

payload + identifiers
→ CRM create
→ optional side effects
→ response

Characteristics:

  • req.body plus required identifiers
  • manual relay URL construction
  • direct bearer-token axios config
  • response typically passes upstream CRM response through respondSuccess(...)
  • some routes add secondary side effects (createcase_api.js also writes a case blob)

D. CRM update/patch

Observed sample routes:

  • updateaccount_api.js
  • patchcase_api.js

Observed shape:

record identifier + payload or patch intent
→ CRM patch/update
→ response

Characteristics:

  • single record identifier in query
  • patch body either supplied directly or built in-route
  • direct axios(config) with hashed relay URL

E. CRM delete

Observed sample routes:

  • deletewatchedcases_api.js
  • deletemyrepresentations_api.js

Observed shape:

record identifier
→ CRM delete
→ response

Characteristics:

  • single record identifier required
  • direct axios(config) delete
  • same manual hashed relay URL pattern as create/update wrappers

F. Proxy/pass-through

Observed sample routes:

  • getwatchedcasesproxy_api.js

Observed shape:

caller request
→ relay-backed wrapper
→ optional transform
→ response

Characteristics:

  • structurally very close to corresponding non-proxy read route
  • often preserves nearly identical query and transform logic
  • main distinction is naming/contract boundary rather than drastically different internal shape

G. Lookup/config/support

Observed indirectly in sample and endpoint-only search evidence:

  • account/login/config/lookup families such as getaccounts_api.js, getpreferredlanguage_api.js, getappealtypes_api.js, getformdata_api.js

Observed shape:

lookup key or config selector
→ CRM option/config/query
→ response

Characteristics:

  • frequently helper-oriented relayGet(...)
  • lighter transforms than search/myportal routes
  • often shared response helper/error contracts

H. Upsert/orchestration hybrid

Observed sample route:

  • createwatchedcases_api.js

Observed shape:

payload bindings
→ pre-check / existence lookup
→ create or patch decision
→ CRM write
→ response

Characteristics:

  • not a pure create route
  • combines a read-style pre-check (relayGetData(...)) with a write-style direct axios relay call
  • looks like a distinct hybrid contract shape inside endpoint/

Implementation style map

Newer helper-oriented routes

Strongly represented by sampled public reads, myportal reads, and many proxy/read families.

Typical characteristics:

  • relayGet(...)
  • sometimes relayGetData(...) for supplementary lookups
  • respondError(...) used for input guards
  • shared errorResponse object passed to relay helper
  • optional transformData
  • optional relay policy preset import
  • optional header-builder injection for paged/custom reads

Sample examples:

  • getbasicsearch_api.js
  • getbasicsearchpaged_api.js
  • getadvancedsearch_api.js
  • getsearchdocumentdetails_api.js
  • getsearchdocumenthistory_api.js
  • getmycases_api.js
  • getmyrepresentations_api.js
  • getwatchedcases_api.js
  • getawaitingsubmission_api.js
  • getpersonalaccount_api.js
  • getwatchedcasesproxy_api.js

Older direct-wrapper routes

Strongly represented by sampled create/update/delete families.

Typical characteristics:

  • direct axios(config)
  • explicit getToken() call
  • manual queryUrl
  • manual WEBAPI_URL + queryUrl + hashAPIPath(queryUrl) construction
  • method-specific config (post, patch, delete)
  • direct upstream response passthrough via respondSuccess(...)

Sample examples:

  • createcase_api.js
  • createaccount_api.js
  • updateaccount_api.js
  • patchcase_api.js
  • deletewatchedcases_api.js
  • deletemyrepresentations_api.js

Hybrid routes

Observed route:

  • createwatchedcases_api.js

Typical characteristics:

  • combines helper-oriented pre-check (relayGetData) with direct-wrapper mutation (axios + hashAPIPath)
  • performs route-local branching between post and patch

Contract consistency findings

Request parameter style

Observed pattern:

  • generally explicit and route-local
  • mostly query-string driven for reads and record-targeted mutations
  • body + query combination common for create/update routes

Assessment:

  • partially consistent
  • parameter naming still varies by route family (searchString, searchstring, loggedInUserId, contactid, contactId, incidentid, watchedCaseID, myRepresentationsID)

Response envelope style

Observed pattern:

  • respondError(...) and respondSuccess(...) are broadly used across both newer and older implementations

Assessment:

  • more consistent than implementation style
  • shared response helpers appear to be a stronger common contract layer than the underlying integration code

Error handling

Observed pattern:

  • required-input guards often return 400
  • route-level catch blocks usually convert failures to route-specific coded 400
  • some non-sampled evidence in the folder shows occasional 404 and 405

Assessment:

  • generally consistent at a high level
  • but status-code precision is not fully uniform across the folder

Status codes

Observed sample emphasis:

  • 400 dominates for missing input and upstream failure handling
  • endpoint-only searches show some explicit 404 and 405 usage in other route types

Assessment:

  • mostly normalized but not fully uniform
  • the sampled create/update/delete routes all converge heavily on 400

Logging

Observed pattern:

  • helper-oriented read routes often avoid explicit in-route logging except for special enrichment failures
  • older direct-wrapper routes commonly call consoleLogger(error) in catch blocks
  • some routes retain more bespoke logging around supplementary sub-queries

Assessment:

  • mixed
  • logging is more consistent in direct-wrapper mutations than in complex read/orchestration routes

Transforms

Observed pattern:

  • common in read families
  • used for:
    • title projection
    • flattening/expanding related CRM objects
    • hash-link enrichment
    • document-date fallback
    • @odata.nextLink normalization
    • post-filter enrichment for advanced search

Assessment:

  • transform-heavy read contracts are a real recurring shape
  • not every read route is a thin pass-through

Pagination handling

Observed pattern:

  • paged search/document families require extra params such as orderby, fieldSort, showNumberOfRecords
  • @odata.nextLink normalization is repeatedly applied
  • paged headers are injected through custom request option builders

Assessment:

  • paged read is a distinct repeated contract variant, not just a small option on base reads

Hash/signing assumptions

Observed pattern:

  • helper-oriented reads generally hide relay signing behind shared helper layers
  • older mutations perform route-local hashAPIPath(queryUrl) construction directly
  • some support/lookup routes such as getportallogin_api.js visibly validate caller-provided hash input before relay read

Assessment:

  • signing assumptions are structurally inconsistent across shapes
  • read families usually abstract signing away; direct write/delete families usually expose it explicitly in route code

Rationalisation insight

Evidence from the sample suggests:

  • few repeated contract shapes

More specifically:

  • the folder appears to contain a large number of routes
  • but many of those routes seem to fit into a comparatively small number of recurring patterns:
    • public CRM read
    • user-owned CRM read
    • paged read variant
    • config/lookup read
    • CRM create
    • CRM patch/update
    • CRM delete
    • proxy/pass-through
    • hybrid upsert/orchestration

So the route count likely overstates the number of distinct underlying contract shapes.

Contract-critical cautions

The following sampled contract shapes look high-risk to change.

Public search/read

High caution.

Reason:

  • public-facing search and document contracts likely drive multiple search and case-view experiences
  • paged/unpaged variants may have frontend expectations around filtering, @odata.nextLink, ordering, and transformed fields

Myportal/dashboard reads

High caution.

Reason:

  • these contracts appear central to dashboard, watched-case, representation, and awaiting-submission views
  • transforms such as pinswg_title, watched-case flattening, and title projection may be relied upon directly by callers

Account/profile reads

High caution.

Reason:

  • getpersonalaccount_api.js is a small route shape but contract-critical because it likely underpins profile bootstrap and account editing journeys

Case creation/update

High caution.

Reason:

  • create/update routes use older direct wrappers and sometimes carry side effects beyond the CRM write itself
  • createcase_api.js is especially sensitive because it combines CRM write with blob-side persistence work

Deletion routes

High caution.

Reason:

  • delete contracts are simple in visible shape but operationally sensitive
  • they rely on record identifiers and direct CRM deletion wrappers

Proxy variants

Medium-high to high caution.

Reason:

  • proxy variants often look almost identical to primary routes, which suggests they may exist for compatibility or caller-specific contract reasons rather than redundancy alone

Risks / cautions

  1. Sample bias remains real
    • this slice still used a bounded subset, not all endpoint handlers
  2. Read routes are not all equally simple
    • some helper-based reads are effectively mini-orchestration routes because transforms and supplementary lookups are embedded in them
  3. Route count may exaggerate uniqueness
    • many files appear to be repeated contract variants rather than genuinely new platform shapes
  4. Implementation age and contract shape are related but not identical
    • newer helper-based reads and older direct-wrapper writes are dominant patterns, but hybrid routes like createwatchedcases_api.js show overlap
  5. Security-boundary concerns should not be conflated with this slice
    • Slice B is about platform contract shapes and maintainability patterns, even though the sampled user-owned routes still expose the previously documented identifier-trust model

Validation performed

Manual inspection and bounded searches only.

Performed:

  • re-read required Slice B context files
  • direct inspection of a representative endpoint-only subset across:
    • public read/search
    • authenticated/myportal read
    • CRM create
    • CRM update/patch/delete
    • proxy/pass-through
  • targeted endpoint-only searches for:
    • relayGet(...)
    • relayGetData(...)
    • axios(...)
    • hashAPIPath(...)
    • respondSuccess(...) / respondError(...)
    • transformData
    • @odata.nextLink
    • explicit status code patterns

Not performed:

  • no full endpoint inventory
  • no repo-wide automated analysis
  • no Python
  • no runtime code changes
  • no lint/tests, because this remains documentation-only assessment work

Recommendation

Next bounded slice only:

Slice C — Endpoint Transform and Pagination Pattern Sample

Restrict scope to a representative subset of pages/api/endpoint routes that use:

  • transformData
  • @odata.nextLink normalization
  • paged/unpaged route pairs
  • supplementary relayGetData(...) enrichment

Goal:

  • determine whether transform/pagination behavior itself collapses into a small number of reusable contract sub-patterns
  • stay assessment-only
  • do not propose implementation yet

Slice C — API Maintenance Map & Reuse Baseline

Required context read

The following files were read before Slice C:

  • context/portal-api-platform-assessment.md
  • context/architecture.md
  • context/integration-map.md
  • memory-bank/debt-list.md
  • memory-bank/change-log.md

Findings

The current API surface appears maintainable only with prior local knowledge because folder responsibility and naming have drifted over time.

The strongest current maintenance pattern is:

  • pages/api/endpoint is still the main historical CRM relay catch-all
  • later folders (file, email, documents, auth, admin) were added for newer needs
  • but those later folders are not purely technical or domain-clean boundaries

The result is a maintenance problem of findability first, consistency second:

  1. a developer must often know the history of the route family to know where to look
  2. once found, they must still determine whether the family uses newer shared helpers or older direct wrappers

The codebase does already contain reusable API building blocks, but they are not yet expressed in one obvious maintenance navigation model.

Folder Responsibility Map

pages/api/endpoint

  • Intended responsibility if visible: general portal business-data APIs via CRM relay
  • Actual responsibility based on sampled evidence: broad catch-all for CRM reads, account/profile support, portal user reads, public search, document metadata, lookup/config, and many create/update/delete mutation wrappers
  • Does folder naming still match responsibility? partially
  • Assessment: mixed / historical

Maintenance note:

  • this is still the first place to look for most CRM-backed portal behavior
  • but it is too broad to communicate ownership clearly by folder name alone

pages/api/file

  • Intended responsibility if visible: file/blob/document upload/download operations
  • Actual responsibility based on sampled evidence: Azure Storage blob operations, uploads, draft reads, delete/download/list flows, generated PDFs, finalisation routes, some queue/completion work, and some CRM-adjacent orchestration/involvement routes
  • Does folder naming still match responsibility? only partially
  • Assessment: mixed

Maintenance note:

  • a developer working on drafts/submission may need this folder even when the main change is not “just files”

pages/api/email

  • Intended responsibility if visible: email and notification handling
  • Actual responsibility based on sampled evidence: direct Notify send, mailing list/event/document gathering, watchlist notification batch assembly, and CRM-backed orchestration before send
  • Does folder naming still match responsibility? partially
  • Assessment: mixed

Maintenance note:

  • some email routes are thin notification endpoints, others are multi-step orchestration routes

pages/api/documents

  • Intended responsibility if visible: document download
  • Actual responsibility based on sampled evidence: essentially a narrow direct document download proxy family
  • Does folder naming still match responsibility? yes
  • Assessment: coherent

Maintenance note:

  • the folder is clear, but broader document-related behavior is still split across documents, endpoint, and file

pages/api/auth

  • Intended responsibility if visible: authentication/session routes
  • Actual responsibility based on sampled evidence: NextAuth boundary plus locale-resolution/auth-support logic with CRM preferred-language lookup and Notify email behavior
  • Does folder naming still match responsibility? yes, mostly
  • Assessment: acceptable

Maintenance note:

  • coherent enough for findability, but auth behavior still crosses into CRM and Notify concerns

pages/api/admin

  • Intended responsibility if visible: admin/internal reporting routes
  • Actual responsibility based on sampled evidence: administrative CRM reporting/read APIs, including status counts, latest documents, and new-appeal reporting-style queries
  • Does folder naming still match responsibility? yes
  • Assessment: coherent

Maintenance note:

  • this folder looks like one of the clearest top-level API ownership areas

pages/api/middleware

  • Intended responsibility if visible: shared API support utilities
  • Actual responsibility based on sampled evidence: response envelopes, multipart parsing, shared relay forwarding, relay retry/timeouts/policy presets
  • Does folder naming still match responsibility? yes
  • Assessment: coherent

Maintenance note:

  • this folder already contains some of the strongest reuse primitives for future API work

Top-level utility API files

Reviewed/observed:

  • pages/api/health.js
  • pages/api/doc.ts
  • pages/api/notices/index.js

Assessment:

  • Intended responsibility: utility/meta/support endpoints
  • Actual responsibility: health/status, swagger/openapi docs, static notice feed
  • Does naming still match? mostly yes
  • Assessment: coherent for utility/meta

Maintenance note:

  • these files are easy to find, but they sit alongside folders in a way that reinforces the overall mixed top-level structure

Feature-to-API Maintenance Map

Feature area Likely API folder(s) Likely route family names Integration touched Contract-critical? Folder fit
public search endpoint getbasicsearch*, getadvancedsearch*, getbasicdnssearch* CRM relay yes acceptable
advanced/address search endpoint getadvancedsearch*, getbasicsearch_by_address_api, getbasicsearch_by_lparref_api CRM relay yes acceptable
case details endpoint getcase*, getincidentbyid_api, getcasemessage_api, getlinkedcases_api CRM relay yes acceptable
document download documents, endpoint, file documents/download/[id], getsearchdocumentdetails*, getsearchdocumenthistory*, blob download routes CRM relay, Azure Storage yes confusing
my portal dashboard endpoint, file getmycases_api, getmyrepresentations_api, getwatchedcases_api, getawaitingsubmission_api, draft blob reads CRM relay, Azure Storage yes acceptable
watched cases endpoint getwatchedcases*, createwatchedcases_api, deletewatchedcases* CRM relay yes good
representations endpoint, file getrepresentations*, getmyrepresentations*, representation involvement/completion routes CRM relay, Azure Storage yes acceptable
new appeal drafts file getprogressobjblob, getbloblist, upload*, deleteblobcase, setupcontainer Azure Storage yes acceptable
representation drafts file getrepsblob*, upload*, deleteblobrep, editRepJson Azure Storage yes acceptable
appeal submission/finalisation file, endpoint createappealcompletemessage*, createcase_api, patchcase_api, updatecase_api Azure Storage, Azure Queue, CRM relay yes historical/unclear
representation submission/finalisation file, endpoint createrepcompletemessage_api, involvement routes, representation delete/update families Azure Storage, Azure Queue, CRM relay yes historical/unclear
account registration endpoint, auth createaccount_api, getemailaccountcheck_api, getportallogin_api CRM relay, NextAuth yes acceptable
personal details/account update endpoint getpersonalaccount_api, updateaccount_api, updatepassword_api CRM relay yes acceptable
authentication/sign-in auth, endpoint [...nextauth], resolve-locale, getportallogin_api, getpreferredlanguage_api NextAuth, GOV.UK Notify, CRM relay yes confusing
email/notifications email, auth notify, getall, getdocuments, getevents, next-auth verification email flow GOV.UK Notify, CRM relay yes acceptable
admin/internal reporting admin, endpoint getnewappeals_api, getlatestdocuments_api, status-count routes CRM relay no/mostly internal good

Folder Drift / Naming Drift

Observed maintenance drift areas:

CRM routes living under file

Examples from existing sampled evidence:

  • involvement creation routes
  • completion/finalisation routes
  • case-related orchestration in file

Why it affects maintenance:

  • a developer may not think to search file/ when the change is really about case submission, involvement, or CRM completion side effects

Orchestration routes living under email

Example:

  • pages/api/email/getall.js

Why it affects maintenance:

  • the route is not just “send an email”; it assembles CRM/watchlist/document/event data before notification send

Document behavior split across endpoint, documents, and file

Examples:

  • documents/download/[id].js
  • search document metadata under endpoint
  • blob document/file flows under file

Why it affects maintenance:

  • developers must know whether they are dealing with published CRM-backed document retrieval, draft/blob files, or a direct download proxy before they know where to look

Finalisation routes under file

Examples:

  • createappealcompletemessage_api.js
  • createrepcompletemessage_api.js

Why it affects maintenance:

  • these are not merely file operations; they sit near a business transition boundary from draft to submitted state

Account/auth-support routes under endpoint

Examples:

  • getportallogin_api.js
  • getpreferredlanguage_api.js
  • getemailaccountcheck_api.js
  • getpersonalaccount_api.js

Why it affects maintenance:

  • account and auth-adjacent responsibilities are split between auth/ and endpoint/, which weakens findability

Historical naming conventions

Examples:

  • _api suffix routes
  • proxy variants
  • paged variants
  • details / history / Types variants

Why it affects maintenance:

  • naming often reflects historical delivery slices more than current ownership boundaries
  • similar names can hide materially different caller expectations or integration behavior

Common Building Blocks

relayGet(...)

  • What it standardizes: CRM relay GET forwarding, token/header/hash handling, success response path, error response path, optional transforms
  • Where it is already used: widely across pages/api/endpoint/**, especially read families
  • Preferred for future work? yes, for new CRM read APIs where the route fits the shared relay-read model
  • Do legacy alternatives still exist? yes, many older direct axios wrappers remain

relayGetData(...)

  • What it standardizes: relay-backed data fetches for sub-queries or enrichments without directly writing to res
  • Where it is already used: complex endpoint reads and hybrids such as advanced search enrichment, address/LPA lookups, createwatchedcases_api.js
  • Preferred for future work? yes, where a route needs supplementary relay reads inside orchestration logic
  • Do legacy alternatives still exist? yes, direct axios.get(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl))

respondSuccess(...) / respondError(...)

  • What they standardize: top-level JSON response conventions and coded error envelopes
  • Where they are already used: broadly across endpoint, file, email, admin, and middleware-aware routes
  • Preferred for future work? yes
  • Do legacy alternatives still exist? yes, some raw res.status(...).json(...) patterns still exist in the wider API surface and utility endpoints

Relay policy presets

  • What they standardize: retry/timeout profiles for read families (STRICT_LOGIN, LOOKUP, BOUNDED_READ, SEARCH_PAGED)
  • Where they are already used: many endpoint read routes
  • Preferred for future work? yes, where relay-backed reads need an existing policy profile
  • Do legacy alternatives still exist? yes, older routes without policy presets and direct axios wrappers

signedRequestClient helpers

  • What they standardize: signed GET/POST/DELETE execution using existing hashed URL generation
  • Where they are already used: service/client layer rather than route layer (actions/clients/signedRequestClient.js)
  • Preferred for future work? likely yes for new signed client/service flows
  • Do legacy alternatives still exist? yes, many inline buildHashedQueryUrl and direct request patterns remain outside or beneath this layer

Hash/path validation helpers

  • What they standardize: HMAC path signing and validation expectations (hashAPIPath(...), signed URL generation)
  • Where they are already used: widespread across relay and file/blob flows
  • Preferred for future work? yes, where existing signed route models must be preserved
  • Do legacy alternatives still exist? yes, many route-local manual candidate-path checks and inline hash construction blocks

Azure storage helpers

  • What they standardize: blob/container/queue operations and related metadata assembly
  • Where they are already used: pages/api/file/**, some endpoint/file orchestration flows, service layer helpers
  • Preferred for future work? yes for storage-facing work
  • Do legacy alternatives still exist? some routes still mix storage helpers with route-local orchestration logic rather than remaining thin wrappers

Notify helpers / Notify integration patterns

  • What they standardize: currently more implicit than explicit; direct Notify client usage exists, but some shared behavior lives in service modules and auth flow
  • Where they are already used: pages/api/email/**, pages/api/auth/[...nextauth].js, service layer
  • Preferred for future work? partially; direct Notify usage is established, but orchestration should be chosen deliberately
  • Do legacy alternatives still exist? yes, thin send routes and broad orchestration routes coexist

Auth/session helpers

  • What they standardize: session establishment primarily via NextAuth route; locale support via resolve-locale; broader auth-context helpers live outside pages/api
  • Where they are already used: pages/api/auth/**, SSR/service layers elsewhere in repo
  • Preferred for future work? yes for auth-specific work inside existing NextAuth boundary
  • Do legacy alternatives still exist? account/auth-support behavior still partly lives under endpoint/

Logging helpers

  • What they standardize: consoleLogger(...), redaction helper usage, some structured relay logging
  • Where they are already used: many API routes, especially catch blocks and relay middleware
  • Preferred for future work? yes
  • Do legacy alternatives still exist? yes, direct console.log(...) / console.info(...) still exist in sampled folders

Future Consistency Baseline

This is guidance only for future maintainability work, not an implementation mandate.

Suggested baseline:

  • new CRM read APIs should prefer shared relay helpers such as relayGet(...) where the route fits that contract shape
  • new relay-backed sub-query/enrichment logic should prefer existing helper-style relay fetches rather than bespoke inline wrappers where suitable
  • new JSON responses should prefer respondSuccess(...) / respondError(...)
  • new storage-facing APIs should reuse existing Azure storage helpers and established hash-validation patterns
  • new Notify-facing APIs should keep thin send routes thin, and only mix broader orchestration where there is a clear need
  • new APIs should make it easier to identify:
    • owning feature area
    • integration touched
    • whether the route is contract-critical
  • existing direct axios + hashAPIPath wrappers may remain where behaviour is stable, but they should not be copied blindly into new work when shared helper patterns already exist
  • future API additions should aim to improve findability as well as technical consistency, so developers can more quickly identify the right folder and family before editing

Maintenance Pain Points

The main maintenance pain points visible in this slice are:

Route findability

  • similar behavior is split across multiple top-level folders
  • some folders are historical rather than cleanly responsibility-based

Route name similarity

  • many near-identical names (proxy, paged, details, history, _api) increase scan cost

Folder responsibility overlap

  • CRM behavior exists in endpoint, file, email, auth, and admin
  • document behavior exists in endpoint, documents, and file

Mixed integration responsibilities

  • some folders contain thin wrappers, others contain orchestration routes that cross CRM/storage/Notify boundaries

Older/newer implementation styles

  • helper-oriented relay contracts and older direct wrappers coexist, so developers must determine style before making even a small change

Missing route ownership documentation

  • a future contributor often has to infer “owning feature” from names and code shape rather than from explicit maintenance guidance

Repeated boilerplate and historical growth

  • even where shared helpers now exist, route families still show signs of incremental historical accretion

Risks / Cautions

  1. This is still a bounded maintenance assessment
    • it is not a full route inventory or migration plan
  2. Folder drift does not automatically mean incorrect architecture
    • some historical placements may still reflect practical delivery constraints or compatibility concerns
  3. Reuse guidance should not erase contract-specific nuance
    • some route families genuinely need transforms, enrichments, or special caller behavior
  4. Findability and consistency are related but different problems
    • a route can be technically well-structured yet still be hard to find in the current folder layout
  5. Legacy patterns should be treated carefully
    • older direct wrappers are not automatically wrong; the main risk is copying them forward uncritically for new work

Validation performed

Manual inspection and bounded searches only.

Performed:

  • re-read required Slice C context files
  • small top-level API listings for:
    • pages/api
    • pages/api/admin
  • direct representative inspection of:
    • admin routes
    • top-level utility/meta routes
    • shared middleware/support files
    • existing shared client/helper files
    • previously reviewed assessment evidence from Slices A and B
  • targeted searches for existing building blocks and helper usage across pages/api

Not performed:

  • no repo-wide automated analysis
  • no Python
  • no bulk route inventory generation
  • no runtime code changes
  • no lint/tests, because this remains documentation-only assessment work

Recommendation

Next bounded assessment step only:

Slice D — API Route Ownership & Change-Entry Sample

Focus on a bounded set of high-value feature journeys and trace:

  • first likely API entry points a maintainer would touch
  • adjacent supporting routes/helpers they would also need to inspect
  • the minimum “change entry set” for safe edits

Suggested bounded feature sample:

  • watched cases
  • account/personal details
  • public document retrieval
  • appeal submission/finalisation

Goal:

  • make future change entry points more explicit without proposing refactor yet

Slice D — API Route Ownership & Change-Entry Sample

Required context read

The following files were re-read before Slice D:

  • context/portal-api-platform-assessment.md
  • context/architecture.md
  • context/integration-map.md
  • memory-bank/change-log.md

Findings

For the sampled journeys, the main maintainer problem is not usually “what does this one route do?” but rather:

which UI entry point started this journey,
which service helper actually owns the API call,
which route performs the final contract,
and which adjacent state/helpers must also be checked before changing behaviour?

The four sampled journeys differ in complexity:

  • watched cases = feature-led CRM relay journey with several UI entry points
  • account/personal details = account/profile journey split across SSR/page state and CRM update APIs
  • public document retrieval = public search-driven document metadata + download proxy journey
  • appeal submission/finalisation = orchestration-heavy draft-to-submission journey crossing storage, queue/finalisation, and CRM mutation boundaries

Journey Change-Entry Sets

1. Watched cases

Primary UI/component entry points
  • components/search/searchresults.js
  • components/search/addresssearchresults.js
  • components/search/dnssearchresults.js
  • components/case/summary.js
  • components/myportal/topthree.js
  • components/myportal/viewall.js
Likely service helpers
  • actions/services/portalDirectService.js
    • getWatchedCases
    • getWatchedCasesProxy
    • createWatchedCases
    • deleteWatchedCases
API routes
  • pages/api/endpoint/getwatchedcases_api.js
  • pages/api/endpoint/getwatchedcasesproxy_api.js
  • pages/api/endpoint/createwatchedcases_api.js
  • pages/api/endpoint/deletewatchedcases_api.js
  • pages/api/endpoint/deletewatchedcasesproxy_api.js as adjacent compatibility variant
Shared clients/helpers
  • relayGet(...)
  • relayGetData(...)
  • respondError(...) / respondSuccess(...)
  • relay policy presets
  • hashAPIPath(...)
  • route/query builders in portal services
  • splitWatchedCasesBySubmissionState(...)
  • getDetailsProxy(...)
State/store modules
  • store/watchedCases/{action,reducer}.js
  • store/currentView/action.js
  • store/accountDetails/action.js
External integration touched
  • CRM relay
  • local-only state/helpers

2. Account / personal details

Primary UI/component entry points
  • pages/account/personaldetails.js
  • components/account/personaldetails.js
  • adjacent completion/check components referenced there:
    • components/account/personaldetailsCheck.js
    • components/account/personaldetailsComplete.js
Likely service helpers
  • actions/services/accountDirectService.js
    • getPersonalAccount
    • updateAccount
    • getPortalLogin as identity/bootstrap adjacent helper
API routes
  • pages/api/endpoint/getpersonalaccount_api.js
  • pages/api/endpoint/updateaccount_api.js
  • adjacent account/auth-support routes often relevant during investigation:
    • getportallogin_api.js
    • getemailaccountcheck_api.js
    • updatepassword_api.js
Shared clients/helpers
  • relayGet(...)
  • respondError(...) / respondSuccess(...)
  • getToken()
  • hashAPIPath(...)
  • signed request / relay client helpers in the service layer
State/store modules
  • store/accountDetails/action.js
    • setAccountDetails
    • setLoggedInUserId
External integration touched
  • CRM relay
  • NextAuth (session presence at page level)
  • local-only state/helpers

3. Public document retrieval

Primary UI/component entry points
  • components/search/searchresults.js and related search flows as user discovery entry points
  • document metadata/search document routes act as upstream API entry before download
Likely service helpers
  • actions/services/searchDirectService.js
    • getSearchDocumentDetails
    • related search document retrieval helpers
API routes
  • pages/api/endpoint/getsearchdocumentdetails_api.js
  • pages/api/endpoint/getsearchdocumentdetailspaged_api.js
  • pages/api/endpoint/getsearchdocumenthistory_api.js
  • pages/api/endpoint/getsearchdocumenthistorypaged_api.js
  • pages/api/endpoint/getsearchdocumentTypes_api.js
  • pages/api/documents/download/[id].js
Shared clients/helpers
  • relayGet(...)
  • respondError(...)
  • document hash-link generation logic using HMAC/hash helpers
  • getToken() inside direct download proxy
  • consoleLogger(...)
State/store modules
  • usually lighter direct store involvement than account/watched cases
  • search result/detail state may still be relevant through search result flows
External integration touched
  • CRM relay
  • local-only helper logic

4. Appeal submission / finalisation

Primary UI/component entry points
  • pages/myportal/[appealtypes].js as journey page entry
  • lib/myportal/loadMyPortalAppealPage.js as key journey loader
  • adjacent finalisation/completion UI evidence from completion components and journey state transitions
Likely service helpers
  • actions/services/documentDirectService.js
    • getFilesFromBlob
    • getProgressFromBlob
    • getAwaitingSubmissionFromBlob
  • actions/services/accountDirectService.js
    • getPersonalAccount
  • route-adjacent helpers in storage layer:
    • actions/azurestorage.js
API routes
  • pages/api/file/createappealcompletemessage_api.js
  • pages/api/file/createappealcompletemessageproxy_api.js
  • pages/api/endpoint/createcase_api.js
  • pages/api/endpoint/patchcase_api.js
  • pages/api/endpoint/updatecase_api.js
  • adjacent draft/blob routes usually relevant:
    • pages/api/file/getbloblist.js
    • pages/api/file/getprogressobjblob.js
    • pages/api/file/upload.js
    • pages/api/file/deleteblobcase.js
Shared clients/helpers
  • Azure storage helpers (getCaseBlob, progress/blob helpers, completion-message helpers)
  • respondError(...) / respondSuccess(...)
  • hashAPIPath(...)
  • relayGet(...) and direct-wrapper mutation patterns
  • route-builder/signed-request helpers in services
  • loader guards in lib/myportal/loadMyPortalAppealPage.js
State/store modules
  • store/accountDetails/*
  • store/appealType/*
  • store/currentView/*
  • store/awaitingSubmission/*
  • store/formData/* as adjacent journey support
External integration touched
  • Azure Storage
  • Azure Queue / completion handoff
  • CRM relay
  • local-only state/helpers

Route Ownership Classification

Watched cases journey

  • getwatchedcases_api
    • feature-owned by watched cases
    • integration: CRM relay
  • getwatchedcasesproxy_api
    • ambiguous/historical
    • integration: CRM relay
  • createwatchedcases_api
    • orchestration-owned by watched cases
    • integrations: CRM relay, helper/read pre-check
  • deletewatchedcases_api
    • feature-owned by watched cases
    • integration: CRM relay
  • deletewatchedcasesproxy_api
    • ambiguous/historical
    • integration: CRM relay

Account / personal details journey

  • getpersonalaccount_api
    • feature-owned by account/profile
    • integration: CRM relay
  • updateaccount_api
    • feature-owned by account/profile
    • integration: CRM relay
  • getportallogin_api
    • helper/support for account/auth bootstrap
    • integration: CRM relay
  • getemailaccountcheck_api
    • helper/support for registration/account support
    • integration: CRM relay
  • updatepassword_api
    • ambiguous/historical in current live account journey terms
    • integration: CRM relay

Public document retrieval journey

  • getsearchdocumentdetails_api
    • feature-owned by public document retrieval/search detail
    • integration: CRM relay
  • getsearchdocumentdetailspaged_api
    • feature-owned by public document retrieval/search detail
    • integration: CRM relay
  • getsearchdocumenthistory_api
    • feature-owned by public document retrieval/history
    • integration: CRM relay
  • getsearchdocumenthistorypaged_api
    • feature-owned by public document retrieval/history
    • integration: CRM relay
  • getsearchdocumentTypes_api
    • helper/support for document retrieval/search filtering
    • integration: CRM relay
  • documents/download/[id].js
    • integration-owned download proxy used by public document retrieval
    • integration: CRM relay

Appeal submission / finalisation journey

  • createappealcompletemessage_api
    • orchestration-owned by appeal finalisation
    • integrations: Azure Storage, Azure Queue/finalisation, CRM/account side effect
  • createappealcompletemessageproxy_api
    • helper/support or ambiguous/historical compatibility wrapper
    • integrations: local proxy + file/finalisation path
  • createcase_api
    • orchestration-owned by appeal submission
    • integrations: CRM relay, Azure Storage side effect
  • patchcase_api
    • feature-owned by appeal submission/final transition
    • integration: CRM relay
  • updatecase_api
    • feature-owned by appeal mutation/submission support
    • integration: CRM relay
  • draft/blob support routes (getbloblist, getprogressobjblob, upload, deleteblobcase)
    • integration-owned storage support for the appeal draft/finalisation journey
    • integration: Azure Storage

Change Risk Classification

Watched cases

  • Risk: high

Reason:

  • multiple UI entry points
  • CRM read + create/delete paths
  • feature state refreshed after mutation
  • proxy and non-proxy variants add maintenance ambiguity

Account / personal details

  • Risk: high

Reason:

  • account/profile contracts are user-critical
  • session/bootstrap and CRM profile identity are tightly coupled
  • mutation route is simple in code shape but high impact to users

Public document retrieval

  • Risk: medium-high

Reason:

  • public users are affected directly
  • metadata, hash-link generation, and download proxy are split across different areas
  • fewer stateful side effects than account/finalisation

Appeal submission / finalisation

  • Risk: very high

Reason:

  • multiple integrations touched
  • orchestration-heavy
  • draft/blob + submission transition + finalisation behavior
  • contract-critical journey
  • state passed across loaders, services, blob data, and CRM write paths

First-Look Checklists

Watched cases

Before changing this journey, inspect:

  1. components/search/searchresults.js and components/case/summary.js
  2. components/myportal/viewall.js and components/myportal/topthree.js
  3. actions/services/portalDirectService.js watched-case helpers
  4. pages/api/endpoint/{getwatchedcases_api,getwatchedcasesproxy_api,createwatchedcases_api,deletewatchedcases_api}.js
  5. store/watchedCases/* and store/currentView/*
  6. Slice B / security-boundary notes touching watched-case identifiers in context/portal-api-platform-assessment.md

Account / personal details

Before changing this journey, inspect:

  1. pages/account/personaldetails.js
  2. components/account/personaldetails.js and adjacent check/complete components
  3. actions/services/accountDirectService.js
  4. pages/api/endpoint/{getpersonalaccount_api,updateaccount_api}.js
  5. adjacent bootstrap/support routes: getportallogin_api.js, getemailaccountcheck_api.js
  6. store/accountDetails/*

Public document retrieval

Before changing this journey, inspect:

  1. search UI entry points that surface document links
  2. actions/services/searchDirectService.js search document helpers
  3. pages/api/endpoint/{getsearchdocumentdetails_api,getsearchdocumenthistory_api,getsearchdocumentTypes_api}.js
  4. pages/api/documents/download/[id].js
  5. any route-local document hash-link generation logic in endpoint/admin/email families
  6. Slice B findings on public read/document contract shapes

Appeal submission / finalisation

Before changing this journey, inspect:

  1. lib/myportal/loadMyPortalAppealPage.js
  2. the page entry and current appeal/draft UI entry points
  3. actions/services/documentDirectService.js draft blob helpers
  4. pages/api/file/createappealcompletemessage_api.js
  5. pages/api/endpoint/{createcase_api,patchcase_api,updatecase_api}.js
  6. actions/azurestorage.js completion/blob helpers
  7. store/{appealType,currentView,awaitingSubmission,accountDetails}/*
  8. Slice C maintenance-map notes on finalisation folder drift

Reuse Opportunities

Watched cases

  • relayGet(...) for read routes
  • relayGetData(...) for upsert pre-check style behavior
  • respondSuccess(...) / respondError(...)
  • relay policy presets
  • logging helpers
  • route-builder/query helper patterns in portal services

Account / personal details

  • relayGet(...) for profile reads
  • respondSuccess(...) / respondError(...)
  • token/hash helpers in update flows
  • signed/relay client helpers in account service layer
  • logging helpers

Public document retrieval

  • relayGet(...) for document metadata/history reads
  • respondError(...)-style guard handling
  • document hash-link generation logic already present in multiple route families
  • logging helpers

Appeal submission / finalisation

  • Azure storage helpers
  • respondSuccess(...) / respondError(...)
  • hash/path validation helpers
  • direct-wrapper mutation pattern already established in CRM write routes
  • signed request / route builder helpers in service layer
  • loader guard patterns in lib/myportal/loadMyPortalAppealPage.js

Risks / Cautions

  1. These are first-look entry sets, not exhaustive dependency maps
    • each journey has adjacent supporting files beyond what is listed here
  2. UI entry points are distributed
    • watched cases especially can begin from search results, case pages, and myportal views
  3. Route ownership is sometimes mixed or historical
    • proxy and finalisation routes especially need careful interpretation
  4. Submission/finalisation should be treated as the most sensitive sampled journey
    • storage, queue/finalisation, and CRM boundaries all meet there
  5. Account and watched-case journeys rely on earlier identity/bootstrap context
    • a maintainer may need to inspect SSR/session/bootstrap files even when changing a single API route

Validation performed

Manual inspection and bounded searches only.

Performed:

  • re-read required Slice D context files
  • targeted bounded searches across components, actions/services, pages, lib, and store for the four sampled journeys
  • direct file inspection of representative first-look journey files including:
    • components/myportal/viewall.js
    • pages/account/personaldetails.js
    • components/account/personaldetails.js
    • components/search/searchresults.js
    • lib/myportal/loadMyPortalAppealPage.js
    • components/case/representation/representationComplete.js
  • reuse of already reviewed route/service evidence from Slices AC for linked API ownership and building-block classification

Not performed:

  • no full dependency inventory
  • no repo-wide automated analysis
  • no Python
  • no runtime code changes
  • no lint/tests, because this remains documentation-only assessment work

Recommendation

Next bounded assessment step only:

Slice E — API Maintainer Decision Guide Sample

Focus on a small sample of common maintenance intents, such as:

  • adding a new CRM read route
  • extending a watched-case style mutation
  • adding a document-related route
  • extending a finalisation-side orchestration path

Goal:

  • document which current patterns a maintainer would most likely copy or reuse
  • identify which existing patterns appear preferred vs legacy-for-compatibility
  • remain assessment-only

Slice E — Wider API Surface Pattern Validation

Required context read

The following files were re-read before Slice E:

  • context/portal-api-platform-assessment.md
  • context/architecture.md
  • context/integration-map.md
  • memory-bank/change-log.md

Findings

The wider validation pass supports the earlier assessment model.

The API surface is large in file count, but the underlying vocabulary still appears relatively small:

  • large route surface
  • small contract vocabulary
  • small implementation-style vocabulary
  • main maintenance issue remains findability and ownership

The folder scan and outlier checks did not reveal a major additional platform family that would overturn Slices AD.

Instead, the wider surface mostly reinforces that:

  1. pages/api/endpoint contains the majority of CRM-facing route variants
  2. pages/api/file is the main secondary mixed folder where storage plus orchestration concerns accumulate
  3. most routes still fit the previously identified contract shapes and implementation styles
  4. the main uncertainty is not “unknown route technology” but “where a maintainer should look first”

Folder-Level Validation

Approximate file counts from the bounded listing/count pass:

  • pages/api/endpoint -> 74 files
  • pages/api/file -> 26 files
  • pages/api/email -> 6 files
  • pages/api/documents -> 1 file
  • pages/api/auth -> 2 files
  • pages/api/admin -> 5 files
  • pages/api/middleware -> 4 files
  • top-level pages/api files -> 4

pages/api/endpoint

  • Approximate size: very large
  • Apparent responsibility: CRM relay-facing portal/business-data API catch-all
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no major new family found

Validation note:

  • route names continue to cluster around search/read, myportal reads, document metadata, account/profile, create/update/delete, lookup/config, and proxy variants

pages/api/file

  • Approximate size: medium-large
  • Apparent responsibility: storage/blob routes plus draft/finalisation and some CRM-adjacent orchestration
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no major new family, but PDF-generation and involvement routes reinforce the mixed/orchestration character

Validation note:

  • outlier review (createcaseinvolvement_api.js, generateappealpdf.js) still fits the same mixed file/storage/orchestration pattern already documented

pages/api/email

  • Approximate size: small
  • Apparent responsibility: Notify send plus document/event/list aggregation for email workflows
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

Validation note:

  • getdocuments.js reinforces that email routes often combine CRM read + document-link generation + downstream notification support rather than introducing a new route family

pages/api/documents

  • Approximate size: very small
  • Apparent responsibility: direct document download proxy
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

pages/api/auth

  • Approximate size: very small
  • Apparent responsibility: auth/session and locale support
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

pages/api/admin

  • Approximate size: small
  • Apparent responsibility: internal/admin reporting and grouped CRM read views
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

Validation note:

  • getStatusCountsByAppealAndLPA_api.js strengthens the view that admin routes are mostly grouped reporting/read transforms over CRM relay data

pages/api/middleware

  • Approximate size: very small
  • Apparent responsibility: shared API support and relay/runtime helper logic
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

Top-level API routes

  • Approximate size: very small
  • Apparent responsibility: health/meta/static support
  • Do Slice AD findings still appear representative? yes
  • Unexpected route families? no

Route Family Validation

Previously identified route families still appear to cover the wider surface:

  • search/read
  • myportal reads
  • account/profile
  • create/update/delete
  • document retrieval
  • storage/blob
  • queue/finalisation
  • notifications
  • admin/reporting
  • auth/session
  • lookup/config/support

Additional observations from wider route-name validation:

  • static/local support data routes such as getmandatoryfields_api, getpicklists_api, and getappealtypesfornewappeal_api are better treated as part of the already-documented lookup/config/support family rather than a genuinely new family
  • CRM task/contact routes such as createcrmtask_api.js fit the existing CRM create/write family
  • involvement routes under file/ fit the existing orchestration-owned CRM-related mutation pattern already noted in earlier slices
  • PDF-generation routes under file/ fit the existing storage/document generation orchestration pattern rather than requiring a wholly separate top-level family

Assessment:

  • no genuinely new major route family identified

Contract Shape Validation

The previously identified contract shapes still appear sufficient for most of the wider surface:

  • Public CRM read
  • User-owned CRM read
  • CRM create
  • CRM update/patch
  • CRM delete
  • Proxy/pass-through
  • Lookup/config/support
  • Hybrid upsert/orchestration

Additional validation insight:

  • local/static JSON/data support routes (getmandatoryfields_api, getpicklists_api) fit comfortably within lookup/config/support
  • admin grouped-reporting routes fit as CRM read + transform rather than a separate contract family
  • file-side involvement and PDF routes fit as orchestration or support variants rather than forcing a new contract class

Assessment:

  • these contract shapes appear to cover most routes
  • no additional mandatory contract shape is currently required for the architecture model

Implementation Style Validation

The implementation-style model also still holds:

1. Helper-oriented relay routes

Still strongly present, especially in endpoint/ and modern admin/reporting reads.

Indicators:

  • relayGet(...)
  • relayGetData(...)
  • respondError(...) / respondSuccess(...)
  • relay policy presets

2. Direct-wrapper routes

Still strongly present, especially for CRM create/update/delete and some file-side CRM mutations.

Indicators:

  • getToken()
  • route-local queryUrl
  • WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)
  • direct axios(config)

3. Orchestration routes

Still clearly present in:

  • file/ completion/finalisation
  • PDF generation
  • involvement creation
  • email-side aggregation routes

Additional major implementation style found?

  • No

Closest extra pattern:

  • local/static support routes using in-repo JSON/data reads

But this is better treated as a small support variant, not a fourth major implementation style.

Folder Drift Validation

pages/api/documents

  • Drift: low
  • Reason: narrow folder name still matches actual responsibility closely

pages/api/auth

  • Drift: low to moderate
  • Reason: still mostly coherent, though CRM locale and Notify behavior cross the folder boundary conceptually

pages/api/admin

  • Drift: low
  • Reason: sampled routes still align with internal/admin reporting responsibility

pages/api/middleware

  • Drift: low
  • Reason: folder remains clearly reuse/support oriented

Top-level API routes

  • Drift: low
  • Reason: health/meta/static support usage remains straightforward

pages/api/email

  • Drift: moderate
  • Reason: naming suggests email-only behavior, but actual routes can perform CRM/document/event aggregation before notification send

pages/api/file

  • Drift: high
  • Reason: storage/blob naming no longer fully describes draft orchestration, finalisation, involvement creation, PDF generation, and CRM-adjacent journey behavior housed there

pages/api/endpoint

  • Drift: high
  • Reason: folder behaves as the historical general-purpose CRM relay catch-all rather than a clearly bounded current responsibility area

Maintenance Hotspots

pages/api/endpoint

  • Hotspot level: high

Reason:

  • highest route count
  • mixed business responsibilities
  • helper-oriented and direct-wrapper styles coexist
  • many contract-critical routes
  • ownership ambiguity highest here

pages/api/file

  • Hotspot level: high

Reason:

  • second-largest route area
  • storage + orchestration + finalisation mixed together
  • touches high-risk flows and multiple integrations

pages/api/email

  • Hotspot level: medium

Reason:

  • smaller route count, but orchestration overlap can surprise maintainers

pages/api/admin

  • Hotspot level: medium-low

Reason:

  • coherent but still CRM-transform heavy

pages/api/auth

  • Hotspot level: medium-high

Reason:

  • low file count, but highly sensitive behavior and cross-cutting auth/session implications

pages/api/documents

  • Hotspot level: low

Reason:

  • very small, narrow responsibility

pages/api/middleware

  • Hotspot level: medium-high

Reason:

  • tiny surface, but shared helper impact is wide and mistakes would propagate broadly

Confidence Assessment

Representativeness of Slices AD

  • Confidence: high confidence

Why:

  1. folder-size validation shows the biggest unknown risk area was endpoint/, and that area has already been sampled repeatedly across earlier slices
  2. file/ outlier checks still fit the previously identified mixed storage/orchestration model
  3. smaller folders (email, documents, auth, admin, middleware) did not reveal materially new route families or implementation styles
  4. the outlier review found support variants and special cases, but not a new dominant architectural pattern

Residual caution:

  • confidence is high at the platform pattern level, not at the full-route behavioral nuance level

Risks / Cautions

  1. This remains a pattern-validation pass, not a full inventory
    • there may still be route-local nuances not captured here
  2. High confidence does not mean all individual routes are equivalent
    • some outlier handlers still have special transforms, signing rules, or side effects
  3. Folder-level conclusions should not be mistaken for migration recommendations
    • this slice validates representativeness, not reorganisation scope
  4. The biggest remaining maintenance risk is still ownership ambiguity
    • especially in endpoint/ and file/

Validation performed

Manual inspection and bounded searches only.

Performed:

  • re-read required Slice E context files
  • bounded folder-size count pass across top-level API folders
  • targeted route-name searches inside endpoint, file, and pages/api to validate naming families and implementation indicators
  • direct representative inspection of selected outlier-style routes, including:
    • pages/api/endpoint/getmandatoryfields_api.js
    • pages/api/endpoint/createcrmtask_api.js
    • pages/api/file/createcaseinvolvement_api.js
    • pages/api/file/generateappealpdf.js
    • pages/api/email/getdocuments.js
    • pages/api/admin/getStatusCountsByAppealAndLPA_api.js
  • reuse of conclusions and evidence from Slices AD for comparison

Not performed:

  • no full route inventory
  • no repo-wide automated analysis
  • no Python
  • no scripts
  • no runtime code changes
  • no lint/tests, because this remains documentation-only assessment work

Architectural Conclusion

The existing API platform model is now considered representative of the wider API surface at the pattern level.

Current architectural conclusion:

  • the wider API surface does not appear to require a materially different platform model from Slices AD
  • the earlier findings generalise well:
    • endpoint/ is the dominant historical CRM relay catch-all
    • file/ is the main secondary mixed storage/orchestration area
    • route families largely collapse into a limited contract vocabulary
    • implementation styles largely collapse into helper-oriented, direct-wrapper, and orchestration styles
    • the primary maintainability issue remains findability and ownership, not discovery of a fundamentally different API architecture

Recommendation

Next bounded assessment step only:

Slice F — API Platform Final Synthesis

Goal:

  • consolidate Slices AE into one concise architecture-level API platform view
  • state the stable route family model, contract model, implementation-style model, drift model, and maintainer guidance baseline
  • remain assessment-only

Slice F — API Platform Final Synthesis

Programme status

Portal Integration Contract & API Platform Assessment
Status: COMPLETE

Closure is supported by the existing evidence because:

  • Slices AE established a stable route-family model
  • the wider validation pass reached high confidence at the platform pattern level
  • no materially different API platform family or implementation model emerged during bounded wider-surface validation

Executive Summary

The PEDW API platform is large in route count but smaller in underlying structure than the file count first suggests.

At a platform level it can be understood as:

~120 route files
    ↓
small route-family vocabulary
    ↓
small contract-shape vocabulary
    ↓
small implementation-style vocabulary

The API platform therefore feels large primarily because:

  • route files are numerous
  • route naming has grown historically
  • folder responsibility has drifted unevenly
  • feature ownership is not always obvious from folder or file name alone
  • older and newer implementation styles coexist

The main maintenance problem is not discovery of a fundamentally different API architecture.

The main maintenance problem is:

  • findability
  • ownership clarity
  • consistency and reuse discipline

Final API Platform Model

Stable architecture-level model:

  • the dominant platform family is still CRM relay-backed portal APIs
  • the main secondary platform family is storage/blob plus draft/finalisation orchestration
  • notification, auth, documents, admin, and middleware form smaller supporting families
  • route count overstates structural diversity because many routes are variants of repeated contract shapes
  • the platform is mixed but explainable once grouped by route family, contract shape, and implementation style

Route-Family Model

The stable route-family model is:

1. CRM relay routes

  • mainly under pages/api/endpoint
  • includes search, myportal reads, account/profile reads, lookups, and CRM mutations

2. Storage/blob routes

  • mainly under pages/api/file
  • includes blob listing, upload, delete, progress, and draft file handling

3. Finalisation/orchestration routes

  • concentrated in pages/api/file, with supporting CRM mutation routes in endpoint
  • includes draft-to-submission transitions, completion-message flows, PDF generation, and related side effects

4. Email/notification routes

  • mainly under pages/api/email
  • includes thin Notify send routes and broader aggregation/orchestration routes

5. Document download routes

  • mainly under pages/api/documents
  • narrow published-document download proxy behavior

6. Auth/session routes

  • mainly under pages/api/auth
  • includes NextAuth/session behavior and locale-aware auth support

7. Admin/internal routes

  • mainly under pages/api/admin
  • grouped CRM reporting/read transforms for internal/admin use

8. Middleware/helper routes

  • under pages/api/middleware
  • response helpers, relay forwarding, multipart support, retry/policy helpers

9. Local utility/meta routes

  • top-level API utility files and a few support-style routes
  • health, docs/static/meta support, and local/config data reads

Contract-Shape Model

The stable contract-shape model is:

CRM-facing shapes

  • Public CRM read
  • User-owned CRM read
  • CRM create
  • CRM update/patch
  • CRM delete
  • Proxy/pass-through
  • Lookup/config/support
  • Hybrid upsert/orchestration

Storage/finalisation/notification shapes

  • Storage read/write/delete
  • Queue/finalisation
  • Notify send / notification orchestration

Assessment note:

  • these shapes are sufficient to explain most of the observed API surface
  • many apparent route differences are variants of one of these shapes rather than separate architectural categories

Implementation-Style Model

The stable implementation-style model consists of three main styles.

1. Newer helper-oriented

Typical indicators:

  • relayGet(...)
  • relayGetData(...)
  • respondSuccess(...)
  • respondError(...)
  • relay policy presets

Typical fit:

  • CRM read routes
  • proxy/read routes
  • grouped read/transform routes

2. Older direct-wrapper

Typical indicators:

  • getToken()
  • direct axios(config)
  • manual WEBAPI_URL + queryUrl + hashAPIPath(queryUrl)

Typical fit:

  • CRM create/update/delete wrappers
  • some file-side CRM mutation helpers

Assessment note:

  • these patterns are not “wrong”; they reflect prior delivery needs and stable historical route construction
  • the main maintainability question is whether they should be copied forward into new work when shared helpers now exist

3. Orchestration-heavy

Typical fit:

  • finalisation routes
  • email aggregation routes
  • storage + queue + CRM side-effect routes
  • PDF generation and file-adjacent journey transitions

Assessment note:

  • these routes are structurally important because they cross integration boundaries and often sit at contract-critical workflow transitions

Folder Drift Model

Folder drift affects maintainability because folder name and actual responsibility do not always align.

Low drift

  • documents
  • admin
  • middleware
  • top-level utility/meta

These are relatively easy to find and reason about.

Low / moderate drift

  • auth

The folder is still coherent, but auth behavior crosses into CRM and Notify concerns.

Moderate drift

  • email

The folder name suggests email-only work, but some routes perform CRM/document/event aggregation before notification send.

High drift

  • endpoint
  • file

Why this matters:

  • endpoint behaves as a historical general-purpose CRM relay catch-all
  • file now contains blob/storage behavior, draft support, finalisation, involvement creation, PDF generation, and CRM-adjacent orchestration
  • this drift increases scan cost and weakens ownership clarity

Maintenance Hotspots

High

  • pages/api/endpoint
  • pages/api/file

Why:

  • highest route concentration
  • mixed responsibilities
  • mixed implementation styles
  • many contract-critical routes
  • ownership ambiguity is strongest here

Medium-high

  • pages/api/auth
  • pages/api/middleware

Why:

  • small surfaces but high leverage and high sensitivity
  • mistakes there can have broad downstream effects

Medium

  • pages/api/email

Why:

  • route count is small, but orchestration overlap makes behavior less obvious than the folder name suggests

Lower

  • pages/api/documents
  • pages/api/admin

Why:

  • narrower and more coherent responsibilities
  • still important, but less structurally confusing than endpoint and file

Maintainer Guidance Baseline

For future API work, the stable baseline should be:

  1. Identify the owning feature or journey first
    • do not start from route name alone if the flow is contract-critical
  2. Identify the integration touched
    • CRM relay, Azure Storage, Azure Queue/finalisation, Notify, NextAuth, or local-only support
  3. Identify contract-criticality before editing
    • public search, myportal, file handling, document delivery, auth/session, and finalisation need higher caution
  4. Prefer existing shared helpers where suitable
    • especially for CRM read routes and standardized response handling
  5. Prefer respondSuccess(...) / respondError(...) for new JSON responses
  6. Prefer helper-oriented relay reads for new CRM reads where appropriate
  7. Reuse storage helpers and established hash validation patterns for storage APIs
  8. Keep Notify routes thin unless orchestration is genuinely required
  9. Do not blindly copy older direct-wrapper patterns into new work
  10. Do not refactor stable legacy routes without explicit approval and characterization

What Is Proven / Not Proven

Proven

  • Slices AE are representative at the API platform pattern level
  • route count overstates true structural diversity
  • the main maintenance issue is findability and ownership
  • a small number of repeated contract and implementation patterns explain most routes

Not Proven

  • no full route-by-route inventory was produced
  • no consolidation safety assessment has been performed
  • no implementation readiness has been approved
  • no route movement or removal is recommended yet

Recommendation

The Portal Integration Contract & API Platform Assessment should now be considered complete.

Recommended future planning stream only:

  • API Route Map / Maintainer Guide

or

  • API Rationalisation Planning

But only as a future planning stream.

No implementation work is recommended from this assessment alone.