- Ownership clarity: high at policy-rule level, moderate at runtime-adoption level
- Characterization confidence: high
Representation Type Availability is the strongest proven business-policy seam.
Representation Entry Policy is partially adopted.
Appeal Type Policy is intentionally narrow and stable.
### Current Domain-Layer Interpretation
The domain layer should now be read as a deliberately small set of behaviour-preserving extraction seams rather than as a large hidden domain architecture.
This means each module still needs to be interpreted according to what it actually owns:
- some modules are genuine business-policy seams
- some modules are presentation interpretation seams
- some modules are compatibility-preserving helpers
---
## Adoption Planning Readiness
Status: Ready
The project now possesses:
- identified policy boundaries
- characterized policy behaviour
- identified consumers
- identified adoption risks
Remaining work is primarily:
- adoption planning
- characterization coverage
- extraction sequencing
- documentation refinement
---
## Programme Phase
Discovery
↓
Characterization
↓
Documentation
↓
Adoption Planning
↓
Extraction
↓
Adoption
The project should now be considered to be entering:
Follow-up investigation determined that PEDW does not currently contain a single explicit Participant & Ownership Domain Model.
The area consists of three overlapping concerns:
1. CRM Compatibility Model
2. Workflow / Orchestration Behaviour
3. Limited Participant-Driven Business Logic
Participant concepts are stable and recurring:
- Appellant
- Agent
- Interested Party
- LPA
- NRW
- Land Owner
However ownership and relationship behaviour is distributed across:
- CRM involvement mappings
- CRM relationship entities
- account registration defaults
- appeal completion side effects
- representation-capacity routing
- watch relationships
- dashboard segmentation
#### Key Finding
The strongest reusable rule seam remains:
Participant Type
↓
Representation Capacity
↓
Representation Type Policy
Participant concepts primarily act as inputs into existing policy models rather than forming a standalone policy model themselves.
#### Architectural Assessment
Participant & Ownership should not currently be considered a proven Domain Policy candidate.
Best current classification:
- CRM Compatibility Model (strong)
- Workflow / Orchestration Behaviour (strong)
- Business Decision Logic (limited)
#### Recommendation
No further broad Participant & Ownership discovery track is recommended unless new evidence emerges.
Confidence: Medium-High
### Domain Layer Status Verification
#### Status
Verified
#### Updated Conclusion
The PEDW domain layer is real but deliberately narrow.
It currently contains a mixture of:
- genuine business decision seams
- presentation/worklist segmentation seams
- compatibility-preserving helper seams
Follow-up verification established that not everything under `lib/domain/**` should be treated as a business-policy boundary.
Current verified status by area:
-`lib/domain/representation-type-policy/**` -> clearest current business decision module
-`lib/domain/representation-policy/**` -> partial business decision boundary with residual UI-side duplication
-`lib/domain/appeal-type-policy/**` -> narrow family-classification helper, not a broad appeal-type policy layer
-`lib/domain/dashboard-policy/**` -> presentation/worklist segmentation only
-`lib/domain/case-lifecycle/**` -> read-only journey interpretation seam, not a lifecycle business policy
#### Key Finding
The domain layer now appears best understood as an intentionally small set of behaviour-preserving extraction seams rather than a large or fully adopted domain architecture.
#### Architectural Assessment
The domain layer exists and is useful, but its boundaries are mixed and must continue to be interpreted module-by-module.
Confidence: High
### Representation Type Availability Adoption Assessment
#### Status
Characterized
#### Updated Conclusion
`lib/domain/representation-type-policy/getAvailableRepresentationTypes.js` is confirmed as the clearest current business decision module in the domain layer.
However, it is not yet the adopted runtime source of truth.
The active runtime path still uses the component-side rule engine:
| Representation entry eligibility and path selection | `lib/domain/representation-policy/*`, `components/case/summary/utils/representationEntry.js`, `components/search/repsonresults.js`, `lib/domain/representation-type-policy/getAvailableRepresentationTypes.js` | Determines if representation entry is available, whether blocked messaging is shown, and which downstream representation types are offered. |
| Dashboard/worklist workflow segmentation | `lib/domain/dashboard-policy/*`, `pages/api/endpoint/getawaitingsubmission_api.js`, `pages/api/endpoint/getwatchedcases_api.js`, `pages/myportal/index.js`, `components/myportal/viewall.js`, `components/myportal/topthree.js` | Splits records into awaiting submission, watched, submitted representations, and related user-facing worklists. |
| Case lifecycle/status interpretation seam outside the already-completed case-progress conclusion | `lib/domain/case-lifecycle/*`, `components/case/status.js`, `components/case/summary/utils/caseStagesByAppealType.js` | Read-only interpretation seam for stage-journey selection and progress display, but not a proven lifecycle business model. |
| Notification/template selection behaviour | `pages/api/email/notify.js`, `actions/services/notifyService.js`, `lib/newappeal/journeyEffects.js`, `components/case/representation/index.js`, `pages/api/auth/[...nextauth].js` | Sends GOV.UK Notify emails for sign-in, partial save, and completion-style events; template choice is driven locally by flow/origin/locale. |
| CRM query-shape compatibility and data-shaping | `actions/selectQueryTypes.js`, `docs/query-profile-compatibility.md`, `pages/api/endpoint/get*` routes | Preserves CRM field/profile compatibility for downstream UI and workflow consumers. |
| Azure queue / completion message handoff | `actions/azurestorage.js`, `pages/api/file/createappealcompletemessage_api.js`, `pages/api/file/createrepcompletemessage_api.js` | Packages finalised appeal/representation data into queue/message handoff for downstream processing. |
| Submission orchestration – New Appeal | **Integration Model** | The code is dominated by sequencing side effects: create CRM case, write blob state, generate PDF, upload docs, send completion message, update account role. No single reusable decision module was found. |
| Submission orchestration – Representations | **Mixed / Unclear** | Mostly orchestration/integration, but includes embedded participant/path decisions and representation-type branching inside UI/orchestration components. |
| Draft/save-resume storage workflow | **Integration Model** | Main concern is blob persistence, restoration, and worklist exposure. Rules appear storage/workflow-oriented, not domain-policy-like. |
| Participant / involvement / ownership handling | **Mixed / Unclear** | There are clear role concepts (Appellant, Agent, Interested Party, LPA) and involvement bindings, but logic is scattered between auth, loaders, UI, and CRM write endpoints rather than centralized as one coherent model. |
| Representation entry eligibility and path selection | **Business Decision Model** | This area already shows reusable rule logic based on appeal type, specialist process, date window, and participant/LPA status. It behaves like a true policy seam. |
| Dashboard/worklist workflow segmentation | **Presentation Model** with workflow markers | `dashboard-policy` owns only watched/submitted bucket classification. It is portal-facing segmentation of records for display, not a broader business policy. |
| Case lifecycle/status interpretation seam | **Presentation Model** | The seam explicitly says it does not own lifecycle semantics; it selects stage catalogues and progress display from CRM inputs. |
| Notification/template selection behaviour | **Integration Model** | Notification behaviour originates from journey orchestration points and auth, with local template IDs and locale checks. No coherent notification policy module exists. |
| CRM query-shape compatibility and data-shaping | **CRM Compatibility Model** | Field selection and naming are preserved to match CRM/Dataverse contracts and entity differences. |
| Azure queue / completion message handoff | **Integration Model** | Concern is message creation and downstream handoff, not business rule ownership. |
---
### Part 3 – Submission Behaviour
#### Conclusion
Submission behaviour appears primarily to be **workflow orchestration plus integration concerns**, with some embedded participant/path decisions. It does **not** currently appear to be one coherent reusable business decision model.
#### Evidence
**New Appeal**
-`lib/newappeal/journeyEffects.js` is a thin effect wrapper over:
-`uploadFiles`
-`sendEmail`
-`generateAppealPDF`
-`sendCaseCompleteMessage`
- This is orchestration glue, not a rule model.
-`pages/api/endpoint/createcase_api.js` creates CRM incidents with hard-coded operational fields:
-`caseorigincode: 3`
-`servicestage: 1`
- contact binding
- appeal type binding
- LPA binding
- That suggests submission starts with an operational CRM creation contract rather than a domain decision engine.
- conditionally updates contact involvement to Appellant (`846040001`) unless current involvement is Agent (`846040000`)
- calls `createCaseCompleteMessage(...)`
- This is a finalisation/handoff chain, not a reusable rule boundary.
**Representations**
-`components/case/representation/index.js` owns:
- draft update body creation
- save-vs-submit behaviour
- partial-save email trigger
- routing/redirect behaviour
- representation capacity branching
- submit enrichment
-`components/case/representation/utils/finalisationBoundary.js` contains helper extraction, but `runFinalisationSequence(...)` is still orchestration:
- set finalising UI state
- generate PDF
- update links
- upload files
- mark submit flags
-`pages/api/file/createrepcompletemessage_api.js` only validates query/hash then calls `createRepCompleteMessage(...)`.
-`pages/api/file/createrepinvolvement_api.js` checks whether a contact/case/type involvement already exists and otherwise creates one in CRM. This is a compatibility/integration write model.
- Existing representation resume is blob-driven via `getRepsFromBlob(...)` and `getRepsFilesBlobs(...)`.
-`getawaitingsubmissionfromblob` and related endpoints expose explicit portal draft storage concepts.
- This strongly suggests portal-owned workflow state separate from CRM lifecycle.
**Queue message creation / CRM / DMS handoff**
-`actions/azurestorage.js` includes queue client use and functions such as:
-`createCaseCompleteMessage`
-`createRepCompleteMessage`
- Completion APIs call those directly after assembling required blob/case data.
- The handoff concern is technical/integration-oriented.
#### Determination
- **Business decisions:** only partially present, mainly around who/what may submit and which representation path/type applies.
- **Workflow orchestration:** strongly present.
- **Integration concerns:** strongly present.
- **Overall:** **Mixed, but primarily workflow orchestration + integration**.
---
### Part 4 – Notification Behaviour
#### Conclusion
Notification decisions originate locally in auth and journey orchestration points. Notification behaviour does **not** currently appear to be driven by a coherent reusable notification policy.
#### Evidence
-`pages/api/auth/[...nextauth].js`
- selects sign-in template by locale:
-`templateId`
-`templateIdcy`
- locale resolution comes from CRM preferred language first, then request/callback URL fallback.
- this is a local auth notification decision.
-`lib/newappeal/journeyEffects.js`
- exposes `sendPartialSaveEmailEffect(...)`
- exposes `sendCompletionEmailEffect(...)`
- but these are thin wrappers only.
-`components/case/representation/index.js`
- partial save email is triggered inside `updateRepresentation(...)`
- template ID is embedded inline: `021b0a7b-df00-41f1-b94e-c269bee98c75`
- reference is embedded inline: `PEDW-PARTIAL-REP`
-`pages/api/email/notify.js` is a generic transport endpoint to GOV.UK Notify.
- Searches found no authoritative notification-policy module governing:
- event → template mapping
- audience selection
- locale strategy across all journeys
- communication suppression/eligibility rules
#### Logic App interactions
- The inspected code and searches did not reveal a clear portal-owned Logic App policy layer.
- Notification/integration references are much clearer for GOV.UK Notify and Azure queue/storage than for Logic App-specific orchestration.
- If Logic Apps are involved downstream, the visible portal code suggests that handoff is likely integration-level rather than decision-model-level.
#### Determination
- Notification behaviour is primarily **integration/orchestration**.
- A coherent **notification policy** does **not** currently appear explicit in the inspected code.
---
### Part 5 – Participant & Ownership Behaviour
#### Conclusion
A coherent participant relationship model is **partially visible**, but it is fragmented and not centralized. The repository shows stable role concepts, yet ownership/relationship behaviour is spread across CRM involvement writes, auth defaults, page loaders, and UI branching.
#### Evidence
-`pages/api/auth/[...nextauth].js` and `context/domain-flows.md` indicate newly registered/authenticated users default to **Interested Party**.
-`pages/api/file/createcaseinvolvement_api.js`
- links contact to incident via case involvement association.
-`pages/api/file/createrepinvolvement_api.js`
- maps string involvement to CRM codes:
-`appellant: 846040001`
-`interestedparty: 846040061`
-`agent: 846040000`
-`LPA: 846040012`
- checks for existing identical involvement before creating a new one.
- after appeal completion, updates contact involvement to Appellant unless current involvement is Agent.
- this is strong evidence that appeal submission can change participant identity/ownership state in CRM.
-`lib/representation/pageLoaders.js`
- determines `isLPA` from account details formatted value.
-`components/case/representation/index.js`
- branches representation capacity and form controls across Appellant / Agent / Interested Party / LPA / Land Owner.
-`isAppellant` is inferred by comparing account email with case contact email in one flow.
-`pages/myportal/case/[ticketnumber].js` and worklist logic separate “My cases”, “Watched cases”, and “Submitted representations”, indicating different user-to-case relationships.
#### Assessment
There is evidence of a meaningful participant model:
- contact role / type of involvement
- case ownership vs watched relationship
- representation capacity
- LPA vs non-LPA role
- Appellant role assignment on appeal completion
But it is not one explicit model yet. It is split across:
- CRM compatibility codes
- flow branching
- identity defaults
- involvement write endpoints
#### Determination
- **Classification:** **Mixed / Unclear**
- There is a likely discoverable participant relationship model, but it is not yet explicit.
---
### Part 6 – Eligibility Behaviour
#### Conclusion
The portal does contain reusable business-rule sets for representation eligibility and type selection. Outside that area, broader “may submit” behaviour is less centralized and often tied to workflow/auth/integration state.
#### Evidence
**Strong evidence of reusable eligibility business rules**
- start / statement due / final comments due dates
- NRW flag
- determines whether options such as Questionnaire, Statement, Final comments, Consultation Response, Local Impact Report, Marine Impact Report are available.
This is the clearest remaining business-rule area in the inspected code.
**Weaker evidence for broader “may submit”**
-`lib/representation/pageLoaders.js` enforces auth/session presence and case query prerequisites.
-`components/case/representation/index.js` branches form route/capacity based on role and current state.
- New appeal eligibility appears more tied to available appeal types and route/store setup than to a centralized submit-eligibility policy.
#### Determination
- Representation participation and type availability: **Business Decision Model**.
- Broader submit eligibility across all journeys: **Mixed**, not yet one reusable general policy.
---
### Part 7 – Lifecycle Behaviour
#### Conclusion
The portal does **not** contain one explicit shared lifecycle model for Draft → Submitted → Accepted → Relayed → CRM-created → Failed → Re-submitted. Instead it contains overlapping workflow and status concepts across storage, CRM status, watched/submitted flags, and presentation seams.
#### Evidence
-`lib/domain/case-lifecycle/README.md` explicitly says the lifecycle boundary:
- is a narrow read-only seam
- does not own lifecycle semantics
- does not own progress/status calculation ownership broadly
-`pages/api/endpoint/createcase_api.js` sets `servicestage: 1` when creating a case, which looks like operational CRM state rather than a portal lifecycle abstraction.
-`getawaitingsubmission_api.js` and blob endpoints define a portal-owned “awaiting submission” concept.
-`lib/domain/dashboard-policy/README.md` classifies watched records by whether `pinswg_representationsubmitted == null`.
| 1 | Appeal Type Availability Filtering Verification | Business-rule filtering check | High | High | High | Verification rather than discovery |
| 2 | Server-Side Ownership Enforcement Verification | Workflow / access enforcement | High | High | High | Verification rather than discovery |
| 3 | Representation Type Context Contract Verification | Business-policy adoption check | High | Medium-High | High | Verification rather than discovery |
| 4 | Representation Entry Divergence Verification | Consumer divergence check | High | Medium-High | High | Verification rather than discovery |
| 5 | Runtime adoption boundary documentation | Documentation / boundary clarity | High | Medium | High | Documentation consolidation |
| 6 | Characterization tests for proven policies | Safety-net verification | High | Medium | High | Verification support |
| 7 | Submission state boundary verification | Workflow/state interpretation | Medium | Medium | Medium-High | Focused verification |
| 8 | Portal workflow vs CRM lifecycle verification | Workflow / compatibility check | Medium | Medium | Medium-High | Focused verification |
| 9 | Notification event/template verification | Integration behaviour check | Medium | Medium | Medium | Focused verification |
| 10 | Query-shape dependency map verification | CRM compatibility check | High | Medium | High | Focused verification |
- Participant & Ownership Behaviour -> Characterized; not current next candidate; not a proven standalone domain-policy candidate.
- Submission Eligibility & Journey Access -> Characterized; not current highest-value next candidate; mixed rather than a coherent policy model.
- New Appeal Start & Resume Behaviour -> Characterized; not current highest-value next candidate; workflow/technical access rather than business policy.
#### Remaining Verification Candidates
1.**Appeal Type Availability Filtering Verification**
- investigate `getappealtypesfornewappeal_api`
- verify whether hidden business restrictions exist before the start UI receives available appeal types
- auth email template choice and GOV.UK Notify send.
---
## Remaining Unknowns
1. Whether participant role/involvement rules are intentional business policy or mainly CRM/write compatibility plus UI branching.
2. Whether any Logic App-based communication or downstream orchestration exists outside the inspected portal-visible code paths.
3. Whether new appeal flow contains a deeper hidden rule set for who may submit on whose behalf, beyond the visible orchestration and role reassignment.
4. Whether a distinct “submission state model” is documented elsewhere, or whether current draft/awaiting-submission/submitted/finalising states are purely incidental workflow markers.
5. Whether CRM operational statuses intentionally align with portal draft/finalisation concepts anywhere outside the case-progress presentation seam.
---
## Recommendation
Broad architectural discovery should now be considered complete.
Future work should focus on adoption-planning activity rather than on identifying additional hidden domain candidates.
Primary focus:
1. Representation Type Availability
2. Representation Entry Policy
3. Appeal Type Policy
Reasoning:
- the main business-policy seams are now identified and characterized
- the domain layer exists and is intentionally narrow
- Representation Type Availability is the strongest proven policy boundary
- Representation Entry Policy is a partially adopted policy seam with known consumer boundaries
- Appeal Type Policy is already stable as a narrow supporting boundary
- the highest-value next work is planning safe adoption of proven policy boundaries rather than continuing discovery
---
## Whether Another Discovery Slice Is Justified
**No broad discovery slice is currently justified.**
If any further work is undertaken before adoption planning, it should be limited to narrow verification or characterization-coverage confirmation.
Those activities would support planning confidence, but they would not reopen the discovery programme.
---
## Recommended Next Workstream
Domain Layer Adoption Strategy
Objective:
Plan safe adoption of proven policy boundaries.
This is an adoption-planning activity, not a discovery activity.
Primary focus:
1. Representation Type Availability
2. Representation Entry Policy
3. Appeal Type Policy
---
### Recommended Next Verification Slice
**Appeal Type Availability Filtering Verification**
Reason:
- The new-appeal start flow depends on `getAppealsTypesForNewAppeal()`.
- The client-side characterization found no strong business-policy gate in the start flow itself.
- The highest-value remaining uncertainty is whether the upstream API is already applying hidden business filtering before the UI renders options.
### Confidence Level For Recommendation
**High**
Participant & Ownership, Submission Eligibility & Journey Access, and New Appeal Start & Resume Behaviour have now all been characterized and deprioritized as broad next streams.
The latest follow-up work establishes that the architecture map has moved beyond broad discovery and toward verification of remaining filtering and ownership-enforcement assumptions.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.