# AUREN Platform Specification & Site Map

**Version 2.0 · Revised 21 July 2026**
**Supersedes:** *Hardwired Data & Technical Specifications* v1.0 (Dec 2025) and
*Website Structure Complete* v1.0 — both withdrawn and merged into this document.

The single reference for what AUREN stores, what it runs on, and what is actually
deployed. Every figure below was checked against the live system on 21 July 2026, not
copied forward from the previous specifications.

---

## Why the two previous documents were withdrawn

They contradicted each other and both contradicted the running system.

The *Hardwired Data* spec was stamped December 2025 while the framework package it
belonged to was stamped July 2026; every worked example inside it carried
`"last_updated": "2024-12-01"` and `"next_review": "2025-01-01"` — around nineteen months
past due. Its "Technical Architecture" section described a system that was never built.
The *Website Structure* document described an information architecture that had since
been implemented with real differences nobody had recorded.

Keeping two stale documents that disagree is worse than keeping none. This document
replaces both, and states the actual position.

### The stack, as specified versus as deployed

| The 2025 spec said | What actually runs |
|---|---|
| Next.js 14.2 | **Next.js 15.4**, React 19 |
| PostgreSQL 15 + Prisma ORM | **MariaDB / MySQL** via `mysql2`, raw SQL migrations in `db/` |
| Vercel hosting | **Self-hosted**, port 3007, nginx in front, PM2 process `auren-ifairy` |
| Claude 3.5 Sonnet primary + GPT-4 fallback | **`@google/genai`** (Gemini) |
| Pinecone / Qdrant vector DB, LangChain, OpenAI embeddings | **None.** Retrieval is MySQL `FULLTEXT` over `knowledge_chunks` |
| Meilisearch, Redis, BullMQ, AWS S3 / R2 | **None present** |
| CI/CD: GitHub Actions → Vercel | Manual build and PM2 restart |

Nothing in the old architecture section should be used to plan work. The table above is
the accurate picture.

---

## 1. Data model

### 1.1 What the old spec asked for

Five separate databases — legislative, platform safety, threat intelligence, support
services, research — each with an elaborate nested JSON schema, targeting "50+ platforms",
"100+ support services" and "200+ research papers".

It supplied **no source URL for any of them.** Across 417 KB of framework text there were
ten URLs and nine were placeholders (`https://www.iwf.org.uk/...`,
`https://www.example.org`). The schemas were detailed; the data behind them did not exist.

### 1.2 What was built instead

**One table, `catalog_sources`, serving all five domains** — because the thing that was
actually missing was never the schema. It was provenance: a verified URL, a licence, and
a date, for every claim the site makes.

A single table with an `auren_db` discriminator gives every domain the same guarantees —
same verification job, same licence gate, same review cadence, one admin screen — instead
of five schemas each needing its own tooling.

**Current contents — 173 entries, 0 dead links:**

| Domain (`auren_db`) | Entries | Bodies storable |
|---|---|---|
| `legislation` | 45 | 45 |
| `platforms` | 31 | 0 |
| `support` | 31 | 6 |
| `content` | 27 | 15 |
| `research` | 25 | 9 |
| `threats` | 14 | 9 |
| **Total** | **173** | **84** |

`platforms` is entirely link-only, and that is correct rather than a shortfall: every
entry is a commercial safety centre or help article whose terms do not permit
redistribution.

### 1.3 The licence gate

The rule that makes the corpus legally distributable:

| Licence | Entries | Body stored? |
|---|---|---|
| `OGL-3.0` | 80 | Yes — Open Government Licence v3.0, redistribution with attribution |
| `Open` | 4 | Yes — UN/WHO/UNICEF terms, attribute, no commercial re-licensing |
| `Copyright-link-only` | 89 | **Never** — metadata and `source_url` only |

Enforced in exactly one place: the licence gate at the top of the per-source loop in
`scripts/harvest-catalog.mjs`. Nothing downstream re-checks it, so no second fetch path
may bypass it. This mirrors the `file_included` flag that made the curriculum database
distributable without negotiating a single licence.

