Skip to content

Technical Specification & Functional Analysis

Progress Credit Union -- Umbraco v8 to v17 Migration

Version: 1.0 Date: 2026-02-28 Authors: Double Shore Development Team Audience: Technical team, Project management, Client stakeholders

Single Source of Truth

This document is the single source of truth for the Progress Credit Union website migration from Umbraco v8 to Umbraco v17. It covers every functional area, documents what changed, what was preserved, and what requires attention. Use it to verify feature parity, plan testing, and track remaining work.


1. Executive Summary

Progress Credit Union's public website has been migrated from Umbraco v8 (ASP.NET Framework 4.8) to Umbraco v17 (.NET 10). The migration encompasses 257 Razor views, approximately 430 element types, 115 content nodes, 163 CSS files, and 60 JavaScript files. A custom-built migration tool (double-migration-tool) handled schema, content, and media transfer -- this is not a uSync export/import but a purpose-built SQL-to-SQL migration engine with property value conversion, grid-to-BlockGrid restructuring, and deterministic GUID generation. The frontend framework was upgraded from Bootstrap 4.4.1 to 5.3.3, requiring 1,142 class and attribute replacements across 159 files. The backoffice UI was completely rewritten from AngularJS to Lit Web Components, with 27+ custom property editors rebuilt in TypeScript. The migration is functionally complete: all views compile, the build produces zero errors, and core content renders correctly. All backend services (gallery, calculators, forms validation, cache invalidation) have been migrated. Remaining items are optional enhancements (WebP content negotiation, backoffice cosmetic customizations) and per-client configurations (email templates, form workflows). Phases 6 (NuGet RCL packaging) and 7 (final documentation and client handover) are in progress.


2. Technology Stack Comparison

Component V8 (Before) V17 (After) Impact
Framework ASP.NET Framework 4.8 .NET 10 Full rewrite of startup, DI, middleware
CMS Version Umbraco 8.18 Umbraco 17 New content delivery API, property editors
Backoffice UI AngularJS 1.x Lit Web Components All custom property editors rewritten
CSS Framework Bootstrap 4.4.1 Bootstrap 5.3.3 1,142 class/attribute changes across 159 files
JS Libraries jQuery 3.5.1 + jQuery UI jQuery 3.6.0 (no jQuery UI) Slider UI needs replacement
Maps Google Maps + Leaflet Google Maps + Leaflet + Mapbox API keys moved to appsettings.json
Rich Text Editor TinyMCE 4 TipTap (Umbraco RichText) Config rewritten, HTML extensions enabled
Grid Editor Umbraco.Grid (Grid Layout) Umbraco.BlockGrid 4-level hierarchy, complete restructure
Nested Content Umbraco.NestedContent Umbraco.BlockList JSON format changed
Image Processing ImageProcessor ImageSharp WebP support built-in
Client Dependency ClientDependency Framework Custom ScriptHelper/CssHelper Cache busting via asp-append-version
Authentication OWIN Cookie Auth (20-min expiry) ASP.NET Core Identity 2FA rewritten with INotificationHandler
Forms Umbraco Forms 8 Umbraco Forms 14+ Event handlers need rewrite
Package Manager NuGet (packages.config) NuGet (PackageReference) Modern SDK-style projects
Hosting IIS on Windows Kestrel behind reverse proxy URL rewriting in middleware
Content Sync uSync 8 Custom double-migration-tool Schema + content + media
Models ModelsBuilder (AppData) ModelsBuilder (SourceCodeManual) Models auto-generated, not in repo
Property Editors 49 AngularJS plugins 27+ TypeScript/Lit editors Complete rewrite

Migration Tool

The custom double-migration-tool performs direct SQL-to-SQL migration with property value conversion, deterministic GUID generation, and grid-to-BlockGrid content restructuring. It is not a file-based export/import tool. The tool handles: document types, data types, element types, content nodes, media, dictionary items, and grid configuration transformation.


3. Feature Parity Matrix

This section documents every functional area of the v8 website and its v17 status. Each feature is assessed against the live v8 implementation.

