<!-- converted from CostusWorx_Feature_Overview_UK.docx -->

CostusWorx
Retirement Decision Engine
Feature Overview Document



# 1. Executive Summary
CostusWorx UK is a web-based retirement income sustainability platform purpose-built for the UK financial advisory market. It enables FCA-authorised advisers to run actuarial-grade Monte Carlo simulations against real FTSE All-Share, UK Gilts, SONIA, and ONS CPI historical data - replacing manual Excel models with a structured, auditable, UK GDPR-compliant workflow.

The platform covers the complete advisory cycle: client onboarding with UK GDPR consent gating, multi-asset scenario construction across UK tax wrappers (SIPP, ISA, workplace pension, State Pension), probabilistic retirement income simulation, confidence-band charting, PDF and CSV report export, fund data management via ISIN/SEDOL, and multi-tier subscription billing via Stripe.

Key differentiator: All Monte Carlo runs bootstrap from 25 years of actual UK market returns (2000-2024). Cross-asset correlations are preserved by resampling historical year-tuples rather than applying parametric (log-normal) assumptions - a methodology aligned with actuarial bootstrapping practice. HMRC Income Tax is computed inside every simulation run using a fixed-point gross-up iteration, ensuring net income targets are met exactly.


# 2. System Architecture
CostusWorx follows a layered, object-oriented architecture with strict tenant isolation. Every layer enforces the tenant boundary from the HTTP router through the repository layer down to individual database queries.

## 2.1 Multi-Tenancy Model
- Every MySQL table carries a tenant_id column.
- BaseRepository always prepends WHERE tenant_id = :tenantId to every query.
- Tenants are resolved from the HTTP session at request time.
- FeatureGate enforces plan-level limits at the controller boundary.
- All PII encrypted at-rest using AES-256-GCM (UK GDPR Art.32). NI numbers stored in ni_number_enc.

## 2.2 Technology Stack


# 3. Monte Carlo Simulation Engine
The simulation engine implements historical bootstrapping - resampling complete annual-return tuples from real UK market history - to produce probability-weighted retirement income sustainability projections.

## 3.1 Bootstrapping Methodology
- Resamples complete year-tuples (equity, bonds, cash, inflation) preserving inter-asset correlations.
- Each simulation run independently samples with replacement from 25 years of UK market history (2000-2024).
- No parametric distribution assumed - outcomes reflect actual fat tails and crisis years (2002, 2008, 2020).
- Default: 500 runs (Starter/Professional), 1,000 runs (Enterprise).
- Per-fund bootstrapping: when an asset links to a fund via ISIN/SEDOL, the engine uses that fund's own annual return history.

## 3.2 UK Market Data Sources

## 3.3 Monthly Cashflow Model
The engine runs 12 sub-periods per simulation year. Each month: (1) withdraw the monthly target gross amount, (2) apply that month's compounded market returns to remaining assets. This sequence-of-returns model is more conservative than year-end withdrawal and more realistic for UK retirees drawing monthly income.

## 3.4 HMRC Income Tax Integration
The annual gross withdrawal is computed once per year using HmrcTaxCalculator::grossUp(). This solves G - tax(G) = N by fixed-point iteration (converges in 4 passes, bounded at 50). State Pension income is subtracted from the annual target before the gross-up calculation, so the portfolio only needs to fund the shortfall.


## 3.5 Failure Definition
A run is marked failed when the portfolio delivers less than 80% of the target net income for 3 consecutive years, OR when the portfolio value reaches zero. The fraction of runs that do NOT fail is the Success Rate.

## 3.6 Simulation Outputs


# 4. Risk Profile Behavioural Models


# 5. UK Asset Types and Portfolio Management
## 5.1 Supported Asset Types

## 5.2 Withdrawal Strategy - Priority Drawdown
PriorityWithdrawal implements WithdrawalStrategyInterface. Assets are drained in priority_order set by the adviser. State Pension income is subtracted from the annual target before any portfolio draw. The remaining shortfall is drawn from wrappers in order.

## 5.3 Phase 3 - Planned Additional Asset Types
- LISA (Lifetime ISA) - 25% government bonus; penalty on non-qualifying withdrawal
- DB Pension Income - defined benefit scheme as guaranteed income stream
- Guaranteed Annuity - fixed income from insurer panel
- Offshore Bond - insurance bond with chargeable event gain treatment
- VCT (Venture Capital Trust) - 30% upfront Income Tax relief; tax-free dividends


# 6. Fund Database and Search
## 6.1 Fund Identifiers

## 6.2 Fund Search API
Live autocomplete with 280ms debounce. Multi-word search splits terms and applies AND-LIKE matching. Returns ISIN, SEDOL, IA sector, TER, asset allocation breakdown, and fund type. On selection, scenario asset fields auto-populate.