68 bodies are stored, about 8 MB, under `data/harvest/<category>/<slug>.<ext>`. That
directory is gitignored and fully reproducible from the manifest.

### 1.4 Link verdicts

| Verdict | Count | Meaning |
|---|---|---|
| `LIVE` | 145 | Resolves; harvestable if the licence allows |
| `BOT_BLOCKED` | 28 | Publisher's WAF refuses scripted clients but serves browsers. **A valid resting state, not an error** |
| `DEAD` | 0 | — |

The 28 blocked hosts include every Ofcom code of practice, all NSPCC and Childline pages,
IWF, Action Fraud, Roblox and OpenAI help centres. Each was confirmed real by hand. A
checker treating 403 as "broken" would delete 28 good entries. No proxying or browser
automation is used to defeat bot management — those entries stay link-only permanently,
which their licences require anyway.

### 1.5 Full table inventory

Twenty-one tables, all MySQL/MariaDB:

| Group | Tables |
|---|---|
| **Catalogue** | `catalog_sources`, `catalog_harvests`, `catalog_harvest_runs` |
| **Documents & knowledge** | `source_documents`, `source_document_versions`, `knowledge_chunks` |
| **Auth & audit** | `admin_users`, `admin_sessions`, `api_secrets`, `audit_log` |
| **Operations** | `backup_runs`, `newsletter_subscribers` |
| **iFairy dashboard** | `ifairy_admin_users`, `ifairy_admin_sessions`, `ifairy_audit_log`, `ifairy_bots`, `ifairy_enquiries`, `ifairy_frontend_sections`, `ifairy_landing_layout`, `ifairy_landing_page_sections` |

Migrations are numbered SQL in `db/`, applied by `node scripts/migrate.mjs`:
`001_auth_and_secrets` · `002_hardening_documents_knowledge` ·
`003_ifairy_dashboard_bots` · `004_source_catalog`.

### 1.6 Retrieval

No vector database. `knowledge_chunks` carries a MySQL `FULLTEXT` index over
`(title, section_title, content)`; documents are chunked on heading boundaries at roughly
1,200–3,500 characters by `chunkMarkdown()` in `lib/server/documents.ts`. The chat route
(`app/api/chat/route.ts`) retrieves against that index.

This is a deliberate scale decision, not an oversight. At a few thousand chunks, full-text
retrieval is adequate and carries no external dependency, no embedding cost and no second
datastore to keep in sync. Revisit if the corpus passes roughly ten thousand chunks.

---

## 2. Site map — verified

56 page components; every URL below returned its stated status on 21 July 2026.

### Public

| Route | Status | Notes |
|---|---|---|
| `/` | ✅ | Home |
| `/crisis` | ✅ | Crisis access; also the target of the `/parent-portal/crisis` redirect |
| `/about` + `/mission` `/how-it-works` `/governance` `/funding` `/contact` `/feedback` | ✅ | 7 pages |
| `/accessibility` `/privacy` `/terms` `/cookies` | ✅ | Statutory pages |

### Parent Portal

| Route | Status | Notes |
|---|---|---|
| `/parent-portal` | ✅ | Hub |
| `/parent-portal/age/[group]` | ✅ | Serves `0-5`, `5-11`, `11-16` |
| `/parent-portal/age/5-11/[stage]` | ✅ | early / middle / upper primary |
| `/parent-portal/age` | ❌ **404** | Planned index page, never built — see §3 |
| `/parent-portal/risks` | ✅ | Hub |
| `/parent-portal/risks/ai-safety` + `/[platform]` | ✅ | 8 AI platforms |
| `/parent-portal/risks/social-media` + `/[platform]` | ✅ | 7 platforms |
| `/parent-portal/risks/gaming` + `/[platform]` | ✅ | 4 platforms |
| `/parent-portal/risks/emerging` | ✅ | |
| `/parent-portal/devices` + `/[device]` | ✅ | `ios`, `android`, `network` |
| `/parent-portal/devices/gaming` + `/[console]` | ✅ | `playstation`, `xbox`, `nintendo` |
| `/parent-portal/crisis` | ↪️ 308 | Redirects to `/crisis` — consolidated, intentional |

### Educator Portal