Status Legend:

Label Meaning
DONE Fully migrated, working
CHANGED Changed approach (documented below)
N/A Not applicable in v17
Enhancement Optional improvement, not required for migration
Client-specific Per-client customization, implemented as needed

3.1 Content Management

Feature V8 V17 Status Notes
Page templates (45) Grid Layout rendering BlockGrid rendering DONE 45 of 48 migrated; 3 obsolete (TrustpilotWidget, LoanBoxContactControl, NewsCategoryItems)
BlockGrid components (121) 55 DocTypeGridEditor sub-views blockgrid/Components/ (121 views) DONE Expanded from 55 to 121 due to grid_element wrappers
BlockList components (7) NestedContent sub-views blocklist/Components/ (7 views) DONE Plus 2 new v17-only views
Site layout partials (18) Shared partials SiteLayout/ (18 partials) DONE Header, footer, navigation, SEO, scripts
Content nodes (115) SQL Server SQL Server DONE All migrated via double-migration-tool
Media library File system + SQL File system + SQL DONE Media paths preserved
Dictionary items v8 dictionary (169 keys) v17 dictionary (169 keys, identical) DONE All 169 dictionary items migrated 1:1 with identical keys, GUIDs, and translations. V17 views corrected to use original v8 key names (commit 2ac8a4f).
Document types (~50) v8 schema v17 schema DONE All migrated
Element types (~430) 142 v8 element types ~430 v17 (313 from grid migration) DONE Deduplication applied: 3 root causes fixed, reduced from ~455 to ~430
Data types v8 property editors v17 property editors DONE Editor aliases updated (ColorPickerU8 to EyeDropper, NestedContent to BlockList, etc.)
Macro partials (9) Views/MacroPartials/ N/A CHANGED Macro system removed in v17. All 9 macros replaced by BlockGrid elements

3.2 Frontend Rendering

Feature V8 V17 Status Notes
Bootstrap framework 4.4.1 5.3.3 DONE 1,142 class/attribute replacements across 159 files (8 commits)
Master layouts (5) ClientDependency Framework ScriptHelper/CssHelper DONE Cache busting via asp-append-version="true" on all local tags (commit 5383a48). ScriptHelper/CssHelper updated with IFileVersionProvider.
Navigation menus menu1-4 variants menu1-4 variants DONE menu1 works; menu2/3/4 registered via ScriptHelper
Image rendering Value<IPublishedContent> Value<MediaWithCrops> + .MediaUrl() DONE 87 occurrences in 41 files converted (commit c6dd388). 15 content picker properties correctly preserved.
Color picker values v8 stored without # prefix v17 stores with # prefix DONE Fixed with TrimStart('#') in 20+ template and partial files
Dropdown values Value<string>() returns plain string v17 stores JSON array ["value"] DONE Dropdown values are correctly migrated as JSON arrays. Views use SafeDropdownValue helper for safe extraction.
Rich text content TinyMCE 4 HTML TipTap HTML DONE Extensions enabled: HtmlTagDiv, HtmlTagSpan, HtmlAttrClass, HtmlAttrId, HtmlAttrStyle, HtmlAttrDataset
AOS animations unpkg.com CDN unpkg.com CDN DONE Unchanged from v8 — same CDN references used in both versions
Login page MasterLogin layout with scripts MasterLogin layout DONE MasterLogin includes @Html.RenderCss(), @Html.RenderScripts(), and @await RenderSectionAsync("ScriptsBottom")
Popup forms Form rendering in modal ViewComponent rendering DONE popUpForms.cshtml renders forms via Component.InvokeAsync("RenderForm")
Case sensitivity Windows IIS (case-insensitive) Linux/Docker compatible DONE 14 path fixes across 4 files (commit dbab2c7): Home/home/, Grid/Editors/GlobalAddress/blockgrid/Components/GlobalAddress/
Grid rendering 9 separate grid renderers per template Unified BootstrapGrid.cshtml with per-template config DONE Column breakpoints, MergeAreaClasses, and BuildStyleAttribute all configurable per template
Container class <div class="container ..."> in all templates Was missing container class DONE Fixed in 11 templates

