From 153f0d679ebe9e2e0f6296d01de58be562112b9a Mon Sep 17 00:00:00 2001 From: Robert Bond Date: Thu, 25 Jun 2026 08:11:14 +0000 Subject: [PATCH] Merged PR 2427: update api facade Related work items: #23754 --- actions/services/portalDirectService.js | 8 +- context/api-grouping-adoption-roadmap.md | 378 ++++++++ context/api-grouping-plan.md | 915 ++++++++++++++++++ memory-bank/change-log.md | 329 +++++++ .../api/subscriptions/create-watched-case.js | 5 + .../api/subscriptions/delete-watched-case.js | 5 + .../subscriptions/get-watched-cases-proxy.js | 5 + pages/api/subscriptions/get-watched-cases.js | 5 + ...api-grouping-facade-subscriptions.test.cjs | 193 ++++ 9 files changed, 1839 insertions(+), 4 deletions(-) create mode 100644 context/api-grouping-adoption-roadmap.md create mode 100644 context/api-grouping-plan.md create mode 100644 pages/api/subscriptions/create-watched-case.js create mode 100644 pages/api/subscriptions/delete-watched-case.js create mode 100644 pages/api/subscriptions/get-watched-cases-proxy.js create mode 100644 pages/api/subscriptions/get-watched-cases.js create mode 100644 tests/phase22/api-grouping-facade-subscriptions.test.cjs diff --git a/actions/services/portalDirectService.js b/actions/services/portalDirectService.js index 28b2bd2b..2db90b28 100644 --- a/actions/services/portalDirectService.js +++ b/actions/services/portalDirectService.js @@ -85,7 +85,7 @@ export const getRepresentationsProxy = (incidentID) => { }; export const getWatchedCases = (loggedInUserId) => { - const route = buildFileQuery("/api/endpoint/getwatchedcases_api", { + const route = buildFileQuery("/api/subscriptions/get-watched-cases", { loggedInUserId }); @@ -95,7 +95,7 @@ export const getWatchedCases = (loggedInUserId) => { }; export const getWatchedCasesProxy = (loggedInUserId) => { - const route = buildFileQuery("/api/endpoint/getwatchedcasesproxy_api", { + const route = buildFileQuery("/api/subscriptions/get-watched-cases-proxy", { loggedInUserId }); @@ -129,7 +129,7 @@ export const getAwaitingSubmission = (loggedInUserId) => { export const createWatchedCases = async (formValues) => { var data = formValues; - var queryUrl = buildFileQuery("/api/endpoint/createwatchedcases_api"); + var queryUrl = buildFileQuery("/api/subscriptions/create-watched-case"); var config = { method: "post", @@ -181,7 +181,7 @@ export const deleteAwaitingSubmissions = (incidentID) => { }; export const deleteWatchedCases = async (watchedCaseID) => { - var queryUrl = buildFileQuery("/api/endpoint/deletewatchedcases_api", { + var queryUrl = buildFileQuery("/api/subscriptions/delete-watched-case", { watchedCaseID }); diff --git a/context/api-grouping-adoption-roadmap.md b/context/api-grouping-adoption-roadmap.md new file mode 100644 index 00000000..aca1c75e --- /dev/null +++ b/context/api-grouping-adoption-roadmap.md @@ -0,0 +1,378 @@ +# API Grouping Adoption Roadmap + +## Status + +Planning only. + +Pilot status update (2026-06-25): + +- first additive grouping façade pilot implemented for watched-case APIs under `pages/api/subscriptions/` +- first internal consumer (`actions/services/portalDirectService.js` watched-case methods) now targets the grouped façade routes +- the active watched-case vertical slice now includes grouped adoption for both normal watched-case reads and proxy watched-case reads used by the current UI journey +- legacy watched-case endpoint routes remain canonical and stable +- no old route removal or migration has occurred +- runtime behaviour is intended to remain unchanged because the grouped routes delegate to the existing handlers + +This document describes how PEDW could **gradually adopt** the future journey-owned API grouping model over time without disrupting existing functionality. + +It is an **architectural roadmap only**. + +It does **not** recommend implementation, migration, route movement, route renaming, API deletion, consolidation, contract change, or behaviour change. + +--- + +## Required Context Read + +The following files were read before drafting this roadmap: + +- `context/api-grouping-plan.md` +- `context/api-route-map.md` +- `context/journey-architecture-map.md` +- `context/portal-api-platform-assessment.md` +- `context/architecture.md` +- `context/integration-map.md` +- `memory-bank/change-log.md` + +--- + +## Files Modified + +- `context/api-grouping-adoption-roadmap.md` +- `memory-bank/change-log.md` + +--- + +## Findings + +- The completed architecture programme already established that PEDW’s API platform is structurally smaller than its route count first suggests. +- The main maintainability problems are already known: + - findability + - ownership clarity + - consistency + - reuse discipline +- The current runtime is stable even though folder ownership is historically mixed. +- The current top-level API shape still reflects historical growth more than clean journey ownership, especially in: + - `pages/api/endpoint` + - `pages/api/file` +- The route map, journey map, and API grouping plan already support a **journey-first conceptual model** without requiring physical route movement. +- The strongest safe planning assumption is therefore: + +> PEDW should adopt future journey-owned API grouping gradually through future development guidance, improved documentation, and incremental consistency rather than large-scale migration. + +--- + +## Adoption Philosophy + +PEDW should favour **gradual evolution** over large structural change. + +Why: + +1. The current platform is already live and stable. +2. Many APIs are contract-critical even where current folder ownership is historically inconsistent. +3. Several route families are orchestration-heavy and cross multiple integrations, making physical reorganisation riskier than conceptual reclassification. +4. The completed architecture programme has already shown that the main problem is not missing discovery; it is making ownership and maintainability clearer. + +For that reason, PEDW should prefer: + +- gradual evolution +- behaviour preservation +- contract preservation +- incremental consistency +- reuse of shared helpers +- documentation-led clarity + +over: + +- large restructures +- wholesale folder moves +- API rewrites +- mass renaming +- cosmetic reorganisation without delivery value + +Adoption guidance: + +- existing APIs should remain stable +- existing routes should continue to work +- existing URLs should continue to work +- existing contracts should continue to work +- future grouping should emerge naturally as future work touches relevant areas + +--- + +## Adoption Stages + +### Stage 1 — Current State + +#### Purpose + +Record today’s platform as the baseline for future adoption thinking. + +#### Current State Summary + +- the API platform reflects historical growth +- current top-level folders remain implementation hosts rather than clean business ownership boundaries +- ownership is mixed across business journeys, integrations, and shared support concerns +- the runtime is stable and should be preserved + +#### Architecture Notes + +- `endpoint/` remains the main historical CRM relay catch-all +- `file/` remains the main secondary storage/orchestration catch-all +- smaller families such as `admin/`, `documents/`, and `auth/` are more coherent, though not always perfectly isolated +- shared helpers and route patterns already exist and provide a safer basis for future consistency than folder movement alone + +#### Roadmap Meaning + +Stage 1 is not a problem statement that justifies migration. + +It is the baseline that explains why PEDW should improve ownership clarity **without destabilising the current runtime**. + +--- + +### Stage 2 — Future Development Guidance + +#### Purpose + +Guide future API work so that PEDW gradually becomes more journey-owned over time without requiring broad reorganisation. + +#### Guidance + +- new APIs should naturally follow journey ownership +- new work should start from the journey-owned model before considering current folder habits +- new APIs should reuse existing shared helpers where suitable +- avoid creating additional catch-all folders +- avoid copying historical direct-wrapper patterns where shared helpers already exist +- keep integrations behind journey-owned API boundaries conceptually, even when current files remain where they are +- preserve published-document and draft-storage distinctions +- preserve established auth/session and authorization boundaries + +#### Practical Interpretation + +This stage does **not** mean: + +- move existing routes now +- rename existing routes now +- rewrite older APIs now + +It means: + +- when future work naturally touches an area, use the future grouping plan as the conceptual ownership guide +- prefer additive clarity over structural churn + +#### Proven pilot pattern + +- The watched-case subscriptions pilot demonstrates a low-risk adoption shape: + - add grouped façade routes in a journey-owned folder + - delegate directly to the existing canonical handlers + - keep existing routes live and unchanged + - adopt the grouped routes incrementally through a carefully selected internal consumer first +- This should be treated as additive proof of the grouping model, not as rationalisation or deprecation. + +#### Incremental adoption proof point + +- The first internal consumer adoption is now in place for watched-case methods in `actions/services/portalDirectService.js`. +- For the intended watched-case journey scope, the active vertical slice now covers: + - `getWatchedCases` + - `getWatchedCasesProxy` + - `createWatchedCases` + - `deleteWatchedCases` +- Legacy watched-case endpoint routes remain the canonical implementations behind the façade. +- No route deprecation, removal, or contract migration has occurred. +- This validates that grouped journey-owned routes can be introduced first and then adopted incrementally without changing runtime behaviour. + +#### Current pilot completion meaning + +- For this pilot, a complete watched-case/subscriptions vertical slice means: + - grouped subscriptions façade routes exist for the active watched-case journey calls + - `actions/services/portalDirectService.js` targets those grouped routes for the active watched-case journey methods + - legacy endpoint handlers remain present and canonical behind the façade + - runtime behaviour remains unchanged through delegation +- `deletewatchedcasesproxy_api` remains a legacy/support route outside the grouped pilot scope because it is not part of the currently adopted normal watched-case service path. + +--- + +### Stage 3 — Documentation Maturity + +#### Purpose + +Improve maintainability through better documentation and route ownership guidance before any physical restructuring is ever considered. + +#### Maturity Outcomes + +- improved maintainer guidance +- improved route ownership clarity +- improved discoverability +- improved architectural consistency in how new work is described and reviewed +- better onboarding for contributors who need to understand where to start + +#### Examples of Documentation-Led Adoption + +- route ownership described by journey rather than folder alone +- shared platform helpers clearly separated from business APIs +- cross-cutting concerns such as auth and notifications documented as cross-cutting rather than forced into one business domain +- future grouping candidates captured as architectural guidance only + +#### Important Constraint + +This stage improves understanding **without moving routes**. + +--- + +### Stage 4 — Future Opportunities + +#### Purpose + +Record possible future opportunities that could align with the grouping model if future work naturally justifies them. + +#### Possible Future Opportunities + +- selective grouping within areas already being changed for other approved reasons +- helper extraction where duplication remains visible +- improved shared platform reuse across journey-owned APIs +- stronger consistency in naming, ownership notes, and maintainer entry guidance +- clearer distinction between journey-owned APIs and shared/platform concerns + +#### Constraint + +These are **future opportunities only**. + +They are not implementation recommendations. + +They do not approve: + +- route movement +- file movement +- migrations +- refactoring programmes +- API rewrites + +--- + +## Adoption Principles + +1. Preserve stable APIs. +2. Preserve contracts. +3. Preserve integrations. +4. Preserve CRM as the source of truth for CRM-owned business data. +5. Preserve Azure Storage ownership boundaries for draft-owned content. +6. Preserve established auth/session and authorization boundaries. +7. Prefer additive improvements. +8. Avoid unnecessary churn. +9. Improve findability first. +10. Improve consistency second. +11. Reuse shared helpers instead of duplicating infrastructure logic. +12. Use journey ownership as the conceptual guide for future work. +13. Consider physical grouping only when future approved work naturally touches an area. +14. Never move APIs solely for cosmetic reasons. +15. Do not force cross-cutting concerns into one journey-owned bucket. +16. Continue treating shared/platform capabilities as shared platform concerns rather than business-domain ownership. + +--- + +## Decision Matrix + +| Situation | Guidance | +| --------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| New API | Place it conceptually within the journey-owned model first, then implement using the safest existing route/helper patterns. | +| Existing stable API | Leave unchanged. | +| Existing API being enhanced | Consider alignment with journey ownership in documentation and helper usage, without assuming route movement. | +| Shared infrastructure | Keep in shared/platform concern classification. | +| Cross-cutting concern | Avoid forcing it into one journey if its real ownership is platform-wide or multi-journey. | +| Historical catch-all folder | Treat it as a current host location, not as the preferred future ownership model. | +| Orchestration-heavy route | Classify conceptually by business journey, but preserve existing integration and sequencing behavior. | +| Documentation update | Improve findability and ownership clarity before considering any structural change. | +| Cosmetic restructuring idea | Do not pursue unless separately justified by future approved work. | + +--- + +## Success Measures + +Success should be understood qualitatively at architecture and maintainability level, not as an implementation delivery target. + +Indicators of success: + +- developers can find relevant APIs faster +- maintainers can identify likely owning journeys more easily +- shared infrastructure code is reused more consistently +- journey ownership becomes clearer in future documentation and code review discussions +- onboarding becomes simpler because route ownership is easier to explain +- maintenance effort is reduced through clearer patterns and less duplicated infrastructure logic +- future API additions align more naturally with business capability rather than historical folder drift + +Avoid treating success as: + +- number of routes moved +- number of folders renamed +- reduction in route count +- migration completion percentage + +--- + +## Non-Goals + +This roadmap explicitly does **not** approve or recommend: + +- migrations +- implementation +- route movement +- route renaming +- API deletion +- API consolidation +- folder restructuring +- refactoring programmes +- mass renaming +- contract changes +- behaviour changes + +This roadmap defines **architectural direction**, not delivery. + +--- + +## Risks / Cautions + +1. This roadmap is intentionally architecture-only. +2. It should not be mistaken for an implementation plan. +3. Stable runtime behavior matters more than conceptual neatness. +4. Several PEDW API areas remain orchestration-heavy and cross integration boundaries; conceptual grouping is safer than physical reorganisation. +5. `endpoint/` and `file/` remain historically important host folders even though they are not ideal future ownership concepts. +6. `auth/` and `notifications/` remain cross-cutting concerns and should not be over-simplified. +7. Dashboard-related APIs are aggregation-oriented and should be mapped back to owning journeys rather than treated as a separate long-term grouping target. +8. Future adoption should happen through natural change pressure, not through standalone cosmetic restructuring. + +--- + +## Validation Performed + +Manual synthesis only. + +Performed: + +- read the required roadmap context listed above +- reused the completed architecture programme as the evidence base +- reused the completed API grouping plan rather than reopening discovery +- kept the roadmap at architecture-roadmap level only + +Not performed: + +- no new API inspection +- no new API inventory +- no implementation design +- no migration proposal +- no refactor proposal +- no lint/tests, because this is documentation-only planning work + +--- + +## Recommendation + +Recommended next architecture planning document only: + +### `context/api-maintainer-guidance-v2.md` + +Suggested purpose: + +- extend the existing maintainer guidance with clearer decision support for future API additions +- strengthen journey-owned ownership cues and shared-helper selection guidance +- improve onboarding and change-entry clarity without recommending implementation or restructuring + +No implementation work is recommended from this roadmap alone. diff --git a/context/api-grouping-plan.md b/context/api-grouping-plan.md new file mode 100644 index 00000000..49b869d3 --- /dev/null +++ b/context/api-grouping-plan.md @@ -0,0 +1,915 @@ +# API Grouping Plan + +## Status + +Planning only. + +Pilot status update (2026-06-25): + +- first additive grouping façade pilot implemented for watched-case APIs under `pages/api/subscriptions/` +- legacy watched-case endpoint routes under `pages/api/endpoint/` remain canonical and stable +- no route removal, migration, contract change, or behaviour change has occurred +- the pilot validates the journey-owned grouping model through additive façade wrappers only + +This document defines a **future journey-owned API grouping model** for PEDW using the completed architecture programme as its evidence base. + +It does **not** recommend implementation, migration, route movement, route renaming, file movement, contract change, or behaviour change. + +--- + +## Required Context Read + +The following files were read before drafting this plan: + +- `context/api-route-map.md` +- `context/journey-architecture-map.md` +- `context/portal-api-platform-assessment.md` +- `context/architecture.md` +- `context/integration-map.md` +- `memory-bank/change-log.md` + +--- + +## Files Modified + +- `context/api-grouping-plan.md` +- `memory-bank/change-log.md` + +--- + +## Findings + +- The completed architecture programme already established that PEDW has a **large route surface** but a **smaller underlying architectural vocabulary**. +- The main API maintenance problem is not missing discovery. It is primarily: + - findability + - ownership clarity + - consistency + - reuse discipline +- Existing top-level folders do not consistently express current business ownership. +- The strongest current drift remains in: + - `pages/api/endpoint` + - `pages/api/file` +- The most stable architecture-level API families are already known and should be treated as established: + - CRM relay routes + - storage/blob routes + - finalisation/orchestration routes + - email/notification routes + - document download routes + - auth/session routes + - admin/internal routes + - middleware/helper routes + - local utility/meta routes +- The journey and route maps already support a journey-owned view of the platform. This plan therefore synthesises those findings into a maintainability-focused future grouping model only. + +--- + +## Proposed API Grouping Model + +Future grouping concepts for documentation guidance only: + +```text +pages/api/ + + account/ + admin/ + appeals/ + auth/ + cases/ + documents/ + notifications/ + platform/ + representations/ + search/ + subscriptions/ + shared/ +``` + +Interpretation guidance: + +- These are **architectural grouping concepts only**. +- They describe **future journey ownership**, not approved folder structure. +- They do **not** imply that current routes should move. +- They do **not** imply that route count should reduce. +- They do **not** imply that contracts, integrations, or behaviour should change. + +--- + +## Group Definitions + +### 1. `account/` + +#### Purpose + +Owns authenticated user account creation, account bootstrap, personal details retrieval, and account maintenance behavior. + +#### Primary Journeys Supported + +- account registration +- personal details +- account maintenance +- post-sign-in account bootstrap + +#### Typical Integrations + +- CRM +- NextAuth + +#### Typical Route Types + +- read +- create +- update +- lookup + +#### Example Existing Routes + +- `pages/api/endpoint/createaccount_api.js` +- `pages/api/endpoint/getpersonalaccount_api.js` +- `pages/api/endpoint/updateaccount_api.js` +- `pages/api/endpoint/getemailaccountcheck_api.js` + +#### Shared Components Used + +- relay helpers +- response helpers +- auth/session helpers +- signed request helpers + +#### Relationship To Other Groups + +- depends on `auth/` for identity establishment +- supports `appeals/`, `representations/`, and `subscriptions/` where CRM contact identity is required +- relies on `shared/` and `platform/` helper layers + +#### Migration Cautions + +- Future grouping candidate only. +- Account routes remain tightly coupled to session bootstrap and CRM contact identity. +- Documentation guidance only; any future grouping would need to preserve current session-to-contact resolution and all existing contracts. + +--- + +### 2. `admin/` + +#### Purpose + +Owns internal reporting, operational summaries, and admin-facing grouped data views. + +#### Primary Journeys Supported + +- admin reporting +- operational status views +- internal appeal/document summaries + +#### Typical Integrations + +- CRM + +#### Typical Route Types + +- read +- lookup +- aggregation + +#### Example Existing Routes + +- `pages/api/admin/getnewappeals_api.js` +- `pages/api/admin/getlatestdocuments_api.js` +- `pages/api/admin/getStatusCountsByAppealAndLPA_api.js` + +#### Shared Components Used + +- relay helpers +- response helpers +- logging helpers + +#### Relationship To Other Groups + +- depends on shared CRM relay/platform helpers +- generally adjacent to `cases/`, `appeals/`, and `documents/` data rather than owning those journeys + +#### Migration Cautions + +- Leave current admin routes effectively unchanged for now at the architecture level. +- This is already one of the more coherent current families. +- Documentation guidance only. + +--- + +### 3. `appeals/` + +#### Purpose + +Owns draft appeal progression, appeal submission/finalisation, and appeal-specific workflow orchestration. + +#### Primary Journeys Supported + +- start appeal +- save and exit +- resume appeal +- upload supporting files for appeal draft +- check answers +- submit appeal +- appeal completion + +#### Typical Integrations + +- CRM +- Azure Storage +- Azure Queue +- NextAuth + +#### Typical Route Types + +- read +- create +- update +- upload +- delete +- orchestration + +#### Example Existing Routes + +- `pages/api/file/getprogressobjblob.js` +- `pages/api/file/getbloblist.js` +- `pages/api/file/createappealcompletemessage_api.js` +- `pages/api/endpoint/createcase_api.js` +- `pages/api/endpoint/patchcase_api.js` + +#### Shared Components Used + +- Azure SDK helpers +- hash helpers +- relay helpers +- response helpers +- auth/session helpers + +#### Relationship To Other Groups + +- depends on `account/` for authenticated contact context +- depends on `platform/` / `shared/` for storage, queue, relay, validation, and response support +- intersects with `documents/` for user-facing file handling patterns + +#### Migration Cautions + +- Future grouping candidate only. +- Appeal flows cross storage-owned draft state and CRM-owned submitted state. +- Any future grouping would need to preserve sequencing, payload shapes, queue handoff, and contract-critical finalisation behavior. + +--- + +### 4. `auth/` + +#### Purpose + +Owns session establishment, sign-in callbacks, locale-aware auth routing, and auth-support bootstrap behavior. + +#### Primary Journeys Supported + +- sign in +- verify request +- callback/redirect handling +- locale-aware auth bootstrap + +#### Typical Integrations + +- NextAuth +- GOV.UK Notify +- CRM + +#### Typical Route Types + +- orchestration +- lookup +- support + +#### Example Existing Routes + +- `pages/api/auth/[...nextauth].js` +- `pages/api/auth/resolve-locale.js` +- adjacent support routes such as `pages/api/endpoint/getpreferredlanguage_api.js` + +#### Shared Components Used + +- auth/session helpers +- Notify helpers +- response helpers +- logging helpers + +#### Relationship To Other Groups + +- foundational cross-cutting dependency for `account/`, `appeals/`, `representations/`, and `subscriptions/` +- shares responsibility boundaries with `notifications/` where auth emails are sent + +#### Migration Cautions + +- Cross-cutting concern; not a simple journey folder. +- Future grouping candidate only. +- Any future grouping would need to preserve current callback, redirect, locale, verification-email, and session behavior exactly. + +--- + +### 5. `cases/` + +#### Purpose + +Owns case-detail retrieval, case messages, linked-case reads, and case-adjacent read models used by public and portal journeys. + +#### Primary Journeys Supported + +- public case details +- linked case viewing +- case messages/notices +- case-adjacent portal detail lookups + +#### Typical Integrations + +- CRM + +#### Typical Route Types + +- read +- lookup +- aggregation + +#### Example Existing Routes + +- `pages/api/endpoint/getcase_api.js` +- `pages/api/endpoint/getcasebyid_api.js` +- `pages/api/endpoint/getcasemessage_api.js` +- `pages/api/endpoint/getlinkedcases_api.js` +- `pages/api/endpoint/getportalmoduledetails_api.js` + +#### Shared Components Used + +- relay helpers +- response helpers +- signed request helpers + +#### Relationship To Other Groups + +- closely related to `search/` because public case detail often begins through search-family reads +- supports `subscriptions/` and `representations/` journeys that need case context +- relies on shared CRM/platform helpers + +#### Migration Cautions + +- Future grouping candidate only. +- Current case-detail retrieval is partly search-shaped rather than purely case-by-route shaped. +- Documentation guidance only; any future grouping would need to preserve current identifier assumptions and case-detail payload contracts. + +--- + +### 6. `documents/` + +#### Purpose + +Owns published document metadata retrieval and published document delivery/download behavior. + +#### Primary Journeys Supported + +- published document discovery +- published document download +- document history/detail retrieval + +#### Typical Integrations + +- CRM +- Azure Relay + +#### Typical Route Types + +- read +- lookup +- download + +#### Example Existing Routes + +- `pages/api/endpoint/getsearchdocumentdetails_api.js` +- `pages/api/endpoint/getsearchdocumenthistory_api.js` +- `pages/api/endpoint/getsearchdocumentTypes_api.js` +- `pages/api/documents/download/[id].js` + +#### Shared Components Used + +- relay helpers +- hash helpers +- response helpers +- signed request helpers + +#### Relationship To Other Groups + +- closely related to `search/` and `cases/` because those journeys surface published document links +- distinct from appeal/representation draft storage APIs + +#### Migration Cautions + +- Natural future grouping candidate for published-document behavior. +- Keep published-document discovery separate from draft-storage document handling in any future planning. +- Documentation guidance only. + +--- + +### 7. `notifications/` + +#### Purpose + +Owns outbound notification sending and orchestration routes that gather business data before sending transactional communications. + +#### Primary Journeys Supported + +- sign-in verification email +- completion notifications +- watchlist-related notifications +- business-triggered outbound email + +#### Typical Integrations + +- GOV.UK Notify +- CRM + +#### Typical Route Types + +- create +- orchestration +- lookup +- aggregation + +#### Example Existing Routes + +- `pages/api/email/notify.js` +- `pages/api/email/getall.js` +- `pages/api/email/getdocuments.js` +- `pages/api/email/getevents.js` + +#### Shared Components Used + +- Notify helpers +- relay helpers +- response helpers +- logging helpers + +#### Relationship To Other Groups + +- intersects with `auth/` for verification/sign-in email behavior +- intersects with `subscriptions/`, `appeals/`, and `representations/` for journey-triggered notifications + +#### Migration Cautions + +- Cross-cutting concern rather than a single business journey. +- Notification routes vary from thin send helpers to broader orchestration routes. +- Documentation guidance only; no implementation recommendation. + +--- + +### 8. `platform/` + +#### Purpose + +Owns platform-level support routes and utility/meta endpoints that are not naturally journey-owned business APIs. + +#### Primary Journeys Supported + +- platform health/support +- utility/meta API behaviors +- route-level support concerns + +#### Typical Integrations + +- local-only +- CRM lookup support where applicable + +#### Typical Route Types + +- support +- lookup +- meta +- health + +#### Example Existing Routes + +- `pages/api/health.js` +- `pages/api/doc.ts` +- `pages/api/notices/index.js` + +#### Shared Components Used + +- response helpers +- logging helpers +- validation helpers + +#### Relationship To Other Groups + +- supports all journey groups indirectly +- distinct from `shared/`, which is a component/helper classification rather than an API-journey group + +#### Migration Cautions + +- Likely leave unchanged for now at the API-family level unless a future planning slice establishes clearer journey ownership. +- Documentation guidance only. + +--- + +### 9. `representations/` + +#### Purpose + +Owns representation retrieval, draft representation lifecycle, and representation submission/finalisation orchestration. + +#### Primary Journeys Supported + +- start representation +- select capacity / representation type +- enter content +- upload supporting files +- save and resume representation draft +- check answers +- submit representation +- representation completion + +#### Typical Integrations + +- CRM +- Azure Storage +- Azure Queue +- GOV.UK Notify +- NextAuth + +#### Typical Route Types + +- read +- create +- update +- upload +- delete +- orchestration + +#### Example Existing Routes + +- `pages/api/file/getrepsblob.js` +- `pages/api/file/editRepJson.js` +- `pages/api/file/createrepcompletemessage_api.js` +- `pages/api/file/createrepinvolvement_api.js` +- `pages/api/endpoint/getrepresentations_api.js` + +#### Shared Components Used + +- Azure SDK helpers +- hash helpers +- relay helpers +- Notify helpers +- response helpers +- auth/session helpers + +#### Relationship To Other Groups + +- depends on `cases/` for case context +- depends on `account/` and `auth/` for identity/bootstrap +- intersects with `notifications/` for representation communications +- depends on `platform/` / `shared/` helpers for storage, queue, relay, and validation + +#### Migration Cautions + +- Future grouping candidate only. +- Representation routes span both read models and orchestration-heavy submission side effects. +- Any future grouping would need to preserve storage ownership, CRM representation relationships, and completion sequencing. + +--- + +### 10. `search/` + +#### Purpose + +Owns public search, advanced search, search-detail expansion, and public discovery-oriented lookups. + +#### Primary Journeys Supported + +- basic search +- advanced search +- result paging and sorting +- search-to-case navigation bootstrap + +#### Typical Integrations + +- CRM + +#### Typical Route Types + +- read +- lookup +- aggregation + +#### Example Existing Routes + +- `pages/api/endpoint/getbasicsearch_api.js` +- `pages/api/endpoint/getbasicsearchpaged_api.js` +- `pages/api/endpoint/getadvancedsearch_api.js` +- `pages/api/endpoint/getadvancedsearchpaged_api.js` +- `pages/api/endpoint/getbasicsearchdetails_api.js` + +#### Shared Components Used + +- relay helpers +- response helpers +- relay policy helpers +- signed request helpers + +#### Relationship To Other Groups + +- upstream journey dependency for `cases/` and `documents/` +- relies on shared CRM/platform helpers + +#### Migration Cautions + +- Natural future grouping candidate. +- Preserve public search contracts, paging assumptions, and detail-expansion behavior. +- Documentation guidance only. + +--- + +### 11. `subscriptions/` + +#### Purpose + +Owns watched-case and unsubscribe-related behavior, including subscription-like user relationships to cases and related notification preferences. + +#### Primary Journeys Supported + +- watch case +- unwatch case +- view watched cases +- unsubscribe / unsubscribe-all flows + +#### Typical Integrations + +- CRM +- GOV.UK Notify + +#### Typical Route Types + +- read +- create +- delete +- update +- orchestration + +#### Example Existing Routes + +- `pages/api/endpoint/getwatchedcases_api.js` +- `pages/api/endpoint/createwatchedcases_api.js` +- `pages/api/endpoint/deletewatchedcases_api.js` +- `pages/api/endpoint/deletewatchedcasesproxy_api.js` + +#### Shared Components Used + +- relay helpers +- relayGetData helpers +- response helpers +- auth/session helpers + +#### Relationship To Other Groups + +- depends on `account/` and `auth/` for identity context +- supports `cases/`, `search/`, and `my portal` style journeys +- intersects with `notifications/` because watchlist state participates in notification behavior + +#### Migration Cautions + +- Future grouping candidate only. +- Some notification behavior is owned by CRM watchlist state rather than Notify routes alone. +- Documentation guidance only; preserve create/upsert/delete semantics and watchlist relationship model. + +#### Additive façade pilot note + +- A first additive façade pilot now exists for watched-case APIs only: + - `pages/api/subscriptions/get-watched-cases.js` + - `pages/api/subscriptions/create-watched-case.js` + - `pages/api/subscriptions/delete-watched-case.js` +- These routes delegate to the existing endpoint handlers. +- Existing endpoint routes remain canonical/stable: + - `pages/api/endpoint/getwatchedcases_api.js` + - `pages/api/endpoint/createwatchedcases_api.js` + - `pages/api/endpoint/deletewatchedcases_api.js` +- No legacy route removal or frontend migration has occurred. + +--- + +### 12. `shared/` + +#### Purpose + +Represents shared platform components and reusable support primitives that should remain shared regardless of journey grouping. + +#### Primary Journeys Supported + +- all journeys indirectly + +#### Typical Integrations + +- CRM relay support +- Azure Storage support +- GOV.UK Notify support +- NextAuth/session support +- local-only middleware/helper support + +#### Typical Route Types + +- not primarily a journey-owned API route family +- middleware +- helper +- support + +#### Example Existing Routes / Areas + +- `pages/api/middleware/apiResponse.js` +- `pages/api/middleware/relayForwarding.js` +- `pages/api/middleware/relayPolicyPresets.js` +- `pages/api/middleware/middleware.js` + +#### Shared Components Used + +- relay helpers +- response helpers +- hash helpers +- signed request helpers +- Azure SDK helpers +- logging helpers +- validation helpers +- auth/session helpers +- Notify helpers + +#### Relationship To Other Groups + +- foundational dependency for every journey-owned group + +#### Migration Cautions + +- This is primarily a classification for **Shared Platform Components**, not a recommendation for a user-facing API area. +- Documentation guidance only. + +--- + +## Shared Platform Components + +The following capabilities should remain classified as **Shared Platform Components**, not journey-owned APIs: + +- relay helpers + - `relayGet(...)` + - `relayGetData(...)` + - relay forwarding helpers + - relay policy presets +- response helpers + - `respondSuccess(...)` + - `respondError(...)` +- hash helpers + - path signing + - integrity validation +- signed request helpers + - signed GET/POST/DELETE request execution +- Azure Storage helpers + - blob/container/queue operations +- auth/session helpers + - session establishment + - locale resolution support + - auth-support bootstrap helpers +- Notify helpers + - send behavior and shared notification composition support +- logging helpers + - structured/redacted logging support +- validation helpers + - required-input and route guard helpers + +Classification note: + +> These are shared platform concerns. They should be reused by journey-owned APIs rather than reclassified as journey-owned business capabilities. + +--- + +## Journey-to-Group Mapping + +This section works at the **journey/API-family level** only. + +It does **not** classify every individual API file. + +| Existing API family / journey area | Proposed future group | Classification | Notes | +| -------------------------------------------------- | --------------------------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| Public search | `search/` | Natural fit | Strong journey ownership already established in the route map. | +| Search detail expansion | `search/` | Natural fit | Closely tied to search contracts and result shaping. | +| Case details | `cases/` | Natural fit | Strong case-read ownership, even where current bootstrapping begins through search. | +| Case messages / notices | `cases/` | Natural fit | Best understood as case-page content rather than notifications. | +| Published documents metadata | `documents/` | Natural fit | Naturally grouped with published document discovery. | +| Published document download | `documents/` | Natural fit | Dedicated download boundary already coherent. | +| My portal dashboard CRM reads | `cases/` or `representations/` depending on journey | Likely fit | Dashboard is an aggregator, not one clean business capability. Leave journey reads with their owning domains conceptually. | +| Watched cases / watchlist | `subscriptions/` | Natural fit | Clear subscription-like relationship model. | +| Unsubscribe flows | `subscriptions/` | Natural fit | Closely tied to watchlist/subscription ownership. | +| Draft appeals | `appeals/` | Likely fit | Strong journey ownership, but current implementation crosses storage/platform boundaries. | +| Appeal submission / finalisation | `appeals/` | Likely fit | Business ownership is appeals, but implementation remains orchestration-heavy. | +| Representation reads | `representations/` | Natural fit | Strong journey ownership. | +| Draft representations | `representations/` | Likely fit | Strong journey ownership with storage/platform dependency. | +| Representation submission / finalisation | `representations/` | Likely fit | Business ownership is clear, but route shape is orchestration-heavy. | +| Account registration | `account/` | Natural fit | Clear account lifecycle ownership. | +| Personal details / account management | `account/` | Natural fit | Clear account lifecycle ownership. | +| Authentication / sign-in | `auth/` | Cross-cutting concern | Foundational platform behavior touching locale, session, and Notify. | +| Notifications / email | `notifications/` | Cross-cutting concern | Includes both thin sends and orchestration-heavy flows. | +| Admin / reporting | `admin/` | Leave unchanged for now | Already relatively coherent compared with `endpoint` and `file`. | +| Documented middleware / helper routes | `shared/` / `platform/` | Shared / Platform concern | Not journey-owned business APIs. | +| Health / meta / support routes | `platform/` | Shared / Platform concern | Platform support rather than business journey ownership. | +| Legacy catch-all CRM relay families in `endpoint/` | Depends on owning journey | Leave unchanged for now | Useful as current implementation location, but not a future ownership concept by themselves. | +| Storage-heavy families in `file/` | Depends on owning journey plus shared platform | Leave unchanged for now | Current folder is an implementation host, not a stable future ownership model. | + +--- + +## Architectural Principles + +Future development guidance only: + +1. Prefer journey ownership over historical folder ownership. +2. Group by business capability rather than by transport or technology alone. +3. Keep integrations behind journey-owned APIs where possible at the architecture level. +4. Reuse shared helpers rather than duplicating infrastructure logic. +5. Preserve API contracts. +6. Preserve current route behavior. +7. Preserve CRM as the source of truth for CRM-owned business data. +8. Preserve Azure Storage ownership boundaries for draft-owned content. +9. Preserve established authorization boundaries and session/bootstrap assumptions. +10. Preserve EN/CY parity and locale-aware behavior. +11. Treat orchestration-heavy routes as business-owned conceptually even when they depend on multiple shared platform capabilities. +12. Do not reorganise stable APIs without explicit business justification and explicit approval. +13. Do not treat `endpoint/` or `file/` as preferred future ownership models simply because they are current implementation locations. +14. Continue distinguishing between published-document APIs and draft-storage file APIs. + +--- + +## Non-Goals + +This document explicitly does **not** approve or recommend: + +- implementation +- migrations +- folder restructuring +- route movement +- route renaming +- API deletions +- API consolidation +- merging APIs +- reducing route count +- changing contracts +- changing payload shapes +- changing validation rules +- changing authorization behavior +- changing session behavior +- changing integration boundaries +- changing business behavior + +This is **architectural direction only**. + +--- + +## Risks / Cautions + +1. This plan is deliberately **planning-only**. +2. Future grouping concepts should not be mistaken for implementation approval. +3. Several current route families are orchestration-heavy and cross integration boundaries; they are easier to classify architecturally than to reorganise safely. +4. `auth/` and `notifications/` remain cross-cutting and should not be oversimplified into narrow folder ownership assumptions. +5. `endpoint/` and `file/` remain current implementation hotspots, but they should be interpreted as historical host folders rather than ideal future ownership concepts. +6. The dashboard remains an aggregation journey and does not justify a separate future grouping here; ownership is clearer when mapped back to cases, representations, subscriptions, and account concerns. +7. Published-document retrieval and draft-storage file handling should remain conceptually distinct. +8. Any future grouping exercise would need explicit migration cautions, but no migration planning is being proposed in this document. + +--- + +## Validation Performed + +Manual synthesis only. + +Performed: + +- read the required context files listed above +- confirmed active branch rules and guardrails before drafting +- reused the completed architecture programme as the evidence base +- checked the current top-level `pages/api` shape only to compare proposed future groups against today’s folder structure without producing a new inventory + +Not performed: + +- no implementation +- no runtime analysis +- no route-by-route re-inventory +- no refactor proposal +- no migration planning +- no lint/tests, because this is documentation-only planning work + +--- + +## Recommendation + +Recommended next architecture planning document only: + +### `context/api-rationalisation-planning.md` + +Suggested purpose: + +- evaluate, at a planning level only, where future API families appear structurally duplicated or historically drifted +- define criteria for when a future rationalisation candidate is documentation-worthy +- preserve the same non-goals as this document: no implementation, no migration, no route movement, and no contract change without separate approval + +No implementation work is recommended from this document alone. diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md index b93a7603..3cfd5dd1 100644 --- a/memory-bank/change-log.md +++ b/memory-bank/change-log.md @@ -18,6 +18,335 @@ Follow-ups: --- +### CL-2026-06-25-API-GROUPING-FACADE-SUBSCRIPTIONS-VERTICAL-SLICE-COMPLETION: watched-case proxy read adoption and scope closure + +date: 2026-06-25 +author: Cline +scope: `pages/api/subscriptions/get-watched-cases-proxy.js`, `actions/services/portalDirectService.js`, `tests/phase22/api-grouping-facade-subscriptions.test.cjs`, `context/api-grouping-adoption-roadmap.md` +type: change +rationale: Complete the intended subscriptions/watched-cases vertical slice by covering the active proxy read path still used by the normal watched-case UI journey, while keeping legacy endpoint and proxy handlers in place as canonical/support implementation routes. +impact: Runtime behaviour is intended to remain unchanged; the grouped subscriptions façade now covers the active watched-case journey service methods including proxy reads, while legacy handlers remain canonical and no route deletion, migration, auth/session change, CRM query change, payload change, or status-code change has occurred. +status: completed + +Summary: + +- Performed a bounded watched-case usage audit across services, pages, and components. +- Audit findings established that: + - no frontend components directly call legacy watched-case endpoint URLs + - normal watched-case journey calls are routed through `actions/services/portalDirectService.js` + - `getWatchedCasesProxy()` is actively used in the current watched-case UI journey + - `deletewatchedcasesproxy_api` remains present but is not part of the currently adopted normal watched-case service path +- Added grouped façade route: + - `pages/api/subscriptions/get-watched-cases-proxy.js` + - delegates directly to `pages/api/endpoint/getwatchedcasesproxy_api.js` +- Updated `actions/services/portalDirectService.js` so `getWatchedCasesProxy` now targets: + - `/api/subscriptions/get-watched-cases-proxy` +- Extended the existing subscriptions façade characterization test to prove: + - grouped proxy façade delegation works + - legacy proxy handler remains present + - watched-case service methods now target grouped subscriptions routes for both normal and proxy watched-case reads + - adopted methods no longer target the legacy watched-case endpoint URLs directly + - delete proxy remains outside grouped pilot scope and legacy support route remains present +- Updated the adoption roadmap to define what “complete vertical slice” means for this pilot and to record the proxy-scope boundary. + +Validation: + +- Focused validation only: + - `npx eslint actions/services/portalDirectService.js tests/phase22/api-grouping-facade-subscriptions.test.cjs pages/api/subscriptions/get-watched-cases.js pages/api/subscriptions/get-watched-cases-proxy.js pages/api/subscriptions/create-watched-case.js pages/api/subscriptions/delete-watched-case.js` + - `node tests/phase22/api-grouping-facade-subscriptions.test.cjs` +- No repository-wide test suite run. + +Follow-ups: + +- For the intended watched-case/subscriptions scope, the pilot now forms a complete vertical slice: + - subscriptions journey + - service layer + - grouped façade routes + - legacy canonical endpoint handlers + - unchanged behaviour +- Any future expansion beyond this scope should be a separate bounded slice (for example, deciding whether legacy/support proxy delete routes also need grouped façade coverage). + +### CL-2026-06-25-API-GROUPING-FACADE-SUBSCRIPTIONS-INTERNAL-ADOPTION: first internal consumer targets grouped watched-case routes + +date: 2026-06-25 +author: Cline +scope: `actions/services/portalDirectService.js`, `tests/phase22/api-grouping-facade-subscriptions.test.cjs`, `context/api-grouping-adoption-roadmap.md` +type: change +rationale: Validate the subscriptions façade pilot through one carefully selected internal consumer by updating watched-case service methods in `portalDirectService` to call the new grouped subscriptions routes while leaving the legacy endpoint handlers unchanged and canonical behind the façade. +impact: Runtime behaviour is intended to remain unchanged because the grouped routes still delegate to the existing watched-case handlers; validates incremental internal adoption without route migration, deprecation, auth/session change, CRM query change, payload change, or signed-request behaviour change. +status: completed + +Summary: + +- Re-read required continuation context before implementation: + - `context/api-grouping-plan.md` + - `context/api-grouping-adoption-roadmap.md` + - `context/api-route-map.md` + - `memory-bank/change-log.md` +- Updated only the watched-case methods in `actions/services/portalDirectService.js` to target grouped façade routes: + - `getWatchedCases` -> `/api/subscriptions/get-watched-cases` + - `createWatchedCases` -> `/api/subscriptions/create-watched-case` + - `deleteWatchedCases` -> `/api/subscriptions/delete-watched-case` +- Did not modify any other service methods in `portalDirectService.js`. +- Did not modify underlying watched-case endpoint handlers or façade handler delegation. +- Extended the existing façade characterization test to prove: + - grouped façade delegation still works + - legacy endpoint handler files remain present + - the internal service layer now targets `/api/subscriptions/...` + - the adopted watched-case methods no longer point at legacy `/api/endpoint/...` routes + - key service-layer request-contract cues remain present (`loggedInUserId`, `watchedCaseID`, POST method) +- Updated the adoption roadmap to record: + - first internal consumer adoption has occurred + - legacy routes remain canonical implementations + - no migration or deprecation has occurred + - this validates incremental adoption of grouped journey-owned routes + +Validation: + +- Focused validation only: + - `npx eslint actions/services/portalDirectService.js tests/phase22/api-grouping-facade-subscriptions.test.cjs context/api-grouping-adoption-roadmap.md memory-bank/change-log.md` + - `node tests/phase22/api-grouping-facade-subscriptions.test.cjs` +- No repository-wide test suite run. + +Follow-ups: + +- The subscriptions façade pattern has now been validated through both additive route introduction and one successful internal service adoption. +- Any further adoption should continue incrementally and only with the same behaviour-preserving characterization discipline. + +### CL-2026-06-25-API-GROUPING-FACADE-PILOT-SUBSCRIPTIONS: additive watched-case subscriptions façade routes + +date: 2026-06-25 +author: Cline +scope: `pages/api/subscriptions/*`, watched-case API façade pilot, focused characterization tests, and grouping-plan/adoption-roadmap documentation +type: change +rationale: Implement the first additive API grouping façade pilot by adding journey-owned subscriptions wrapper routes for watched-case read/create/delete operations that delegate to the existing canonical endpoint handlers without changing current frontend call sites, contracts, or behaviour. +impact: Runtime impact is intentionally additive only; existing watched-case endpoint routes remain canonical/stable; no auth/session, CRM query, hash/signing, payload, status-code, i18n, or frontend-callsite behaviour change intended; documentation now records the pilot and its non-migration status. +status: completed + +Summary: + +- Confirmed required implementation context was read before changes: + - `context/api-grouping-plan.md` + - `context/api-grouping-adoption-roadmap.md` + - `context/api-route-map.md` + - `context/journey-architecture-map.md` + - `context/portal-api-platform-assessment.md` + - `context/architecture.md` + - `memory-bank/change-log.md` +- Added the first grouped façade routes under `pages/api/subscriptions/`: + - `get-watched-cases.js` + - `create-watched-case.js` + - `delete-watched-case.js` +- Implemented each façade as the smallest safe compatibility wrapper: + - import the existing watched-case endpoint handler + - delegate `req` and `res` directly to that existing handler +- Preserved the existing canonical watched-case routes unchanged: + - `pages/api/endpoint/getwatchedcases_api.js` + - `pages/api/endpoint/createwatchedcases_api.js` + - `pages/api/endpoint/deletewatchedcases_api.js` +- Did not change frontend call sites; `actions/services/portalDirectService.js` continues to call the legacy endpoint routes. +- Added a focused characterization test file to prove: + - grouped façade route files exist and delegate to the expected legacy handlers + - legacy endpoint files still exist + - frontend watched-case service call sites were not migrated to `/api/subscriptions/` +- Updated the API grouping plan and adoption roadmap to record: + - this is the first additive grouping façade pilot + - existing watched-case endpoint routes remain canonical/stable + - new subscriptions routes are grouped façade routes + - no old route removal or migration has occurred + +Validation: + +- Focused implementation only; no broad refactor performed. +- Characterization coverage added for façade delegation and unchanged frontend call sites. +- Intended validation set for this slice: + - `npx eslint pages/api/subscriptions/*.js tests/phase22/api-grouping-facade-subscriptions.test.cjs` + - `node tests/phase22/api-grouping-facade-subscriptions.test.cjs` +- Existing watched-case endpoint files were preserved in place. + +Follow-ups: + +- If the pilot is accepted, use the same additive façade pattern for future journey-owned grouping candidates only where behaviour preservation can be equally well characterized. + +### CL-2026-06-25-API-GROUPING-ADOPTION-ROADMAP: gradual adoption roadmap for future journey-owned API grouping + +date: 2026-06-25 +author: Cline +scope: `context/api-grouping-adoption-roadmap.md`, architecture roadmap for gradual adoption of future API grouping concepts +type: milestone +rationale: Create a planning-only roadmap document describing how PEDW could gradually adopt the future journey-owned API grouping model over time through documentation guidance, additive consistency, and future-development discipline rather than migration or restructuring. +impact: Documentation/context only; improves architecture planning clarity for gradual API grouping adoption, maintainability direction, and future decision support; no runtime, auth, CRM, storage, queue, notification, i18n, contract, or behaviour change. +status: completed + +Summary: + +- Confirmed the required roadmap context was read before drafting: + - `context/api-grouping-plan.md` + - `context/api-route-map.md` + - `context/journey-architecture-map.md` + - `context/portal-api-platform-assessment.md` + - `context/architecture.md` + - `context/integration-map.md` + - `memory-bank/change-log.md` +- Added new document: `context/api-grouping-adoption-roadmap.md`. +- Kept the roadmap explicitly scoped to **architecture planning only**. +- Recorded the core adoption philosophy that PEDW should favour: + - gradual evolution + - behaviour preservation + - contract preservation + - incremental consistency + - reuse of shared helpers + over large restructures, wholesale moves, rewrites, or mass renaming. +- Added a staged roadmap covering: + - Stage 1 — Current state + - Stage 2 — Future development guidance + - Stage 3 — Documentation maturity + - Stage 4 — Future opportunities +- Added concise adoption principles emphasising: + - preserve stable APIs + - preserve contracts and integrations + - prefer additive improvements + - improve findability first + - avoid unnecessary churn + - never move APIs solely for cosmetic reasons +- Added a future-development decision matrix covering: + - new APIs + - existing stable APIs + - existing APIs being enhanced + - shared/platform concerns + - cross-cutting concerns + - orchestration-heavy routes +- Added qualitative success measures focused on maintainability outcomes rather than implementation metrics. +- Added explicit non-goals including: + - no migrations + - no implementation + - no route movement + - no route renaming + - no API deletion + - no consolidation + - no contract changes + - no behaviour changes +- Recommended the next architecture planning document only: + - `context/api-maintainer-guidance-v2.md` + +Validation: + +- Documentation-only planning work; no runtime code changed. +- Non-destructive synthesis only: + - reused the completed architecture programme as the evidence base + - reused the newly completed API grouping plan rather than reopening discovery + - remained at architecture-roadmap level and did not widen into implementation or migration guidance +- Did not perform another API inventory. +- Did not recommend implementation, migration, refactor, or route moves. +- No repo-wide automated analysis performed. +- No Python used. +- Lint/tests not run because this was documentation-only work. + +Follow-ups: + +- Next architecture planning document only: + - `context/api-maintainer-guidance-v2.md` + +--- + +### CL-2026-06-25-API-GROUPING-PLAN-PHASE-1: future journey-owned API grouping model + +date: 2026-06-25 +author: Cline +scope: `context/api-grouping-plan.md`, architecture planning for future journey-owned API grouping concepts +type: milestone +rationale: Create a planning-only architecture document that synthesises the completed API platform, route map, journey map, integration map, and architecture findings into a future journey-owned API grouping model focused on maintainability, findability, consistency, and extensibility without reopening discovery or recommending implementation. +impact: Documentation/context only; improves future architecture planning clarity around journey-owned API grouping, shared platform concerns, and API-family classification; no runtime, auth, CRM, storage, queue, notification, i18n, contract, or behaviour change. +status: completed + +Summary: + +- Confirmed the required planning context was read before drafting: + - `context/api-route-map.md` + - `context/journey-architecture-map.md` + - `context/portal-api-platform-assessment.md` + - `context/architecture.md` + - `context/integration-map.md` + - `memory-bank/change-log.md` +- Added new document: `context/api-grouping-plan.md`. +- Kept the document explicitly scoped to **architecture planning only**. +- Recorded the key evidence-base finding that the main API maintenance problem is: + - findability + - ownership clarity + - consistency + - reuse discipline +- Assessed the proposed future grouping concepts only as documentation guidance: + - `account/` + - `admin/` + - `appeals/` + - `auth/` + - `cases/` + - `documents/` + - `notifications/` + - `platform/` + - `representations/` + - `search/` + - `subscriptions/` + - `shared/` +- For each proposed group, documented: + - purpose + - primary journeys supported + - typical integrations + - typical route types + - representative existing routes + - shared components used + - relationship to other groups + - migration cautions +- Added a **Shared Platform Components** section classifying reusable helpers such as: + - relay helpers + - response helpers + - hash helpers + - signed request helpers + - Azure Storage helpers + - auth/session helpers + - Notify helpers + - logging helpers + - validation helpers +- Added a **Journey-to-Group Mapping** section working at journey/API-family level only and classifying areas as: + - Natural fit + - Likely fit + - Shared / Platform concern + - Cross-cutting concern + - Leave unchanged for now +- Added future guidance principles and explicit non-goals, including: + - no implementation + - no migrations + - no folder restructuring + - no route movement + - no route renaming + - no API deletions + - no API consolidation + - no behaviour change + - no contract change +- Recommended the next architecture planning document only: + - `context/api-rationalisation-planning.md` + +Validation: + +- Documentation-only planning work; no runtime code changed. +- Non-destructive evidence gathering and synthesis only: + - read required context files + - targeted extraction from existing route/journey/platform architecture documents + - top-level `pages/api` listing only to compare current shape with future grouping concepts without producing a new API inventory +- Did not reopen architectural discovery. +- Did not perform a new route inventory. +- Did not recommend implementation, refactor, migration, or route moves. +- No repo-wide automated analysis performed. +- No Python used. +- Lint/tests not run because this was documentation-only work. + +Follow-ups: + +- Next architecture planning document only: + - `context/api-rationalisation-planning.md` + +--- + ### CL-2026-06-22-JOURNEY-ARCHITECTURE-MAP-SLICE-8: case-messages-notices and related-published-case-communications lifecycle map date: 2026-06-22 diff --git a/pages/api/subscriptions/create-watched-case.js b/pages/api/subscriptions/create-watched-case.js new file mode 100644 index 00000000..b16b2050 --- /dev/null +++ b/pages/api/subscriptions/create-watched-case.js @@ -0,0 +1,5 @@ +import legacyCreateWatchedCaseHandler from "../endpoint/createwatchedcases_api"; + +export default async function createWatchedCaseFacade(req, res) { + return legacyCreateWatchedCaseHandler(req, res); +} diff --git a/pages/api/subscriptions/delete-watched-case.js b/pages/api/subscriptions/delete-watched-case.js new file mode 100644 index 00000000..6a2a2587 --- /dev/null +++ b/pages/api/subscriptions/delete-watched-case.js @@ -0,0 +1,5 @@ +import legacyDeleteWatchedCaseHandler from "../endpoint/deletewatchedcases_api"; + +export default async function deleteWatchedCaseFacade(req, res) { + return legacyDeleteWatchedCaseHandler(req, res); +} diff --git a/pages/api/subscriptions/get-watched-cases-proxy.js b/pages/api/subscriptions/get-watched-cases-proxy.js new file mode 100644 index 00000000..2c409c60 --- /dev/null +++ b/pages/api/subscriptions/get-watched-cases-proxy.js @@ -0,0 +1,5 @@ +import legacyGetWatchedCasesProxyHandler from "../endpoint/getwatchedcasesproxy_api"; + +export default async function getWatchedCasesProxyFacade(req, res) { + return legacyGetWatchedCasesProxyHandler(req, res); +} diff --git a/pages/api/subscriptions/get-watched-cases.js b/pages/api/subscriptions/get-watched-cases.js new file mode 100644 index 00000000..d1365ffc --- /dev/null +++ b/pages/api/subscriptions/get-watched-cases.js @@ -0,0 +1,5 @@ +import legacyGetWatchedCasesHandler from "../endpoint/getwatchedcases_api"; + +export default async function getWatchedCasesFacade(req, res) { + return legacyGetWatchedCasesHandler(req, res); +} diff --git a/tests/phase22/api-grouping-facade-subscriptions.test.cjs b/tests/phase22/api-grouping-facade-subscriptions.test.cjs new file mode 100644 index 00000000..5c649533 --- /dev/null +++ b/tests/phase22/api-grouping-facade-subscriptions.test.cjs @@ -0,0 +1,193 @@ +const assert = require("assert"); +const fs = require("fs"); +const path = require("path"); + +const { loadModule, createRes } = require("../phase21/_shared.cjs"); + +const rootDir = path.resolve(__dirname, "..", ".."); + +const tests = []; +const test = (name, fn) => tests.push({ name, fn }); + +const read = (relativePath) => + fs.readFileSync(path.join(rootDir, relativePath), "utf8"); + +test("subscriptions get-watched-cases facade delegates to legacy handler", async () => { + const calls = []; + const mod = loadModule("pages/api/subscriptions/get-watched-cases.js", { + legacyGetWatchedCasesHandler: async (req, res) => { + calls.push({ req, res }); + return res.status(200).json({ ok: true, route: "get" }); + } + }); + + const req = { method: "GET", query: { loggedInUserId: "user-1" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(calls.length, 1); + assert.strictEqual(calls[0].req, req); + assert.strictEqual(calls[0].res, res); + assert.strictEqual(res.state.statusCode, 200); + assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { + ok: true, + route: "get" + }); +}); + +test("subscriptions create-watched-case facade delegates to legacy handler", async () => { + const calls = []; + const mod = loadModule("pages/api/subscriptions/create-watched-case.js", { + legacyCreateWatchedCaseHandler: async (req, res) => { + calls.push({ req, res }); + return res.status(200).json({ ok: true, route: "create" }); + } + }); + + const req = { + method: "POST", + body: { + "pinswg_WatchedCase@odata.bind": "/incidents(inc-1)", + "pinswg_Contact@odata.bind": "/contacts(con-1)" + } + }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(calls.length, 1); + assert.strictEqual(calls[0].req, req); + assert.strictEqual(calls[0].res, res); + assert.strictEqual(res.state.statusCode, 200); + assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { + ok: true, + route: "create" + }); +}); + +test("subscriptions delete-watched-case facade delegates to legacy handler", async () => { + const calls = []; + const mod = loadModule("pages/api/subscriptions/delete-watched-case.js", { + legacyDeleteWatchedCaseHandler: async (req, res) => { + calls.push({ req, res }); + return res.status(200).json({ ok: true, route: "delete" }); + } + }); + + const req = { method: "DELETE", query: { watchedCaseID: "watch-1" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(calls.length, 1); + assert.strictEqual(calls[0].req, req); + assert.strictEqual(calls[0].res, res); + assert.strictEqual(res.state.statusCode, 200); + assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { + ok: true, + route: "delete" + }); +}); + +test("subscriptions get-watched-cases-proxy facade delegates to legacy handler", async () => { + const calls = []; + const mod = loadModule( + "pages/api/subscriptions/get-watched-cases-proxy.js", + { + legacyGetWatchedCasesProxyHandler: async (req, res) => { + calls.push({ req, res }); + return res.status(200).json({ ok: true, route: "proxy-get" }); + } + } + ); + + const req = { method: "GET", query: { loggedInUserId: "user-2" } }; + const res = createRes(); + await mod.default(req, res); + + assert.strictEqual(calls.length, 1); + assert.strictEqual(calls[0].req, req); + assert.strictEqual(calls[0].res, res); + assert.strictEqual(res.state.statusCode, 200); + assert.deepStrictEqual(JSON.parse(JSON.stringify(res.state.jsonBody)), { + ok: true, + route: "proxy-get" + }); +}); + +test("legacy watched-case endpoint files remain present", async () => { + const legacyFiles = [ + "pages/api/endpoint/getwatchedcases_api.js", + "pages/api/endpoint/getwatchedcasesproxy_api.js", + "pages/api/endpoint/createwatchedcases_api.js", + "pages/api/endpoint/deletewatchedcases_api.js" + ]; + + legacyFiles.forEach((filePath) => { + assert.strictEqual( + fs.existsSync(path.join(rootDir, filePath)), + true, + filePath + ); + }); +}); + +test("portalDirectService watched-case methods now target subscriptions facade routes", async () => { + const source = read("actions/services/portalDirectService.js"); + + assert.match(source, /\/api\/subscriptions\/get-watched-cases/); + assert.match(source, /\/api\/subscriptions\/get-watched-cases-proxy/); + assert.match(source, /\/api\/subscriptions\/create-watched-case/); + assert.match(source, /\/api\/subscriptions\/delete-watched-case/); +}); + +test("portalDirectService no longer targets legacy watched-case routes for adopted methods", async () => { + const source = read("actions/services/portalDirectService.js"); + + assert.doesNotMatch(source, /\/api\/endpoint\/getwatchedcases_api/); + assert.doesNotMatch(source, /\/api\/endpoint\/getwatchedcasesproxy_api/); + assert.doesNotMatch(source, /\/api\/endpoint\/createwatchedcases_api/); + assert.doesNotMatch(source, /\/api\/endpoint\/deletewatchedcases_api/); +}); + +test("portalDirectService still preserves watched-case runtime contracts around inputs", async () => { + const source = read("actions/services/portalDirectService.js"); + + assert.match(source, /loggedInUserId/); + assert.match(source, /watchedCaseID/); + assert.match(source, /method:\s*"post"/); +}); + +test("delete watched-case proxy route remains outside the grouped subscriptions pilot scope", async () => { + const source = read("actions/services/portalDirectService.js"); + + assert.doesNotMatch(source, /deletewatchedcasesproxy_api/); + assert.strictEqual( + fs.existsSync( + path.join( + rootDir, + "pages/api/endpoint/deletewatchedcasesproxy_api.js" + ) + ), + true + ); +}); + +async function run() { + let failures = 0; + + for (const { name, fn } of tests) { + try { + await fn(); + console.log(`✓ ${name}`); + } catch (error) { + failures += 1; + console.error(`✗ ${name}`); + console.error(error); + } + } + + if (failures > 0) { + process.exit(1); + } +} + +run();