docs: bring CLAUDE.md in line with the current repositories and product rules

Core's agent guidance still described modules living in this monorepo and
manifest v7, and said nothing about the product rules that now govern every
change. Record that first-party modules live in their own Zayin repositories
and install as Module Packages, that the parent ROADMAP.md and DESIGN.md are
authoritative for product direction, the ownership, branding, token, dark-mode
and no-native-dialog rules, that display pairing is transitional until Stage 1,
and the branch-per-PR, no-push-to-main, and no-release-tag workflow.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-10-12 21:31:36 -05:00
co-authored by Claude Opus 5.5
parent ae976ca229
commit 06bad2fe36
+57 -15
View File
@@ -6,27 +6,60 @@ contents, because restated details drift.
## What this repository is
Ekklesia is a modular, self-hosted church platform built as a strictly layered pnpm/TypeScript
monorepo:
Ekklesia is a modular, self-hosted church platform. **This repository is the platform** — Core, the
API, the Dashboard and display shell, and the public `@ekklesia/*` module-development packages — built
as a strictly layered pnpm/TypeScript monorepo:
- **Core** (`core/`) owns platform infrastructure: identity, database connectivity, migration
execution, module discovery/lifecycle, and other feature-agnostic services. Core never imports a
feature module, a surface, or an app.
- **Modules** (`modules/*`, template at `templates/module`) are independently versioned product
packages. They own their own data and migrations, declare capabilities/permissions through
`@ekklesia/contracts` and `@ekklesia/module-sdk`, and must never import Core, another module, or a
surface directly. Per ADR 0021 a module owns its UI; manifest v7 permits independently optional
primary and full-viewport display artifacts, authored in React against the same role-neutral
`@ekklesia/module-ui-sdk` ABI. Ekklesia mounts each through a separate surface role, while
`pnpm boundaries` still rejects every non-React UI framework and non-`.tsx` presentation source.
execution, module discovery/lifecycle, devices, and other feature-agnostic services. Core never
imports a feature module, a surface, or an app.
- **Modules** are independently versioned product packages. First-party modules live in **their own
repositories** (Signage is `Zayin/Signage`), build against the published `@ekklesia/*` packages
(ADR 0053), and reach an installation as a Module Package (ADR 0049) installed into module storage
outside the image (ADR 0048). No module source lives in this repository; `templates/module` is the
example, and `modules/` is only an optional, ignored local installed-modules directory. A module owns
its data, migrations, and **its own domain UI** (ADR 0021), declares capabilities/permissions through
`@ekklesia/contracts` and `@ekklesia/module-sdk`, and never imports Core, another module, or a
surface. Manifest v8 permits independently optional primary and full-viewport display artifacts,
authored in React against the role-neutral `@ekklesia/module-ui-sdk` ABI; database access is the
Module Database ABI v1 (ADR 0050).
- **Surfaces** (`surfaces/*`) own the containing application shell, navigation, and every
presentation concern a module does not. They consume public API/client contracts only, never Core
or module internals directly.
presentation concern a module does not. The shell **hosts** module UI through the generic loader;
it never rebuilds a module's domain screens. Surfaces consume public API/client contracts only.
These boundaries are enforced by `pnpm boundaries` (`scripts/check-boundaries.ts`), not just
documented. Read `docs/architecture/repository-boundaries.md` and
`docs/architecture/platform-architecture.md` before proposing any change that crosses a layer.
## Product direction lives beside this repository
The current roadmap and product/interface design contract are `ROADMAP.md` and `DESIGN.md` in the
parent development directory (`../ROADMAP.md` and `../DESIGN.md` from a checkout in the standard
`~/development/ekklesia/` layout). They are deliberately **not** committed here; do not copy them into
this repository to make them available. They are authoritative for product direction: read the
relevant stages and sections before designing a change. If this repository's documentation disagrees
with them, flag the conflict, correct the repository-local documentation where appropriate, and never
silently follow the stale text. Architectural decisions still change only through ADRs (below).
Rules from those documents that every change here must respect:
- **Ownership.** Modules own their domain data, behaviour, and UI. Shared resources — displays and
devices, accounts and identity, roles and authorization, branding, mail, push, storage providers,
and module installation/lifecycle — belong to the platform, and modules consume them.
- **Branding.** Normal user-facing UI never hard-codes "Ekklesia"; product identity comes from
installation branding (ADR 0046). Package names, diagnostics, logs, and developer tooling may.
Existing hard-coded shell strings are known debt for Stage 1, not a pattern to copy.
- **Visual direction.** Simple, minimal, and calm; responsive for phone, tablet, and desktop; light,
dark, and system modes. Normal UI colours come only from the shared design tokens
(`@ekklesia/design-tokens`, ADR 0039) — never a hard-coded colour.
- **No browser-native dialogs.** `window.alert`, `window.confirm`, and `window.prompt` are prohibited
in product UI. Destructive actions use in-product confirmation proportional to their impact.
- **Displays are transitional.** Displays are platform-owned. Today's device pairing (the Dashboard
sidebar's *Display devices* panel) and Signage's own display roster are a transitional
implementation that Stage 1 migrates to **Settings → Displays**. Fix defects in them, but do not
build the Stage 1 Settings, global Displays, theme editor, module installer, or responsive shell
redesign early, and keep existing paired displays working across any change.
## ADRs are authoritative
`docs/architecture/decisions/` records durable architectural decisions. **Accepted ADRs are
@@ -43,6 +76,7 @@ At minimum, read the current versions of:
- `docs/architecture/decisions/README.md` and every ADR relevant to your change
- `docs/architecture/platform-architecture.md` and `docs/architecture/repository-boundaries.md`
- `README.md` (current platform status — what is and is not implemented)
- `../ROADMAP.md` and `../DESIGN.md` (current product direction; see above)
- `docs/development/repository-workflow.md` and `docs/development/testing.md`
- `CONTRIBUTING.md`
@@ -52,8 +86,16 @@ your own memory of a prior session** — treat stale assumptions as a bug to cat
## Working conventions
- Work on a clean branch off an up-to-date `main`; never commit or push directly to `main`; never
change branch-protection settings.
- The canonical repositories are on the church Gitea under the `Zayin` organization:
`ssh://[email protected]:2222/Zayin/Ekklesia.git` (this one), `Zayin/Signage.git`, and
`Zayin/Classroom_Desktop.git`. A local clone may be behind the server: `git fetch --prune --tags`
and branch from `origin/main`, never from whatever is checked out.
- One branch per PR, off an up-to-date `origin/main`. Never commit or push directly to `main`, never
merge your own PR, and never change branch-protection settings.
- Never create or push a release tag. Release tags belong to the human maintainer.
- A change that needs both a platform contract change and a module change is two PRs: Core first, on
its own branch, with the compatibility boundary stated explicitly; then the module. Do not copy
platform logic into a module to avoid making the correct Core change.
- Keep PRs focused on one bounded slice. Record major architectural changes in an ADR rather than
burying them in an implementation.
- Add or update tests when you change a contract or architectural rule. New behavior needs new