Skip to content

Project NEXUS Architecture

Last reviewed: 2026-10-25

New-installation scope and implementation assessment — 25 October 2026

The owner clarified that new installations must work on either backend with both web frontends unchanged. Laravel remains supported. Existing-community data transfer, a shared live database and simultaneous cross-engine synchronization are not part of this stage. Fresh database, first tenant/admin, configuration, workers, media, install/recovery and all required current client workflows are included. Audit and planning are authorized; implementation remains paused. See the costed restart scope. The audit contains an unstarted work breakdown and verification requirements; it is not authority to implement or deploy.

Audit reconciliation — 25 October 2026 (two passes)

The owner authorized a code-led ASP.NET/Laravel comparison against both unchanged web frontends and documentation updates on 25 October. This is a narrow exception to the September pause, not a resumption. ASP.NET is not currently interchangeable; earlier completeness or active-delivery statements are superseded by the current audit.

Current readiness: code-led contract audit. Development remains paused; this audit/doc update does not authorize implementation, CI reactivation, container restart or deployment.

Last reviewed: 2026-08-15 Platform version: 3.2.0

This document is the maintained architecture map for Project NEXUS. It is intentionally compact: use it to understand the runtime boundaries, primary code paths, and documents to read next.

System Shape

Project NEXUS is a multi-tenant community platform for timebanking and adjacent community-exchange workflows. The production system is a Laravel 12 API/backend, a React 19 primary frontend, the Web UK HTML-first accessible frontend, MariaDB, Redis, Meilisearch, Pusher, Firebase Cloud Messaging, and supporting deployment/observability tooling.

The repository also contains an ASP.NET Core 10 second edition with its own PostgreSQL database and RabbitMQ broker. It is a committed deliverable, driven by public-sector buyers who require a .NET application stack as a condition of procurement (ADR-0003) — not a research track. It is not yet certified and has no deploy path from this repository. Its production eligibility depends on journey equivalence at consumed boundaries (ADR-0004), operational readiness including working backups, and an explicit owner decision; traffic growth alone is never a promotion trigger.

flowchart TD
    subgraph Clients
        U[Members & admins]
        M[Mobile PWA / native wrapper]
    end
    U -->|app.project-nexus.ie| RC[React 19 SPA<br/>react-frontend/]
    U -->|accessible.project-nexus.ie| AC[Web UK accessible frontend<br/>web-uk/]
    M --> RC

    RC -->|JSON / Bearer + CSRF| API[Laravel 12 API<br/>routes/api.php]
    AC -->|Laravel API by default| API

    API --> SVC[Domain services<br/>app/Services]
    SVC --> DB[(MariaDB 10.11)]
    SVC --> RED[(Redis 7)]
    SVC --> MEI[(Meilisearch)]
    SVC --> PUSH[Pusher WebSockets]
    SVC --> FCM[Firebase Cloud Messaging]

    subgraph Deployment
        BG[Blue/green switch<br/>scripts/deploy]
    end
    BG -.atomic Apache route swap.-> API

    subgraph SEC ["SECOND EDITION - committed, not yet certified, no deploy path from this repo"]
        ASP[ASP.NET Core 10 API<br/>aspnet-backend/]
        PG[(PostgreSQL 16<br/>separate database)]
        MQ[RabbitMQ 3.13]
        ASP --> PG
        ASP --> MQ
    end
    AC -. future, uncertified .-> ASP
    ASP -. must reproduce .-> API
    style SEC stroke-dasharray: 5 5

Runtime Boundaries

