# M00 · Master plan: Tutelora Atrium

**Status:** the order and the foundation's decisions are made, 6 November 2026. **Build:** nothing is built until its module has passed the gate
in §1; the foundation's mockups were approved on 6 November 2026, and it's built up to slice A8: running here under agents, then staged on cPanel before a VPS (the Architect, 7 November 2026). Nuntius's send path (NS) is decided, its mockups approved, and it's being built. **Concept:** `reji/Tutelora Atrium Shared Platform Services.docx` ("the spec"). **System map:**
`reji/docs/reference/atrium-system-map.html` (source in `src/`). **First plan:** `2026-11-06-AF-atrium-foundation.md`. **Identity:** `2026-11-06-IA-identity-architecture.md`.

> **Changed 6 November 2026 by plan IA, whose decisions are all made.** One account at `id.tutelora.com`, as at Atlassian; organisations (Album) with no
> product information; subscriptions and billing (Tabula) apart; all hosts on `tutelora.com`; and nothing changes in TuteCore. This plan now says so. The
> spec is unedited: `reji/docs/spec-amendments.md` records what overrides it.

---

## 0 · The one-paragraph version

Atrium is one internal app that does, once, the jobs every Tutelora product would otherwise rebuild: signing people in, holding
organisations and what they subscribe to, billing them, sending messages, short links, voucher codes, the assistant, payments and reading documents. Users never see the name. The
spec sets the order of the work and gives the reasons, and those reasons hold, but it assumes more is unbuilt than is. Checked
against the code on 6 November 2026, Campus has already built phone sign-in, a full SMS and e-mail system, vouchers and three
payment gateways, and it is live. So most of Atrium is **extraction from a running product**, not new work, and that changes
two things. Clavis can't go first as the spec has it, because Campus's sign-in sends its codes by SMS; a small part of Nuntius
has to come before it. And Tessera has no second consumer yet, so Tutelink goes ahead of it. Everything after that waits for a
named trigger rather than a place in a queue. Accounts, organisations and subscriptions are three separate subsystems, and billing comes straight after
Clavis, because you've decided to have it from the start. Each module is discussed with you and mocked up before any of it is built.

---

## 1 · How we build: standing policies

| # | Policy | What it means in practice |
|---|---|---|
| P1 | **Discuss, plan, mock up, review, then build** | Every module, the foundation included, goes through this gate in order: **discussion** with you → **plan** (`reji/plans/`) → **mockups** (`reji/ui/html/<plan>/`) → **your review** → build → test → manual journey. Each is approved separately. A finished module opens the next discussion, not the next build (the Architect, 6 November 2026: "we must discuss each module and plan mockups ahead of each build") |
| P2 | **The way in** | A capability goes into Atrium only when two or more apps need it and it enforces one rule across apps, or is heavy or expensive to run, or is sensitive or needs one audit trail (spec). Otherwise it's a shared Composer package |
| P3 | **Read what's built first** | Before a module's discussion, read how the apps already do it. A better version in an app is lifted into Atrium, not reinvented. Campus's live code is the starting point for Clavis, Nuntius, Tessera and Aerarium; Desk's billing for Tabula |
| P4 | **A live product moves safely** | Campus is in production. A product moves to a module behind a switch, one school first, with its own code kept until the module has proved itself, then its code is removed in a plan of its own |
| P5 | **Atrium only** | No change is made to the TuteCore repository (the Architect, 6 November 2026); it stays as released, a reference to read. Everything Atrium needs is built in Atrium, and each difference from 2.1.1 is listed in `PROJECT.md`'s exceptions, which is how a difference stays clear of drift under handbook 13.3 |
| P6 | **Atrium knows who; the products know what** | Atrium holds people, organisations, what they subscribe to and broad roles. Detailed roles and every record stay in the product |
| P7 | **Every module, the same contract** | Versioned path, the organisation named and checked against the server's live instance, an idempotency key on anything that creates, long work in the background with a signed webhook back, usage metered from day one, and a planned fallback when Atrium is down |
| P8 | **Users never see "Atrium"** | Only Tutela and Tutelink are shown as names. Branding is out of Atrium's scope (the Architect, 6 November 2026) |
| P9 | **Docs are part of done** | In the same pass as the code: `CHANGELOG.md`, the manual journey (the seven parts, each with its seat), the map row, the journey chapter, `reji/tasks/`, this plan's table in §3 |
| P10 | **The house rules apply** | Option lists from Input Fields, roles are data, no hard-coded e-mail (one row per mail in the log), singular names, one audited sweep for a cross-cutting change, `develop` only. See the house rules and the family rules |
| P11 | **Open with what it is, its scope and its failsafe** | Every module's discussion and plan start with three things, before any decision: what the module is, in simple terms; what Atrium handles and what stays in the product; and how things carry on if Atrium fails for a short period. The Architect, 7 November 2026: it guides the conversation and keeps us aligned |