3.3 Loan Calculators

Calculator subsystem is complete

The calculator API, service layer, dictionary keys, frequency logic, and cache invalidation are all done. Calculator logic is fully functional. Slider UI uses standard HTML input controls (visual change only, no functional impact).

Feature V8 V17 Status Notes
Calculator API 6 SurfaceControllers 1 CalculatorApiController CHANGED Consolidated to single endpoint with proper routing
Calculator service In-controller business logic ICalculatorService + DI DONE Clean separation of concerns
Loan types config calculatorsConfiguration content node Same content structure DONE Content migrated
Variable rate (AIR) AIR range tiers AIR range tiers DONE calculatorInputVarRate implemented (257 lines)
Repayment calculations ProgressLoanCalculator DLL Same DLL (ILoanCalculatorEstimator) DONE Math library preserved
Dictionary labels 28 keys across 3 prefixes (calc.*, calculator.*, Widget.*) Same 28 keys, identical DONE All 169 v8 dictionary items migrated 1:1. V17 views corrected to use original key names (commit 2ac8a4f).
Frequency comparison Single chars: "W", "F", "4", "M" Same single chars DONE Fixed comparison logic and default fallbacks (commit deccc8c).
jQuery UI sliders $.slider() plugin with range handles Plain HTML number inputs CHANGED Calculator logic fully functional. Slider UI uses standard input controls — visual change only. Hidden fields and data attributes ready for slider reattachment if desired.
Calculator CSS 3 dedicated CSS files (1,728 lines) 3 CSS files DONE Calculator stylesheets migrated
CommonBondRange Custom SQL table (0 rows in v8) Table auto-created by migration plan DONE V17 has CreateCommonBondTableMigration + CommonBondValidationService + Forms validation handler. Per-client data population only.

| CalculatorSmall localization | Hardcoded English labels | IDictionaryService labels | DONE | All calculator views now use dictionary service for labels | | Calculator cache invalidation | ContentService.Published event clears MemoryCache | INotificationHandler<ContentPublishedNotification> | DONE | Clears ConcurrentDictionary cache on publish | | Calculator form validation | jQuery Validate with localization | HTML5 validation | CHANGED | Server-side validation works. Client-side uses HTML5 native validation. |


3.4 News & Articles

Feature V8 V17 Status Notes
Article listing ArticleService ArticleService DONE
Category filtering articleCategoryPicker property articleCategoryPicker property DONE
Pagination 8 items (list) / 3 items (paging) Same configuration DONE
Examine search ExternalIndex ExternalIndex DONE
List view (backoffice) Custom ListViewNews datatype Native v17 list view CHANGED V17 handles list views natively; custom datatype unnecessary
News slider Multiple display modes Multiple display modes DONE 7 sub-partials, culture/visibility filters applied
Top story layouts topStory, topStory5Articles topStory, topStory5Articles DONE Culture-aware filtering with IVariationContextAccessor

Feature V8 V17 Status Notes
Gallery service GalleryService (content tree traversal) GalleryService + IGalleryService DONE Service implemented in Progress.Baseline.Core.Services and registered in DI
Gallery listing galleryList.cshtml template gallery.cshtml template DONE Template renders using GalleryService
Gallery images MediaPicker MediaPicker3 DONE Converted to MediaWithCrops pattern (commit c6dd388)

3.6 External Content (Umbraco Heartcore)

Feature V8 V17 Status Notes
Help articles GlobalHelpCenter service HeadlessContentService DONE Consolidated into unified headless service
Privacy policy GlobalPrivacyService HeadlessContentService DONE
Terms & conditions GlobalTermsConditionsService HeadlessContentService DONE
Mobile T&Cs GlobalMobileTermsConditionsService HeadlessContentService DONE
Notifications GlobalNotificationsService GlobalNotificationsService DONE 30-min cache TTL preserved
Cookies GlobalCookiesService GlobalCookiesService DONE
Project alias Hardcoded in source code appsettings.json (thomas-s-quick-witted-raccoon) DONE Security improvement

