Files
member-console/README.md
T
cgalo5758 fe19ee415c Add CLA and SPDX headers, fix docs
- Pin Dockerfile to Go 1.23 to match go.mod
- Record README front-door audit findings
2026-09-07 21:32:14 -05:00

175 lines
8.3 KiB
Markdown

# member-console
**One system for memberships and the hosted services they pay for.**
member-console is open-source software for offering hosted services on a paid
membership. In one place it handles the pieces that otherwise get stitched
together by hand — who each member is, what they're entitled to, what they pay —
then turns that into the actual, metered services running on their behalf, kept
in sync as members join, upgrade, and leave. New kinds of service attach through
a shared contract instead of reshaping how membership or billing work, so the
offering can grow on one foundation.
It has two sides: an **operator panel** where staff run the service, and a
**member panel** where members sign in to manage their own plan and workspace.
_Developed by the Wiki Cafe Multistakeholder Cooperative, and built for any organization to run._
![Operator overview — at-a-glance deployment counts, recent activity, and system status](docs/images/operator-overview.png)
_The operator landing surface_
> **Status: pre-production.** The engine is feature-complete for its first
> service tiers, but this is not yet a hardened, turnkey deployment. Expect
> rough edges in first-run setup. [docs/production-deployment.md](docs/production-deployment.md)
> sequences a real path to a running production instance, but it is a
> self-hoster's guide to follow and adapt, not a one-command install — the
> test stack remains the fastest way to see the console running. See
> [`status/`](status/) for the honest state of every milestone.
License: **AGPL-3.0-only**, with commercial licensing available — see
[LICENSE](LICENSE) and [COMMERCIAL.md](COMMERCIAL.md).
## What it does
- **Governance spine** — identity (via any OIDC provider) → organization → workspace,
with auto-provisioning of a default workspace for new members.
- **Entitlements** — grants resolve to numeric limits (e.g. FedWiki site count and
storage) materialized per resource pool; plan ladders model upgrade/downgrade
paths with a generic transition primitive.
- **Billing** — Stripe is the billing execution engine. Products, prices,
customers, subscriptions, and invoices are mirrored via a webhook pipeline;
the console never holds card data.
- **Integrations** — an integration contract (manifest, namespaced resource
keys, lifecycle verbs) lets a new hosted service conform without reshaping the
operator panel or entitlement layer. FedWiki (wiki site provisioning) and
Discourse (forum group membership) are the two conforming integrations today.
## Architecture
- **Go 1.23**, server-rendered **HTMX** multi-page app — no SPA framework — under a
strict Content-Security-Policy (`script-src 'self'`, `style-src 'self'`; all JS
and CSS is self-hosted, no inline `<script>`/`style=`).
- **PostgreSQL** with a schema-ownership boundary between core and integrations:
the console's own data lives in a single `core` schema, and each integration
owns its schema (`fedwiki`, `discourse`, `stripe`) and its own migration
ledger — so adding one renumbers nothing (core-first is the only ordering
rule). Queries are
generated with **sqlc**; migrations run with **goose**.
- **Temporal** for durable workflows (provisioning, integration sync, billing
sweeps).
- **OIDC** for authentication — member-console is identity-provider-agnostic and
works with any OIDC-compliant IDP (the test stack ships Keycloak).
Full documentation is indexed in [`docs/`](docs/README.md), grouped by audience
(developer / admin / user). Highlights:
[deployment architecture](docs/deployment-architecture.md),
[hosting](docs/hosting.md),
[building an integration](docs/building-an-integration.md),
[database management](docs/database-management.md), and [Stripe](docs/stripe.md).
## Running it
**What you need:**
- **At least one conforming integration** — FedWiki (wiki site provisioning)
and Discourse (forum group membership) are the two available today (see
"What it does" above); a deployment with neither has no product to
actually deliver to a paying member. See
[fedwiki-setup.md](docs/fedwiki-setup.md) and
[discourse-setup.md](docs/discourse-setup.md).
- An **OIDC identity provider** — any OIDC-compliant provider; the console
authenticates members and operators against it and never stores passwords
itself. See [identity-provider-setup.md](docs/identity-provider-setup.md).
- **PostgreSQL**, **Valkey**, and **Temporal** — the console's own data
store, session store, and durable-workflow engine (provisioning,
integration sync, billing sweeps). See
[database-management.md](docs/database-management.md) and
[deployment-architecture.md](docs/deployment-architecture.md).
- **Stripe** — optional, only needed to sell paid products; a deployment
offering only free or unmetered products can skip it. See
[stripe.md](docs/stripe.md).
**First run, in order:**
1. Deploy the console and the dependencies above — see
[docs/production-deployment.md](docs/production-deployment.md) for the
sequenced path from a built image to a running instance.
2. Sign in as an operator (the account holding the `operator-member` role
configured on the identity provider).
3. Follow the in-app setup checklist at `/operator/setup`, which walks
through everything still needed to reach a deliverable product.
## Quickstart (local development)
Prerequisites: Docker (with Compose), Go 1.23+, and `make`.
The test stack brings up Postgres, Valkey, Temporal, and Keycloak in
containers, then runs the console from source against them. All commands run
from the `test/` directory:
```bash
cd test
./bootstrap-stack.sh # generate a per-worktree .env with collision-free ports
docker compose up -d # Postgres, Valkey, Temporal, Keycloak
set -a; . ./.env; set +a # load the generated host ports / secrets
go run .. start --config mc-config.yaml
```
Integrations are opt-in, not baked into the stack: a FedWiki farm or a live
Discourse forum is composed by adding its name to the `COMPOSE_PROFILES` knob
in the generated `test/.env` (and uncommenting that integration's `MC_*` block
in the same file). The console runs fine with neither.
`bootstrap-stack.sh` prints the URL table it allocated. With default ports the
console is at **http://member-console.localhost:9481**; sign in to the operator
panel as `alice` / `password`.
> On a fresh stack the console rides out Temporal's cold-start with a bounded
> connect retry, so the first `start` may pause briefly before the server comes
> up — no re-run needed.
See [`test/AGENTS.md`](test/AGENTS.md) for the full stack contract (idempotency,
Stripe webhook constraints, teardown, running multiple worktrees concurrently).
## Project status & roadmap
See [`status/`](status/) for the development roadmap, milestones, and notes.
Substantial changes are tracked as [OpenSpec](https://openspec.dev) proposals
under [`openspec/`](openspec/).
## Contributing
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the
development workflow, building and testing, and the project conventions.
## Security
To report a vulnerability, see [SECURITY.md](SECURITY.md). Please do not open a
public issue for security reports.
## License
member-console is free software, licensed under the GNU Affero General Public
License v3.0 (`AGPL-3.0-only`). See [LICENSE](LICENSE) for the full text.
AGPLv3 is and will remain the default license for this project. If you use,
modify, or deploy member-console — including over a network — you must comply
with the AGPLv3, which includes making the corresponding source available to
users of the service.
If the AGPLv3 does not fit your needs — for example, you want to embed
member-console in a proprietary product or run it as a hosted service without
the AGPL's source-sharing obligations — a separate commercial license is
available. See [COMMERCIAL.md](COMMERCIAL.md).
As the sole copyright holder, Christian Galo can offer member-console under both
the AGPLv3 and separate commercial terms. Contributions are accepted under a
Contributor License Agreement that preserves that ability ([CLA.md](CLA.md);
how to sign is in [CONTRIBUTING.md](CONTRIBUTING.md)), and commercial licenses
fund continued development. Anything already published under the AGPLv3 stays
under the AGPLv3; the public license is not withdrawn retroactively.
Third-party components redistributed in this repository keep their own
licenses. See [NOTICE](NOTICE).