Dashboard: monthly recurring revenue after discounts, overdue invoices,
per-product installs, latest version, behind, critical and licences.
Install page: the church's other products and whether they're listed to
this site.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cap and markup move from the licence to the customer (migrated), use
is counted over all the church's installs under one lock per church, and
the licence token carries the church's cap. Settings → AI shows product.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Own domain R0, Cross Code address R10, domain included R25 (custom price
for other endings), once per invoice and never discounted; renewal date
with a reminder 30 days before, once per renewal, and Renewed to move it on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- One invoice per customer per period for all its products; the schedule
moves from Licence to Customer (migration copies it, so billing carries
on unchanged); licences get billedFrom / billedUntil
- Website (R99, 5 GB) and App (on active members) prices next to the
Events tiers; founding prices per product, then bundles (15% two, 25%
three); extra website storage R20 per 5 GB, never discounted
- A product added to a billed customer starts after its free month; days
before its first full period are prorated, never charged twice
- Annual review per product (Events income, App members), one notice of
licence change per product; invoices, PDFs and emails name products
- Customer page: schedule, per-product billing, next-invoice preview
- Invoices from before 2.0 kept as they were (still recalculable)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Release.product and requires; unique (product, version); latest version
per product (latest_version stays Cross Events' latest)
- Release sources per product (Releases page): repository, tag prefix,
notes file. Defaults: every product from crosscode-platform plus Cross
Events' v1.2.3 tags from hope-events. A product's releases are only
removed when all its sources were read and found tags
- "— requires accounts 1.2.0" in a notes heading: Request update answers
409 REQUIREMENT_NOT_MET until the church's install of that product is new
enough; install page and Releases page show it; v2 replies carry requires
- @crosscode/contracts 1.1.0 vendored (optional requires on releases)
- Alerts, dashboard and install lists compare against each product's latest
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Product enum (events, accounts, website, app) on Licence and Install,
Install.publicKey; existing rows are events
- One open licence per product per customer: partial unique index, with a
migration guard that names customers with duplicates (npm run check:hub2
lists them beforehand)
- Licence keys per product (CEH-, CCA-, CCW-, CCP-); free Accounts licence
created with the first other product licence
- Protocol v1 registers Events licences only (409 WRONG_PRODUCT); only Events
licences can be invoiced until billing per customer
- Cross Code Hub in the UI, emails and PDFs
- @crosscode/contracts 1.0.0 vendored (backend/vendor)
- Steps merge into release/2.0, not main (plan updated)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Invoices drafted 14 days before each licence's invoice date and emailed
to the alert email for approval; approved ones go out on their date from
08:00 SA time. Drafts can be edited, recalculated, sent early, put back
to draft or voided; one-off invoices too.
- Annual tier review from the 12-month event-income band; approving a tier
change emails a notice of licence change, applied when the invoice goes out.
Notices can also be sent by hand.
- Founding churches (35% off as its own line), payments with receipts,
statements for any dates.
- Every billing email is styled HTML with a PDF (invoice / tax invoice,
receipt, statement, licence change) and logged per customer.
- Settings -> Billing: business and bank details, VAT (off: plain invoices;
on: VAT-inclusive tax invoices), timing and numbering.
- Migration 20261103111645_invoicing; pdfkit 0.17.2; tests/billing.test.js;
scripts/sample-billing-pdfs.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Install page shows the 12-month event-income band (Cross Events 2.0.2+),
the tier it falls in with its price and founding price, and flags a
licence whose plan is a different tier.
- Licence card: Plan picker (Trial or Seed to Network).
- Protocol doc: 14 income bands and eventIncome12m.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings -> AI picks the model from a list (utils/aiModels.js: Sonnet,
Haiku, Opus 5.5 with list prices) or takes another model ID; choosing
one fills in its prices. Blank prices use the built-in ones, and cache
reads are metered at each model's own price.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed /installs/ai/status and /installs/ai/complete (protocol 3b):
the Hub holds the Claude key, holds each call's worst case against the
licence's monthly cap in a locked transaction, calls Claude Haiku 5.5
and meters real cost and charged amount (markup) in rand. Settings ->
AI, licence markup override, AI use on the install page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Notes still only attach to tagged versions, so they can be written ahead of a
release or corrected afterwards without tagging a new version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Hub reads the Cross Events repo's v* tags (each a release, the newest the
latest version) and the client notes from WHATS-NEW.md as of the newest tag,
every 15 minutes and on Sync now. Urgent/security in a version heading marks it
urgent. Repo address, notes path and an optional encrypted token on the
Releases page; manual releases only when no repo is set.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Releases page: each Cross Events version with notes and an urgent flag; the
newest is the latest version (moved off Settings; the old setting becomes the
first release). Installs get the notes for every newer version.
- Notices page: a banner for site admins and supervisors (with a time window),
an email to the customer and admin contact, or both; for every install or
chosen ones.
- POST /api/installs/update-request/cancel resolves the request and emails Joshua.
- Protocol doc: releases and notices in the heartbeat/register replies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Installs, Customers, Alerts and the audit log get a search box and
25-per-page paging (Installs also a health filter); install History pages too.
- Settings is split into Releases and alerts / Email / Login and security /
Audit log tabs, remembered in the URL hash.
- The side navigation is sticky at window height, so Sign out no longer
scrolls off long pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SMTP server, port, user, password and from address are now Hub settings in
the database instead of SMTP_* in .env. The password is encrypted with
HUB_ENCRYPTION_KEY and never sent to the browser; a blank field keeps it.
POST /api/admin/settings/smtp-test logs in with the form's values (saved or
not) and sends a test email, returning the server's reason on failure; it is
rate limited and audited. On first start an existing SMTP_* setup is copied
into Settings once. The audit log no longer records the SMTP password.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ls1vMaqhrehXcHJe32jLL9
The heartbeat's stats.campuses and stats.campusCount were stored but never
shown. The Usage card now has a Campuses row: Off, or On with the active count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hope Events is now Cross Events. Protocol identifiers (hel1. tokens, CEH- keys)
are unchanged so existing installs keep working.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>