chore(refactor): commit current refactor branch updates and slice1 xml/form derivation extraction

This commit is contained in:
2026-04-10 09:39:28 +01:00
parent bd3d311cfb
commit e9d4b65a3d
28 changed files with 1340 additions and 439 deletions
+176
View File
@@ -0,0 +1,176 @@
# Contributing with AI (Refactor Branch — PEDW FrontEnd)
## Purpose
This guide defines how engineers and AI agents should work safely and efficiently in this refactor branch.
This branch focuses on **safe, behaviour-preserving refactor of the new appeal flow**.
---
## Start Here (Required Order)
1. Read `.clinerules/refactor-branch-rules.md`
2. Read `GUARDRAILS.md`
3. Read core context:
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
- `context/architecture.md`
- `context/domain-flows.md`
Only read additional files when directly relevant.
Do **not** load all context, templates, or memory-bank files by default.
---
## Core Principle
This is a **refactor branch**, not a feature branch.
- Preserve current live S78 behaviour
- Do not introduce business-rule changes unless explicitly requested
- Prefer small, safe, reversible changes
- Focus on structure, not behaviour
---
## Standard AI-Assisted Workflow
### 1. Scope
- Define requirement
- Confirm non-goals
- Identify impacted flow areas
- Identify risk level
### 2. Plan
- Keep plan small and incremental
- Identify safe boundaries
- Avoid mixing refactor + feature work
### 3. Implement
- Make the smallest viable change
- Prefer extraction over rewrite
- Preserve interfaces and payload shapes
### 4. Validate
Minimum required:
- `npm run lint`
- targeted manual checks
- EN/CY parity checks (if user-facing)
- negative-path checks for sensitive flows
### 5. Document (only when needed)
- update `memory-bank/change-log.md` for non-trivial work
- record decisions or pitfalls if useful
---
## Templates (Use Only When Needed)
Templates are optional tools, not default context.
Use **only one** template if needed:
- feature implementation
- bug fix
- refactor
- debugging
- code review
Do not load all templates.
Do not treat templates as baseline context.
---
## Context Loading Rule (Critical)
Always use the **minimum required context**.
### Default context for this branch:
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
- `context/architecture.md`
- `context/domain-flows.md`
### Only load additional files when:
- working with integrations → `integration-map.md`
- reviewing test gaps → `test-coverage-map.md`
- performing release work → `runbook.md`
- working on specific planned sequence → `context/plans/*`
Never load:
- all context files
- all templates
- onboarding or overview docs
---
## Branching Protocol
This repository currently uses different branch rules depending on the work type.
### For BAU / normal delivery work
- create work branches from `SIPS-Development`
### For new appeal refactor work
- use the `refactor` branch as the base branch
- do refactor implementation either:
- directly on `refactor`, if that is the agreed working model, or
- on a short-lived feature branch created from `refactor`
Do not perform refactor implementation directly on `SIPS-Development`.
If unsure which branch model applies, stop and confirm before making changes.
---
## No-Break Rules (Always Enforce)
- Do not weaken auth/session behaviour
- Do not weaken security headers/CSP
- Keep EN/CY behaviour aligned
- Do not expose secrets or personal data
- Protect save/resume/upload/submit journeys
---
## PR Minimum (AI-Assisted)
Every change must include:
- Scope summary
- Files changed
- Risk notes (auth/data/i18n/a11y)
- Validation evidence
- Rollback plan
---
## Handling Unknowns
If unsure:
1. Choose the safer option
2. Do not change behaviour
3. call out assumptions clearly
4. log open questions if needed
---
## Summary Rule
If in doubt:
> Preserve behaviour, reduce risk, keep changes small.
+95
View File
@@ -0,0 +1,95 @@
# Default Rules (Reference Only)
## Important
This file is **not the active rule set for this refactor branch**.
Active working rules are defined in:
- `.clinerules/refactor-branch-rules.md`
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
Do not load this file by default.
---
## Purpose
This file provides general repository-wide guidance and may be referenced when needed for broader context.
---
## Repository Mission
Deliver safe, accessible, bilingual (EN/CY), and reliable public-service functionality without regressing core journeys.
---
## General Priorities
1. Safety and security of user data
2. Stability of public-facing journeys
3. Accessibility and bilingual parity
4. Maintainability of code
5. Controlled, safe delivery
---
## General Coding Guidance
- Follow existing repo patterns
- Keep page-level logic thin
- Move reusable logic into `components/`, `actions/`, or `lib/`
- Avoid broad refactors in feature or bugfix work
- Prefer small, focused changes
---
## Architecture Guardrails (General)
- Do not bypass auth/session handling
- Do not weaken security controls
- Preserve relay request integrity
- Maintain EN/CY route parity
- Keep Redux hydration/persistence stable
---
## Validation Expectations (General)
- linting must pass
- user-facing changes must be verified
- accessibility and EN/CY checks required
- sensitive flows require negative-path checks
---
## When To Use This File
Only reference this file when:
- broader repository rules are required
- behaviour conflicts are unclear
- no branch-specific guidance exists
---
## Summary
This file is background guidance only.
For this refactor branch:
- follow branch-specific rules first
- prioritise behaviour preservation
- keep context minimal and focused
## Branching Guidance (Reference)
Branching depends on work type:
- BAU work typically branches from `SIPS-Development`
- refactor-stream work for the new appeal flow uses `refactor` as the base branch
Follow branch-specific rules first.
+228
View File
@@ -0,0 +1,228 @@
# Refactor Branch Rules (Active)
## Purpose
This file defines the active working rules for this refactor branch.
This branch is focused on **safe, behaviour-preserving refactor of the new appeal flow**.
---
## Core Rule (Highest Priority)
Do not change live S78 behaviour unless explicitly instructed.
Refactor = improve structure, not behaviour.
---
## Primary Objectives
1. Make the new appeal flow easier to understand and maintain
2. Reduce risk when making future changes
3. Prepare the system for multiple appeal types
4. Improve separation of concerns (UI, workflow, data, integrations)
---
## Non-Negotiable Rules
- Preserve all current user journeys:
- start appeal
- save and exit
- resume appeal
- upload documents
- check answers
- submit appeal
- confirmation
- Do not:
- change payload structures
- change validation rules
- change business logic
- hardcode logic that is currently dynamic/config-driven
- mix refactor with feature work
---
## Refactor Approach
Always:
1. Understand current behaviour first
2. Identify smallest safe change
3. Prefer extraction over rewrite
4. Keep public interfaces stable
5. Make changes easy to review and revert
---
## Change Size Guidance
- Prefer small PRs (<400 LOC where possible)
- Avoid large multi-concern changes
- Split work into safe slices
---
## Context Usage Rules (Critical for Efficiency)
### Default context (only load these):
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
- `context/architecture.md`
- `context/domain-flows.md`
### Only load additional context when needed:
- integrations → `integration-map.md`
- testing gaps → `test-coverage-map.md`
- release concerns → `runbook.md`
- specific work plan → `context/plans/*`
### Never load by default:
- all context files
- onboarding or overview docs
- all templates
- memory-bank contents
---
## Templates Usage
Templates are optional helpers.
- Use only ONE template when needed
- Do not load all templates
- Do not treat templates as baseline context
---
## Safety Rules
- Do not weaken authentication or session logic
- Do not weaken security headers or middleware
- Do not expose secrets or personal data
- Preserve EN/CY parity
- Maintain accessibility standards
---
## Testing & Validation Expectations
Minimum:
- `npm run lint`
- targeted manual verification
- EN/CY checks (if user-facing)
- negative-path checks (for sensitive flows)
Before changing critical logic:
- add or update regression protection where possible
---
## When Unsure
If any uncertainty exists:
1. Choose the safest option
2. Do not change behaviour
3. Call out assumptions
4. Keep the change minimal
---
## Definition of Success
A successful change:
- preserves behaviour
- reduces complexity
- improves clarity or structure
- is small and safe to merge
- does not introduce regression risk
---
## One-Line Rule
If in doubt:
> Keep behaviour the same, reduce risk, and make the smallest safe change.
---
## Documentation Rule (Minimal and Targeted)
Only document information that is necessary to safely understand or change the system later.
Document:
- key decisions (why something was changed)
- non-obvious behaviour
- risks or constraints (what must not be changed)
- important assumptions
Do not document:
- obvious code behaviour
- step-by-step implementation details
- temporary or experimental work
- duplicated explanations across files
Prefer short, focused notes over long explanations.
If unsure:
> Will someone break the system in the future if this is not written down?
If yes → document it
If no → do not document it
Documentation should be minimal, high-signal, and never outweigh the value of the code itself.
## Branch Safety Rule
This refactor stream uses the `refactor` branch as its working base branch.
For refactor work:
- do all implementation from the `refactor` branch or a short-lived feature branch created from `refactor`
- do not implement refactor work directly on `SIPS-Development`
`SIPS-Development` remains the BAU integration branch.
Refactor changes may be merged into `SIPS-Development` only when proven safe.
If branch context is unclear, stop and confirm before making changes.
## Branch Model
- `SIPS-Development` = BAU branch
- `refactor` = refactor integration branch
- optional short-lived working branches for individual slices should be created from `refactor`
## Regression Safety Rule (Critical)
This is a live system. All refactor work must prove behaviour is unchanged.
Before completing any slice:
- verify core journey behaviour has not changed
- verify protected flows still work:
- save and exit
- resume appeal
- upload documents
- check answers
- submit appeal
- confirmation
- verify EN/CY parity for any affected areas
A slice is NOT complete until regression behaviour is confirmed.
If regression cannot be confidently ruled out:
→ do not proceed to next slice
+15
View File
@@ -0,0 +1,15 @@
# Bugfix Workflow
1. Clarify the bug symptoms and expected behavior.
2. Inspect the relevant files and execution path.
3. Identify the most likely root cause.
4. Implement the smallest safe fix.
5. Check for:
- side effects
- regression risk
- validation gaps
- missing error handling
6. Summarize:
- root cause
- fix
- preventive improvements worth noting
+17
View File
@@ -0,0 +1,17 @@
# Code Review Workflow
Review the relevant code or changes for:
- correctness
- edge cases
- data integrity
- security concerns
- performance concerns
- maintainability
- readability
- consistency with repo conventions
Return:
1. key findings
2. impact / severity where useful
3. suggested improvements
4. strengths worth preserving
@@ -0,0 +1,18 @@
# Database Migration Workflow
1. Understand the desired schema or data change.
2. Inspect current data model, queries, and dependent code.
3. Identify:
- forward migration steps
- backward compatibility concerns
- rollback considerations
4. Implement or propose the minimal safe migration path.
5. Review for:
- data integrity
- ordering issues
- application compatibility
- deployment timing risk
6. Summarize:
- schema/data changes
- impacted code paths
- rollout / rollback notes
+17
View File
@@ -0,0 +1,17 @@
# Debugging Workflow
1. Capture the symptom, error, or incorrect behavior.
2. Inspect the relevant path and recent changes.
3. Form the most likely hypotheses.
4. Narrow the cause using the smallest practical evidence checks.
5. Propose or implement the minimal safe fix.
6. Review for:
- hidden assumptions
- unhandled states
- logging or observability gaps
- regression risk
7. Summarize:
- symptom
- cause
- fix
- prevention ideas
@@ -0,0 +1,10 @@
# Documentation Update Workflow
1. Identify what changed in the code or workflow.
2. Inspect the affected docs and support files.
3. Update only the relevant sections.
4. Keep the docs concise, factual, and current.
5. Summarize:
- what changed
- which docs were updated
- anything still uncertain
@@ -0,0 +1,16 @@
# Feature Implementation Workflow
1. Understand the requirement and desired outcome.
2. Inspect the relevant files, patterns, and data flows.
3. Propose a short implementation plan for non-trivial work.
4. Implement the smallest maintainable change that satisfies the requirement.
5. Review for:
- correctness
- edge cases
- error handling
- compatibility with existing behavior
- maintainability
6. Summarize:
- what changed
- why
- any follow-up considerations
+13
View File
@@ -0,0 +1,13 @@
# Planning Workflow
1. Clarify the objective.
2. Inspect the relevant code areas and constraints.
3. Identify implementation options.
4. Compare trade-offs.
5. Recommend the most practical path.
6. Return:
- objective summary
- proposed plan
- risks
- dependencies
- suggested execution order
+16
View File
@@ -0,0 +1,16 @@
# PR Review Workflow
Review the pull request or change set for:
- correctness
- scope discipline
- regression risk
- compatibility impact
- tests or validation gaps
- security and performance concerns
- maintainability
Return:
1. summary of change intent
2. key risks
3. requested changes
4. optional improvements
+16
View File
@@ -0,0 +1,16 @@
# Refactor Workflow
1. Understand the current behavior that must be preserved.
2. Inspect the relevant modules and dependencies.
3. Identify safe refactor boundaries.
4. Propose a scoped plan.
5. Refactor incrementally.
6. Review for:
- preserved behavior
- reduced complexity
- improved readability
- regression risk
7. Summarize:
- what was simplified
- what was preserved
- remaining debt
@@ -0,0 +1,15 @@
# Release Readiness Workflow
1. Review the scope of changes.
2. Check:
- build readiness
- environment assumptions
- configuration changes
- database implications
- CI/CD impact
- rollback expectations
3. Identify release risks and missing checks.
4. Summarize:
- release blockers
- risks
- final recommended checks
+2 -6
View File
@@ -52,11 +52,7 @@ pages/holding-min.html
pages/holding.html
# Cline / AI-assistant governance artifacts (keep local-only)
.clinerules
.clinerules/
CONTRIBUTING_AI.md
GUARDRAILS.md
ai-prompts/
workflows/
AI_CONTEXT.md
pages/baracuda.min.html
+46
View File
@@ -0,0 +1,46 @@
# AI Context — PEDW FrontEnd
## Overview
PEDW FrontEnd is a Next.js 14 (Pages Router) bilingual (EN/CY) public-service portal for planning case search, case detail/document viewing, and authenticated portal workflows (appeals, representations, watchlists, dashboard views).
## Architecture
- Monorepo-style Next.js app with UI routes in `pages/` and API handlers in `pages/api/**`.
- Redux (`next-redux-wrapper` + `redux-persist`) for shared client/server state.
- `next-auth` for auth/session with Prisma adapter.
- Integration-heavy BFF pattern: API routes proxy to relay/CRM and storage/notify services.
## Key components
- `components/breadcrumbs.js`: central breadcrumb/back-link behavior.
- `components/case/summary.js`: case-detail tabs, representation eligibility logic, watch/email actions.
- `actions/index.js`: shared API utilities, token/header/hash helpers, many side-effect wrappers.
- `pages/api/endpoint/**`: relay-backed business-data APIs.
- `pages/api/file/**`: blob/document/PDF/upload endpoints.
## Data model boundaries
- Prisma (`prisma/schema.prisma`) stores auth/session entities only (`User`, `Account`, `Session`, `VerificationToken`) on SQL Server.
- Business/case data is external (Dynamics/relay path), not persisted as Prisma domain models here.
## API/integration patterns
- Many endpoint handlers compute HMAC hash query params (`hash`) for relay-bound requests.
- Token acquisition + OData headers are reused across proxy handlers.
- File endpoints often validate request hash for sensitive blob actions.
- GOV.UK Notify used for email, including language-specific template selection in some flows.
## Infrastructure/tooling
- Scripts: `npm run dev`, `npm run build`, `npm start`, `npm run lint`.
- CI/CD artifacts present: `azure-pipelines.yml`, `Jenkinsfile`, `Dockerfile` (active production source-of-truth not explicit in repo).
- Security controls: `middleware.js` CSP/runtime headers + `next.config.js` security headers.
## Development constraints
- Preserve auth/session behavior in `pages/api/auth/[...nextauth].js`.
- Do not weaken CSP/security headers in `middleware.js` or `next.config.js`.
- Keep EN/CY parity across routes and locale resources (`i18n.js`, `locales/**`, rewrites).
- Treat relay hash behavior as security-sensitive; keep path/hash compatibility stable.
- Avoid logging secrets/personal data in auth/email/file/account flows.
+83
View File
@@ -0,0 +1,83 @@
# PEDW FrontEnd Guardrails
## Purpose
This document is a fast pre-flight checklist to reduce regressions in high-risk areas. Use it before coding, before opening a PR, and before merge.
## Non-Negotiable Guardrails
1. **Auth/session integrity**
- Do not bypass `next-auth` flow in `pages/api/auth/[...nextauth].js`.
- Preserve secure redirect behavior and cookie/session settings.
2. **Security headers and CSP**
- Do not weaken `middleware.js` CSP/header behavior or `next.config.js` security headers without explicit rationale.
3. **Data model safety**
- Treat `prisma/schema.prisma` as source-of-truth for auth/account persistence.
4. **Bilingual parity (EN/CY)**
- Any user-facing route/content change must validate both locales.
- Keep `i18n.js`, `locales/`, and `next.config.js` rewrites aligned.
5. **Public-service reliability**
- Avoid breaking core flows: search, case, account, myportal, admin.
## Sensitive Flow Protection
Apply extra checks for:
- `pages/api/auth/**`
- `pages/api/file/**`
- `pages/api/email/**`
- `pages/api/endpoint/*_api.js` handling account/user data
## Relay Hash Integrity Rules (CRM-bound APIs)
Apply when changing relay-bound portal endpoints and helpers (notably `pages/api/endpoint/**` and `actions/index.js`):
1. Keep relay endpoint configuration sourced from `API_ROOT`.
2. Preserve path-hash generation behavior:
- hash input must be request path/query (excluding domain),
- appended hash parameter must remain compatible with relay expectations.
3. Do not change hash algorithm/key usage contract without coordinated relay change.
4. Treat hash validation failures as security-relevant negative paths; verify graceful rejection handling.
5. Never log hash key material or sensitive request payloads.
Required for sensitive changes:
- Negative-path validation (unauthorized, invalid input, malformed payload).
- Safe logging (no secrets/tokens/personal data in cleartext).
- Explicit rollback steps.
## Relay Policy Change Guardrail (timeouts/retries/logging)
When changing shared relay forwarding policy (for example in `pages/api/middleware/relayForwarding.js`), treat this as an operationally sensitive change even if endpoint contracts are unchanged.
Minimum required before merge:
1. Complete the relay governance gate in `context/runbook.md` (Relay Hardening Rollout Playbook).
2. Attach non-prod smoke evidence for:
- deterministic non-retry classes (`400`, `401`, `403`, `404`)
- transient retry classes (`429`, `503`, timeout/network-transient)
3. Confirm structured redacted logging and duplicate-log suppression behavior.
4. Provide fast mitigation + rollback path (`RELAY_RETRY_MAX=0` and commit-revert path).
## Pre-PR Quick Checklist
- [ ] Ran `npm run lint` (or documented why unavailable)
- [ ] Verified changed routes/APIs manually
- [ ] Verified EN + CY behavior for impacted user-facing flow
- [ ] Performed accessibility smoke checks (keyboard, focus, labels, headings)
- [ ] Added risk notes (auth/data/i18n/a11y)
- [ ] Updated `memory-bank/change-log.md` for non-trivial changes
## If Assumptions Are Unclear
1. Record assumptions in PR notes.
2. Add unresolved items to `memory-bank/open-questions.md`.
3. Choose the safer behavior and clearly mark as temporary.
## Related Docs
- `.clinerules`
- `CONTRIBUTING_AI.md`
- `context/runbook.md`
- `context/integration-map.md`
- `memory-bank/README.md`
+32 -36
View File
@@ -2,20 +2,28 @@ import { JSONPath as jsonpath } from "jsonpath-plus";
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import { connect } from "react-redux";
import xpath from "xpath";
import {
getPickListLabel,
getRadioLabel,
bytesToSize,
getDocumentTypeFromFilename,
getThumbnailIconByExtension,
getThumbnailIconByExtension
} from "../../components/utils";
import fieldLookup from "../../data/crmfieldlookuptranslations.json";
import {
setCurrentSection,
setFormComplete,
setFormComplete
} from "../../store/appealType/action";
import {
parseRowOuterHTML,
parseXml,
selectCurrentSectionRows,
selectRowDataFieldName,
selectRowDocumentTypeCode,
selectRowFieldType,
selectRowLabelDescriptions
} from "../../lib/newappeal/formDerivation";
let BuildCheckRow = (props) => {
let { t } = useTranslation();
@@ -30,18 +38,12 @@ let BuildCheckRow = (props) => {
onSubmit,
updateCurrentSection,
setCurrentSection,
mandatoryFieldsData,
mandatoryFieldsData
} = props;
const parser = new DOMParser();
var doc = parser.parseFromString(props.formXML, "text/xml");
var doc = parseXml(props.formXML);
var rowXML = xpath.select(
"/form/tabs/tab[" +
whichSection +
"]/columns//sections/section/rows/row",
doc
);
var rowXML = selectCurrentSectionRows(doc, whichSection);
function formatDate(dateObj) {
var m = new Date(dateObj);
@@ -66,7 +68,7 @@ let BuildCheckRow = (props) => {
let formObj = jsonpath({
path: "$['" + appealtypes + "']",
json: fieldLookup,
eval: true,
eval: true
});
let labelTrans =
@@ -74,7 +76,7 @@ let BuildCheckRow = (props) => {
? jsonpath({
path: '$..[?(@ && @.value=="' + label + '")].value_cy',
json: formObj,
eval: true,
eval: true
})
: label;
return labelTrans;
@@ -91,29 +93,23 @@ let BuildCheckRow = (props) => {
return (
<>
{Object.keys(rowXML).map((key, index) => {
var doc = parser.parseFromString(
rowXML[key].outerHTML,
"text/xml"
);
var doc = parseRowOuterHTML(rowXML[key].outerHTML);
if (_.isEmpty(rowXML[key].innerHTML)) {
("");
} else {
var rows = xpath.select("//label/@description", doc);
var fieldtype = xpath.select("//@classid", doc);
var datafieldname = xpath.select("//@datafieldname", doc);
var rows = selectRowLabelDescriptions(doc);
var fieldtype = selectRowFieldType(doc);
var datafieldname = selectRowDataFieldName(doc);
const isRequiredField = jsonpath({
path:
"$..value[?(@ && @.LogicalName=='" +
datafieldname[0].value +
"')]",
json: mandatoryFieldsData,
eval: true,
eval: true
});
var documentTypeCode = xpath.select(
"//@ishareDocumentCode",
doc
);
var documentTypeCode = selectRowDocumentTypeCode(doc);
// if (datafieldname[0].value.indexOf("fileUpload") > 0) {
// isRequiredField.push({
@@ -155,7 +151,7 @@ let BuildCheckRow = (props) => {
dangerouslySetInnerHTML={{
__html: props.props.form[
"appealForm"
].values[datafieldname[0].value],
].values[datafieldname[0].value]
}}
/>
) : fieldtype[0].value ==
@@ -212,14 +208,14 @@ let BuildCheckRow = (props) => {
style={{
display: "flex",
alignItems:
"flex-start",
"flex-start"
}}
className="govuk-!-margin-bottom-2"
>
<img
style={{
minWidth: "50",
width: "50",
width: "50"
}}
src={getThumbnailIconByExtension(
blob.name
@@ -229,7 +225,7 @@ let BuildCheckRow = (props) => {
/>
<span
style={{
maxWidth: "85%",
maxWidth: "85%"
}}
className="govuk-body govuk-!-font-size-14 govuk-!-margin-left-2"
>
@@ -266,7 +262,7 @@ let BuildCheckRow = (props) => {
display:
"flex",
alignItems:
"flex-start",
"flex-start"
}}
className="govuk-!-margin-bottom-2"
>
@@ -274,7 +270,7 @@ let BuildCheckRow = (props) => {
style={{
minWidth:
"50",
width: "50",
width: "50"
}}
src={getThumbnailIconByExtension(
blob.name
@@ -287,7 +283,7 @@ let BuildCheckRow = (props) => {
<span
style={{
maxWidth:
"85%",
"85%"
}}
className="govuk-body govuk-!-font-size-14 govuk-!-margin-left-2"
>
@@ -326,7 +322,7 @@ let BuildCheckRow = (props) => {
<div
key={index}
style={{
display: "flex",
display: "flex"
}}
>
<div className="govuk-!-width-one-half">
@@ -397,12 +393,12 @@ const mapDispatchToProps = (dispatch) => {
updateCurrentSection: (whichSection) => {
dispatch(setCurrentSection(whichSection));
dispatch(setFormComplete("true"));
},
}
};
};
const mapStateToProps = (state) => ({
count: state.count,
count: state.count
});
export default connect(mapStateToProps, mapDispatchToProps)(BuildCheckRow);
+38 -38
View File
@@ -1,8 +1,25 @@
import _ from "lodash";
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import xpath from "xpath";
import BuildField from "./buildfield";
import {
parseRowOuterHTML,
selectRowDataFieldContent,
selectRowDataFieldName,
selectRowDateEnd,
selectRowDateStart,
selectRowDocumentTypeCode,
selectRowFieldType,
selectRowHint,
selectRowLabelDescriptions,
selectRowMaxFieldLength,
selectRowMaxSubField,
selectRowParentField,
selectRowParentFieldShowOnValue,
selectRowRequiredDocumentLabel,
selectRowRequiredDocumentValue,
selectRowValidation
} from "../../lib/newappeal/formDerivation";
export default function BuildRow(props) {
let { t } = useTranslation();
@@ -20,56 +37,39 @@ export default function BuildRow(props) {
uploadCount,
setFileCount,
completedUploadFilesCount,
setCompletedUploadFilesCount,
setCompletedUploadFilesCount
} = props;
const parser = new DOMParser();
return (
<div className="govuk-grid-column-full">
{Object.keys(rowXML).map((key, index) => {
var doc = parser.parseFromString(
rowXML[key].outerHTML,
"text/xml"
);
var doc = parseRowOuterHTML(rowXML[key].outerHTML);
if (_.isEmpty(rowXML[key].innerHTML)) {
("");
} else {
var rows = xpath.select("//label/@description", doc);
var fieldtype = xpath.select("//@classid", doc);
var validation = xpath.select("//@validation", doc);
var maxFieldLength = xpath.select("//@maxFieldLength", doc);
var maxSubField = xpath.select("//@maxsubfield", doc);
var datafieldname = xpath.select("//@datafieldname", doc);
var datafieldcontent = xpath.select(
"//@datafieldcontent",
doc
);
var parentField = xpath.select("//@parentField", doc);
var rows = selectRowLabelDescriptions(doc);
var fieldtype = selectRowFieldType(doc);
var validation = selectRowValidation(doc);
var maxFieldLength = selectRowMaxFieldLength(doc);
var maxSubField = selectRowMaxSubField(doc);
var datafieldname = selectRowDataFieldName(doc);
var datafieldcontent = selectRowDataFieldContent(doc);
var parentField = selectRowParentField(doc);
var parentFieldShowOnValue = xpath.select(
"//@parentFieldShowOnValue",
doc
);
var parentFieldShowOnValue =
selectRowParentFieldShowOnValue(doc);
var requiredDocumentValue = xpath.select(
"//@requiredDocumentValue",
doc
);
var requiredDocumentValue =
selectRowRequiredDocumentValue(doc);
var requiredDocumentLabel = xpath.select(
"//@requiredDocumentLabel",
doc
);
var requiredDocumentLabel =
selectRowRequiredDocumentLabel(doc);
var documentTypeCode = xpath.select(
"//@ishareDocumentCode",
doc
);
var documentTypeCode = selectRowDocumentTypeCode(doc);
var hint = xpath.select("//label/@hint", doc);
var dateStart = xpath.select("//@dateStart", doc);
var dateEnd = xpath.select("//@dateEnd", doc);
var hint = selectRowHint(doc);
var dateStart = selectRowDateStart(doc);
var dateEnd = selectRowDateEnd(doc);
hint = !_.isEmpty(hint) && hint[0].value;
+17 -23
View File
@@ -4,7 +4,6 @@ import { useRouter } from "next/router";
import { useState } from "react";
import { connect } from "react-redux";
import { formValueSelector, reduxForm } from "redux-form";
import xpath from "xpath";
import { uploadFiles } from "../../actions/services/documentService";
import { sendEmail } from "../../actions/services/notifyService";
import {
@@ -16,6 +15,14 @@ import {
} from "../../store/appealType/action";
import { getFormCollectionByID, getProgressObj, updateLinks } from "../utils";
import BuildRow from "./buildrow";
import {
parseXml,
selectAllTabTitleDescriptions,
selectCurrentSectionRows,
selectCurrentSectionTitleDescriptions,
selectErrorFieldLabelDescription,
selectFormTabs
} from "../../lib/newappeal/formDerivation";
import { FieldsTranslations } from "../elements";
import BuildProgress from "./buildprogress";
@@ -55,26 +62,13 @@ let BuildSection = (props) => {
const documentListObj = props.appealType.documentList;
const currentSection = props.appealType.currentSection;
const parser = new DOMParser();
var doc = parser.parseFromString(props.formXML, "text/xml");
var titles = xpath.select(
"//form/tabs/tab[" + currentSection + " ]/labels/label/@description",
doc
);
var rowXML = xpath.select(
"/form/tabs/tab[" +
currentSection +
"]/columns//sections/section/rows/row",
//"/form/tabs/tab/columns//sections/section/rows/row",
doc
);
var doc = parseXml(props.formXML);
var titles = selectCurrentSectionTitleDescriptions(doc, currentSection);
var rowXML = selectCurrentSectionRows(doc, currentSection);
var formObjXML = xpath.select("/form/tabs", doc);
var formObjXML = selectFormTabs(doc);
var titleList = xpath.select(
"//form/tabs/tab[*]/labels/label/@description",
doc
);
var titleList = selectAllTabTitleDescriptions(doc);
const progObj = getProgressObj(
formXML,
@@ -370,10 +364,10 @@ let BuildSection = (props) => {
errorsobj = _.keys(errorsobj);
const getErrorLabel = (whichField) => {
var doc = parser.parseFromString(props.formXML, "text/xml");
var errorFieldLabel = xpath.select(
"//*[control/@id='" + whichField + "']//@description",
doc
var doc = parseXml(props.formXML);
var errorFieldLabel = selectErrorFieldLabelDescription(
doc,
whichField
);
return errorFieldLabel[0].value;
-35
View File
@@ -1,35 +0,0 @@
# Current State Scorecard (2026-03-25)
Purpose: provide a single operational view of architecture/debt progress with evidence references.
## RAG Legend
- Green: materially addressed for current stream
- Amber: partial progress, follow-on needed
- Red: unresolved/high risk remains
## Scorecard
| Area | Status | Current position | Evidence |
| --------------------------------- | ------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| API contract consistency | Green | Large endpoint clusters normalized on structured contracts with phase21 coverage. | `memory-bank/change-log.md` (endpoint hardening stream), `tests/phase21/endpoint-handler-contract.test.cjs` |
| Actions/service decomposition | Amber | Shared clients and route builders introduced; monolith risk reduced but full domain split remains. | `actions/clients/*`, `actions/services/*`, `memory-bank/debt-list.md` |
| Endpoint sprawl/proxy duplication | Amber | Shared relay forwarding and helper reuse reduced duplication; long-tail handlers still exist. | `pages/api/middleware/relayForwarding.js`, `context/architecture.md` |
| High-risk automation | Green | Focused checks now cover auth redirect safety, signed-delete/upload negatives, and EN/CY rewrite parity. | `tests/phase22/auth-redirect-safety.test.cjs`, `tests/phase22/i18n-route-parity.test.cjs`, `tests/phase22/index.test.cjs` |
| i18n parity assurance | Amber | Targeted parity checks in place; CI-level parity enforcement still pending. | `tests/phase22/i18n-route-parity.test.cjs`, `context/architecture.md` |
| Logging redaction consistency | Amber | Relay-side structured redaction improved; broader auth/email/file logging hardening remains open. | `memory-bank/open-questions.md` (Q-001), `context/architecture.md` |
| Runtime canonicalization | Red | `server.js` and `server/server.js` ambiguity not yet formally closed. | `memory-bank/architect-review.md`, `context/architecture.md` |
## Next execution focus
1. Sequence B: signed-request consolidation + logging hardening.
2. Sequence C: CI-level i18n parity gates + endpoint long-tail reduction.
3. Runtime canonicalization decision with explicit operational owner.
## Update cadence
- Update after every non-trivial architecture/debt slice.
- Keep this file aligned with:
- `context/architecture.md`
- `memory-bank/debt-list.md`
- `memory-bank/change-log.md`
+117
View File
@@ -0,0 +1,117 @@
# New Appeal Refactor Guardrails
## Purpose
These guardrails apply to all AI-assisted and human-assisted work on the refactor branch for the new appeal flow.
## Critical Rule
Preserve the current live S78 behaviour unless the task explicitly requires a behaviour change.
Do not assume a cleaner implementation is allowed to alter behaviour.
## Protected Areas
Treat the following as protected flow files:
- `pages/newappeal/index.js`
- `pages/newappeal/[appealtypes].js`
- `components/newappeal/buildsection.js`
- `components/newappeal/buildchecksection.js`
- `components/newappeal/buildrow.js`
- `components/newappeal/buildfield.js`
- `components/newappeal/buildcheckrow.js`
- `components/newappeal/complete.js`
- `components/newappeal/aboutyou.js`
- `components/newappeal/createCase.js`
- any helpers or service modules used directly by save/progress/upload/submit/finalise logic
## Protected Behaviour
The following must not regress:
1. Start a new S78 appeal
2. Create case / initial journey entry
3. Section rendering from form definition
4. Section progression
5. Save and exit
6. Resume saved appeal
7. File/document upload behaviour
8. Check answers page
9. Appeal PDF generation/download path
10. Final submit/finalisation
11. Confirmation page behaviour
12. Email/notification side effects
13. English/Welsh parity for touched areas
## Required Refactor Approach
When refactoring:
1. Understand current behaviour first
2. Identify the smallest safe boundary
3. Prefer extraction of pure/helper logic
4. Keep public interfaces stable where possible
5. Avoid changing UI, business rules, and structure in one step
6. Keep each slice easy to review and revert
## Required Testing Mindset
Before changing critical flow behaviour, add or update protection such as:
- characterization tests for current behaviour
- targeted integration/service tests
- journey-level regression checks
- payload-shape assertions for save/submit/finalise paths
If automation is not practical yet, include an explicit manual verification matrix.
## Payload/Integration Safety
Do not change without explicit need:
- CRM payload field names or structure
- boolean/value normalization behaviour
- document/file metadata shape
- save/resume payload expectations
- PDF generation inputs
- notification template selection or personalisation structure
## i18n / Accessibility Safety
For touched user-facing behaviour:
- keep EN/CY behaviour aligned
- keep labels, messages, and route behaviour consistent
- preserve semantic structure, focus behaviour, and validation messaging
## Delivery Safety
Preferred pattern for each change:
1. protect current behaviour
2. extract one concern
3. run focused validation
4. keep rollback straightforward
5. merge only when safe
## What To Avoid
Do not:
- perform broad rewrites
- mix feature delivery with refactor work
- replace dynamic/config-driven logic with one-off hardcoding
- move many responsibilities at once
- introduce new dependencies unless clearly justified
- silently change business rules while “cleaning up”
## Refactor Success Criteria
A refactor slice is successful when it:
- preserves behaviour
- reduces complexity or coupling
- improves readability or testability
- keeps regression risk controlled
- remains small enough to merge safely into `SIPS-Development`
-101
View File
@@ -1,101 +0,0 @@
# Sequence B Work Plan (2026-03-25)
Scope: implement the next architecture lane after Sequence A completion.
Sequence B objectives:
1. Consolidate signed-request patterns.
2. Harden logging policy in sensitive paths.
## Workstream B1: Signed-request consolidation
### Goal
Reduce duplicate hash/header/method composition logic across service modules without changing behavior contracts.
### Target scope
- `actions/services/portalDirectService.js`
- `actions/services/documentDirectService.js`
- `actions/services/caseDirectService.js` (if signed routes exist)
- shared client layer in `actions/clients/`
### Proposed implementation
1. Introduce a focused signed-request helper (or helper set) in `actions/clients/`:
- signed GET
- signed POST
- signed DELETE
2. Normalize hash/signing + header behavior through helper API.
3. Migrate in bounded slices (module by module), preserving current catch semantics.
### Acceptance criteria
- No route URL/signature behavior regressions.
- Existing signed flows preserve:
- hash generation behavior
- request method
- required headers
- error-return/catch contracts.
- Phase22 behavioural tests expanded where relevant.
### Validation checklist
- `node tests/phase22/index.test.cjs`
- `node tests/phase7/service-behaviour.test.cjs`
- `npm run lint`
### Rollback plan
- Revert helper adoption commit(s) for affected service only.
- Keep migrations bounded so each module rollback is isolated.
## Workstream B2: Logging hardening in sensitive paths
### Goal
Replace ad-hoc verbose logging in auth/email/file/account-sensitive paths with redacted, structured logs.
### Target scope
- `pages/api/auth/[...nextauth].js`
- selected `pages/api/email/**`
- selected `pages/api/file/**`
- any adjacent shared helper used by these routes
### Proposed implementation
1. Define/confirm minimal redaction policy (link to `memory-bank/open-questions.md` Q-001).
2. Introduce/standardize structured logger usage pattern for sensitive flows.
3. Replace high-risk direct logs in bounded route clusters.
### Acceptance criteria
- No secrets/tokens/personal data in new logs.
- Error correlation remains operationally useful.
- Existing route behavior/contracts unchanged.
### Validation checklist
- `npm run lint`
- targeted route-level negative-path checks for changed handlers
- manual review of log payload fields against redaction policy
### Rollback plan
- Revert logging-hardening commit(s) by cluster.
- Restore previous logger call sites if operational diagnostics regress.
## Delivery sequencing
1. B1 signed-request helper design + one pilot migration.
2. B1 full module rollout (portal/document, then any remaining signed paths).
3. B2 redaction policy confirmation.
4. B2 auth cluster hardening.
5. B2 file/email cluster hardening.
## Ownership and governance
- Track each slice in `memory-bank/change-log.md`.
- Record policy decisions in `memory-bank/decisions.md`.
- Escalate unresolved policy questions in `memory-bank/open-questions.md`.
-112
View File
@@ -1,112 +0,0 @@
# Engineer Onboarding Guide — PEDW FrontEnd
## 1) Project Overview
PEDW FrontEnd is the Planning and Environment Decisions Wales (PEDW) portal for discovering planning appeals and accessing personalised casework journeys. It supports public search/browse and authenticated dashboard workflows, with strong accessibility and bilingual (English/Welsh) requirements.
## 2) Technology Stack
- **Frontend:** Next.js 14 (Pages Router), React 18
- **Language:** Primarily JavaScript (some TypeScript tooling present)
- **State:** Redux, `next-redux-wrapper`, `redux-persist`, `redux-thunk`, `redux-form`
- **Auth:** `next-auth` + Prisma adapter (email magic-link flow)
- **Auth data layer:** Prisma + SQL Server (`prisma/schema.prisma`) for next-auth identity/session tables
- **Portal business data layer:** Dynamics 365 CRM queried via REST + OData through frontend API routes
- **i18n:** `next-translate` + `i18n.js` + Welsh rewrites in `next.config.js`
- **Integrations:** Azure Service Bus Relay (CRM transport), Azure Blob/Queue, GOV.UK Notify, Application Insights, mapping (Leaflet/google-map-react), PDF generation
## 3) Architecture Overview
- Active runtime is **Next.js runtime** (legacy custom server files exist but are inactive).
- UI routes and APIs live in `pages/` and `pages/api/**`.
- Security controls are applied through `middleware.js` + security headers in `next.config.js`.
- Auth/session logic is centralized in `pages/api/auth/[...nextauth].js`.
- Shared integration/service logic sits mostly in `actions/` (notably large `actions/index.js`).
- Portal data calls are sent from `pages/api/endpoint/**` to Dynamics 365 CRM through Azure Service Bus Relay.
- For relay-bound calls, a hash is generated from request path (excluding domain) and appended; relay validates using the same shared hash key.
## 4) Repository Structure
- `pages/` — routes + API handlers
- `components/` — UI/features (case, DNS, account, admin, mapping, PDF templates)
- `actions/` — API client and side-effect helpers
- `lib/` — reusable form/domain helpers
- `store/` — Redux reducers/store setup/hydration/persistence
- `prisma/` — schema + migrations
- `locales/` — EN/CY translations
- `data/` — lookup and form metadata files
- `tests/` — test area (appears limited)
- `server/`, `server.js` — legacy/inactive runtime artifacts
## 5) Core System Components
- **Public search/case flows:** basic search (`/search`), advanced search (`/advancedsearch`), and address search (`/addresssearch`) with result pages and case detail/document UIs
- **Account/auth:** next-auth email verification and Prisma-backed sessions
- Portal routes (`/myportal/**`): user-specific case/representation/watchlist workflows
- **File/doc pipeline:** upload/download/blob flows and PDF generation under `pages/api/file/**`
- **Notifications:** GOV.UK Notify integrations under `pages/api/email/**` + auth email provider
## 5a) User Involvement / Role Model
- Newly registered/authenticated users default to **Interested Party** involvement.
- Users who raise a new appeal become **Appellants**.
- CRM contact constraints allow only one role type; once Appellant is assigned, it remains their role.
- **Agents** can submit appeals on behalf of multiple Appellants.
- **LPA (Local Planning Authority)** users are a separate persona with a distinct dashboard view.
- LPA dashboards focus on appeals within that authority.
- LPA users cannot raise appeals (option is hidden), but they can submit representations.
## 6) Data Model
Prisma schema is focused on next-auth persistence (SQL Server):
- `User`
- `Account`
- `Session`
- `VerificationToken`
Datasource is SQL Server (`DATABASE_URL`). This model underpins authentication/session behavior and should be treated as sensitive core infrastructure. Portal business/case data is sourced separately from Dynamics 365 CRM via relay-backed API calls.
## 7) Key Workflows
- **Sign-in:** user requests magic link -> email via Notify -> callback/session via next-auth.
- **Search journey:** frontend query -> `pages/api/endpoint/**` proxy endpoint(s) -> path hash appended -> Azure Service Bus Relay (validates hash with shared key) -> Dynamics 365 CRM (REST/OData) -> normalized UI rendering.
- **Case summary to representation:** user selects case reference from results -> lands on case summary -> “make representation” shown only when criteria/date rules allow -> user can start flow but must be authenticated to submit.
- **Dashboard journey (`/myportal`):** signed-in users can raise new appeals, search appeals, view watched cases, view partially completed appeals, view submitted appeals, and manage submitted/partially submitted representations.
- **Role behavior:** default involvement starts as Interested Party; new appeal creation sets Appellant role (persistent due to CRM single-role contact model); Agent users may act for multiple Appellants.
- **LPA dashboard behavior:** LPA users see an authority-scoped dashboard, do not see raise-appeal options, and can raise representations on existing appeals.
- **Document workflow:** user upload/submit -> blob storage + metadata updates -> PDF/document retrieval.
- **Bilingual routing:** Welsh aliases rewired in `next.config.js`, locale resources in `locales/en|cy`, page namespace mapping in `i18n.js`.
## 8) Development Workflow
From scripts and runbook:
- `npm run dev` — local dev
- `npm run build` + `npm start` — production build/start
- `npm run lint` — baseline validation
Expected change protocol emphasizes:
- scoped changes,
- EN/CY parity checks,
- accessibility smoke checks,
- negative-path checks on sensitive flows,
- memory-bank/log updates for non-trivial changes.
## 9) Observed Conventions
- 4-space indentation, no trailing commas (per local conventions)
- Keep page-level logic thin where possible; place reusable logic in `lib/`/`components/`/`actions/`
- API naming pattern commonly uses `*_api.js`
- Heavy use of proxy-style API handlers
- Existing AI governance artifacts define guardrails (`.clinerules`, `GUARDRAILS.md`, `context/`, `memory-bank/`)
## 10) Potential Risks / Weak Areas
1. **Large `actions/index.js` coupling** (many responsibilities in one module)
2. **API contract inconsistency** (error/response handling varies across endpoints)
3. **Extensive `console.log` footprint** (signal/noise and potential sensitive logging concerns)
4. **Duplication across API proxy handlers** (token/header/hash/relay logic repeated)
5. **i18n complexity drift risk** (rewrite + locale namespace parity maintenance)
6. **Limited automated tests for high-risk flows** (manual validation burden)
-88
View File
@@ -1,88 +0,0 @@
# PEDW FrontEnd Project Overview
## Purpose
PEDW FrontEnd is a public-service web platform for planning casework and DNS (Developments of National Significance) journeys, with public search and citizen self-service plus authenticated portal/admin capabilities.
## Current Stack
- **Frontend:** Next.js 14 (`pages` router), React 18
- **Server runtime:** Next.js runtime (legacy server files remain in-repo but are not used)
- **State:** Redux + `next-redux-wrapper` + `redux-persist`
- **Auth:** `next-auth` with Prisma adapter and email sign-in flow
- **Auth persistence:** Prisma + SQL Server schema (`prisma/schema.prisma`) for next-auth tables
- **Portal case data source:** Microsoft Dynamics 365 CRM (queried via REST + OData)
- **Portal API transport path:** Frontend API routes -> Azure Service Bus Relay -> Dynamics 365 CRM
- **Relay request integrity:** Forwarded API calls include a hash derived from request path (excluding domain). Relay recomputes hash with shared key and rejects mismatches.
- **i18n:** `next-translate`, locales `en` and `cy`, Welsh rewrites in `next.config.js`
- **Integrations:** Azure storage/queues, GOV.UK Notify, Application Insights, mapping, PDF generation
## Repository Shape (Intent)
- `pages/`: routes and API handlers (`pages/api/**`)
- `components/`: UI and feature components (case, account, admin, mapping, PDF templates)
- `actions/`: API client + shared side-effect logic
- `lib/`: reusable domain helpers and form-related logic
- `store/`: Redux reducers/store hydration/persistence
- `prisma/`: schema and migrations
- `locales/`: translation resources (EN/CY)
- `server/` + root `server.js`: legacy runtime files retained in repository
## Core User/Business Areas
1. Public appeal discovery via:
- basic search (`/search`)
- advanced search (`/advancedsearch`)
- address search (`/addresssearch`)
2. Search results and case summary journey (case reference selection -> summary page)
3. Representation flow from case summary (criteria/date dependent “make representation” action)
4. Passwordless authentication via next-auth magic links for authenticated submissions
5. Authenticated dashboard (`/myportal/**`) for personalised casework
6. New appeal and representation lifecycle management (partial + submitted states)
7. Admin/document workflows
## Planning Casework Portal Dashboard (My Portal)
The Planning Casework dashboard is the authenticated Appellant/Interested party users operational home page for:
- starting new appeal submissions
- Viewing the users submitted appeals
- finding existing cases quickly
- resuming in-progress submissions
- monitoring submitted cases/representations
- tracking watched cases
- Information to view infrastructure project activity
The Planning Casework dashboard is the authenticated LPA users operational home page for:
- finding existing cases quickly
- resuming in-progress submissions
- monitoring submitted cases/representations
- tracking watched cases
- Information to view infrastructure project activity
The dashboard is organized into task-focused panels that separate **action entry points** (for example, “Make a new appeal”, “Search for a case”) from **state-based worklists** (for example, “Appeals awaiting submission”, “My cases”, and representation lists).
## Public Basic Search Results (Search Journey)
In the public case-discovery journey, the basic search results page provides a structured list of matched cases and key metadata. The page supports sorting and pagination, links each case reference through to case detail, and presents a clear no-results or loading/error state when appropriate.
Results content is locale-aware (EN/CY labels and formatted values) and includes highlighted query matches in key visible fields where supported by returned data.
## User Involvement Model (Portal)
- Newly registered/authenticated portal users default to **Interested Party** involvement.
- Users who raise a new appeal become **Appellants**.
- CRM contact constraints allow only one role type, so once set to Appellant this remains their role.
- **Agents** can submit appeals on behalf of multiple Appellants.
- **LPA (Local Planning Authority)** users have a distinct persona/dashboard view scoped to appeals raised within their authority.
- LPA users do **not** see the “raise appeal” option.
- LPA users can still make/submit representations on appeals.
## Operating Constraints
- Public-sector reliability expectations: avoid regressions on live service paths.
- Bilingual parity is mandatory for user-facing route/content changes.
- Accessibility expectations are high (keyboard and semantic behavior).
- Security-sensitive areas include auth/session, uploads/documents, notifications, and account data.
- Distinguish data paths: next-auth identity/session data is persisted in SQL Server; portal business data is sourced from Dynamics 365 CRM via relay-backed API calls with request-path hash validation.
+90
View File
@@ -0,0 +1,90 @@
# Refactor Branch Charter — New Appeal Flow
## Purpose
This branch exists to safely refactor the live new appeal flow so it is easier to maintain, safer to change, and better prepared to support additional appeal types beyond the current S78 planning appeal flow.
This is a **behaviour-preserving refactor branch**, not a feature branch.
## Primary Goal
Create a safer internal structure for the new appeal flow while preserving current live behaviour for the S78 appeal journey.
## Why This Branch Exists
The current new appeal implementation has grown over time to meet business need and now contains a mix of:
- page composition
- flow orchestration
- XML-driven form rendering
- validation
- file/document handling
- progress/save logic
- submission/finalisation logic
- integration shaping for CRM, PDF generation, and notifications
This branch exists to improve those boundaries incrementally without disrupting the live service.
## Scope
In scope:
- behaviour-preserving refactor of `pages/newappeal/**` and `components/newappeal/**`
- extraction of reusable workflow logic from UI-heavy components
- improved boundaries between rendering, workflow, and integration logic
- regression test coverage for critical S78 journeys
- preparing the codebase for future appeal-type extensibility
Out of scope unless explicitly requested:
- business rule changes
- visual redesign
- broad framework/library migration
- replacing working dynamic form behaviour with hardcoded appeal-specific logic
- changes to live BAU behaviour beyond strictly necessary bug fixes
## Branch Relationship to BAU
- BAU continues on `SIPS-Development`
- this branch is the protected refactor lane
- safe, proven slices may be merged back into `SIPS-Development` when ready
- urgent live fixes should go to `SIPS-Development` first, then be synced into this branch
## Non-Negotiable Principles
1. Preserve live S78 behaviour unless explicitly told otherwise.
2. Prefer extraction over rewrite.
3. Prefer small, mergeable slices over long-lived hidden change.
4. Add or update regression protection before changing critical flow logic.
5. Keep English/Welsh behaviour aligned.
6. Treat save/resume/upload/check/submit/complete as protected journey stages.
## Target Direction
The long-term direction is:
- shared new appeal workflow engine
- appeal-type definitions/configuration separated from UI rendering
- smaller, clearer components
- isolated validation and payload-shaping logic
- safer addition of future appeal types through definition + bounded type-specific rules
## Definition of Success
This branch is succeeding when:
- core S78 journey behaviour remains stable
- regression confidence increases
- high-risk logic moves out of large render-heavy components
- new appeal code becomes easier to understand and test
- future appeal types can be added with less change to core flow code
## Working Branch Model
This refactor stream uses the `refactor` branch as its working base.
- BAU continues on `SIPS-Development`
- refactor work is performed from `refactor`
- safe refactor slices may later be merged into `SIPS-Development`
This branch should not be treated as BAU, and BAU should not be treated as the refactor workspace.
+104
View File
@@ -0,0 +1,104 @@
# New Appeal Refactor Tracker
Base branch for this tracker: `refactor`
## Status
Current slice: Slice 1 — XML/Form Derivation Extraction
Status: NOT STARTED
---
## Slice List
### Slice 1 — XML/Form Derivation Extraction
Status: NOT STARTED
- Extract XML parsing helpers into lib
- Keep selectors identical
- No behaviour change
---
### Slice 2a — Payload Cleanup Helpers
Status: NOT STARTED
- Extract boolean normalization
- Extract null/internal key stripping
---
### Slice 2b — File Merge/Dedupe Helpers
Status: NOT STARTED
- Extract file list merge logic
- Extract dedupe logic
---
### Slice 3 — Side Effect Facade
Status: NOT STARTED
- Wrap existing service calls
- No logic changes
---
### Slice 4 — BuildSection UI Extraction
Status: NOT STARTED
---
### Slice 5 — BuildCheckSection UI Extraction
Status: NOT STARTED
---
### Slice 6 — BuildCheckRow Formatter Map
Status: NOT STARTED
---
### Slice 7 — Props Boundary Cleanup
Status: NOT STARTED
---
### Slice 8 — Start Flow Cleanup (CreateCase / AboutYou)
Status: NOT STARTED
---
## Rules
- Only work on ONE slice at a time
- Do not move to next slice until current is COMPLETE
- Do not combine slices
- Preserve behaviour at all times
## Notes
- Save/resume payload shape is sensitive
- File upload logic duplicated in multiple places
- BuildSection is highest risk area
## Regression Checklist (Run After Each Slice)
- Start new appeal
- Save and exit
- Resume saved appeal
- Navigate sections
- Upload file
- View check answers
- Submit appeal (if safe to test)
- View confirmation page
- Verify EN/CY parity
+102
View File
@@ -0,0 +1,102 @@
import xpath from "xpath";
export const parseXml = (xmlStr) => {
const parser = new DOMParser();
return parser.parseFromString(xmlStr, "text/xml");
};
export const selectCurrentSectionTitleDescriptions = (doc, currentSection) => {
return xpath.select(
"//form/tabs/tab[" + currentSection + " ]/labels/label/@description",
doc
);
};
export const selectCurrentSectionRows = (doc, currentSection) => {
return xpath.select(
"/form/tabs/tab[" +
currentSection +
"]/columns//sections/section/rows/row",
doc
);
};
export const selectFormTabs = (doc) => {
return xpath.select("/form/tabs", doc);
};
export const selectAllTabTitleDescriptions = (doc) => {
return xpath.select("//form/tabs/tab[*]/labels/label/@description", doc);
};
export const parseRowOuterHTML = (outerHTML) => {
const parser = new DOMParser();
return parser.parseFromString(outerHTML, "text/xml");
};
export const selectRowLabelDescriptions = (doc) => {
return xpath.select("//label/@description", doc);
};
export const selectRowFieldType = (doc) => {
return xpath.select("//@classid", doc);
};
export const selectRowValidation = (doc) => {
return xpath.select("//@validation", doc);
};
export const selectRowMaxFieldLength = (doc) => {
return xpath.select("//@maxFieldLength", doc);
};
export const selectRowMaxSubField = (doc) => {
return xpath.select("//@maxsubfield", doc);
};
export const selectRowDataFieldName = (doc) => {
return xpath.select("//@datafieldname", doc);
};
export const selectRowDataFieldContent = (doc) => {
return xpath.select("//@datafieldcontent", doc);
};
export const selectRowParentField = (doc) => {
return xpath.select("//@parentField", doc);
};
export const selectRowParentFieldShowOnValue = (doc) => {
return xpath.select("//@parentFieldShowOnValue", doc);
};
export const selectRowRequiredDocumentValue = (doc) => {
return xpath.select("//@requiredDocumentValue", doc);
};
export const selectRowRequiredDocumentLabel = (doc) => {
return xpath.select("//@requiredDocumentLabel", doc);
};
export const selectRowDocumentTypeCode = (doc) => {
return xpath.select("//@ishareDocumentCode", doc);
};
export const selectRowHint = (doc) => {
return xpath.select("//label/@hint", doc);
};
export const selectRowDateStart = (doc) => {
return xpath.select("//@dateStart", doc);
};
export const selectRowDateEnd = (doc) => {
return xpath.select("//@dateEnd", doc);
};
export const selectErrorFieldLabelDescription = (doc, whichField) => {
return xpath.select(
"//*[control/@id='" + whichField + "']//@description",
doc
);
};
+57
View File
@@ -912,6 +912,63 @@ Follow-ups:
- Breadcrumb route-state extraction closure slices (1/2/3) complete.
### CL-22541-Z4: breadcrumbs post-closure hotfix — callable label resolver parity (static + view-all)
date: 2026-04-09
author: Cline
scope: `components/breadcrumbs.js`, `tests/phase22/breadcrumbs-route-map-structure.test.cjs`
type: change
rationale: Fix post-refactor regression where some breadcrumbs rendered blank labels because mapped label entries were returned as function references instead of resolved values.
impact: Restores user-visible breadcrumb labels for static and view-all keyed routes; no auth/session/API/security behavior change.
status: completed
Summary:
- Fixed static text breadcrumb label resolver to invoke mapped label functions:
- `getStaticTextCrumbLabel(path)` now resolves callable entries (`resolver ? resolver() : null`).
- Fixed view-all label resolver parity to support both function-backed and string-backed map entries:
- `getViewAllLabel(viewKey)` now invokes function entries and returns string entries directly.
- Added structure guard assertions to prevent regression of callable label resolution behavior.
Validation:
- `node tests/phase22/breadcrumbs-route-map-structure.test.cjs` -> pass (4/4).
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
Follow-ups:
- Breadcrumb label resolver parity now aligned across mapped/static/view-all label paths.
### CL-22541-Z5: architecture comparison overview refresh (senior architecture review)
date: 2026-04-09
author: Cline
scope: `context/architecture-overview-2026-04-09.md`
type: change
rationale: User requested a fresh senior architecture review and comparison baseline covering scalability, maintainability, coupling, boundary quality, operational/deployment risk, and prioritized technical debt actions.
impact: Documentation-only architecture guidance update; no runtime/auth/session/security/API behavior change.
status: completed
Summary:
- Added new architecture comparison baseline document:
- `context/architecture-overview-2026-04-09.md`
- Included requested structure:
1. current architecture summary
2. strengths
3. risks (scalability, maintainability, coupling, weak boundaries, operational/deployment)
4. prioritized recommendations
5. low-risk next improvements
- Added explicit comparison notes vs existing `context/architecture.md` and identified strategic focus areas for the next modernization wave.
Validation:
- Documentation coherence review against current repo architecture docs (`context/architecture.md`, `context/integration-map.md`, `context/project-overview.md`).
Follow-ups:
- Optionally elevate this architecture overview into a periodic architecture scorecard cadence and add measurable KPIs in memory-bank.
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
date: 2026-04-07