A tier add aligns every organization holding a live provision of the product inside one transaction that holds the exclusive rendezvous, so its hold grew with the product's holders, and it locked their pools in the order their provisions were created, the one catalog path that did not lock in pool id order (#194). It checked the product outside its transaction, answered "Product not found." for any failed read, showed the database's text when a pool already held a rung, and answered a lock wait with "see server logs" (#216). AddTier now runs on runPlanAct. Inside the exclusive transaction it: - reads the product and refuses one that is missing ("Product not found.") or not published; any other failed read is a failed add; - counts the holders and refuses above planActHolderCap, naming the count and the limit, and, when more than half hold the product through an org type's default on a ladder, the way through: a default change with Migrate; - locks the holders' pools in ascending id, reads their provisions again, records the act (tier_added, with names read inside) and inserts the tier; - reads ListTierAddCollisions for the locked pools and refuses the first pool, in pool id order, that already holds a rung on the ladder or holds two live provisions of the product, naming the organization and the product, before any alignment; - aligns each pool and materializes it once, with a reason that names the ladder rather than its id. planActHolderCap is 200. A timed run on PostgreSQL 18.1, one run per holder count from 50 to 3,200, measured a removal with migrate at 2.2 to 2.6 ms per holder and an add at 0.7 to 1.0 ms. The removal, which takes the same cap in a later change, binds: 200 holders hold the rendezvous for about half a second. The timing test lifts the cap so it can still measure past it. CreatePlanLadderTier only parses, calls and renders. A lock wait or a deadlock at any step answers "Another change collided with this one; try again." A collision answers under the product field. Every other failure, including a CF003 the collision read should have prevented, answers "Failed to add tier. Reference: {request id}." and logs the step and the driver text through the request's logger; the driver text is never shown. Goldens: add-aligns-a-live-provision and tier-change-during-conferral/ a-tier-add gain the act row, the ascending pool locks and the ladder's name in the reason; add-begin-fails answers with the reference and logs the step; add-collides-with-a-held-rung is refused by the collision read with no alignment statement; contention's add answers the collision sentence. Placeholders renumber in three of them because a request id or a provision id moved. New: add-above-the-limit, add-above-the-limit-default-sourced, add-product-unread and add-product-held-twice. The full suite passes.
title, audience, summary
| title | audience | summary | |||
|---|---|---|---|---|---|
| Documentation index |
|
Index of member-console documentation, grouped by audience, plus the front-matter convention every doc follows. |
Documentation
Every document in this directory carries YAML front matter declaring its audience, so readers can find what's for them and contributors know who they're writing for.
Front-matter convention
Start each doc with a front-matter block:
---
title: "Human-readable title"
audience: [admin, developer] # one or more of: developer, admin, user (primary first)
summary: "One sentence describing what the doc covers."
---
The three audiences:
- developer — contributing to or understanding the codebase: architecture, design decisions, dev setup, testing, UX research and conventions, the provider-extension contract.
- admin — hosting and operating an instance: installing, configuring an identity provider, building the image, generating secrets, running the service.
- user — the general public or a member using a running service. (None yet — the tag is reserved for member-facing docs.)
List the primary audience first; a doc may name more than one.
For administrators — hosting & operating
- Production Deployment — the sequenced path from a fresh host to a running instance; start here.
- Environment Reference — every configuration key with its default and
MC_*override. - Settings and Configuration — why software uses two words for what a program is told, and how this console applies the rule.
- Hosting member-console — build the image and generate secrets.
- Deployment Architecture — how the console fits alongside a public site and an identity provider.
- Identity Provider Setup — configure an OIDC IdP for login.
- Temporal Authorization Setup — emit the
permissionsclaim Temporal's JWT authorizer expects. - Plan Management — operator guide to plan ladders and grants.
- Stripe Integration — flags, secrets, webhooks, and purchasability.
For developers — contributing & internals
- Database Management — goose migrations and sqlc.
- Database Locks — every advisory and serializing row lock, how each key is built, and the order each path takes them in.
- Design System — UI conventions.
- Domain Model Cards — the model catalog: one card per domain model with invariants, dimensions, and traps.
- FedWiki Integration — provisioning via the FarmManager API.
- Go Conventions — where a rule and an act live, transactions and locks, output order, error handling, and dead code.
- HTMX Setup — HTMX under a strict CSP.
- Identifiers — IDs, names, and keys: which entities carry a key, its grammar and scope, and how seeds and lookups use it.
- Operator Information Architecture — the operator panel's IA contract.
- Operator UX Conventions — form and action conventions.
- First-Contact UX Walk Process — the repeatable method for walking the console as a stranger.
- First-Contact UX Rubric — the instrument that method scores with: the A–G question bank, the walker protocol, and the screen coverage checklist.
- Agent Runner — how an agent from another model family reviews or ideates on the code inside a disposable copy: what contains it, how a task is shaped, and what a finding must carry before it counts.
- Operator UI Accessibility Baseline — what operator-UI changes are diffed against.
- Building an Integration — adding a new integration.
- Testing — the test taxonomy and how to run each kind, plus the gates:
make lint(page-anatomy rules and the Go static checks) andmake screens(contact sheets at two widths).
For users
No member-facing documentation yet.
One page per rule
A rule is written on the one page that owns it. Another page that needs the rule links to that page instead of restating it, because two copies of a rule are edited separately and drift apart.
Where things are not
Research, drafts, audits, walkthrough evidence, and other records of how a
decision was reached are not documentation; they stay in a local notebook
that git ignores, so a clone never carries them. When a decision lands,
whatever a reader still needs is written into this directory, which holds
the result without the history. The rule for every kind of file is in
status/MAINTAINING.md.