Correct OC runbook: email null was a missing email scope, not a regression

This commit is contained in:
inference-bot committed 2026-09-22 15:50:27 -06:00
1 parent 16b4d6368c
commit d6e697a0c3
1 file changed
+19 -22
+19 -22
View File
@@ -66,32 +66,29 @@ Env vars for custom apps are set via:
- Cloudron CLI: `npm install -g cloudron` (install on your workstation, not the server), then `cloudron login my.inference.coop`. - Cloudron CLI: `npm install -g cloudron` (install on your workstation, not the server), then `cloudron login my.inference.coop`.
- Cloudron API docs: `docs.cloudron.io/api/`. - Cloudron API docs: `docs.cloudron.io/api/`.
## Open Collective email visibility can regress (Sept 2026) ## Open Collective: the bot token needs the `email` scope (Sept 2026)
The portal identifies members by email, read via the bot's OC personal token The portal identifies members by email, read via the bot's OC personal token
(`OC_PERSONAL_TOKEN`) as `collective.members.nodes[].account.email` with the (`OC_PERSONAL_TOKEN`) as `collective.members.nodes[].account.email` with the
`... on Individual { email }` inline fragment. This is normally populated `... on Individual { email }` inline fragment.
because the bot is an **admin** of the collective.
**Failure mode:** the GraphQL `email` field can flip to `null` for *every* **The `email` scope is load-bearing.** The bot's personal token must be minted
member — including the bot's own `me { email }` — while: with the `email` scope. Without it, the GraphQL `email` field returns `null` for
*every* member — including the bot's own `me { email }` — even though:
- the bot still authenticates and reports `isAdmin: true`, - the bot still authenticates and reports `isAdmin: true`, and
- the OC **admin CSV export still shows emails**. - the OC **admin CSV export still shows emails** (it's a separate, non-GraphQL
path; its `contributorEmail` column is not a GraphQL field).
When this happens, `fetch_members()` filters out empty emails and returns `[]`, **Symptoms when the scope is missing:** `fetch_members()` filters out empty
so the webhook can't provision anyone by email and the nightly sweep goes into emails and returns `[]`, so the webhook can't provision anyone by email and the
its empty-list fail-safe (skips, doesn't deactivate). Symptoms: a new member's nightly sweep goes into its empty-list fail-safe (skips, doesn't deactivate).
webhook fires cleanly but no "Sent email to …" log line follows, and no A new member's webhook fires cleanly but no "Sent email to …" log line follows,
Cloudron user is created. and no Cloudron user is created. (This is easy to misread as a "guest with no
email" problem — it is not; verify the scope first.)
**Diagnosis:** run `me { email }` with the bot token. `null` here (while **Diagnosis:** run `me { email }` with the bot token. `null` here while
`isAdmin: true`) confirms the regression is OC-side in the GraphQL layer, *not* `isAdmin: true` → the token is missing the `email` scope (or the scope was
a token rotation and *not* a lost admin grant. The CSV is the independent revoked). Fix: re-add the `email` scope to the token on Open Collective
ground-truth check. (Settings → Developers → Personal Tokens). No token rotation, no re-granting of
admin — just the scope.
**Interim workaround:** for any member who can't be provisioned by email, get
their address another way and onboard via the manual path — add to
`MANUAL_MEMBERS`, then `POST /admin/provision` (X-Admin-Token header). The
guest-with-no-email case is *not* the cause; verify with `me { email }` before
concluding a member is unreachable.