Only publish blocks that are still in force
docker-build-push / build-push (push) Successful in 4s

ipblock_registered and domain_blocked only ever meant "we posted this
block once" — they said nothing about whether it still exists. When the
API went live it was publishing 24 /32 ranges that had been removed by
hand on 2026-07-21, so ~17% of the IP list didn't block anything. That's
a bad thing to hand another admin an importer for.

app/reconcile_blocks.py fetches Mastodon's live Admin::IpBlock and
Admin::EmailDomainBlock lists and maintains a new block_active column on
both tables: off for rows whose block is gone or whose expires_at has
elapsed, back on for any that reappear. The API serves only active rows.
Re-registering a block reactivates its row, so a range the bot blocks
again after a manual cleanup comes back on its own.

A failed fetch changes nothing — not a 403 from a missing scope, not
Mastodon being down, not a half-failure where one list answers and the
other doesn't. An outage must never be read as "every block was
removed"; the list degrades to over-reporting rather than emptying
itself, and there's a test for each of those paths.

Needs admin:read:ip_blocks + admin:read:email_domain_blocks, added to
the live token in place (scopes updated on the existing Doorkeeper
token, matched by digest) rather than by minting and rotating, so the
token value is unchanged and .env needed no edit.
This commit is contained in:
pmb committed 2026-09-13 01:05:52 -07:00
1 parent 8966de2a1d
commit 8490048d2d
6 files changed
+370 -9

No files matched your search

+12 -1
View File
@@ -206,6 +206,17 @@ as an error; nothing else in the bot is affected).
report-triggered suspend override) will 403 (logged as an error; the suspend
itself still goes through since that only needs `admin:write:accounts`).
**The blocklist reconcile (`app/reconcile_blocks.py`) needs two more scopes,
`admin:read:ip_blocks` and `admin:read:email_domain_blocks`**, to `GET` the
live `/api/v1/admin/ip_blocks` and `/api/v1/admin/email_domain_blocks` lists
and check whether the blocks we registered are still there. Added to the live
token **in place** on 2026-09-13 (`Doorkeeper::AccessToken#update!(scopes:)`
on id 11334, matched by SHA-256 digest against admin's `.env`) rather than by
minting and rotating — the token value is unchanged, so no `.env` edit was
needed. Without these scopes the reconcile 403s and exits having changed
nothing, which is the deliberate failure mode: never read an outage as "every
block was removed".
**The suspicious-signup sweep (`app/suspicious_sweep.py`) needs another scope,
`admin:read:accounts`**, to `GET /api/v1/admin/accounts/:id` (fetches current
post/follow counts + role/suspended state to decide whether to suspend) —
@@ -217,7 +228,7 @@ Mint a correctly-scoped token from the Rails console on mammut:
```bash
ssh mammut 'docker exec $(docker ps -f name=live-web-1 -q) bin/rails runner "
acct = Account.find_local(%q{bot})
scopes = %q{read:statuses write:statuses admin:read:reports admin:write:accounts admin:write:ip_blocks admin:write:email_domain_blocks admin:read:accounts}
scopes = %q{read:statuses write:statuses admin:read:reports admin:write:accounts admin:write:ip_blocks admin:write:email_domain_blocks admin:read:accounts admin:read:ip_blocks admin:read:email_domain_blocks}
app = Doorkeeper::Application.create!(name: %q{Abuse handler vN}, scopes: scopes, redirect_uri: %q{urn:ietf:wg:oauth:2.0:oob})
tok = Doorkeeper::AccessToken.create!(application_id: app.id, resource_owner_id: acct.user.id, scopes: scopes)
puts tok.token