## 6.3 OpenFIGI Integration
Admin forms include a Lookup via OpenFIGI button. Lookup by ISIN or SEDOL ticker. Auto-fills fund name, SEDOL, and fund type. LSE/London exchange filter applied first, then global fallback for funds not listed on LSE. Key stored in OPENFIGI_API_KEY env var.


# 7. Client and Scenario Management
## 7.1 Client Model - UK GDPR Compliance

ConsentWithdrawn event: nulls name_enc and ni_number_enc, sets ukgdpr_consent = 0, records to gdpr_consents audit table (Art.7(3)). Audit log retained 6 years (FCA COBS minimum).

## 7.2 Scenario Model
- One scenario = one retirement income plan for one client
- Contains: annual income target (GBP net), inflation rate, simulation years, risk profile, State Pension income, SIPP access age (default 57)
- Multiple assets per scenario, each with type, value, fund link, allocation weights, priority order
- Multiple saved simulation runs per scenario (app_version stamped for FCA audit trail)


# 8. Billing and Subscription Tiers
## 8.1 Stripe Integration
StripeBilling replaces the legacy PayFast integration. Stripe handles UK SCA (Strong Customer Authentication), recurring billing in GBP, and webhook events for subscription lifecycle management.


## 8.2 Subscription Tiers


# 9. UK Regulatory Compliance


# 10. Admin Portal