`/educator-portal` plus `/kcsie` `/policies` `/ai-education` `/training` `/incidents` — all ✅ (6 pages).

### Legal Library

`/legal-library` plus `/legislation` `/legislation/[act]` `/timeline` `/compliance` `/cases` — all ✅.
`[act]` resolves `data-protection`, `childrens-code`, `online-safety-act`, `kcsie`, `devolved`.

### Resources

`/resources` plus `/guides` `/tools` `/research` `/videos` `/newsletter` `/source-documents` — all ✅.

### Admin — 8 routes, session-gated

`/admin/login` · `/admin/catalog` · `/admin/documents` · `/admin/secrets` · `/admin/ifairy` ·
`/admin/health` · `/admin/audit` · `/admin/account`

Gated by `middleware.ts` on the `auren_admin_session` cookie, plus a `requireAdmin()` call
in every page. Shared navigation via `app/admin/layout.tsx`.

**Implementation note.** The old structure document listed each legislation act and each
platform as a separate static route. They were built as dynamic segments instead — same
public URLs, one component each. Where the old document listed a URL, that URL works; the
file layout behind it differs.

---

## 3. Known gaps

| Gap | Impact | Status |
|---|---|---|
| `/parent-portal/age` returns 404 | The age hub is linked as a concept but has no index; users reach age pages only via `/parent-portal` | **Open** — the only genuine dead route on the site |
| Ages 0–5 content depth | Thinner than 5–11 and 11–16 | Open |
| `platforms` domain is 100% link-only | No stored bodies to search or ground answers on | By design — licences forbid storage |
| Harvest is shell/cron only | No admin button | By design — long network job, not for a request handler |

---

## 4. Update and maintenance protocol

Review cadence is stored per entry as `next_review_at`, derived from the declared
`update_freq`: live/weekly → 30 days, monthly → 60, quarterly → 120, annual → 200,
static → 365. The admin dashboard counts entries past that date.

**Quarterly, minimum:**

```bash
npm run catalog:verify              # fix any DEAD before continuing
npm run catalog:seed
npm run catalog:harvest -- --dry-run
npm run catalog:harvest
```

The first verification pass found **19 stale URLs in a corpus barely a year old** — UK
regulators restructure their URL trees constantly. This is not a cadence to let slip.

**Also on a cycle:** legislative and support-service verification quarterly; platform
review and content freshness monthly; threat monitoring weekly; backup and uptime daily
(`scripts/backup-db.mjs`, `scripts/monitor-services.mjs`).

---

## 5. Standing rules

1. **No statistic is published without a catalogue entry behind it.** Claims that cannot
   be traced are corrected or removed, and the removal is recorded.
2. **`Copyright-link-only` bodies are never stored** — not on disk, not in the database,
   not in an AI prompt's grounding context.
3. **`BOT_BLOCKED` entries stay link-only permanently.** No proxying, no browser
   automation to defeat a publisher's bot management.
4. **Re-verify quarterly.**
5. **This document is the architecture reference.** If something here disagrees with an
   older AUREN document, this one is right — it was checked against the running system.

---

## Change log — v1.0 → v2.0

| Change | Reason |
|---|---|
| **Merged** *Hardwired Data* + *Website Structure* into one document | They disagreed with each other and with the deployed system |
| **Corrected** the entire technology stack section | Every line of it described software that was never installed |
| **Replaced** the five-database design with the single `catalog_sources` table, documented as built | One table, one verification job, one licence gate, one admin screen |
| **Replaced** aspirational counts ("50+ platforms", "200+ research papers") with verified counts | 173 entries, each with a real URL and a verification date |
| **Added** the licence gate, link verdicts and harvest model | Absent from v1.0, and the thing that makes the corpus distributable |
| **Verified** every route and recorded build status | v1.0 described intent; this records reality, including the `/parent-portal/age` 404 |
| **Removed** all `2024-12-01` / `2025-01-01` example dates | Nineteen months stale |
| **Removed** PostgreSQL DDL and nested JSON schemas | Superseded by `db/004_source_catalog.sql`, which is the real schema |

---

*AUREN Guardian AI · iFairy Studios CIC*