Surface Primary path Responsibility
React app react-frontend/ Main member UI, current admin UI, PWA shell, translated client experience.
Accessible frontend web-uk/ Production HTML-first tenant UI built with Express, Nunjucks, and GOV.UK Frontend.
Laravel API routes/api.php, app/Http/Controllers/Api/ JSON API for React, mobile, integrations, and admin operations.
Domain services app/Services/ Business rules for listings, exchanges, federation, volunteering, messages, notifications, reporting, and adjacent modules.
Data model database/migrations/, database/schema/mysql-schema.sql, migrations/ Current Laravel migrations, schema dump, and historical SQL migration record.
Public web root httpdocs/ Apache entrypoints, health endpoints, version endpoint, and compatibility routing.
Legacy views views/ Retired PHP UI except the documented live email and module-404 exceptions.
ASP.NET backend (secondary) aspnet-backend/ Complete second backend: ASP.NET Core 10, EF Core, its own PostgreSQL 16 database, RabbitMQ, 165 migrations, 3,386 tests. Must reproduce Laravel's externally observable contract. Shares no database with Laravel.

The ASP.NET backend remains stopped and has no deploy path from this repository. Web UK is production and deploys only through the explicit --with-webuk path. See PLATFORM-MONOREPO.md for the isolation that preserves those distinct roles.

Tenant and Feature Model

All business logic must preserve tenant isolation. PHP code should resolve tenant scope through the established tenant context/middleware patterns, and React code should use the tenant context/hooks already present in react-frontend/src/.

Feature availability is tenant-configured. User-facing routes, API actions, accessible frontend pages, notifications, search entries, and navigation should all check the same feature gate rather than assuming a module is globally enabled.

Authorisation Model

Authorisation has these access levels — member, broker/coordinator, tenant admin, tenant super admin, global super admin, and global super admin with god status — expressed as a users.role string plus boolean flags, with app/Support/Authorization/AdminTier.php as the canonical predicate. A broker is an operational role with its own application and its own routes, not a junior administrator; AdminTier deliberately excludes it from the admin tier.

