Finalizes the docs section after an adversarial audit (code review + per-page fact-check + coherence critic) and two content requests. - Accuracy: fixed 10 invented cross-link slugs, the admin-vs-board gating claims the verifiers caught (permissions matrix, /settings, invites, onboarding, connect-payments, proposal withdraw, Stripe reconciliation, member fields, door.operate), and 2 issues in the new pages (project area-at-creation, forum thread-delete role). - Coverage: added 5 how-to pages so every module is documented (recurring Stripe dues, tasks & chores, projects, comms & forum, ops knowledge base + secrets vault). 34 pages total. - Screenshots: 12 captioned app screenshots under public/docs-media/, embedded as figures. Each tutorial now has 2-3 step screenshots. - Style: removed all em-dashes/en-dashes/ellipses from the docs (natural ASCII punctuation). - Handoff (docs/HANDOFF-audit-cleanup.md) updated with the current state. typecheck 0 · lint 0 errors · build ok (all 34 /docs pages prerendered)
6.5 KiB
The classes, certifications, and equipment modules share one spine: a certification type awarded by completing a class can gate who may reserve a piece of equipment. This page is the exhaustive reference for their data model, statuses, capacity rules, and the permissions that guard each action.
Classes
A class is a per-space offering; a session is a scheduled occurrence; a signup is one member's place in a session. Members browse and sign up at /classes; managers create classes and sessions at /classes/manage.
Class fields
| Field | Notes |
|---|---|
title |
1-200 chars, required |
description |
optional |
payment_link |
optional http(s) URL only; a manual link, no live payment integration |
capacity |
optional default per-session capacity; > 0; null = unlimited |
grants_certification_id |
optional; completing a session of this class can award this certification |
required_form_id |
optional; a published form that must be on file before signup |
is_active |
archive flag; inactive classes are hidden from members |
Session fields
class_sessions carry starts_at, optional ends_at (must be >= starts_at), location, an optional capacity override, notes, and a status.
| Session status | Meaning |
|---|---|
scheduled |
open; the default |
cancelled |
closed to signups; signed-up members are emailed |
completed |
run and closed; set only via completion, which fires cert awards |
Signup and waitlist rules
- Effective capacity = the session
capacityif set, else the classcapacity, else unlimited. - A new signup is
registeredwhen the current registered count is below effective capacity, otherwisewaitlisted. - At most one non-cancelled signup per member per session; cancelling leaves the row as history and a re-signup is allowed.
- When a
registeredmember cancels and a seat frees, the earliest-signed-upwaitlistedmember is promoted toregisteredand emailed. - Signup and cancel run inside per-session transactional functions (
class_signup_tx/class_cancel_tx) so concurrent signups cannot over-enroll and concurrent cancels cannot double-promote.
| Signup status | Set by |
|---|---|
registered |
signup below capacity, or waitlist promotion |
waitlisted |
signup at or above capacity |
cancelled |
member or manager cancel |
Signing up needs no permission, only space membership. If the class has a required_form_id, the member must have a completed submission on file first; a manager acting with override bypasses this and can sign another member up.
Attendance and completion
Instructors mark attended per signup and complete a session. Completing sets the session to completed; if the class has grants_certification_id, the certification is awarded to every attended, non-cancelled member. That award goes through the normal certifications path, so it only succeeds if the acting instructor also holds certifications.grant; otherwise completion still succeeds and the response reports that certificates were not issued.
Class permissions
| Permission | Grants |
|---|---|
classes.manage |
create/edit/archive classes; schedule/cancel/delete sessions |
classes.instruct |
view attendees, mark attendance, complete a session |
Both seed to the board role by default.
Certifications
A certification is a per-space type (name unique case-insensitive, description, optional validity_months, is_active). A grant (member_certifications) awards one type to one member. Managed alongside members at /certifications and /members.
expires_atis computed and stored at grant time from the type'svalidity_months(null = never expires). Later edits to the type never change existing grants.- At most one active (non-revoked) grant per member per type; revoked grants stay as history and a re-grant is allowed.
- Revoking is a soft revoke (
revoked_at,revoked_by,revoked_reason); grants are never hard-deleted by clients. - Renewing a non-revoked grant resets
granted_atand recomputes expiry. A revoked grant is terminal, issue a fresh grant.
| Cert status | Rule |
|---|---|
active |
not revoked, not expired |
expiring_soon |
expires within 30 days |
expired |
past expires_at |
revoked |
revoked_at set (always wins) |
| Permission | Grants |
|---|---|
certifications.manage |
create/edit/archive certification types |
certifications.grant |
award/revoke/renew grants; this is the "instructor" capability |
Equipment and reservations
Equipment is a per-space tool record; a reservation is one member's time window on one tool. Members browse and reserve at /equipment; managers maintain the registry at /equipment/manage. See Reserve equipment for the task walkthrough.
Equipment fields: name (1-200), description, location, asset_tag, is_active, an optional required_certification_id, and an operational status.
| Equipment status | Reservable? |
|---|---|
available |
yes |
maintenance |
no |
retired |
no |
Reservation rules
- Reservations use half-open
[starts_at, ends_at)windows;ends_atmust be afterstarts_atand cannot start in the past. - Only
reservedrows block;cancelledandcompletednever do. Tworeservedwindows on the same equipment may not overlap. Touching end-to-start does not overlap. - No-overlap is enforced in the database by a GiST exclusion constraint, so concurrent requests cannot double-book.
- If the equipment has
required_certification_id, the member must hold an active grant of it. A manager withequipment.manageoverride bypasses the cert gate and may book on another member's behalf, but override never bypasses an operational status block.
| Reservation status | Meaning |
|---|---|
reserved |
active; blocks overlaps |
cancelled |
released; member or manager |
completed |
past/closed |
Reserving needs only membership. equipment.manage covers registry CRUD, status changes, and adjusting or cancelling any reservation. Equipment that has reservations must be archived rather than deleted; likewise a class with sessions and a session with signups.
Cert-gating ties the modules together: grant a certification on class completion, require that certification to reserve a machine. Roles and the seeding of these permissions are covered in Roles and permissions.