retireuk.costusworx.co.za  ·  Feature Overview  ·  v2026.05.27.1  ·  May 2026
| Field | Value |
| --- | --- |
| Version | 2026.05.27.1  |  May 2026 |
| Product | CostusWorx UK Retirement Decision Engine |
| Category | Multi-tenant SaaS - Financial Planning Software |
| Target Users | FCA-authorised Independent Financial Advisers (IFAs) |
| Technology | PHP 8.5  .  MySQL 8  .  Chart.js 4  .  Stripe  .  mPDF |
| Compliance | UK GDPR 2018  .  FCA COBS 9A / COBS 19  .  HMRC Income Tax |
| Data Sources | FTSE All-Share  .  UK Gilts  .  SONIA  .  ONS CPI (2000-2024) |
| Production URL | https://retireuk.costusworx.co.za |
| Layer | Technology |
| --- | --- |
| Backend | PHP 8.5+ with strict types, readonly properties, native enums, custom PSR-4 autoloader |
| Database | MySQL 8 via PDO native prepared statements (ATTR_EMULATE_PREPARES = false) |
| Front-end | Vanilla JS, Chart.js (CDN), jsPDF + html2canvas (CDN), en-GB locale, GBP formatting |
| PDF Reports | Server-side mPDF (optional drop-in) or client-side jsPDF fallback |
| Billing | Stripe (UK SCA / cards) with Stripe-Signature webhook verification |
| Hosting | Shared cPanel / Linux / Apache - UK datacentre - no Docker, no Composer at runtime |
| Data series | Source | Represents |
| --- | --- | --- |
| equity_return | FTSE All-Share Total Return Index | Shares (dividends reinvested) |
| bond_return | FTSE UK Gilts All Stocks Total Return | Government bonds |
| cash_return | SONIA (Bank of England overnight rate) | Cash savings |
| inflation | ONS CPI (Consumer Price Index, all items) | UK inflation |
| Asset type | Taxable fraction | Treatment |
| --- | --- | --- |
| SIPP / Workplace Pension | 0.75 (75%) | 25% PCLS tax-free. 75% enters HMRC gross-up. |
| ISA | 0.00 (0%) | All withdrawals tax-free. Gross-up step skipped entirely. |
| State Pension | Income offset | Subtracted from annual target before portfolio draw. Technically taxable but treated as net offset. |
| Cash / Unit Trust (GIA) | 1.00 (100%) | Full amount taxable. May also trigger CGT (not currently modelled). |
| Output | Description |
| --- | --- |
| Success Rate (%) | Percentage of runs where the portfolio survived all simulation years |
| Median Years Remaining | Years of portfolio value at the 50th-percentile run |
| Worst Depletion Year | Earliest year at which any run depleted |
| Confidence Bands | P10 / P25 / P50 / P75 / P90 portfolio value per simulation year (in GBP) |
| Portfolio Paths | Best (P90), Median (P50), Worst (P10) paths for charting |
| State Pension income | Annual income subtracted from target before portfolio draw |
| HMRC tax breakdown | Gross drawn, HMRC Income Tax, net to client per simulation year |
| Profile | Default Equity | Default Bonds | Default Cash | Behaviour |
| --- | --- | --- | --- | --- |
| Conservative | 30% | 50% | 20% | ConservativeProfile mutates PortfolioState to reduce withdrawal in high-drawdown years. |
| Moderate | 60% | 30% | 10% | ModerateProfile returns state unchanged. |
| Aggressive | 80% | 15% | 5% | AggressiveProfile returns state unchanged. |
| Type | Access | Tax wrapper | Notes |
| --- | --- | --- | --- |
| SIPP | Age 57+ (2028) | Yes - pension | TAXABLE_FRACTION=0.75; 25% PCLS tax-free; drawdown capped at adviser-set rate |
| ISA | Any age | Yes - ISA | TAXABLE_FRACTION=0.0; all withdrawals fully tax-free |
| Workplace Pension | Age 57+ (2028) | Yes - pension | Same tax rules as SIPP; often with employer contributions |
| State Pension | State Pension age | Income offset | annualIncome() subtracts from annual target; withdraw() returns 0; applyReturn() inflates by CPI |
| Cash | Instant | No | Capital guaranteed; SONIA-based return |
| Unit Trust / OEIC | Daily | No | Linked to UK fund universe via ISIN/SEDOL; IA sector classification |
| Identifier | Standard | Notes |
| --- | --- | --- |
| ISIN | ISO 6166 (12-char) | Primary identifier. UK funds typically IE00, GB00 prefix. |
| SEDOL | LSE 7-char | sedol column added. Reads: COALESCE(sedol, jse_code) for compat. |
| IA sector | Investment Association | Replaces ASISA category. E.g. UK All Companies, Global, Strategic Bond. |
| OpenFIGI | Bloomberg | Admin lookup button: ISIN -> SEDOL, fund name, type via OpenFIGI API. |
| Field | Storage | Notes |
| --- | --- | --- |
| Client name | name_enc (AES-256-GCM) | Encrypted at-rest per UK GDPR Art.32 |
| NI number | ni_number_enc (AES-256-GCM) | UK National Insurance number. Encrypted. |
| UK GDPR consent | ukgdpr_consent (TINYINT) | Must be 1 before client save. Right to withdraw per Art.7(3). |
| Date of birth | date_of_birth | Used to calculate current age and simulation term |
| Life expectancy | life_expectancy | Default: 87 (ONS UK median). Adviser-adjustable. |
| Detail | Implementation |
| --- | --- |
| Webhook endpoint | POST /billing/notify |
| Signature verification | Stripe-Signature HMAC SHA-256 (STRIPE_WEBHOOK_SECRET env var) |
| Subscription field | stripe_sub_id on subscriptions table (payfast_token retained for compat) |
| Idempotency | webhook_event_id stored to prevent double-processing |
| Test mode | Stripe test keys for staging; live keys in .htaccess SetEnv on production |
| Tier | Price (GBP/mo) | Simulation runs | Features |
| --- | --- | --- | --- |
| Starter | GBP 35 | 500 | Core simulation, PDF reports, fund search |
| Professional | GBP 65 | 1,000 | All Starter features + strategy comparator, CSV export |
| Enterprise | GBP 130 | Unlimited | All Professional features + white-label PDF, bulk import, priority support |
| Regulation | Obligation | Implementation |
| --- | --- | --- |
| UK GDPR Art.6 | Lawful basis for processing | Contractual necessity (client advisory relationship) |
| UK GDPR Art.32 | Data security | AES-256-GCM encryption of PII at-rest (name_enc, ni_number_enc) |
| UK GDPR Art.7(3) | Right to withdraw consent | ConsentWithdrawn event nulls PII; records to gdpr_consents audit table |
| UK GDPR Art.5(2) | Accountability | Immutable audit log; 6-year FCA retention minimum |
| UK GDPR Art.17 | Right to erasure | Consent withdrawal nulls PII; account deletion flow planned (Phase 5) |
| FCA COBS 9A | Suitability obligation | FCA COBS disclosure on every PDF report page 4 |
| FCA COBS 19 | Pension transfer advice | State Pension, SIPP rules documented in scenario notes |
| HMRC SIPP rules | Minimum access age | SippAsset::MIN_ACCESS_AGE = 57 (from 2028); Phase 5 enforces against sim start |
| ISA rules | Annual allowance | GBP 20,000/yr; flagging planned in Phase 5 |
| Lump Sum Allowance | GBP 268,275 tax-free limit | Documented; enforcement planned in Phase 5 |
| Feature | Path | Description |
| --- | --- | --- |
| Platform funds | /admin/platform/funds | Full CRUD for platform-wide fund library. Export/import CSV. OpenFIGI bulk cleanse. |
| Fund performance | /admin/platform/funds/:id/performance | Add/edit annual return rows per fund. |
| FIGI Cleanse | /admin/platform/funds/figi-cleanse | Batch OpenFIGI lookup for funds missing SEDOL. Auto-fill or manual override. |
| Market data import | /admin/market-data | Import FTSE / UK Gilts / SONIA / ONS CPI annual CSV. Upsert by year. |
| UK tax brackets | /admin/tax-brackets | View HMRC brackets. Admin edit UI planned (Phase 5). |
| Users (global) | /admin/users | All users across all tenants. Edit name/email/role/status. Reset password. |
| Tenants | /admin/tenants | Full tenant CRUD. Add/edit/delete tenants and their users. |
| Audit log | /admin/audit-log | Immutable record of all sensitive actions. Retained 6 years. |