Compare commits

..
Author SHA1 Message Date
joshuaandClaude Opus 5.5 cc855ec8bb Docs: Hub 2.0.0 released (phase 1); hub-protocol.md with protocol v2
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 09:10:33 +02:00
joshuaandClaude Opus 5.5 0a9b08e1fd Merge branch 'docs/sites-folder'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 14:54:05 +02:00
3 changed files with 55 additions and 15 deletions
+12 -9
View File
@@ -1,7 +1,8 @@
# Handover — where things stand and how to carry on
Last updated: 2026-11-04, after **2.1.1** (deployed), Hub **1.7.0** and **contracts 1.0.0**;
ROADMAP-v3 updated for the monorepo move and the `crosscode` deploy script (decisions 21–24). **The plan from here is
Last updated: 2026-11-05, after **2.1.1** (deployed), **Hub 2.0.0** (released, not deployed yet),
**contracts 1.1.0** and the crosscode-site address prices (not deployed yet); ROADMAP-v3 updated for
the monorepo move and the `crosscode` deploy script (decisions 21–24). **The plan from here is
[ROADMAP-v3.md](./ROADMAP-v3.md)** (Accounts, Church Website, Church App, Cross Code Hub; decisions
table near the end). How Cross Events got to 2.x is in [ROADMAP-v2.md](./ROADMAP-v2.md); the round
before that in [FEATURES-ROUND-1.md](./FEATURES-ROUND-1.md).
@@ -95,13 +96,15 @@ encrypted settings unreadable or break existing installs.
crosscode.co.za, with prices) is live. Build order (§9):
- **0 — contracts 1.0.0: released 2026-11-04** (`../crosscode-platform`, tag `contracts@1.0.0`):
`crosscode.event/1`, `crosscode.church/1`, `crosscode.identity/1`, Hub protocol v2, generated
JSON Schema in `packages/contracts/schemas/`. Not published to Gitea's package registry, and
won't be (decision 22).
- **1 — Hub 2.0.0** (`../events-hub`): Cross Code Hub — products, one licence per product,
**one install of each product per customer**, domain per customer, bundles, sibling discovery,
**releases per product** (Events from `crosscode-platform` `events@…` tags, keeping the
`hope-events` `v…` releases) **with requirements** (`— requires accounts 1.2.0`, Request update
disabled until met). Contracts as `vendor/crosscode-contracts-1.0.0.tgz` (ROADMAP-v3 §2, §5).
JSON Schema in `packages/contracts/schemas/`. **1.1.0** (2026-11-04) adds `requires` on Hub
releases. Not published to Gitea's package registry, and won't be (decision 22).
- **1 — Hub 2.0.0: released 2026-11-05** (`../events-hub`, tag `v2.0.0`; plan and what each step
did in its `docs/HUB-2.0-PLAN.md` and CHANGELOG): products and one licence per product, protocol
v2 next to v1 (Linked products), releases per product with requirements, billing per church
(bundles, founding, Website storage, App tiers, prorating), the church's address, AI per church,
dashboard per product. **Deploying it:** `events-hub/deployment.md` → "Upgrading to 2.0" (run
`check-hub2` first). crosscode-site has the address prices (merged, deploy it too). Then
installs show up per product; Cross Events 2.1.x keeps speaking protocol 1 until 2.4.0.
- **1b — Cross Events 2.2.0: moves into the monorepo** as `apps/events` with its history, and the
**`crosscode` script** (`deploy <church> [events] [website] [app]` — Accounts always —,
`status`, `install`, `adopt`) replaces `scripts/deploy.sh` / `install.sh`. Run
+1 -1
View File
@@ -562,7 +562,7 @@ place.
| Phase | Version | What | Why this order |
|-------|---------|------|----------------|
| 0 | contracts 1.0.0 | `crosscode.event/1`, `crosscode.church/1`, `crosscode.identity/1`, Hub protocol v2: schemas, generated JSON Schema, docs, sample payloads, the monorepo set up. **Released 2026-11-04** | Everything else depends on them |
| 1 | **Hub 2.0.0** | Cross Code Hub: products, licence per product, per-customer billing with bundles, protocol v2 (v1 still accepted), sibling discovery, AI usage per product, **releases per product with requirements** (§5), contracts as a committed file (§2) | Must exist before a second product is sold, and before Events releases come from the monorepo |
| 1 | **Hub 2.0.0** | Cross Code Hub: products, licence per product, per-customer billing with bundles, protocol v2 (v1 still accepted), sibling discovery, AI usage per product, **releases per product with requirements** (§5), contracts as a committed file (§2). **Released 2026-11-05** (crosscode-site address prices merged) | Must exist before a second product is sold, and before Events releases come from the monorepo |
| 1b | **Cross Events 2.2.0** | **Moves into the monorepo** as `apps/events`, with its git history (merged in, not copied); its packages become workspaces; the **`crosscode` script** (`deploy`, `status`, `install`, `adopt`; §8) replaces `scripts/deploy.sh` and `scripts/install.sh`; every install moved with `crosscode adopt`; `hope-events` archived. No feature changes, so a problem is clearly the move | Before more products, so every product is released and deployed the same way from the start |
| 1c | **Cross Events 2.3.0** | **Authenticator app 2FA** (TOTP) next to email and WhatsApp, with recovery codes; admins can see which method each staff account uses | Independent and useful now; the Accounts migration later carries it over |
| 2 | **Cross Events 2.4.0** | Reports `product: "events"` (protocol v2), **Linked products**, the event feed (publish + show events from siblings), `packages/seo` (§11) with canonical links for imported events | Small; ready for when the Website exists |
+42 -5
View File
@@ -1,9 +1,13 @@
# Hub protocol (version 1)
# Hub protocol (versions 1 and 2)
The contract between a **Cross Events install** (the church's site) and the **Cross Events
Hub** (`events-hub.crosscode.co.za`). A copy of this file lives in both repositories
(`joshua/hope-events` → `docs/hub-protocol.md`, `joshua/events-hub` → `docs/hub-protocol.md`);
change both together.
The contract between an **install** (one of a church's products: Cross Events, Accounts, Church
Website, Church App) and **Cross Code Hub** (`hub.crosscode.co.za`; `events-hub.crosscode.co.za`
keeps working as an alias). Sections 1–5 describe **version 1**, which Cross Events 2.1 speaks;
**[version 2](#6-protocol-version-2-hub-20)** (every product, Hub 2.0) is section 6. A copy of this
file lives in both repositories (`joshua/hope-events` → `docs/hub-protocol.md`,
`joshua/events-hub` → `docs/hub-protocol.md`); change both together. From Hub 2.0 the formats are
defined once, in `@crosscode/contracts` (`crosscode-platform/packages/contracts`, `src/hub.ts`,
with JSON Schema and samples).
Principles:
@@ -288,3 +292,36 @@ grace starts). Blocking the Hub can't keep a suspended licence active for more t
fields to a heartbeat or a token doesn't need a new version — both sides ignore fields they
don't know.
- The Hub accepts protocol `N` and `N-1`; anything else is `400 UNSUPPORTED_PROTOCOL`.
## 6. Protocol version 2 (Hub 2.0)
The formats are in `@crosscode/contracts` (`hub.registerRequestSchema`, `hub.heartbeatRequestSchema`,
… with JSON Schema in `schemas/hub-*.json` and samples in `samples/hub-*.json`). The Hub accepts
versions 1 and 2 (`/api/public-key` lists `[1, 2]`); a v1 request is treated as Cross Events and
answered exactly as in sections 1–5. Signing, offline licence checks, update requests and AI calls
are as in version 1.
What version 2 changes:
| | Version 1 | Version 2 |
|---|---|---|
| Who | Cross Events | Every product: `product` is `events`, `accounts`, `website` or `app` |
| Licence keys | `CEH-…` | `CEH-` Events, `CCA-` Accounts, `CCW-` Website, `CCP-` App |
| Register | as §2 | adds `product` (must match the licence: `409 WRONG_PRODUCT`) and `install.publicKey` (the install's Ed25519 public key, PEM) |
| Heartbeat | as §3 | adds `product` (must match the install: `409 WRONG_PRODUCT`); `stats` per product (Events as v1; Website: pages, messages, events, editors, `storage`; App: `activeMembers90d` band, modules, prayer coverage; Accounts: accounts, 2FA methods) |
| Replies | as §2, §3 | add `linkedProducts`: the church's other installs in use that have a public key, as `{ product, installId, url, publicKey }`, nothing else. Releases carry `requires` (below) |
| Bodies | checked by hand | checked against the contract schemas: `400 INVALID_REQUEST` with the field that's wrong; unknown fields are dropped |
| Licence token | as §4 | also `customerId` and `product` (still `v: 1`; a v1 install ignores them). `limits.aiMonthlyCapCents` is the church's cap |
**Releases per product.** An install is told its own product's releases and latest version. A
release can need a minimum version of a sibling (`— requires accounts 1.2.0` in its WHATS-NEW.md
heading): v2 replies carry it as `requires: [{ product, version }]`, and an update request answers
`409 REQUIREMENT_NOT_MET` (with `requirements: [{ product, version, current }]` and a message saying
what's needed) until the church's install of that product runs that version or later.
**AI.** The monthly cap and markup are the church's, shared by all its installs: a call from any of
them counts what all of them used this month.
**Moving an install to v2** (e.g. Cross Events 2.4.0): register again with `protocolVersion: 2`,
the product and a public key (same licence and address: same install id, new secret), then send v2
heartbeats. Nothing on the Hub needs changing.