Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c432edbae2 |
No files matched your search
@@ -24,6 +24,7 @@ Read it on the web here: <https://git.inference.coop/co-op/ops-docs>
|
|||||||
| Path | Contents |
|
| Path | Contents |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `operator-token-runbook.md` | The Cloudron token model (agent vs portal, admin vs webhook), how to rotate each without breaking the stack |
|
| `operator-token-runbook.md` | The Cloudron token model (agent vs portal, admin vs webhook), how to rotate each without breaking the stack |
|
||||||
|
| `membership-allowances.md` | How a member's monthly allowance renews, how a lapse is handled, and the join-day anchoring rule |
|
||||||
| `maintenance/chat-task-models.md` | The small pinned model used for chat titles/tags/suggestions |
|
| `maintenance/chat-task-models.md` | The small pinned model used for chat titles/tags/suggestions |
|
||||||
| `maintenance/librechat-sandbox.md` | Operating the LibreChat evaluation instance (config, overlay image, key sync, pitfalls) |
|
| `maintenance/librechat-sandbox.md` | Operating the LibreChat evaluation instance (config, overlay image, key sync, pitfalls) |
|
||||||
| `incidents/` | Post-incident write-ups, one file per incident |
|
| `incidents/` | Post-incident write-ups, one file per incident |
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Membership allowance renewal and lapse
|
||||||
|
|
||||||
|
Operator-facing record of the decision taken **2026-11-04** on how a member's
|
||||||
|
monthly allowance renews, and how a lapse is handled. The member-facing summary
|
||||||
|
is `co-op/support#44`; the code lives in `co-op/member-portal`.
|
||||||
|
|
||||||
|
## The rule
|
||||||
|
|
||||||
|
- **Renewal is decided by asking Open Collective, on our own schedule.** A
|
||||||
|
scheduled reconciliation asks whether the member has a *live recurring
|
||||||
|
contribution* (order status `ACTIVE` or `PROCESSING` — a payment in flight is
|
||||||
|
not a missed payment). Renewal is a decision of the sweep, not a side effect of
|
||||||
|
webhook delivery, so a lost webhook costs a delayed renewal, never a silently
|
||||||
|
skipped month.
|
||||||
|
- **Anchor to the member's join day, never the payment date.** Open Collective
|
||||||
|
aligns a whole collective's charges onto one common billing day, so anchoring
|
||||||
|
to a charge lets an early charge move the boundary and skip a cycle. The
|
||||||
|
member's join day is stored (`members.anchor_day`) and the reset is pinned to
|
||||||
|
its next occurrence.
|
||||||
|
- **Grace before deactivation.** One reminder email per cycle; deactivate only
|
||||||
|
after `PAYMENT_GRACE_DAYS` unpaid.
|
||||||
|
- **Deactivate by removing group access and stopping renewal, keeping the
|
||||||
|
account**, so a returning payer resumes cleanly at the next cycle.
|
||||||
|
- **Log every decision** (`allowance_log`) with the Open Collective evidence —
|
||||||
|
renewed / reminded / deactivated, plus the payment date or its absence — so a
|
||||||
|
dispute is answered from a record, not reconstructed.
|
||||||
|
|
||||||
|
## Scope: monthly only
|
||||||
|
|
||||||
|
Verified **2026-11-04** that there are **no annual contributors**: 104 orders on
|
||||||
|
Open Collective, 87 MONTHLY and 17 ONETIME, zero annual, and no order has a
|
||||||
|
charge gap over 45 days. Only the monthly case is implemented. One-time
|
||||||
|
contributions are not an allowance cycle — they top up the non-expiring credit
|
||||||
|
balance and stay in the existing credits model.
|
||||||
|
|
||||||
|
## Operating it
|
||||||
|
|
||||||
|
- `ALLOWANCE_POLICY` = `report` (default) | `on`. `report` computes every
|
||||||
|
decision and changes nothing; `on` performs renewals and sends the reminder.
|
||||||
|
- `ALLOWANCE_DEACTIVATE` = `off` (default) | `on`. Gated separately so renewals
|
||||||
|
and reminders can run before anyone loses access.
|
||||||
|
- `PAYMENT_GRACE_DAYS` (default `7`).
|
||||||
|
- Manual check: `POST /admin/allowance?mode=report` (`X-Admin-Token`) is a no-op
|
||||||
|
report; `mode=test&to=<addr>` emails one sample reminder; `mode=send` requires
|
||||||
|
`ALLOWANCE_POLICY=on`.
|
||||||
|
|
||||||
|
## The bug that prompted it
|
||||||
|
|
||||||
|
A member who joined on the 15th was charged on the 2nd (Open Collective's common
|
||||||
|
billing day). The reset rule re-anchored his allowance to the new payment date
|
||||||
|
and pushed his renewal from the 14th to the 2nd of the next month — skipping the
|
||||||
|
reset he was owed while he had already paid. The fix is both changes above:
|
||||||
|
anchor to the join day, and decide renewal on a schedule rather than on the
|
||||||
|
payment.
|
||||||
Reference in new issue
Block a user