# Atrium: task list

The current state of the work. The plan for the whole is `reji/plans/2026-11-06-M00-atrium-master-plan.md`, whose §3 has the
module-by-module status. Newest section first.

## Now: for discussion

The foundation is built up to A8 (see Next). Each of these needs the Architect.

- [x] Billing: TB-1 to TB-7 as recommended (the Architect, 6 November 2026; plan IA §8)
- [x] Self-service billing from the start, adapted from Desk's (the Architect, 6 November 2026; IA-6)
- [x] Names: Album for organisations, Tabula for subscriptions, Clavis for accounts only (the Architect, 6 November 2026; IA-10)
- [x] Accounts may exist with no organisation (IA-4); parents and pupils hold the same account and reach `id` quietly (IA-5); Atrium owns an organisation's details (IA-8); the organisation record and subscription core join the foundation (IA-9) (the Architect, 6 November 2026)
- [x] Atrium only: no changes to the TuteCore repository (the Architect, 6 November 2026; AF-8, IA-7) <!-- brand-guard: allow -->
- [x] Organisations register both alone at `id` and from a product's "Start free" (the Architect, 6 November 2026; IA-3)
- [x] `id.tutelora.com` and `api.tutelora.com`, not `tutelora.app` (the Architect, 6 November 2026; IA-1)
- [x] Organisations and billing stay at `id.tutelora.com`, no `admin` host (the Architect, 6 November 2026; IA-2, IA-11)
- [x] Admins can add people both at `id` and inside the product (the Architect, 6 November 2026; plan IA §7)
- [ ] Legal advice on central accounts for pupils under Ghana's data protection law, before Clavis is approved (plan IA §11)
- [x] The build order, BO-1 to BO-3, and the foundation, AF-1 to AF-7, as recommended (the Architect, 6 November 2026)
- [x] Atrium is the platform's name (the Architect, 6 November 2026)
- [ ] The TuteCampus pilot date, if there is one (none is recorded)
- [ ] GWCL's status (moves Tessera up if signed)

## Next, in this order

