Accessible Frontend Takeover¶
Last reviewed: 2026-08-17
🔴 CURRENT STATUS, AND THE ONLY STATUS CLAIM THAT COUNTS¶
The takeover is COMPLETE. There is ONE accessible frontend: web-uk. The Laravel
Blade accessible frontend was DELETED on 2026-08-14.
Measured on the live server that day, not inferred from any document:
| Address | Serving | Community resolved from |
|---|---|---|
accessible.project-nexus.ie |
web-uk |
URL slug — /{tenantSlug}/accessible/... |
accessible-uk.timebank.global |
web-uk |
hostname (slug-less) |
accessible-minehead-and-coast.timebank.global |
web-uk |
hostname (slug-less) |
| all 11 communities via the platform host | web-uk |
URL slug |
/version is the discriminator: web-uk answers it with "service":"nexus-webuk".
Nothing else serves these addresses, so a host that does not answer /version is
broken, not "still on the old frontend" — that inference was valid before
2026-08-14 and is actively misleading now.
🔴 "The takeover is complete" means Blade is gone and web-uk serves every accessible
address. It does NOT mean web-uk does everything React does. Measured for the first
time on 2026-08-17: it covers 71% of member-facing React routes (179 of 251). The
route matrix's 707/707 cannot show this, because it measures parity with the deleted
Blade frontend. What is missing, what is deliberately absent, and in what order the rest
is being built are recorded once, in
web-uk/docs/REACT_PARITY_AND_ROADMAP.md.
Two owner decisions from that date are load-bearing: a platform admin panel is not
required on the accessible frontend, and the Caring Community module is experimental
and deferred (on for 2 of 11 communities; on the roadmap for investigation).
What was deleted: accessible-frontend/, app/Http/Controllers/GovukAlpha/,
routes/govuk-alpha.php, routes/govuk-alpha-parity/, the AlphaSetLocale and
StripTenantSlugOnAccessibleDomain middleware, App\Support\AccessibleErrorPage,
App\Http\Middleware\EnsureAccessibleCustomDomain, and the Blade half of the visual
comparison tooling.
What deliberately survives, and must not be tidied away:
lang/*/govuk_alpha*.php— the sourceweb-uk's eleven translation catalogues are generated from, and read byEventsController,MemberDataExportServiceandStaticPublicPageContentService. Deleting it strips the live site's translations.web-uk/scripts/blade-route-inventory.frozen.json— the final Blade route inventory (707 routes, 707 matched, 0 missing).npm run route:matrixcompares against this snapshot, so the check still catches aweb-ukroute regression even though the codebase it originally compared against is gone.
Deploying: bash scripts/deploy.sh --with-webuk. The flag is mandatory — see
DEPLOYMENT.md. A guard on the server refuses a deploy that would
drop web-uk, because there is no working fallback any more.
Irish localisation status: both maintained frontends are current locally. Web UK's generated Irish catalogue has 39 namespaces and 9,348 strings with zero unreviewed English fallbacks, question-mark mismatches, or terminology violations. React has zero structural or aggressive-scan Irish gaps, and every one of its 737 intentional English-identical values is pinned by exact key, value, and review reason. These are automated completeness and reviewed- exception results, not a claim that every sentence has received independent native-speaker sign-off. Google Translate remains prohibited for Irish.
What the cutover cost: the fast rollback is gone. Until 2026-08-14, removing one
Define line from the Apache routes file sent every accessible address back to a
working Blade site in seconds. Blade is no longer in the release, so the only
rollback is to revert the removal commit and deploy again — roughly 15–20 minutes.
The owner accepted that trade explicitly.
History of the decision¶
Everything below is the record of how the takeover was decided and executed. It is kept for provenance. Where it disagrees with the status block above, the status block above wins — in particular, every statement below that Blade "is still deployed and still serving real members" was true when written and is now false.
The decision¶
On 2026-08-11 the owner decided that web-uk becomes the production
accessible frontend and the Laravel Blade accessible frontend retires.
Before that decision, web-uk was an uncertified candidate and Blade was the
deployed product. Documentation written in that period says so, and much of it
also prohibits replacing Blade. Those prohibitions were correct when written and
are now superseded by this page.
🔴🔴 BLADE IS NOW HISTORIC — React + Laravel are the sources of truth (owner decision, 2026-08-13, later the same day)¶
This SUPERSEDES the Phase A rule below, which made Blade the observable-behaviour specification. The owner's words:
"We can start forgetting about the blade version. I think it's falling behind, and you can document that it's now historic. We plan to retire it once we are 100% sure we have everything we need from it. I think the React frontend and the Laravel backend are now better sources of truth for what we need building."
The new model, in priority order:
- GOV.UK Design System and WCAG 2.2 are the presentation authority. How a page looks, announces itself, validates, and is navigated follows GDS. Where GDS and any internal precedent disagree, GDS wins. Every page polished to that standard.
react-frontend/defines WHAT a member can do — the feature set, the workflow, the states. It is the live product with the most complete behaviour.- The Laravel API defines the CONTRACT — methods, paths, payloads, status codes, auth, roles, module gates, side effects. This never changed and does not change now.
- Blade is HISTORIC. Read it only to recover something not yet obtainable from React or the API. It is no longer the arbiter of correct behaviour.
What this changes in practice:
- 🔴 A difference from Blade is no longer automatically a defect. Previously Blade was right unless the divergence was a recorded improvement; now the question is whether web-uk matches GDS, React and the API. Blade being different may simply mean Blade is behind.
- 🔴 The generated route matrix stops being a drift alarm and becomes coverage evidence. A route in Blade and absent from web-uk is now a QUESTION, not a gap — it may be something Blade has and the product no longer wants. Do not "close" such a gap without checking React and the API first.
- The rubric row "Observable Blade behaviour" is now misnamed for what it measures. It is left in place for continuity of the score, and its deductions still stand, but it should be re-scoped to "Observable product behaviour (React + API)" at the next rubric revision rather than silently reinterpreted.
- The web-uk ↔ Blade screenshot comparison set becomes a historical baseline, useful for spotting unintended change in web-uk, not a target to converge on.
🔴 SUPERSEDED 2026-08-17 — everything from here to the end of "The two frontends" below describes the state BEFORE 2026-08-14, when Blade was still serving members. Blade was deleted on 2026-08-14 and there is now exactly ONE accessible frontend,
web-uk. The instructions in the next few sections — "it is not deleted and not switched off", "do not remove its routes", "open them freely", "both are serving live traffic right now" — cannot be followed, because the files they refer to do not exist. The measured table under "What each surface ACTUALLY serves" is the current state.These sections are kept, not deleted, because they record the owner's freeze decision and because an agent who half-remembers them otherwise goes hunting for
accessible-frontend/and concludes the repository is damaged. Read them as history.
Blade is still deployed and still serving real members on the community accessible
domains and every /{tenantSlug}/accessible/... path. Historic means "no longer the
specification", not "switched off". Retirement remains a separate reviewed change, and
the owner's condition is explicit: once we are 100% sure we have everything we need
from it. Until then, do not delete it, do not remove its routes, and do not disable its
tests or build.
🔴 The Blade track is FROZEN — read-only reference (owner decision, 2026-08-13)¶
The 2026-08-11 decision said Blade would retire. On 2026-08-13 the owner stopped work on it, two days before retirement itself:
Blade is kept read-only, as reference for building
web-uk. It retires whenweb-ukis judged finished. No further build effort goes into Blade — all build effort goes into the new frontend.
What that means in practice:
- No new build work in Blade. No new pages, features, routes, fields, or
parity work in
accessible-frontend/orapp/Http/Controllers/GovukAlpha/. - Reading it is the point. It stays the observable-behaviour specification
web-ukis built against (see Phase A below), so its templates, controllers and tests are the reference material — open them freely. - Narrow exceptions still allowed, because it is still serving real members: a security fix, a fault making a live page unusable, or a mechanical repo-wide sweep it cannot be excluded from (SPDX, lint, translation parity, a dependency bump). Anything wider needs the owner.
- It is not deleted and not switched off. It still serves the community
accessible domains and every
/{tenantSlug}/accessible/...path. Its routes, tests and build stay in place until retirement is done as its own reviewed change.
🔴 This reverses the direction of the eight commits in the week to 2026-08-13 that added parity features to Blade (safeguarding tiers, linked-account activity views, the message-access consent loop). That work is done and stays; work of that shape must not be started in Blade again.
Retirement itself is still a separate, unstarted change — see the table below. Freezing the track is not retiring it.
The two frontends¶
| Laravel Blade accessible frontend | web-uk |
|
|---|---|---|
| Location | accessible-frontend/ plus app/Http/Controllers/GovukAlpha/ |
web-uk/ |
| Stack | Laravel Blade, rendered by the PHP application | Node/Express + Nunjucks + GOV.UK Frontend, consuming the Laravel HTTP API |
| Served by | The Laravel/PHP application container | Its own container, deployed |
| Status | Still deployed, serving the community accessible domains and every /{tenantSlug}/accessible/... path. Retires at the end of the changeover. |
Deployed and live. Took over accessible.project-nexus.ie on 2026-08-12. |
🔴 Both are serving live traffic right now. The cutover moved one host, not the
whole track. /version is the only way to tell which one answered a request:
web-uk returns {"service":"nexus-webuk",…} and Blade does not.
🔴 END OF THE SUPERSEDED RUN (see the banner above). The table and paragraph immediately above were true until 2026-08-14 and are false now: there is one accessible frontend,
web-uk, and it serves all three accessible hostnames./versionis still the way to tell what answered — but a response that is NOTnexus-webuknow means something is wrong, not that Blade answered. The uptime monitor asserts exactly that.
Both are separate from react-frontend/, which is the main product UI and is not
affected by this changeover.
Public URL shapes — both are preserved exactly¶
No public address changes. Two shapes exist and both keep working:
/{tenantSlug}/accessible/...on the shared host- slug-less paths on a community's own domain, resolved from the
Hostheader
🔴 How the community domain actually reaches the platform, because this was
mis-recorded as a risk and cost an unnecessary worry. There are two hops. The
browser sends Host: <community domain> to web-uk. web-uk then calls the
platform with the upstream host — a container name — and forwards the community
domain as Origin. TenantBootstrapController resolves tenants.domain from
HTTP_ORIGIN, deliberately only when the Host resolved to the master tenant, which
a container name does. Verified 2026-08-11 by placing an echo server between the two
and reading what was actually sent. So the question "does Node's fetch forward a
custom Host?" was the wrong one: it does not, and must not.
Legacy /{tenantSlug}/alpha/... paths permanently redirect to /accessible/...
and remain redirect-compatibility only.
🔴 Qualified 2026-08-17 — that redirect no longer works everywhere. It works on
every hostname proxied to web-uk (all three accessible hosts), because web-uk
handles it itself in web-uk/src/middleware/tenant-routing.js. It does not work on
the API host (api.project-nexus.ie) any more: the redirect there lived in
routes/govuk-alpha.php, which was deleted on 2026-08-14. The sentence above used to
claim the redirect applied without qualification. Nothing member-facing depends on the
API-host redirect — members reach the accessible site through
accessible.project-nexus.ie — but an old /alpha bookmark on the API host now 404s
instead of redirecting.
The internal Laravel translation files still say govuk_alpha; that is an internal
name, not a public one. (The GovukAlpha namespace and govuk-alpha.* route names are
gone — only lang/*/govuk_alpha*.php survives, and it must not be deleted.)
🔴 What each surface ACTUALLY serves — measured 2026-08-17¶
Read this table before any claim about what serves an accessible address. Every row was probed live, not inferred, because several sentences in these documents were wrong on exactly this point.
| Surface | Served by | Evidence |
|---|---|---|
accessible.project-nexus.ie (+ /{slug}/accessible/... on it) |
web-uk | /version returns {"service":"nexus-webuk","release":"5afb43ff73da","color":"blue"} |
accessible-uk.timebank.global (root, slug-less) |
web-uk | same /version response. Community timebanking-org. |
accessible-minehead-and-coast.timebank.global (root, slug-less) |
web-uk | same /version response. Community minehead-and-coast-timebank. |
api.project-nexus.ie/{slug}/accessible |
nothing — Blade is gone | the Blade routes that answered here were deleted on 2026-08-14. Not a member-facing path; the React utility bar never linked to it. |
/{slug}/accessible on the MAIN app domains (app.project-nexus.ie, timebanks.us, pairc-goodman.com) |
the React SPA answers | returns React's shell (id="root"), title "NEXUS — Community Timebanking Platform". There is no React route for accessible, so it lands on a client-side 404. |
Apache reaches web-uk through Define NEXUS_WEBUK_PORT in the production routes file —
3500 when blue is active, 3600 when green is. The active colour on 2026-08-17 was
blue. The PHP app ports (8090 blue, 8190 green) must never be used for accessible traffic.
🔴 What this table said before, and why it changed — do not restore the old rows.
Until 2026-08-17 this table was headed "measured 2026-08-14" and recorded Blade as
serving accessible-uk.timebank.global, accessible-minehead-and-coast.timebank.global
and api.project-nexus.ie/{slug}/accessible. Those rows described the state before
the 2026-08-14 cutover, when Blade still held the two community domains and the API-host
paths. They are kept in this note as history because half-remembering them is how an
operator ends up proxying an accessible domain to the PHP app and taking the live site
down. The cutover moved all three hosts to web-uk on 2026-08-14 and deleted Blade.
🔴 Two older claims in this document were also FALSE and remain corrected:
- It said Blade served "all
/{tenantSlug}/accessible/...paths". It never did — on the main app domains that path is swallowed by the React SPA, and that is still true today withweb-ukin place. - It said no community had an accessible domain. Two do, and both are live. That claim came from reading the LOCAL snapshot instead of production.
Members do not reach the React 404, because the utility-bar link on every tenant's
React frontend points at accessible.project-nexus.ie/{slug}/accessible (built by
buildAccessibleFrontendUrl()), which is web-uk. An old bookmark of /{slug}/accessible
on a main domain would land on the React 404 — recorded, low priority, not a member-facing
regression.
🔴 Which phase are we in — Phase B, the takeover is COMPLETE¶
Phase B, since 2026-08-14: Blade is decommissioned and deleted. web-uk owns every
accessible address. Therefore:
web-ukowns browser behaviour. GOV.UK Design System + WCAG 2.2 are the presentation authority,react-frontend/defines what a member can do, and the Laravel API defines the contract — see the 2026-08-13 section above.- The route matrix under
web-uk/docs/generated/is a historical record, not a live drift alarm. It compares against the frozen snapshotweb-uk/scripts/blade-route-inventory.frozen.json(707 routes), so it still catches aweb-ukroute that disappears. - The Laravel API is the contract source of truth for methods, paths, request and response shapes, status codes, auth, roles, modules and side effects. That never changed.
🔴 This heading and section used to read "Which phase are we in — Phase A" and "Phase A: Blade is still deployed", saying the cutover of 2026-08-12 did not end Phase A and that Blade remained the observable-behaviour specification. That was true when written and is false now: Blade was deleted on 2026-08-14, which is exactly the "Blade is decommissioned" event that ends Phase A. The old wording is recorded here rather than deleted because an agent or operator who half-remembers it goes looking for a Blade site that no longer exists.
Anything you read elsewhere that says "Blade is the source of truth" without qualification is superseded — it means the old Phase A rule described above.
Where the changeover stands¶
| Piece | State |
|---|---|
| Route and page coverage | Complete. 707 of 707 Laravel accessible routes matched, 0 missing. The last gap — recording event attendance from a signed check-in code — was closed on 2026-08-11. |
| Legal acceptance enforcement | Built. Server-side enforcement, a web-uk interstitial, and a mobile acceptance screen. |
| Bot protection on the contact form | Built. The challenge renders on the contact form, and the platform-side configuration fault that silently disabled it is fixed. |
| Cookie-consent record keeping | Built. Anonymous visitors' choices are now recorded, as Blade already did. |
| Deployment path | Built, and locally rehearsed 2026-08-11. Container service, deploy-script support, /version, Apache include, domain inventory with a drift probe, and guards all exist. The production image was run against the local platform and proved: it does not listen at all until Redis is reachable (so a broken deploy aborts); /health then returns OK; /version returns {"service":"nexus-webuk",…} — the exact string the deploy smoke test matches; and a real accessible page renders at 200 in 25 KB. Deployed to the server and cut over on 2026-08-12, with twelve post-cutover checks passing; the rollback path is documented and verified on the real server, and the guard that stops an ordinary deploy reverting the switch has been armed. From now on a deploy must pass --with-webuk or it refuses to run. |
| Manual accessibility sign-off | Partly done. Keyboard, focus and reflow evidence exists. Screen-reader sign-off needs a human. |
| Blade retirement | Done, 2026-08-14. Blade was deleted and the deletion is deployed. 🔴 This row read "Not started, and now the only remaining phase-ending step" until 2026-08-17; that is superseded. |
Current score: 873/1000 under rubric WEBUK-W2-PROD-R1 (rescored 2026-08-13,
651 -> 710 -> 745 -> 730 -> 830 -> 836 -> 845 -> 851 -> 867 -> 873). See the scoring
table below before comparing that with any earlier number.
🔴 This line read 787 for part of 2026-08-13, which was wrong and was never a real
score. 787 was an inflated figure produced by awarding credit for fixing defects that
had never been deducted; the honest figure at that moment was 730. It was corrected in
the scoring document but NOT here, because check-doc-scores.mjs validates the marker
keys and the rubric column — it cannot see a number written in prose on this page. If
these two documents ever disagree again, the scoring document wins.
🔴 Do not restate that number here from memory. This page carried 640 and
592 simultaneously for the same rubric until 2026-08-13, while the canonical
document said 651. scripts/check-doc-scores.mjs could not catch it: the gate
cross-checks values carried in machine-readable doc-consistency comment markers,
and both numbers here were bare prose with no marker. Read the score from
web-uk/docs/CURRENT_WEBUK_PRODUCTION_STATUS.md, which is the only scoring
source, and quote it in one place only. Adding a marker to this page is the
wrong fix — the gate will demand it be registered, and a second registered home
for one score is how the disagreement started.
Prerequisites — six resolved, one still needs an owner answer¶
✅ Resolved¶
- Spare memory on the production VM — MEASURED 2026-08-11, and there is room.
The VM has 16 GB. Idle it uses 6.6 GB with 9.3 GB available. A deploy peaks at
roughly 12.3 GB, because the React image build is given a 4 GB allowance and
builds at the same time as the PHP image, while both colours stay running — so
about 3 GB is spare at the worst moment.
web-ukwas then measured directly rather than estimated: 66.5 MB idle, 71.3 MB peak across ~260 requests over ten distinct templates, with the server process at 123 MB. Its limit is set to 384 MB per colour, not the 512 MB originally planned — the measurement did not justify it. 🔴 One separate finding worth knowing: the only out-of-memory kill on that machine (6 August) was the page-prerendering worker hitting its own 3 GB container limit, not the host running out. It sits at 99.99% of that limit permanently. More host memory would not have prevented it, and it has nothing to do withweb-uk. - Two free host ports — 3500 (blue) and 3600 (green). Checked against
the API ports (8090/8190), frontend ports (3000/3400/3100) and
web-uk's dev port (5180); a test asserts they stay distinct. - A Redis database index that is not 0 — index 4. The Laravel cache store
issues a flush, so sessions on index 0 would be destroyed by
php artisan cache:clear, signing out every accessible-frontend user. The service refuses to start without this variable set. -
The list of community accessible domains — no longer an owner task.
scripts/list-accessible-domains.shproduces it read-only from the database, and--checkprobes each hostname's/versionto report which frontend is actually serving it. -
The production container map — RECOVERED 2026-08-11, and the hold it describes is already satisfied. Several documents make production work conditional on
.claude/production-containers.md, which the 2026-08-09 monorepo move did not bring across. It was not lost: it was still in the previous ASP.NET checkout on the development machine and has been restored to.claude/, which is gitignored — so it stays machine-local rather than entering the public repository, exactly as it was before. It contains no credentials and no IP addresses: it is a map of which container is which, per-stack deploy rules, the recorded blue/green pair (dated 2026-05-12, marked "verify live before use"), datastores, and things not to recreate. 🔴 The important part: its "Web UK deployment hold" is narrower than the phrase suggests. It forbids deployingweb-ukfrom the ASP.NET production Compose path, pointed at the ASP.NET backend, because that backend is uncertified for an unchanged accessible frontend. The deployment path built on 2026-08-11 does neither — it deploys from the Laravel blue/green stack withLARAVEL_BASE_URLpointed at the same-colour Laravel container. The hold's condition is met by design. Because the map is machine-local, a fresh clone still will not have it. If that matters, supersede it with a section in DEPLOYMENT.md — an owner decision, since it would make the container topology public. -
Error reporting — DONE 2026-08-11. Sentry project
nexus-webukcreated in the existing organisation, matching thenexus-php/nexus-reactnaming. 🔴 The project was only half the job:web-ukhad no Sentry integration at all, so theSENTRY_DSNthe compose overlay passed was read by nothing. The SDK is now wired in, privacy-matched toconfig/sentry.php(no PII, query strings and cookie headers scrubbed), with health and version endpoints ignored so machine traffic does not flood the quota. Verified end to end by sending a real event and confirming it arrived asNEXUS-WEBUK-1, then resolving it. The release tag isnexus-webuk@<commit>, matching the other two — without that exact shape the service would have been invisible to the 30-minute post-deploy error watch, which now counts it as an optional third project. The DSN is recorded in.secrets.local/sentry.envand was added to/opt/nexus-php/.envon the server on 2026-08-11 — appended only, after a backup (.env.bak-pre-webuk-sentry-20260811-163656), verified as present exactly once with a value hash matching local, and with the rest of the file proven byte-identical to the backup. It is inert untilweb-ukis deployed.
The three session variables were installed on 2026-08-11. Without them the
overlay refuses to load and a deploy aborts, because
compose.webuk.bluegreen.yml declares them with Compose's ${VAR:?} form so a
deployment cannot boot with a guessable session secret.
| Variable | Installed as |
|---|---|
WEBUK_COOKIE_SECRET |
64 hex characters, generated on the server |
WEBUK_SESSION_SECRET |
64 hex characters, verified different from the cookie secret — the image refuses to start if they match |
WEBUK_SESSION_REDIS_URL |
redis://nexus-php-redis:6379/4 |
🔴 Why index 4 and never 0, now confirmed with numbers rather than
reasoning: production Redis has 16 databases, db0 holds 521 keys — the
Laravel cache — and php artisan cache:clear issues FLUSHDB. Sessions on
index 0 would be destroyed by an ordinary cache clear, signing out every
accessible-frontend user. db4 was verified empty.
Both secrets were generated on the server with openssl rand -hex 32, so
they never crossed the network and exist in only one place. Hex is deliberate: a
$ or # inside a value would be reinterpreted by Compose interpolation or env
parsing. Appended after a backup
(.env.bak-pre-webuk-secrets-20260811-164701), verified as one occurrence each
with the correct length and the two proven distinct, and diff confirmed a pure
append. There is no local copy — nothing on the development machine needs
them, and the fewer places they exist the better.
Still needed from the owner¶
- Whether to publish per-tenant accessible domains in the public uptime target list.
🔴 Also outstanding, and not an owner decision¶
The Apache Define / <IfDefine> behaviour that makes rollback cheap is
rehearsed on Apache 2.4, but not yet on the production Apache build. The
accessible vhost include falls back to the PHP port when NEXUS_WEBUK_PORT is not
defined, so that a rollback to a release predating web-uk does not fail its own
configuration test and thereby abort the rollback.
- Rehearsed 2026-08-17 by
scripts/test/rehearse-bluegreen-rollback.sh, a disposable harness that drives the realwrite_apache_routes()function and the real accessible vhost template against a throwawayhttpd:2.4-alpinecontainer (no production, no Cloudflare, nosystemctl). All 11 checks pass: the route swap is accepted by a realapachectl configtest+ graceful reload; a colour switch moves live traffic; a rollback withNEXUS_WEBUK_PORTabsent still passes configtest via the<IfDefine !...>arm and routes to the PHP port; and a bad config is rejected with the previous route file auto-restored. This confirms the logic. - Still outstanding: the same
apachectl configtest, in both states, on the real production Plesk Apache build. It is now an expected pass rather than a leap of faith, but it must still be run before any cutover — not discovered during a rollback.
🔴 RETIRING BLADE — the assessment (2026-08-14)¶
Scored 5/50. This is the largest single item left in the readiness score, and it is much closer than the score suggests, because what Blade still serves turned out to be two hostnames, not a whole URL space.
What retirement actually requires¶
Blade serves exactly three things (see the table above). Two of them are community hostnames; the third is the API host, which no member is pointed at.
Step 1 — the code prerequisite is DONE but NOT DEPLOYED. Both community domains are
accessible_domain values, and until 2026-08-13 web-uk could not resolve them at all:
TenantBootstrapController matched tenants.domain only, so a member arriving at either
address through web-uk would have reached the community chooser instead of their own
community. Fixed, with two regression tests proven to fail on the old query — but it is
sitting in unpushed commits. Cutting either domain over before that fix deploys would
break it for a real community.
Step 2 — repoint two vhosts. Each domain is configured on the SERVER, not in this
repository, at
/var/www/vhosts/system/<domain>/conf/vhost_ssl.conf, and currently proxies to
http://127.0.0.1:${NEXUS_API_PORT} (8090 — the Laravel/Blade app). The template to copy
is accessible.project-nexus.ie, which proxies to ${NEXUS_WEBUK_PORT} (3500) inside an
<IfDefine NEXUS_WEBUK_PORT> arm with a Blade fallback — the arrangement that makes
rollback cheap, and which is already verified against the production Apache build.
🔴 These files are not in the repo, so a rebuild loses them; the same trap is already
recorded for pairc-goodman.com.
Step 3 — soak, then remove. Only after both domains have run on web-uk for a soak
period does deleting accessible-frontend/, app/Http/Controllers/GovukAlpha/ and the
govuk-alpha routes become a separate, reviewable change.
The evidence that makes this low-risk¶
Blade's accessible frontend has essentially no human traffic. Measured on the active
colour over 7 days to 2026-08-14: 1,070 requests to /accessible paths, of which 1,065
were a single crawler (jscrawler/0.1), 2 were my own curl probes, 1 was
scrape_central/1.0, and 2 were generic browser agents with no session behind them.
🔴 State that honestly rather than as "nobody uses it": the Apache access log has no vhost field, so this total cannot be split per hostname, and a handful of requests are indistinguishable from a real person visiting once. What it does establish is the order of magnitude — there is no measurable member population on Blade's accessible pages.
What is NOT a blocker, and was previously listed as one¶
- Route parity. 707 of 707 Laravel accessible routes are matched by web-uk. Under the 2026-08-13 decision the matrix is coverage evidence, not a drift alarm.
- "Still needed from Blade as a reference." The freeze made Blade a read-only reference for BUILDING web-uk. Whether anything more is needed from it is an owner judgement, and the honest answer today is that the remaining web-uk gaps are translation strings and human sign-off, neither of which Blade can supply.
What genuinely blocks it¶
- The
accessible_domainfix must be deployed. Non-negotiable and first. - Both community domains must be cut over and soaked. Two real communities.
- An owner decision to retire, which is not a technical step. Freezing is not retiring, and this document has said so since the freeze.
- The blue/green rollback has never been exercised on production — 0 of 322 recorded
deploys used the
rollbacksubcommand. That matters more here than for an ordinary deploy, because the cheap-rollback arm in those vhosts is the safety net for a cutover. - Partly retired 2026-08-17: the rollback's route-switch logic is now rehearsed off
production by
scripts/test/rehearse-bluegreen-rollback.sh(11/11 pass — see theDefine/<IfDefine>note above). What remains genuinely unexercised is a full end-to-endrollbackon the real two-colour production stack (worker draining, health gating, public-host smoke, Cloudflare purge), which needs a live deploy window and explicit owner authorisation.
Recommended order¶
Deploy the fix → repoint accessible-minehead-and-coast first (the smaller community) →
soak → repoint accessible-uk → soak → rehearse a rollback while there is still something
to roll back to → then, and only then, propose deleting the Blade tree.
Documents that carry a status claim¶
Read this page first; then the specific document for its own subject. Paths under
web-uk are given as text rather than links because the published documentation
site builds only docs/.
| Document | What it is authoritative for | Watch out for |
|---|---|---|
| This page | The decision, the phase, the URL shapes, the prerequisites | — |
web-uk/docs/CURRENT_WEBUK_PRODUCTION_STATUS.md |
The current score and its rubric | The only current scoring source |
web-uk/docs/CURRENT_LARAVEL_FIRST_PARITY_STATUS.md |
The retired W1 audit trail | Retired. Its 663/1000 is not current and must not be quoted as such |
web-uk/docs/generated/accessible-route-matrix.* |
Route coverage | Generated. Regenerate rather than editing |
web-uk/docs/generated/frontend-api-consumer-ledger.* |
Which platform endpoints web-uk calls, and whether tests prove each request |
Generated |
web-uk/docs/MANUAL_ACCESSIBILITY_EVIDENCE.md |
Directed manual and assistive-technology checks | An entry is evidence for exactly the page, browser, input method and viewport listed — not a conformance claim |
web-uk/docs/PRODUCTION_RELEASE_RUNBOOK.md |
The release procedure | Its hold references the missing file in prerequisite 5 |
web-uk/CLAUDE.md and web-uk/AGENTS.md |
Working rules inside web-uk |
Written during the candidate period; the takeover supersedes their replacement prohibition |
| PLATFORM-MONOREPO.md | Repository boundaries and deployment isolation | Its ASP.NET warnings remain in force |
| DEPLOYMENT.md | How the platform deploys | Describes the Laravel/React path. The web-uk path is built and was used on 2026-08-12; every deploy must now pass --with-webuk |
aspnet-backend/docs/CURRENT_ASPNET_CONTRACT_STATUS.md |
The ASP.NET backend score | A different rubric. Never add it to the web-uk score |
🔴 On the ~185 lines elsewhere that still call web-uk a candidate. They were
left as written, deliberately. They are dated evidence records carrying commit
SHAs: rewriting them would destroy the audit trail, "certified" is a property of a
rubric row rather than of a page, and a find-and-replace would also corrupt the
legitimate uses where "candidate" describes Blade's behaviour. Each affected
document instead carries one short status header pointing here, and the retired W1
document redirects readers from its own first screen — so a pointer to it lands on
a redirect rather than on a stale number.
Scoring surface¶
Four separate scores exist in this repository. Each names its own rubric, and a CI check refuses a score marker that does not.
| Score | Rubric | Value | Measures | Status |
|---|---|---|---|---|
web-uk production readiness |
WEBUK-W2-PROD-R1 |
873/1000 | Is web-uk safe to serve, and can Blade retire? |
Current — read it from web-uk/docs/CURRENT_WEBUK_PRODUCTION_STATUS.md, never from here |
web-uk Laravel-first parity |
WEBUK-W1-FIXED-R1 |
663/1000 | How closely does the candidate clone Blade? | Retired 2026-08-11 |
| ASP.NET journey equivalence | see its own status doc | see its own status doc | Does the product work on the ASP.NET edition? | Active — read it from aspnet-backend/docs/CURRENT_ASPNET_CONTRACT_STATUS.md, never from here. Development resumed 2026-08-14; the rubric was replaced 2026-08-21 and older totals are not comparable |
| Documentation health | DOCS-HEALTH-D3-R1 |
1000/1000 index | Documentation and handoff quality | Not a product score |
🔴 The current 873 exceeds the retired 663, and the two are still not comparable. The W1 rubric scored no deployment path, no cutover, no rollback and no Blade retirement. Those 200 points enter the new denominator for the first time and start near zero, while three previously-measured areas improved. The mandatory mapping table in the W2 document accounts for every W1 row. Do not convert one number into the other, and do not describe either as "nearly finished".
What is still fenced off¶
The takeover lifts the pause on web-uk work. It lifts nothing else.
- The ASP.NET backend stays paused, and its database boundary stays closed. Its live database has had no successful backup since 2026-03-08 while the application runs migrations on every start, so restarting that service can irreversibly change live data with nothing to restore from. See PLATFORM-MONOREPO.md.
- Nothing is deployed without explicit authorisation. Building the deployment path is not permission to use it.