**The mockup standard.** One file per concept, generated by the plan's `build-mockups.py` with `reji/ui/html/_mockkit.py`:
every state on the floating switcher, light and dark through the page's own switch, the phone as a state in a phone frame.
Each is checked in all of those before it's shown: right composition, concise words, one clear next step per state, drawn
from what the reader is deciding and never from the database's rows.

---

## 2 · What Atrium is made of

| Module | Codename · ID | What it does | What exists today | So it is |
|---|---|---|---|---|
| Foundation | · | Server keys, hosts, metering, the console's server dashboard, and the core of Album and Tabula | TuteCore 2.1.1 gives the base; 7 of 12 checklist items part-way, 5 missing (plan AF) | New, on TuteCore |
| Accounts | Clavis · `accounts` | One login per person, at `id.tutelora.com`. Needs no organisation and no product | **Campus, live:** SMS sign-in codes, phone-only accounts, one account per number, an `identity` across schools, verified custom domains. About 2,800 lines in `app/Services/Auth`. No app is an OIDC provider | Extraction, plus OIDC as new |
| Organisations | Album · `organisation` | The record, its people and broad roles. No product information | **Atrium:** `tenant` already has no product columns. Each product's tenant holds its own copy, Campus's with 53 columns | New, on TuteCore |
| Subscriptions and billing | Tabula · `subscription` | What's sold, who holds it, where it's running, and paying for it | **Desk:** self-service billing built, switched off, about 1,600 lines, never run on a server. **Campus:** a price catalogue with no subscription | Adapted from Desk |
| E-mail, SMS, WhatsApp | Nuntius · `notify` | The company post office | **Campus, live:** about 4,600 lines of SMS (five providers, wallets, sender IDs, delivery reports, bulk sends); mail streams, a provider chain, suppression. **Loop:** its own SMS driver and templates. **Desk:** its own mail engine, inbound replies, about 1,500 lines of WhatsApp, not switched on | Large extraction |
| Short links | Tutelink · `links` | Short links on `tutel.ink` | Nothing, anywhere | New, small |
| Voucher codes | Tessera · `vouchers` | Unique, single-use codes | **Campus:** about 350 lines; online purchase only, bound to a name. Redemption isn't atomic | Extraction, mostly rewritten |
| AI assistant | Tutela · `tutela` | Chat in every product | No widget or knowledge base. Campus has one masked AI call with a per-school cost cap, and already uses "Tutela" as a name for its reading agent | New |
| Payments | Aerarium · `payments` | One cash desk for money products collect from their own customers | **Campus:** Paystack, Flutterwave, ExpressPay, remittance; about 1,800 lines. **Loop:** no gateway | Extraction. Its gateway core starts with Tabula |
| Reading documents | Lector · `ocr` | Text out of photos and scans | Nothing; Campus reads PDF text layers only | New |

---

## 3 · Build order and status

Each column is approved separately (P1).