The reach rule (owner, 12 October 2026): a tenant admin acts on its own tenant; a tenant super admin acts on its own tenant and every tenant below it in the hierarchy, never one above or beside it — and a tenant super admin on the master tenant (id 1) has no special level; global super admins and god act platform-wide. Inside the super-admin panel, app/Core/SuperPanelAccess.php resolves a level: master (global super admin or god only; platform-global) or regional (a tenant super admin: its own hub tenant and its descendants only, enforced by a trailing-slash-anchored materialised-path prefix match). Any cross-tenant action must check both the source and the destination tenant. Outside the panel, the HTTP layer (TenantContext, Authenticate, via app/Support/Authorization/CrossTenantEntry.php) pins every account to its home tenant except a global super admin or god (any tenant) and a tenant super admin entering a tenant below its own for administration requests (/api/v2/admin/*) only; the React app does not yet take a tenant super admin there — see ROLES-AND-PERMISSIONS.md.

A second permission/RBAC schema (roles, permissions, user_roles, user_permissions, with per-organisation scoping) coexists with the tier model and is used for a narrow, specific set of capabilities. It has not replaced the tier model, and a grantable permission slug is not necessarily an enforced one.

See ROLES-AND-PERMISSIONS.md.

Safeguarding, guardian relationships and consent form a substantial subsystem of roughly thirty tables spanning four largely independent mechanisms: staff-created guardian↔ward assignments, per-event guardian consent for minors, per-opportunity guardian consent for volunteering, and member-to-member linked accounts. Consent records are versioned and hashed with provenance; the per-event implementation additionally uses encrypted guardian identity, single-use expiring tokens, and an append-only history table protected by database triggers.

Concern-raising is separate again: safeguarding_reports is a case-management workflow with severity-driven SLAs, escalation and an append-only action log, distinct from generic content reporting. There are currently four independent reporting systems across the platform.

Two architectural rules follow from how this is built. A relationship record is never itself authorisation — a guardian gains no capability unless an explicit check grants it. And a permission must not be presented to users unless something enforces it.

See SAFEGUARDING-AND-CONSENT.md.

Reporting and Analytics

Reporting is not a single subsystem. There are roughly twenty-five admin-facing report, analytics and dashboard surfaces spread across the tenant admin panel, the broker panel, the caring-community panel and the super-admin panel, with per-module analytics living alongside their own modules rather than in a shared reporting area. Date-range handling, export parameters and export formats are decided per surface rather than centrally, and only a minority accept an arbitrary calendar range.

Anything new in this area should reuse ReportExportService and, critically, send the same filters to the export endpoint that the screen is displaying — an export whose figures cannot be reconciled with the screen is worse than no export.

User Interfaces

The React frontend is the primary UI. It uses React 19, TypeScript, HeroUI v3, Tailwind CSS 4, Lucide icons, translation namespaces, CSS tokens, and the local motion shim. New user-facing UI belongs here unless it is specifically part of the accessible frontend.

The production React frontend lives under react-frontend/, the production accessible client lives under web-uk/, and both speak the Laravel API contract by default. The ASP.NET second edition lives under aspnet-backend/. Its work must make ASP.NET reproduce the behaviour Laravel's clients consume — never weaken a frontend, never introduce backend-specific branches, and never return a success-shaped response over missing work. See REACT-DUAL-BACKEND.md and PLATFORM-MONOREPO.md.

The accessible frontend is a maintained second surface, not legacy PHP. It uses GOV.UK Frontend markup/classes/Sass/JS with Project NEXUS branding and attribution. Its controller and translation paths must stay isolated from the React app while preserving the same tenant, module, auth, and AGPL attribution rules.

Backend Organization

Laravel is the sole production API and the canonical behavior source of truth. Controllers should stay thin and delegate business rules to services. Services should follow existing static/service patterns, tenant scoping, and database conventions already used under app/Services/. ASP.NET is a committed second edition with a commercial driver (public-sector buyers who require a .NET stack), not an assumed successor to Laravel; it is not production-deployable until it passes journey certification plus the go-live gate in ADR-0003. What equivalence does and does not require is defined in ADR-0004: a response field is in scope only if a client reads it.

New schema changes should use Laravel migrations in database/migrations/. The root migrations/ directory is historical; do not add new legacy SQL migrations.

Cross-Cutting Requirements

Requirement Enforcement
Translations End-user React text uses t(...); email/notification PHP text uses translation keys and recipient locale wrapping.
Tenant isolation Middleware, tenant context, scoped queries, and feature gates.
Open-source attribution AGPL Section 7(b) footer/about attribution and NOTICE terms.
Version consistency VERSION plus npm run check:version.
Documentation hygiene docs/README.md, DOCUMENTATION.md, plus npm run check:docs.
Changelog discipline CHANGELOG.md under [Unreleased], then npm --prefix react-frontend run copy-changelog.

Operations and Deployment

Production runs on Apache/Plesk/Azure using the blue/green deployment engine under scripts/deploy/. Do not deploy without an explicit user instruction. The maintained deployment reference is DEPLOYMENT.md; incident response and observability references are RUNBOOK-INCIDENTS.md, MONITORING.md, SLO.md, and SENTRY.md.

Local development is Docker-first: the Laravel/PHP app, MariaDB, Redis, and Meilisearch run from Docker Compose, while the default React workflow uses native Vite for fast HMR and proxies /api to the Docker PHP app. The Docker frontend profile exists for container-specific frontend checks.

Documentation Sufficiency

The maintained documentation covers setup, topology, deployment, incident response, monitoring, SLOs, Sentry, API reference policy, testing, security scanning, federation, custom domains, accessible frontend constraints, contributor terms, versioning, and changelog discipline. 24 curated module guides live under docs/modules/; federation, mobile, and the accessible frontend use dedicated cross-cutting references linked from MODULES.md. One live product module is still uncovered: Caring Community (feature gate caring_community, default off) has 3 API controllers, 49 services, 227 routes, a member SPA at caring/*, admin pages and scheduled commands, but no guide — it is listed in MODULES.md with its code paths only.

The ongoing risk is implementation drift. Update the relevant guide and machine-readable API contract in the same change as behaviour, keep every maintained page indexed from README.md, and run the documentation, version, and changelog checks before release.