README gets the full contract (request/response shape, the cost ceiling and why it exists, the block-width cap and expiry, and the two new tables). CLAUDE.md gets the two rules that are easy to undo by accident: the endpoint must never serve unauthenticated, and the width cap and expiry are policy decisions rather than tuning knobs.
This commit is contained in:
1 parent
6952fbadf6
commit
47e92ca10f
2 files changed
+135
-1
No files matched your search
@@ -19,6 +19,18 @@ A FastAPI webhook server. One Mastodon admin webhook delivers `account.created`,
|
||||
and auto-**silence** young/dormant accounts past the threshold — lowered for
|
||||
accounts with a flagged signup IP (see README).
|
||||
|
||||
Alongside the webhook it serves a **reputation query API** — `POST
|
||||
/api/reputation` — which is the pre-emptive counterpart to all of the above.
|
||||
Mastodon calls it during signup, immediately before its own IpBlock /
|
||||
EmailDomainBlock lookups; it classifies the IP/email domain, records it,
|
||||
registers the block, and only then returns, so the lookup that follows
|
||||
rejects the signup outright. It **writes**, so it is authenticated
|
||||
(`X-Reputation-Key`) and 404s unless `REPUTATION_API_ENABLED` *and*
|
||||
`REPUTATION_API_KEY` are both set. The caller is the
|
||||
`call-welcomebot-reputation-api` patch on the Mastodon fork — see
|
||||
`~/secondbrain/yttrx-documentation/mastodon-fork-patches.md`. README.md's
|
||||
"Reputation query API" section has the full contract.
|
||||
|
||||
Alongside the webhook it serves an optional read-only **blocklist API** —
|
||||
`GET /api/blocks`, `/api/blocks/ip-ranges`, `/api/blocks/email-domains` —
|
||||
publishing the IP ranges and email domains the bot has auto-blocked. It is
|
||||
@@ -62,6 +74,17 @@ user-memory note `project_welcomebot` has the current state.
|
||||
check-mail.org's disposable/risk fields back into the response — that would
|
||||
be redistributing a paid reputation feed's data. Account identifiers
|
||||
(handles, ids, emails, raw signup IPs) are out for the usual reasons.
|
||||
- **The reputation API must never serve unauthenticated.** It installs IP
|
||||
blocks; an open endpoint that does that is a denial-of-service lever. An
|
||||
empty `REPUTATION_API_KEY` disables the route rather than opening it, and
|
||||
that behaviour is asserted in `test_local.py` — don't "fix" it into a
|
||||
permissive default.
|
||||
- **Don't remove the block-width cap or the block expiry.** `IP_SCRUTINY_MAX_
|
||||
BLOCK_PREFIX_V4`/`_V6` (24/48) and `IP_SCRUTINY_IPBLOCK_EXPIRES_IN` (24h)
|
||||
exist because ipapi.is reports whole ASN routes: without the cap a single
|
||||
`abuser` flag on a consumer address blocks its entire ISP route (routes of
|
||||
/8–/11 are routine, and `197.211.32.0/19` was already registered against a
|
||||
Benin mobile carrier). Raising them is a policy decision, not a tuning knob.
|
||||
- **`admin.yttrx.com`'s `/root/yttrx-welcomebot/` is not a git repo any more**
|
||||
(cleaned up 2026-07-06). Don't `git init`/clone it back into place — the
|
||||
registry image + `docker-compose.yml`/`.env` is the whole deploy surface now.
|
||||
@@ -217,6 +240,10 @@ 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 reputation API needs no scopes beyond those above — it registers the same
|
||||
`Admin::IpBlock` / `EmailDomainBlock` records as the webhook path, so
|
||||
`admin:write:ip_blocks` + `admin:write:email_domain_blocks` cover it.
|
||||
|
||||
**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) —
|
||||
|
||||
Reference in new issue
Block a user