| # | Module | Plan ID | Spec's step | Discussed | Plan | Mockups | Built |
|---|---|---|---|---|---|---|---|
| 0 | Foundation, with Album's record and Tabula's core | AF | 0 | ☑ | ☑ | ☑ | built; A8 (staging) waits on the Architect's cPanel account and DNS |
| 1 | Nuntius: the send path | NS | part of 2 | ☑ | ☑ | ☑ | built, no real provider called yet |
| 2 | Clavis, with Album's pages | CL | 1 | ☑ (`2026-11-07-CL-clavis-accounts.md`) | ☑ | ☑ | built, 7 November 2026 |
| 3 | Tabula: billing, and money back | TB | not in the spec's order | ☑ | ☑ | ☑ | built, 7 and 8 November 2026 (TB1 to TB9) |
| 3a | Tabula: withholding's review step (the review's Priority 2) | TB10 | · | ☑ | ☑ | ☑ | built, 8 November 2026 |
| 3b | Before the first deployment: id's Priority 1, and Atrium's own risks assessed | SEC | · | ☑ | ☑ | ☑ | built, 8 November 2026 (SEC1 to SEC4; id 7.6, the platform 7.9) |
| 4 | Nuntius: the rest | NU | 2 | ☑ (`2026-11-08-NU-nuntius-the-rest.md`) | ☑ | ☑ | built, 8 and 9 November 2026 (NU1 to NU7; reviewed 8.1, `SECURITY_REVIEW_NUNTIUS.md`); WhatsApp and inbound wait for Desk |
| 5 | Tutelink | TL | 4 | ☑ (`2026-11-09-TL-tutelink.md`) | ☑ | ☑ | built, 9 November 2026 (TL1 to TL3); `tutel.ink`'s DNS waits on the Architect |
| 6 | Tessera | TE | 3 | ☑ (`2026-11-09-TE-tessera-vouchers.md`) | ☑ | ☑ | built, 9 November 2026 (TE1 to TE4; reviewed, `SECURITY_REVIEW_TESSERA.md`) |
| 7 | Legatus, the Atrium client library (IA step 7; the Architect asked for it, 9 November 2026) | LG | · | ☑ (`2026-11-09-LG-legatus-client-library.md`) | ☑ | · (no screen) | built, 9 November 2026 (LG1 to LG4; proved against Atrium and live); installing it is each product's, after deployment (`reji/tasks/other-apps.md`) |
| When triggered | Tutela | TU | 5 | ☐ | ☐ | ☐ | ☐ |
| When triggered | Aerarium | AE | 6 | ☐ | ☐ | ☐ | ☐ |
| When triggered | Lector | LE | 7 | ☐ | ☐ | ☐ | ☐ |

