docs(teams): use the correct presentation of the project name, and match both
"Runic Gateway" (two words) is the correct presentation; "RunicGateway" is accepted only where the name has to condense to a single token — the Gitea org, a package name, a URL segment. Three prose uses in TEAMS.md had the condensed form for no reason, including the upload warning text, and are corrected. The `RunicGateway/<repo>` slugs throughout android/PLAN.md are condensed by necessity and are left alone. This turned out to matter beyond presentation. The reserved-name matcher (2.8) specified whole-word matching over a normalisation that case-folds, strips punctuation and collapses whitespace — under which "RunicGateway" is a SINGLE word and would never have matched the two-word term "Runic Gateway". The condensed form is the one an impersonator reaches for, precisely because it is what the org and every URL already use, so the check would have missed its most likely input. Multi-word terms are now additionally compared with whitespace removed on both sides, so `Runic Gateway` matches `RunicGateway`, `runic-gateway`, `Runic_Gateway` and `RUNIC GATEWAY` alike. The widening applies only to terms CONTAINING whitespace, which keeps it clear of the single-word terms where whole-word matching is doing the false-positive work: `admin` is still compared as a word and still does not fire on "Badminton". Listing the condensed form as a separate reserved term was the alternative and was rejected — it is a second thing to keep in sync and would still miss the hyphenated and underscored variants. The same reasoning applies to a deployment's own BRAND_NAME, which is free text and may well be spaced. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WnDSWzpUjw8t8C2hghysNz
This commit is contained in:
@@ -569,6 +569,16 @@ runtime configuration):
|
|||||||
| The project | `Runic Gateway` — impersonating the software project is as much a problem as impersonating the operator |
|
| The project | `Runic Gateway` — impersonating the software project is as much a problem as impersonating the operator |
|
||||||
| Operator additions | a `teams_reserved_terms` setting, comma-separated, for anything a particular community needs |
|
| Operator additions | a `teams_reserved_terms` setting, comma-separated, for anything a particular community needs |
|
||||||
|
|
||||||
|
> **The project's name has two legitimate presentations, and both must match.** **Runic Gateway** (two
|
||||||
|
> words) is the correct form; **RunicGateway** is accepted only where the name has to condense to a
|
||||||
|
> single token — the Gitea org, a package name, a URL segment. A reserved term is therefore stored in
|
||||||
|
> its correct two-word form and matched against *both*, which §2.8.2's whitespace-insensitive
|
||||||
|
> comparison gives for free. Listing the condensed form as a separate term would be a second thing to
|
||||||
|
> keep in sync, and it would still miss `runic-gateway` and `Runic_Gateway`.
|
||||||
|
>
|
||||||
|
> The same applies to a deployment's own brand: `BRAND_NAME` is free text and an operator may well
|
||||||
|
> have set a spaced name whose condensed form is what a would-be impersonator types.
|
||||||
|
|
||||||
**Not `filter_words`.** That table exists but is **bot-owned** (its own pool, `bot/src/model/`,
|
**Not `filter_words`.** That table exists but is **bot-owned** (its own pool, `bot/src/model/`,
|
||||||
never read by the website — `MODERATION_APPEALS.md` §2 is explicit that the two sides share no live
|
never read by the website — `MODERATION_APPEALS.md` §2 is explicit that the two sides share no live
|
||||||
FK) and it is a profanity filter, which is a different question with a different answer. Reusing it
|
FK) and it is a profanity filter, which is a different question with a different answer. Reusing it
|
||||||
@@ -587,6 +597,18 @@ Normalisation: case-fold, strip punctuation and repeated characters, collapse wh
|
|||||||
**no leet-speak folding** in v1 (`4dm1n`) — it multiplies false positives, and the consequence of a
|
**no leet-speak folding** in v1 (`4dm1n`) — it multiplies false positives, and the consequence of a
|
||||||
miss is a hidden-by-a-human Team rather than a breach.
|
miss is a hidden-by-a-human Team rather than a breach.
|
||||||
|
|
||||||
|
**A multi-word term is additionally compared with whitespace removed on both sides**, so a term stored
|
||||||
|
as `Runic Gateway` matches `RunicGateway`, `runic-gateway`, `Runic_Gateway` and `RUNIC GATEWAY`
|
||||||
|
alike. Without this the whole-word rule fails on exactly the case that matters: `RunicGateway` is a
|
||||||
|
*single* word and would never match a two-word term, so the condensed form — the one an impersonator
|
||||||
|
would reach for, because it is what the Gitea org and every URL already use — would sail straight
|
||||||
|
through.
|
||||||
|
|
||||||
|
That widening applies **only to terms containing whitespace**, which keeps it away from the
|
||||||
|
single-word terms where whole-word matching is doing the false-positive work: `admin` is still
|
||||||
|
compared as a word and still does not fire on "Badminton". A two-word term is specific enough that
|
||||||
|
running the letters together cannot collide with ordinary vocabulary.
|
||||||
|
|
||||||
#### 2.8.3 What a match does: hide, never reject
|
#### 2.8.3 What a match does: hide, never reject
|
||||||
|
|
||||||
A Team whose name trips the list is created **normally** and then **auto-hidden**: `hidden = 1`,
|
A Team whose name trips the list is created **normally** and then **auto-hidden**: `hidden = 1`,
|
||||||
|
|||||||
Reference in New Issue
Block a user