- [x] A0: the mockups (`reji/ui/html/af/`, starting at `dashboard.html`), approved by the Architect, 6 November 2026
- [x] C1: worker pools, on Redis
- [x] C2: idempotency keys reserved before running
- [x] C3: signed outbound webhooks
- [x] C4: request IDs, JSON logs, an honest `/up`
- [x] A1: the name and the leftovers
- [x] A2: hosts and routing
- [x] A3: Album's record and Tabula's core
- [x] A4: servers, keys, the check, `/v1/ping`
- [x] A5: metering, server reports and checks, job IDs
- [x] A6: the console, to the approved mockups
- [x] A7: docs
- [x] The repository: `tutelora/atrium`, private, `develop` pushed (7 November 2026)
- [x] The dev agents on this Mac: server, queue, bulk queue, scheduler (7 November 2026)
- [ ] A8: the cPanel account, on the real names (`api.tutelora.com` holding the app, `id.tutelora.com` on the same folder; the Architect, 9 November 2026), as staging until the VPS. The Architect's: the account and DNS. To confirm first: PostgreSQL 15 or later with `pg_trgm`. The step-by-step manual: `reji/docs/reference/deployment.html`
- [x] SEC1–SEC3: id's Priority 1 before its first deployment: the page policy, files away from the session, a fresh proof before what matters (8 November 2026, plan SEC)
- [x] SEC4: Atrium's own risks assessed (`SECURITY_ASSESSMENT_ATRIUM.md`, 6.2 to 7.9), four serious and seven lesser findings fixed (8 November 2026)
- [ ] From SEC4: invitations waiting on Home also let a person a product linked take the place; the key and address on each usage event; a second channel told when a key is issued; webhook secret rotation
- [ ] The first deployment: `CSP_MODE=report` for a week, its `csp.violation` lines read, then `enforce`; `HOST_FILES` once its DNS resolves
- [x] Decide what happens when a grant's year ends: Free renews itself, a paid one gets 7 days' grace then Free (TB-8, TB-11; the Architect, 7 November 2026)
- [x] LG: Legatus, the Atrium client library, decided, built, proved and reviewed (LG1 to LG4, 9 November 2026; `reji/plans/2026-11-09-LG-legatus-client-library.md`)
- [ ] Each product joins Atrium through Legatus once Atrium is deployed, one product at a time from its own folder: the list is `reji/tasks/other-apps.md` (the Architect, 9 November 2026: no other product is changed from an Atrium session)
- [ ] The Architect's, with the first product: Legatus's own repository (LG-1)
- [x] NS decided: NS-1 to NS-11 (the Architect, 7 November 2026; `reji/plans/2026-11-07-NS-nuntius-send-path.md`)
- [x] N0: NS's mockups, approved by the Architect, 7 November 2026
- [x] N1–N6 and N7's docs, plan NS §6 (7 November 2026)
- [ ] The first real text: the company's Sailup key in the console, and a sender name recorded. The Architect's
- [ ] Campus's gateway (NS-9), in Campus's own plan and on the Architect's say-so
- [x] NU decided and drawn: NU-1 to NU-12 under the Architect's autonomy grant (8 November 2026; `reji/plans/2026-11-08-NU-nuntius-the-rest.md`)
- [x] NU1: what a text costs; NU2: buying SMS credit at id (8 November 2026)
- [x] NU3: bulk sends, the batch API, paced runs, cancel, the console's page (9 November 2026)
- [x] NU4: sender names asked at id or by API, registered in the console (9 November 2026)
- [x] NU5: product e-mail through Nuntius, a provider chain (9 November 2026)
- [ ] The Architect's, before a product sends e-mail: the SES account, each product's `notify.<domain>` verified with SPF, DKIM and DMARC, a configuration set per product
- [x] NU6: blocks and unsubscribing, SES through SNS with a topic allow-list (9 November 2026)
- [x] TL: Tutelink decided, drawn and built (TL1 to TL3, 9 November 2026)
- [x] TE: Tessera decided, drawn, built and reviewed (TE0 to TE4, 9 November 2026; `SECURITY_REVIEW_TESSERA.md`)
- [ ] Campus: `stubSettle` settles any pending payment for anyone signed in (plan TE §2.1), recorded in `reji/tasks/other-apps.md` for Campus's own session
- [ ] The Architect's: `tutel.ink`'s DNS and certificate pointed at Atrium, `HOST_INK=tutel.ink`, before a link is sent for real
- [ ] The Architect's, with SES: an SNS topic for each product's configuration set's bounces and complaints, subscribed to `/v1/notify/report/ses`, its ARN in `NOTIFY_SES_TOPICS`
- [x] NU7: a fresh reader's review of the money and send paths (9 November 2026; `SECURITY_REVIEW_NUNTIUS.md`, 8.1)
- [ ] The pilot is free (the Architect, 9 November 2026): `notify.charge_texts` stays off and no pack goes on sale until the Architect sets prices
- [ ] Bulk sends go one text at a time per provider: measure the real provider's answer time before sending several at once
- [x] CL decided: CL-1 to CL-18 (the Architect, 7 November 2026; four take the alternative)
- [x] CL: the throwaway OIDC proof (CL-7): go, with Passport and our own layer (`reji/plans/2026-11-07-CL-P-oidc-proof.md`)
- [x] CL: mockups approved by the Architect, 7 November 2026 (`reji/ui/html/cl/`, six files)
- [x] CL1: accounts without organisations (7 November 2026)
- [x] CL2: sign-in at id (7 November 2026)
- [x] CL3: Atrium as the products' OIDC provider (7 November 2026)
- [x] CL4: joining at id (7 November 2026)
- [ ] The Architect checks Ghana's 261 districts (`app/Support/InputFields/Places.php`) against the official list
- [x] CL5: web addresses (7 November 2026)
- [x] CL6: the account and organisation at id (7 November 2026)
- [ ] People in id's own design, invitations waiting on Home (the billing-only view came with TB2: Billing and their own pages, nothing else)
- [x] CL7: passkeys, Google and Microsoft (7 November 2026)
- [ ] Google and Microsoft keys, from the Architect (`GOOGLE_*`, `MICROSOFT_*`)
- [x] CL8: the products' side of the API (7 November 2026)
- [x] CL9: the docs and the security assessment of id (7 November 2026)
- [x] Before id's first deployment: the assessment's Priority 1 (CSP, uploads off id, a fresh check for organisation changes): done by SEC1 to SEC3, 8 November 2026
- [x] Children's data: Clavis holds no children's accounts; pupils stay in the products, where it's cleared (the Architect, 7 November 2026)
- [ ] Turnstile's keys, from the Architect (the puzzle stands in until then)
- [ ] The Architect's: Turnstile, Google and Microsoft keys; today's Campus account counts; any pilot date
- [x] TB decided: TB-8 to TB-15 as recommended, and TB-16 (complimentary by default; billing for one organisation) (the Architect, 7 November 2026; `reji/plans/2026-11-07-TB-tabula-billing.md`)
- [x] TB-16's three-way setting, grace days and "agreed with": kept, all three (the Architect, 7 November 2026)
- [x] TB: mockups approved by the Architect, 7 November 2026 (`reji/ui/html/tb/`, five files)
- [x] TB1: the catalogue as data, and complimentary by default (7 November 2026)
- [x] TB2: paying, through Paystack's own page with a stand-in for development; plans and paying at id for owners and billing people (8 November 2026)
- [x] TB6: the money paths reviewed (reji/docs/SECURITY_REVIEW_TABULA.md, 7.4 / 10), one serious fault and four lesser fixed; Tabula built (8 November 2026)
- [x] Money back discussed: TB-17 to TB-22 decided as recommended (8 November 2026); plan TB §7; mockups drawn (reji/ui/html/tb/moneyback.html)
- [x] Money back mockups approved by the Architect (8 November 2026)
- [x] TB7: refunds, built 8 November 2026 (RefundingTest; the console's Money back)
- [x] TB8: credit notes, built 8 November 2026 (CreditNotesTest)
- [x] TB9: chargebacks, and the money paths reviewed again (7.7 / 10), built 8 November 2026 (DisputesTest, MoneyBackReviewTest)
- [ ] Before live money: confirm Paystack's dispute resolutions with test keys
- [x] Withholding's review step (TB10), built 8 November 2026 under the autonomy grant (WithholdingReviewTest); the money paths now 8.0 / 10
- [x] TB5: switching billing on for a product, blocked until it's lawful, with 60 days' notice, the announcement and a founding price; the console's money figures (8 November 2026)
- [x] TB4: tax invoices and receipts, cleared through E-VAT by a driver (a receipt until the GRA's access comes), withholding with its certificate, invoices at id (8 November 2026)
- [x] TB3: renewals and lapses by Atrium's scheduler (cards renewed, mobile money reminded, the grace days, Free), and the organisation's Billing with the ribbon (8 November 2026)
- [ ] Before billing is switched on, the Architect's: the tax rates as seeded (NHIL 2.5%, GETFund 2.5%, VAT 15% under Act 1151), and the day they apply from
- [ ] Before billing is switched on, the Architect's: prices and each Free offering's limits, the VAT registration and E-VAT access, a live Paystack account, who is on agreed terms, the public terms

## Start early, whatever the build order

- [ ] The Architect's, for slice A8: the VPS, DNS and the GitHub repo (suggested: `tutelora/atrium`) (AF-7)
- [ ] Before billing is switched on: the prices and Free offerings; the public site's wording; VAT registration and the E-VAT set-up with the GRA; Tutelora's own live Paystack account; which schools are on agreed terms (plan IA §8; the Architect's)

## Apart from Atrium

- [ ] Campus's voucher redemption isn't atomic, has no throttle on its route and no audit (master plan §4.2). A live fault on
      real money, to fix in Campus, not here
- [ ] Faults found in TuteCore: plan AF §7. Noted only, because that repository isn't being changed <!-- brand-guard: allow -->
- [ ] `registry.html` shows three ports outside their block (Campus docs 8063, Loop docs 8053, TutePortal 8082)

## Done

### 6 November 2026
- [x] Started from TuteCore 2.1.1, renamed to Atrium, port block 8100–8109 <!-- brand-guard: allow -->
- [x] Checklist worked through; plan AF drafted
- [x] The apps surveyed; master plan, system map, journey and the standard documents written

## Review: 6 November 2026

Suite: 618 passed, 3 skipped, none failed, after `npm run build`. Only documents changed after that run, so it wasn't repeated;
the brand guard and `core:status` were re-run. The map's data was checked by script and the pages opened in light, dark and at
phone width. Not done: nothing has run on a server; the OIDC packages are unproven on this stack.
