VIP-Liste-Sektion: zwei Kachel-Sektionen statt flacher Chips — "Meine VIP-Domains" (eigene Custom-Domains, Stern + Status-Badge) und "Vordefinierte Top-Seiten" (kuratiert, schlicht). Read-only, kein Freigabe-Button. Kein Pulse-Ring (auf User-Wunsch entfernt). docs/concepts/brand-token-matching.md: abgenommenes Konzept für geteiltes Brand-Token-Matching (Layer 1 DNS + Mail/Mo) gegen den Nummern-Trick der Gambling-Industrie (slotoro.bet → slotoro88.bet). Im Backlog. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
7.9 KiB
Konzept: Geteiltes Brand-Token-Matching
Status: Konzept abgenommen (2026-05-22) — im Backlog, Umsetzung später (§10) Datum: 2026-05-22 Scope: Layer 1 (DNS-Sinkhole / PacketTunnel) + Mail-Scan (Mo). NICHT Layer 2.
1. Problem
Glücksspiel-Marken umgehen exakte Blocklisten mit dem Nummern-/Suffix-Trick: dieselbe wiedererkennbare Marke, variierende Zahl/Suffix/TLD.
slotoro.bet → slotoro88.bet · slotoro2.com · slotoro-casino.net · slotorobet.io
winrolla.com → winrolla57.com · winrolla-bet.net
- Layer 1 (DNS-Hash-Set, 329k Hashes): matcht nur exakt. Hashes erlauben
kein Substring-/Prefix-Matching —
slotoro88.bethasht zu etwas völlig anderem alsslotoro.bet. Architektur-bedingt. - Layer 2 (Apple
ManagedSettings-WebDomain): matcht nur exakte Domain + Subdomains. Keine Substring-API. Nicht erweiterbar — out of scope. - Mail-Scan (Mo): hat dasselbe Problem (
winrolla → winrolla57).
Die HaGeZi-Feed-Liste fängt viele Varianten mit Latenz — der Feed muss die neue Variante erst aufnehmen. Brand-Token-Matching schließt genau diese Latenzlücke und greift sofort bei jeder Variante einer bekannten Marke.
2. Ziel & Scope
Ziel: Ein einziges, geteiltes Brand-Token-System — dieselbe kuratierte Token-Liste + derselbe Matching-Algorithmus für Layer 1 (DNS) und Mail-Scan.
Im Scope: Varianten bekannter Marken abfangen. Nicht im Scope:
- Brandneue Marken ohne Token (kein Token → kein Match).
- Layer 2 (Apple-API kann es nicht).
- Ersatz für Feed/Blocklist — das System ergänzt sie, ersetzt sie nicht.
3. Kernidee: der Brand-Token
Ein Brand-Token = ein distinktiver, kleingeschriebener Marken-Kern, der eine Glücksspielmarke identifiziert und in legitimen Domains praktisch nicht vorkommt.
Gute Tokens: slotoro · winrolla · spinrollz · wazamba
Schlechte Tokens: bet · win · play · casino · slot · vegas
(Wörterbuch-/Generikwörter → False-Positive-Magneten)
Regel: kuratiert, nie automatisch. Mindestlänge ≥ 5 Zeichen. Kürzere Marken bleiben bei der exakten Blocklist.
4. Der Matching-Algorithmus (das geteilte Stück)
Der entscheidende Teil. Kein freies Substring (host.contains(token) ist
gefährlich). Stattdessen Entnummerierung + Segment-Exaktvergleich:
Ablauf (pro Host)
1. Host in Labels splitten an '.' slotoro88.bet → ["slotoro88", "bet"]
2. Pro Label: in Segmente splitten an '-' play-slotoro → ["play", "slotoro"]
3. Pro Segment:
a. Trailing-Ziffernlauf abschneiden → `core` slotoro88 → slotoro
b. core EXAKT in tokenSet? → MATCH
c. sonst: core beginnt mit einem Token UND
der Rest ∈ genericSuffixSet? → MATCH
d. sonst → kein Match
4. Kein Segment matcht → kein Block.
genericSuffixSet = generische Glücksspiel-Anhängsel, die nur als Rest nach
einem Token zählen (nie standalone): bet bets casino casinos slot slots spin spins win wins play vegas game games poker sport sports wetten lotto gambling.
Warum das robust ist
Es ist Exaktvergleich auf dem entnummerierten Segment, kein Substring.
Ein kurzes Token wie win würde winter NICHT treffen: winter → core
winter → winter ≠ win → kein Match. False Positives entstehen nur, wenn
ein legitimes Segment exakt ein Token ist — bei distinktiven Tokens ~null.
Beispiele
| Host | Segment-core | Ergebnis |
|---|---|---|
slotoro.bet |
slotoro |
MATCH (exakt) |
slotoro88.bet |
slotoro88→slotoro |
MATCH (entnummeriert) |
slotoro2.com |
slotoro2→slotoro |
MATCH |
play-slotoro.net |
Segment slotoro |
MATCH |
slotoro-casino.io |
Segment slotoro |
MATCH |
slotorobet.com |
slotorobet = slotoro+bet |
MATCH (Token+Suffix) |
stat.slotoro88.bet |
Label slotoro88→slotoro |
MATCH |
winter.com |
winter |
kein Match (≠ Token) |
slotorox.com |
slotorox = slotoro+x, x∉Suffixe |
kein Match |
Verbindlichkeit
Der Algorithmus muss bit-identisch in Swift (PacketTunnel) und TS
(Mo-Scan + Backend-Validierung) implementiert sein — analog zu
domainHash.ts ↔ DomainHasher.swift. Ein gemeinsamer Spec-Testvektor-Satz
(Input-Host → erwartetes Ergebnis) wird in beiden Test-Suites geprüft.
5. Token-Liste: Kuration & Quelle
- DB-Tabelle
brand_tokens(token, source, addedAt, isActive, note). - Kuratiert von ReBreak-Admins — nie auto-generiert (FP-Risiko).
- Bootstrap: die existierende 329k-Blocklist nach gemeinsamen SLD-Präfix- Clustern minen → Token-Vorschläge → menschliche Freigabe.
- Laufende Quelle: wenn ein User über die Custom-Domain-/Submission-Flows eine offensichtliche Variante einreicht, kann der Admin statt nur der Domain das Brand-Token promoten.
- Allowlist-Notausgang (
brand_token_allowlist): falls ein Token doch kollidiert, einzelne legitime Domains explizit ausnehmen. v1 optional, im Design vorgesehen.
6. Verteilung aufs Gerät (Layer 1)
- Neuer Endpoint
GET /api/url-filter/brand-tokens— JSON/Zeilenliste, ETag- gecacht. Spiegelt exakt denblocklist.bin-Sync-Mechanismus: App lädt → schreibt in App-Group → Darwin-Notification → Extension reloadet. - Datei klein (~wenige KB bei einigen hundert Tokens).
- File-Protection
.completeUntilFirstUserAuthentication— wie nach dem Layer-1-Bugfix (2026-05-22), damit die Extension sie auch bei gesperrtem Gerät lesen kann. - Privacy-Abwägung (ehrlich): die Hash-Liste ist gehasht, damit keine
Klartext-Casino-Domains auf dem Gerät eines Spielers liegen. Brand-Tokens
sind Klartext-Markenfragmente — Substring-Matching gegen Hashes ist
unmöglich, Klartext ist also nötig. Es sind aber nur einige hundert
Markenfragmente, kein browsing-history-verräterischer Datensatz. Datei
file-protected. Entscheidung (2026-05-22): Klartext akzeptiert.
hans-mueller-DSGVO-Gegencheck bei der Umsetzung (kein Blocker fürs Konzept).
7. Integration
Layer 1 — DnsFilter.classify
Nach dem hashList.matchesAnySuffix(domain)-Miss, vor .forward:
if hashList-Miss:
if brandTokens.matches(domain): // der Algo aus §4
return .block
return .forward
Neue Klasse BrandTokenList (Pendant zu HashList) — lädt die Token-Datei,
reloadet via Darwin-Notification. Performance: pro verfehlter Query ein paar
Set-Lookups → Mikrosekunden, NE-Memory-unkritisch.
Mail (Mo)
Derselbe brandTokens.matches(...) auf die Absender-Domain (und optional den
Display-Namen) anwenden. Owner der Integration bleibt Mo; das geteilte Stück
ist die Token-Liste + der §4-Algorithmus.
8. Was es NICHT tut (ehrliche Grenzen)
- Keine neuen Marken (ohne Token kein Match).
- Glued-Varianten ohne Ziffern/Trenner/Generik-Suffix (
slotoroxyz.com) → Miss; bleibt Sache des Feeds. - Kein Layer-2-Support.
- False Positives werden stark reduziert, nicht zu 100% eliminiert → Allowlist.
9. Entscheidungen
Entschieden (2026-05-22):
- Privacy: Klartext-Brand-Tokens auf dem Gerät akzeptiert, file-protected.
hans-mueller-DSGVO-Gegencheck bei der Umsetzung (kein Blocker fürs Konzept). - Generic-Suffix-Regel (§4c): drin — v1 enthält Token+Suffix-Matching
(
slotorobet=slotoro+bet).
Noch offen (bei Umsetzung klären):
3. Token-Kuration: rein Admin, oder community-/submission-gespeist?
4. Sync-Kanal: eigener Endpoint, oder in den blocklist.bin-Sync bündeln?
5. Bootstrap-Aufwand: Mining der 329k-Liste nach Präfix-Clustern — wie viel
manuelle Freigabe ist realistisch?
10. Rollout-Phasen
- Phase 1: DB-Tabelle + §4-Algo-Spec + Testvektoren + Bootstrap-Mining + Admin-Kuration-UI.
- Phase 2: Endpoint + Sync +
BrandTokenList+DnsFilter-Einbau (Layer 1). - Phase 3: Mo-Mail-Integration.
- Hinter Feature-Flag, mit FP-Report-Pfad zum Monitoring.