**Autonomy, 8 November 2026.** The Architect: "Take over go autonomous. decide the build order and only pause if you need some input
from me." From here the order and each module's open decisions are mine, taken as I'd recommend and written into each plan (marked
"decided under the Architect's autonomy grant") with its mockups, so the reasoning stays reviewable; the build goes on without waiting for
approval. I pause only for a fact only the Architect holds, a credential, or something outward or irreversible. The order above keeps the
Architect's BO-1 to BO-3 and puts two things in front of Nuntius' rest, because they close risks rather than add features: withholding's
review step (Tabula's lowest score, 5 of 10) and what must be true before Atrium is first deployed (id's Priority 1, and an assessment of
Atrium's own risks, which nobody has made yet). Staging itself (A8) needs the Architect's cPanel account and DNS, so this work makes Atrium
ready for it rather than waiting on it.

You decided this order on 6 November 2026 (BO-1 to BO-3, §5). Billing's place follows your decision IA-6. It differs from the spec in two other places (§4.3).

---

## 4 · Why this order

### 4.1 · The tests applied

The spec gives two principles: **build what is expensive to retrofit before there are users, and build the rest only when a
second product actually needs it.** I added a third, which only shows once the apps are read: **a module can't land before
what it depends on, and "land" means a live product using it, not code existing.** Each position below was tested by asking
what happens if the module moves earlier and what happens if it moves later.

### 4.2 · Step by step

**0 · Foundation (AF).** *Needs:* the decisions in plan AF.
- **Why first:** no module can be called without it. An API token today must belong to a person and a membership
  (`ResolveTokenTenant.php:38-44`), so a product's server can't hold one at all. Every route answers on every host, so
  `tutel.ink` would serve the login page.
- **Why it can't wait:** usage counted from day one can't be recovered later, and `app_id` is cheap on an empty table.
- **Cost of being wrong:** low. There are no consumers yet.
- **Now also holds:** Album's organisation record and Tabula's catalogue, entitlements and instances, so a request has something to be checked against (IA-9).

**1 · Nuntius, the send path (NS).** *Needs:* 0.
- **Why here:** Clavis has to send sign-in codes, and Atrium can't send anything. Campus's phone sign-in is live and sends
  codes by SMS (`tutecampus/app/Services/Auth/SignInCodes.php`), and accounts can have no e-mail at all
  (`2026_11_01_400000_an_account_can_be_phone_only.php`). Moving Campus to a Clavis without SMS takes sign-in away from
  phone-only people.
- **What it is:** only the provider drivers lifted from Campus, one transactional send, a receipt, and the count. No wallets,
  bulk sends or sender registration.
- **Why it's also the right first test:** it's the smallest real use of the foundation (keys, scopes, metering, webhooks), with
  one caller, before anything as sensitive as sign-in rests on them.
- **If later:** the only alternatives are Clavis carrying its own SMS code, to be removed later, or Clavis without phones.

**2 · Clavis (CL).** *Needs:* 1; a proof of concept for OIDC; the sign-in model lifted from Campus into Atrium.
- **Why as early as this:** it's the most expensive module to retrofit, and it's cheaper now than it will ever be again. Campus
  production held **6 active accounts and 201 inactive, mostly imported learners,** on 5 November (the Architect's own check). Every
  school added raises the cost.
- **A saving the spec doesn't count:** Desk isn't deployed ("Production doesn't exist",
  `tutedesk/reji/docs/SECURITY_ASSESSMENT.md:349`) and Books isn't either. If Clavis lands first, they never need a migration.
- **What else waits on it:** the shared opt-outs in Nuntius ("for the same person") and Tutela (a signed-in user's token) both
  need one identity.
- **The honest risk:** this is the largest step. It spans two repositories (Atrium, then Campus), changes a core rule in Atrium's
  copy (`Membership::lets()`), and touches a live product. Passkeys bound to `tutecampus.app` won't follow to
  `id.tutelora.com`. That's why it gets the longest discussion (§6).

**3 · Tabula, billing (TB).** *Needs:* 0; 2, because someone must be signed in at `id` to pay.
- **Why here:** your decision (IA-6). This is the earliest it can land: a billing admin needs an account and a page at `id`, which Clavis brings.
- **What it is:** Desk's self-service billing, adapted to many products: plans, card and mobile money through Paystack, invoices, and one switch.
- **Why not before Clavis:** with no one signed in there's no one to bill, and staff recording payments by hand isn't what you asked for.
- **Why before the rest of Nuntius:** it doesn't depend on it. Reminders only need the send path.
- **The honest risk:** no pricing model is settled, and Desk's code has never taken a real payment. The switch means it can be built before either is settled.

**4 · Nuntius, the rest (NU).** *Needs:* 1; 2 for shared opt-outs.
- **Why after Clavis, when Campus's sending already works:** nothing is blocked while it waits, so there's no rush to move a
  system that earns money (SMS is sold through a ledger). Opt-outs and bounces shared per person need Clavis's person.
- **Why not much later:** each product that adds sending raises the cost. Loop already has its own SMS driver; Desk is unlaunched
  and can start on Nuntius instead of its own engine.
- **If earlier:** a money ledger moves before identity is settled, and opt-outs get keyed to addresses and then re-keyed.

**5 · Tutelink (TL).** *Needs:* 0; 4 for automatic shortening.
- **Why here:** it's new, small and depends on almost nothing. It passes the way-in test at once: Nuntius, and through it every
  product. A 160-character SMS can't hold a 120-character link, and splitting a text costs money each time.
- **If earlier:** it would have no consumer.
- **If later:** the spec's fallback, the full URL, keeps working at a cost per text.
- **Whitelisting `tutel.ink`:** dropped. Sailup has no such step (the Architect, 7 November 2026).

**6 · Tessera (TE).** *Needs:* 0; 4 for delivery by SMS.
- **Why after Tutelink (the spec has it before):** the spec's reason is that the admissions e-voucher is in the Campus spec, and
  that's done: Campus built it. The reason for sharing is uniqueness across products, and **no other app issues codes,** so today
  it fails the spec's own way-in test. Its second consumer, GWCL, depends on a commercial decision the spec lists as open.
- **Why not simply wait:** the printed batches sold at a bank are in the spec and not in Campus, and they're different in kind:
  a bearer code, where Campus's is bound to a name.
- **What can't wait for Tessera:** Campus's live redemption checks the code outside its transaction with no lock
  (`PublicController.php:206`, `:227`, `:250`), so two people can spend one code. It has no throttle on the route and no audit. A
  voucher is money, so that gets fixed in Campus now, as its own piece of work (§7).
- **The rule until then:** the next *new* voucher capability is built in Tessera, not added to Campus.

**When triggered: Tutela, Aerarium, Lector.** The spec already says two of these wait for need; the survey shows what the
need actually is. Whichever trigger fires first goes next, so these have no order among themselves.

| Module | The trigger | What has to be true first | Why not sooner |
|---|---|---|---|
| **Tutela** | A decision to launch her on Campus | Clavis; a knowledge base (none exists); **Desk deployed with a way to open a ticket** (no API, not deployed); **an API on the product** to answer "what's my status?" (`routes/api.php` doesn't exist in Campus, Desk or Loop) | Most of the prerequisites are outside Atrium. AI calls cost money on a free plan, so she needs quotas working first |
| **Aerarium** | **Loop taking dues online,** or another product collecting from its own customers | Tabula's gateway core in place | Tutelora charging its own customers is Tabula's job, and that includes Desk's Paystack code. What's left is money products collect from *their* customers. Only Campus does today, so it fails the way-in test until a second does, and the spec was right that Loop is likely. Campus is the school's account first, with remittance |
| **Lector** | A product commits to needing it | A real document type and an accuracy bar | Nothing depends on it. Campus's textbook review plans AI transcription of scans, which may be the nearest need |

### 4.3 · Where this departs from the spec

| Spec | Proposed | Because |
|---|---|---|
| Clavis, then Nuntius | A small part of Nuntius, then Clavis, then the rest of Nuntius | Campus's live sign-in sends SMS. The spec's order doesn't allow for it; phone sign-in was built on 1–2 November, days before the spec's date |
| Tessera before Tutelink | Tutelink before Tessera | Vouchers are already built and have one consumer; links have every product. Campus's voucher faults get fixed where they are |
| Steps 5, 6, 7 in sequence | Triggered, in no fixed order | Their prerequisites are mostly outside Atrium |
| Payments only when a second product needs them | Tutelora's own billing straight after Clavis; fees and dues stay with Aerarium | Your decision (IA-6). They're two different jobs |
| "Steps 0 to 3 are on the pilot's critical path" | Not a blocker, an economic case | Campus is already in production with its own sign-in, mail, SMS and vouchers, so no Atrium module blocks a pilot. What the order protects is the migration cost. No pilot date is recorded anywhere |

What stays exactly as the spec says: the foundation first, Clavis as early as it can land, one app rather than services,
and the voucher fallback if time is short (though the "voucher interface" it relies on doesn't exist yet, and would have
to be added to Campus).

### 4.4 · What would change this order

- **A pilot date inside the time Clavis needs:** Campus pilots as it is; Clavis lands after, at some extra migration cost. Tell
  me the date and I'll size it.
- **GWCL signed, or printed vouchers needed for an admissions season:** Tessera moves up to straight after step 2.
- **Desk's launch date set:** Desk should launch on Clavis and Tabula if the dates allow, rather than switching on its own billing.
- **The OIDC proof of concept fails on this stack:** Clavis's shape changes, not its position, and step 2 waits on the answer.

---

## 5 · Decisions needed

**About the order, decided by the Architect, 6 November 2026, as recommended:**

| # | Decision | Recommended | Alternative |
|---|---|---|---|
| **BO-1** | Split Nuntius so its send path comes before Clavis | Yes | Keep the spec's order, with Clavis holding its own SMS sender until Nuntius arrives |
| **BO-2** | Tutelink before Tessera | Yes, with Campus's voucher faults fixed now in Campus | Keep the spec's order; build Tessera third |
| **BO-3** | Tutela, Aerarium and Lector wait for the triggers in §4.2 | Yes | Keep them in sequence as steps 6 to 8 |

**The foundation:** AF-1 to AF-8 are decided (plan AF). **Billing:** TB-1 to TB-7 are decided (plan IA §8). **Facts only you have:** the pilot date;
GWCL's status. **The spec's other open items** (commercial terms for outside clients, retention, free-tier quotas) each
land in the module they block (§6).

---

## 6 · Discussion and mockups, module by module

These are starting agendas, not decisions. Each discussion ends in a plan, and each plan in mockups for review.

### Foundation (AF)
- **Decided:** AF-1 to AF-8. Staff roles wait until someone besides the Service needs the console.
- **Mockups (`af/`):** the *dashboard*, Atrium among the products' servers (today, a server down, nothing connected); each server's *side drawer* (its resources, state and Service figures); *an organisation's record*; *usage*; the page for an *unknown address on each host*.

### Nuntius, the send path (NS)
- **To discuss:** which of Campus's five SMS providers come; whose provider account sends sign-in codes and who bears the cost;
  how Campus's cost brake (`SignInWatch`) carries over; what a template is here, given "no hard-coded e-mail" and handbook 12.9;
  the real sending domain (§7).
- **Mockups (`ns/`):** the *message log* (one row per message, with its recipients); *one message* (its receipt: queued, sent,
  delivered, failed); *channels* (provider status, which is in use).

### Clavis (CL)
- **To discuss:** whose person model wins (Campus's `identity` or TuteCore's `person`); one number, one account, and families
  sharing a phone; usernames, which the spec wants and nobody has; organisation-created accounts and how the holder claims one;
  the mapping to Campus's UUID tenants; Google and Microsoft sign-in; passkeys; what `id.tutelora.com` shows for a school
  on its own domain; signing out everywhere; how Campus's accounts move; handbook 2.3; how outside clients stay apart.
- **Mockups (`cl/`):** *sign-in* (phone, e-mail, username; wrong code, paused, unknown number; phone first); *which school*
  (Kofi's picker); *sign-up and registering an organisation* (Ama's "Start free"); *add a product* (scenario 2); *people in an
  organisation* (removing someone from every product at once); *adding a teacher*, at `id` and inside Campus, and *the invitation they
  get*; *a parent's quiet arrival, from invitation to signed in, on a phone*; *claiming an account*; *returned to the product*; and, for billing, *what a billing-only person sees at `id`*.

### Tabula, billing (TB)
- **Decided:** TB-1 to TB-7 (plan IA §8). **To discuss:** what happens when a year ends, above all on a Free offering; the prices themselves, each product's Free offering and its limits; which parts of Desk's M18b come
  across, and which of its decisions still hold.
- **Mockups (`tb/`), starting from Desk's `m18b` set (8 pages, 26 states):** *plans side by side*, per product; *paying*, leaving for Paystack and back (paid,
  failed, abandoned); *your subscription* (active, renews on, mobile money ending soon, renewal failed, fell back to Free); *invoices and receipts*, with the tax lines and GRA's QR code; *withholding*, paying net and recording the certificate;
  *what a billing-only person sees*; in the console, *offerings and prices*, *an agreed price for one organisation* and *switching billing on*.

### Nuntius, the rest (NU)
- **To discuss:** where the SMS money lives (wallets, allowances, and that schools can't yet buy credit themselves); how a bulk
  send is paced; which bounces are shared across products; WhatsApp (Desk's, unused); inbound replies, which Desk needs and the
  spec doesn't mention; Loop's move; outside clients' sender IDs.
- **Mockups (`nu/`):** *a bulk send* (queued, pacing, finished with counts); *wallet and allowances* (running low, out);
  *undeliverable addresses*; *sender IDs* (pending, approved, refused); the product's *"top up SMS" prompt*.

### Tutelink (TL)
- **To discuss:** which destinations are allowed and how a tenant domain gets verified; default expiry; code length; what we count
  without tracking; whether Nuntius always shortens; the neutral domain for outside clients.
- **Mockups (`tl/`):** the *page a person lands on when a link has expired, been revoked or never existed* (mostly on phones, and
  the one screen almost every user will see); *links in the console* (search, clicks, revoke).

### Tessera (TE)
- **To discuss:** bearer or bound to a name, or both per campaign (a setting); the code format and what happens to codes already
  sold; check character; who may void; how printing works; GWCL's wording.
- **Mockups (`te/`):** *a campaign* (new, in progress, ended); *a batch* (generating, ready to print); the *printed voucher*;
  *entering a code* (valid, used, expired, mistyped, blocked; on a phone); *one code's history*.

### Tutela (TU)
- **To discuss:** the name collision with Campus's reading agent; the knowledge base; which model and what budget per tenant;
  retention; what she may ask a product; hand-over to Desk; the AI vendor must not be named in the app (Campus's rule, D38).
- **Mockups (`tu/`):** the *chat* (first open, an answer with a link, "I can't see that", hand-over to a person, budget reached,
  Atrium down with a leave-a-message form; phone first); *conversations in the console*.

### Aerarium (AE)
- **To discuss:** merchant of record per product; Campus's decimal amounts against integer pesewas; Hubtel, which Loop's brief names;
  holding and delivering a late confirmation; remittance.
- **Mockups (`ae/`):** *reconciliation* (matched, mismatched, held); *the month-end report*; *a held confirmation*.

### Lector (LE)
- **To discuss:** which document first; the accuracy bar; deletion and retention; the Python worker.
- **Mockups (`le/`):** *confirm what was read* (field by field beside the image; low confidence flagged; phone).

---

## 7 · Where the spec and what's built disagree

To settle in the module concerned; none blocks the foundation.

| Spec says | What's there | Settled in |
|---|---|---|
| E-mail from `mail.tutecampus.app` | Production uses `notify.tutecampus.app` (`tutecampus/reji/docs/DEPLOYMENT.md:924`); `EMAIL_SETUP.md` and defaults say `mail.tutecampus.com`; `mail.tutecampus.app` appears nowhere | **Settled by the Architect, 7 November 2026: `notify.`** |
| "The SES setup is still being settled" | Campus has a chain of mail providers (`ProviderChain`); its changelog shows production on Mandrill, and `EMAIL_SETUP.md` is out of date. The current provider I couldn't determine | NS |
| Second payments product is "likely TuteLoop dues" | Holds for fees and dues. Desk's Paystack is Tutelora charging its customers, which becomes Tabula | TB, AE |
| "The school in TuteCampus is the organisation, with the same ID" | Campus: UUID in a string. Atrium: bigint with a ULID public ID | AF-4, CL |
| Sign-in "with phone numbers and usernames" | Campus and Loop have phone; nobody has usernames | CL |
| Admissions e-voucher "in the Campus spec" | No such spec is in the repository; the feature is built | TE |
| "Tutela" names the assistant | Campus's textbook review already calls its reading agent Tutela | TU |
| Money "in integer pesewas" | Campus's payments use a decimal `amount` | AE |

**To fix now, apart from Atrium:** Campus's voucher redemption (§4.2, step 5) is a live fault on real money.

---

## 8 · Out of scope

Each product's own records and detailed roles (P6). A public "shorten any URL" feature (spec). A separate domain for Atrium
(spec). Packages for the other shared code (tenancy trait, money handling, UI components, audit helpers): the spec names them,
and they come when a second app needs them, in a plan of their own rather than this one.