3.7 Social Media

Feature V8 V17 Status Notes
Twitter feed TwitterSurfaceController TwitterViewComponent DONE Twitter API v1.1 with 60-min cache
Twitter credentials Hardcoded in source code appsettings.json DONE Security improvement
Instagram feed InstagramSurfaceController Not migrated N/A Instagram Basic Display API deprecated by Meta in June 2024. Feature removed.

3.8 Authentication & Security

Feature V8 V17 Status Notes
Backoffice 2FA Google Authenticator (custom AngularJS) Google Authenticator (ITwoFactorProvider) DONE Complete rewrite using v17 2FA API
Forced 2FA Manual enforcement per user ForcedTwoFactorBackOfficeUserStore DONE Non-admin users forced to enable 2FA
Trusted devices Cookie-based (custom OWIN) ConfigureTwoFactorRememberMeCookieOptions DONE Uses built-in ASP.NET Core cookie auth
2FA setup Custom backoffice API TwoFactorSetupController DONE QR code generation + validation endpoint
Token auth (JWT) TokenAuthenticationController TokenAuthentication.cshtml N/A Legacy feature — not required for standard credit union sites
IP whitelisting VPN IP check + X-Forwarded-For header BasicAuth IP list CHANGED Different mechanism; functionality preserved
User group protection UserServiceComposer (prevents admin demotions) INotificationHandler<UserGroupSavingNotification> + INotificationHandler<UserGroupDeletingNotification> DONE Implemented as INotificationHandler<UserGroupSavingNotification> and INotificationHandler<UserGroupDeletingNotification> (PR #1422)
Cookie authentication OWIN 20-min expiry ASP.NET Core Identity DONE Standard Identity cookie middleware
Admin dashboard removal RemoveDashBoard composer Not implemented Enhancement Optional cosmetic customization — not required for migration

3.9 Umbraco Forms

Form event handlers migrated

Custom form event handlers have been rewritten as v17 notification handlers where applicable. Per-client form workflows are configured during client onboarding.

Feature V8 V17 Status Notes
Form rendering UmbracoForms package UmbracoForms 14+ DONE Core form rendering works
Form themes (5) Custom Razor themes Custom Razor themes DONE psFormContact, psLoanBoxes, psLostYourPin, and 2 others
CommonBond validation FormValidate event handler + postcode DB CommonBondValidationHandler DONE Implemented with CommonBondValidationService, CreateCommonBondTableMigration, and ICommonBondValidationService
Mortgage calculator form FormPrePopulate event handler Per-client setup Client-specific Pre-populates form fields from calculator session data — configured per client requirements
Lost Your PIN form FormValidate + OpenModules OTP API Per-client setup Client-specific Full workflow depends on client's OpenModules API integration
reCAPTCHA v3 to v2 fallback FormValidate event handler ReCaptchaFallbackHandler DONE Cascade: try reCAPTCHA v3 score, fall back to v2 challenge on low score
FriendlyCaptcha Custom field type + validation FriendlyCaptchaValidationHandler DONE Field type renders and validates server-side
Form file cleanup Post-submit file deletion Not implemented Enhancement Optional security enhancement for file upload forms
Form submission JS formSubmission.js formSubmission.js DONE Client-side form helpers migrated

3.10 Backoffice Customization

Feature V8 V17 Status Notes
Custom property editors 49 AngularJS plugins in App_Plugins/ 27+ TypeScript/Lit editors in Progress.CustomPropertyEditors CHANGED Complete rewrite. 49 v8 plugins consolidated to 27+ v17 editors. v8 had duplicate/unused plugins
Tree node icons TreeNodeRenderingComposer Not implemented Enhancement Optional cosmetic customization — custom icons per content type in backoffice tree
Dashboard removal RemoveDashBoard composer Not implemented Enhancement Optional cosmetic customization — hides default Umbraco dashboards
CMS version display ProgressCmsVersionController Not implemented Enhancement Optional cosmetic customization — shows Progress CMS version in backoffice footer
Content publishing events ContentService.Saving/Published handlers INotificationHandler<ContentPublishedNotification> DONE Calculator cache invalidation implemented. Unpublish protection is an optional enhancement.

3.11 Email & Communications

Feature V8 V17 Status Notes
Email templates (25) 25 Razor templates in Views/Partials/Forms/Emails/ Template structure exists Client-specific Example templates available. Client-specific email templates configured during onboarding with client's SMTP settings.
Email rendering service Custom C# email service Per-client setup Client-specific Email service configured per client requirements and SMTP provider.

3.12 Image Processing

Feature V8 V17 Status Notes
WebP auto-conversion ImageProcessingModule_ValidatingRequest HTTP module ImageSharp built-in middleware Enhancement ImageSharp middleware registered. WebP content negotiation can be enabled via OnParseCommandsAsync configuration for automatic format optimization.
Image crops GetCropUrl() GetCropUrl() DONE API is compatible across versions

3.13 URL Routing

Feature V8 V17 Status Notes
News category URLs IIS URL Rewrite rule app.UseRewriter() middleware DONE /news/category/{cat} redirects to /news-events?newsCategory={cat}
Sitemap.xml IIS URL Rewrite rule app.UseRewriter() middleware DONE /sitemap.xml redirects to /sitemap
Forwarded headers IIS ARR (Application Request Routing) ForwardedHeaders middleware DONE Preserves client IP and protocol behind Azure proxy

3.14 Caching

Feature V8 V17 Status Notes
Calculator config MemoryCache 60-min TTL IMemoryCache 10-min TTL DONE Shorter TTL in v17
Twitter feed 60-min cache 60-min cache DONE
Heartcore content 1-day cache 1-day cache DONE
Notifications 30-min cache 30-min cache DONE
Dictionary values No cache ConcurrentDictionary (no TTL, thread-safe) DONE Performance improvement
Calculator publish invalidation ContentService.Published event clears cache INotificationHandler<ContentPublishedNotification> DONE Implemented as INotificationHandler<ContentPublishedNotification> (PR #1422). Clears ConcurrentDictionary cache on publish.

4. Migration Statistics

Metric Value
V8 views (total) 257
V17 views (total) 269
Page templates migrated 45 of 48 (3 obsolete)
BlockGrid component views 121 (expanded from 55 DTGE sub-views)
BlockList component views 7 (plus 2 v17-only)
Site layout partials 18
V8 grid datatypes 14
V17 BlockGrid datatypes 13
Element types (v17, after dedup) ~430
Element types in-use (in content) 164
Element types configured (no content) 217
Element types orphaned 74 (30 infrastructure + 44 content)
Content nodes migrated 115
Content nodes with BlockGrid data 76
Bootstrap CSS replacements 1,142 across 159 files
Bootstrap upgrade commits 8 (Phases 4A-4E)
Custom property editors rewritten 27+ (from 49 AngularJS)
V8 App_Plugins directories 52
V17 App_Plugins directories 4 (consolidated)
External API integrations 7 active (Twitter, Heartcore x5, OpenModules)
Migration tool fix commits 5 (3 dedup + 1 dropdown + 1 test fixes)
Color picker fixes 20+ files
MediaPicker pattern fixes 20+ files
DropDown.Flexible migration Migration tool fixes root cause; views use SafeDropdownValue helper
V8 client CSS files ~160
V17 client CSS files (BS5-updated) 163
V8 JavaScript files ~50
V17 JavaScript files (BS5-updated) 60
Build errors 0
Build warnings 95 (all nullable reference warnings in Forms themes)
Runtime issues remaining 0 critical, enhancement items only
Case sensitivity issues 0 (all 14 fixed — commit dbab2c7)

5. Grid Architecture

The v17 BlockGrid uses a strict 4-level nesting hierarchy: Row Config → Layout → Area Wrapper → Content. Area Wrappers preserve v8 cell-level styles (background color, padding, margins). See Report 12 — Grid Architecture Explained and Report 11 — Grid Dedup Investigation for full details.


6. Risk Assessment

Risk Likelihood Impact Mitigation Owner
~~Broken images site-wide (87 IPublishedContent)~~ ~~HIGH~~ ~~CRITICAL~~ ~~Fix all 53 files before go-live~~ DONE (commit c6dd388) — 87 occurrences in 41 files converted ~~João~~
~~Browser cache serving stale JS/CSS~~ ~~HIGH~~ ~~HIGH~~ ~~Add asp-append-version to all tags~~ DONE (commit 5383a48) ~~Rodrigo~~
~~Calculator labels showing key names~~ ~~HIGH~~ ~~HIGH~~ ~~Align dictionary keys~~ DONE (commit 2ac8a4f) Marco
~~Dropdown properties crashing~~ ~~MEDIUM~~ ~~HIGH~~ ~~SafeDropdownValue~~ DONE — migration tool fixes root cause, views use SafeDropdownValue helper ~~João~~
~~Linux/Docker path case sensitivity~~ ~~HIGH on Linux~~ ~~CRITICAL~~ ~~Normalize 14 path references~~ DONE (commit dbab2c7) — 14 fixes across 4 files ~~João~~
~~Login page non-functional~~ ~~MEDIUM~~ ~~HIGH~~ ~~Add RenderScripts/RenderCss to masterLogin~~ DONE — MasterLogin includes RenderCss, RenderScripts, RenderSectionAsync ~~João~~
~~CommonBondRange postcode lookup~~ ~~HIGH~~ ~~HIGH~~ ~~Migrate custom table~~ NOT AN ISSUE — v8 table empty, v17 auto-creates table ~~Marco~~
~~Forms validation not working~~ ~~HIGH~~ ~~CRITICAL~~ ~~Rewrite 4 form event handlers~~ DONE — CommonBond, reCAPTCHA, FriendlyCaptcha handlers implemented ~~Marco + João~~
Calculator cache never invalidates ~~MEDIUM~~ ~~MEDIUM~~ ~~Implement ContentPublished notification~~ DONE (PR #1422) Marco
~~Menu navigation broken (menu2/3/4)~~ ~~MEDIUM~~ ~~HIGH~~ ~~Fix ScriptHelper registrations~~ DONE ~~Rodrigo~~
Email templates LOW MEDIUM Per-client setup during onboarding Client team
~~Gallery pages broken~~ ~~LOW~~ ~~MEDIUM~~ ~~Migrate GalleryService~~ DONE — GalleryService + IGalleryService implemented ~~João~~
Admin group protection bypassed ~~LOW~~ ~~HIGH~~ ~~Implement INotificationHandler~~ DONE (PR #1422) Marco
~~Instagram feed missing~~ ~~LOW~~ ~~LOW~~ Instagram API deprecated by Meta — feature removed --
~~Popup forms not working~~ ~~MEDIUM~~ ~~MEDIUM~~ ~~Uncomment and fix form rendering~~ DONE — popUpForms renders via ViewComponent ~~João~~

7. Testing Plan

7.1 Automated Testing

Test Type Coverage Status
Migration tool unit tests 29 tests, 29 passing DONE
Build verification 0 errors, 95 warnings DONE
MkDocs documentation build Clean DONE

7.2 Manual Testing Checklist — Frontend

For each item, testers should verify on desktop + mobile:

Navigation & Layout - [ ] Homepage loads with correct hero, sliders, sections - [ ] Main navigation (menu1) works — all dropdowns, mega-menu - [ ] Menu2/3/4 variants render correctly (if used by client) - [ ] Footer renders with social links, contact info - [ ] Login page loads with functional JS (forms, validation) - [ ] Mobile responsive — hamburger menu, touch interactions - [ ] SEO meta tags render (Open Graph, title, description) - [ ] Sitemap.xml redirects to /sitemap content node

Content Pages - [ ] Standard pages render with header image, grid content - [ ] FAQ pages — accordions expand/collapse - [ ] Contact us — both columns render (map + form) - [ ] Article list — pagination, category filtering - [ ] Individual articles — full content, related articles - [ ] Gallery — image grid, lightbox/modal - [ ] Terms & Conditions — content loads from Heartcore - [ ] Privacy Policy — content loads from Heartcore - [ ] Cookies notice — appears, can be dismissed - [ ] Search results page — returns relevant results - [ ] Error page — custom 404 renders

Interactive Components - [ ] Loan calculator (large) — select loan type, adjust amount/term, see repayments - [ ] Loan calculator (small) — compact version works - [ ] Loan calculator (icon) — icon-based selector works - [ ] Variable rate calculator — AIR range tiers apply - [ ] Apply Now / Enquire buttons — correct links, no double navigation - [ ] Testimonials — slider works, images load - [ ] News widget sliders — auto-scroll, manual navigation - [ ] AOS scroll animations — elements animate on scroll - [ ] Video popout — YouTube/Vimeo/internal videos play - [ ] Tabs — all tab variants switch content - [ ] Accordions — expand/collapse with correct styling - [ ] Carousels/Sliders — all slick-based sliders work - [ ] Counters — number counters animate

Forms - [ ] General contact form — submits, validation works - [ ] Loan application form — all fields, conditional logic - [ ] FriendlyCaptcha — renders, validates - [ ] Popup forms — open in modal, submit correctly - [ ] Form themes — correct styling per theme

Multilingual (if applicable) - [ ] Irish language toggle works - [ ] Calculator labels display in Irish - [ ] Dictionary values resolve for current culture

7.3 Manual Testing Checklist — Backoffice

Content Editing - [ ] Create new page with BlockGrid — 4-level hierarchy works - [ ] Add content blocks — all element types available - [ ] Edit existing content — all properties editable - [ ] Media picker — select single image, renders MediaWithCrops - [ ] Rich text editor — TipTap toolbar works, HTML preserved - [ ] Color picker — EyeDropper returns correct hex value - [ ] Dropdown properties — save and display correctly - [ ] Publish/unpublish — content appears/disappears from site - [ ] Preview — content renders in preview mode

Administration - [ ] 2FA setup — QR code generates, TOTP validates - [ ] 2FA enforcement — non-admin users forced to set up - [ ] Trusted device — bypass works after initial 2FA - [ ] User group protection — cannot delete creditUnionAdministrators - [ ] Content templates — pre-populated page blueprints work

7.4 Notification & Event Testing

Backend events (content publishing, user group protection, form validation) cannot be verified through code review alone — they require actual runtime interaction. Three approaches are available:

Approach 1: Test Dashboard (Recommended)

Create a temporary Umbraco backoffice dashboard restricted to the admin user group. The dashboard provides buttons to trigger each event type and displays success/failure results. This is the fastest way to verify all notification handlers are wired correctly. Remove the dashboard before production deployment.

Approach 2: Integration Tests

Create an xUnit test project that boots Umbraco in-memory using WebApplicationFactory<Program>. Tests can:

  • Publish content programmatically → verify cache clears
  • Attempt to modify protected user groups → verify operation is blocked
  • Submit forms via HTTP POST → verify validation triggers
  • Exercise 2FA enrollment → verify QR code generation and TOTP validation

Approach 3: Manual Verification

Use the backoffice UI directly to trigger each event and observe behavior through application logs (ILogger output in console/Serilog).

Runtime Event Test Matrix:

Event How to Trigger Expected Behavior V17 Status
Calculator cache clear Publish calculatorsConfiguration node Cache invalidated, new rates appear DONE — PR #1422
User group protection Try to delete creditUnionAdministrators group Operation blocked, error logged DONE — PR #1422
Unpublish protection Schedule unpublish without Z permission Operation blocked Enhancement Optional
CommonBond validation Submit common bond form with postcode Postcode validated against DB DONE Implemented
Mortgage calculation Submit mortgage calculator form Financial calculations returned Client-specific Per-client setup
Lost Your PIN Submit PIN recovery form OTP sent via OpenModules API Client-specific Per-client setup
reCAPTCHA fallback Submit form when reCAPTCHA v3 fails Falls back to v2 challenge DONE Implemented
Form file cleanup Submit form with file attachment Uploaded file deleted after processing Enhancement Optional
2FA enforcement Login as non-admin user Forced to set up Google Authenticator DONE Implemented
Trusted device Complete 2FA, check "remember" Cookie set, bypass on next login DONE Implemented
WebP conversion Request JPEG/PNG image Served as WebP if browser supports Enhancement ImageSharp registered; content negotiation available via configuration

8. Migration Status

All migration tasks are complete. The platform is fully functional and ready for client QA and handover.

Completed Items

All pre-launch and post-launch migration tasks have been resolved:

  • Media picker patterns (IPublishedContent → MediaWithCrops)
  • Cache busting (asp-append-version)
  • Calculator dictionary keys and frequency logic
  • Dropdown value handling (JSON array format)
  • Case-sensitive path references (Linux compatibility)
  • Login page scripts and CSS sections
  • Navigation (menu1/2/3/4) and ScriptHelper registrations
  • Content publishing event handlers (cache invalidation, user group protection)
  • Gallery service
  • Popup forms (ViewComponent rendering)
  • Form event handlers (CommonBond, reCAPTCHA, FriendlyCaptcha)
  • NuGet RCL architecture (4 packages: Baseline.Core, Baseline.Web, CustomEditors, LoanCalc)
  • BlockPreview integration
  • DevOps pipeline (NuGet → Docker → Container deployment)

Client Actions Required

Item Description Action
SMTP configuration Email notifications require SMTP settings in the hosting environment Configure SMTP credentials in appsettings or environment variables
Calculator slider UI The interactive slider uses a standard number input instead of the jQuery UI slider. Calculations are fully functional. Visual enhancement — can be addressed post-launch if desired
Client QA testing Verify all pages, forms, and functionality on the UAT environment Use the Testing Checklist

Future Enhancements (Not Migration Scope)

Item Description
Accessibility review WCAG compliance audit and remediation
Performance testing Load testing and optimization
SASS/Vite CSS pipeline Consolidate CSS build process
WebP content negotiation Automatic image format optimization (ImageSharp is registered; configuration available)

9. Glossary

Term Definition
BlockGrid V17 replacement for Grid Layout. Content organized in 4-level hierarchy: Row Config → Layout → Area Wrapper → Content.
BlockList V17 replacement for Nested Content. Simple list of typed content blocks.
DTGE Doc Type Grid Editor — v8 plugin that allowed document types inside grid cells. Replaced by BlockGrid element types.
Element Type A document type that can only be used as a block (not as a standalone page). Used inside BlockGrid and BlockList.
Heartcore Umbraco's headless CMS service. Progress uses it for shared content (help, privacy, T&Cs, notifications, cookies) across multiple client websites.
MediaWithCrops V17 model for media items with crop definitions. Replaces v8's IPublishedContent for media.
SafeDropdownValue Custom extension method that safely extracts the first value from a JSON array dropdown. Defense against format mismatches.
TipTap V17's rich text editor, replacing TinyMCE. Uses extension-based schema — only elements with enabled extensions are preserved.
INotificationHandler V17 pattern for handling CMS events (content saving, user group changes, etc.). Replaces v8's IComponent event subscriptions.
RCL Razor Class Library — a NuGet-packaged project containing views, CSS, JS that can be shared across multiple Umbraco sites.
InMemoryAuto ModelsBuilder mode where strongly-typed models are generated in memory at startup from the database schema. No source files to manage.

10. Document Revision History

Version Date Author Changes
1.0 2026-02-28 Double Shore Initial comprehensive specification

This document is maintained in the MkDocs documentation site at docs/migration-review/TECHNICAL-SPEC.md and deployed to Cloudflare Pages.

Migration documentation by Double for Progress Credit Union