# Central Blacklist — Policy, Criteria & Appeal Flow

**Version:** 1.0 (draft) · **Status:** Policy for legal/management review before launch · **Owner:** Checkrace Co., Ltd.
**Companion to:** [`result-integrity-spec.md`](result-integrity-spec.md)

The Central Blacklist is a **shared, organizer-internal registry** of runners with a
**confirmed** integrity violation (impersonation, using another's bib, course-cutting,
sending a substitute to collect a prize). Because Checkrace spans many events and feeds the
Thailand Runner Rank, a confirmed offence can be enforced **across the ecosystem** — which is
the strongest deterrent available and a moat competitors can't replicate.

It is also the **highest-risk feature legally.** A wrong entry is more harmful than a missed
cheat. This document exists so the blacklist never operates on a system flag alone, never
defames anyone, and never becomes a permanent unappealable stigma.

> **Five hard rules (non-negotiable)**
> 1. **Human-confirmed only.** A system flag (Fraud Score) can *propose*; only a referee + evidence can *confirm*.
> 2. **Due process.** Every entry passes `under_review → notified → appeal window → confirmed`.
> 3. **Internal, never public.** The blacklist lives inside the organizer console. No public naming. (Defamation risk.)
> 4. **Tiered & expiring.** Most sanctions are time-bound. Permanent bans are rare and require management sign-off.
> 5. **PDPA-compliant.** National IDs hashed, access logged, retention bounded, runner has access/objection rights.

---

## 1. What gets someone listed

### 1.1 Eligible violations (confirmed)
| Code | Violation | Typical sanction |
|---|---|---|
| `impersonation` | Ran under another person's identity / bib | Suspension 12–24 months |
| `bib_transfer_illegal` | Gave/sold/used a bib outside the official transfer window | Warning → 6-month suspension |
| `course_cut` | Skipped mandatory course / checkpoints to gain placing | DSQ + 6–12 month suspension |
| `proxy_award` | Sent a substitute to run and/or collect a prize | Suspension 24 months + prize clawback |
| `repeat_offender` | Second confirmed violation of any kind | Escalate one tier; review for permanent |

### 1.2 What is **NOT** grounds for listing
- A high Fraud Score with no human verdict.
- A no-show at the award with a legitimate reason (injury, medical).
- A breakout performance with a clean identity trail.
- A newcomer with no history.
- Suspicion from a single performance signal alone.

### 1.3 Evidence standard
An entry requires **at least one identity/course artifact** on file — a face mismatch,
a missing-CP record, a refused face check, a duplicate-identity match — **plus** a named
referee's verdict. No artifact, no entry.

---

## 2. Sanction tiers

| Tier | Label | Effect | Who can apply |
|---|---|---|---|
| **T0** | Warning | Logged; no restriction; visible to organizers on future registration | Event referee |
| **T1** | Event DSQ | Result removed for that event only | Event referee |
| **T2** | Temporary suspension (3–24 mo) | Blocked from competitive entry; Rank entry suspended | Referee + organizer lead |
| **T3** | Permanent ban | Indefinite competitive block | **Management sign-off required** |

- **Competitive categories only.** A suspension blocks prize/championship/age-group entry.
  Whether it blocks fun-run participation is each organizer's choice (default: allowed).
- **Rank effect:** T2/T3 suspends the runner's Thailand Runner Rank standing for the sanction period; T0/T1 do not.

---

## 3. Lifecycle & appeal flow

```
 Fraud Score (Investigate)            ← system proposes only
        │
        ▼
 [under_review]  ── referee opens an IntegrityCase, gathers evidence
        │
        ├── insufficient evidence ──► [cleared]  (case closed, nothing recorded)
        │
        ▼ referee verdict = violation
 [notified]  ── runner contacted (email/SMS), shown the basis, told their rights
        │
        ▼  appeal window opens (default 14 days)
 [appeal] ──────► review panel (≥2 people, not the original referee)
        │                 │
        │                 ├── upheld  ──► [confirmed] → blacklist entry created
        │                 └── overturned ► [cleared]  → no entry, record purged
        │
        ▼ no appeal filed by deadline
 [confirmed] → blacklist entry created (sanction tier applied)
        │
        ▼ sanction period elapses OR successful later appeal
 [expired] / [cleared] → entry deactivated, enforcement stops
```

- **Notification is mandatory** before any enforcement beyond a single-event DSQ.
- **Appeals are reviewed by a different panel** than the one that raised the case.
- **Clearing purges**, it doesn't just flip a flag — an overturned case leaves no residual mark.

---

## 4. Data model

```json
{
  "blacklist_id": "bl_00231",
  "runner_id": "RID-7Q3KD8ZP",
  "nid_hash": "b64(sha256(nid + salt))",       // matching key; raw nid never stored here
  "reason_code": "impersonation",
  "evidence_refs": ["case_5567"],               // links to the IntegrityCase + artifacts
  "severity": "T2",
  "sanction_start": "2026-06-25",
  "sanction_end": "2027-06-25",                 // null only for T3 permanent
  "status": "confirmed",                         // under_review | notified | appealed | confirmed | expired | cleared
  "decided_by": "ref_pong",                      // accountable human
  "panel": ["mgr_aoy", "ref_kan"],               // appeal reviewers (when applicable)
  "notified_at": "2026-06-23T10:00:00+07:00",
  "appeal": {
    "filed_at": null,
    "outcome": null,                             // upheld | overturned
    "note": ""
  },
  "created_at": "2026-06-22T11:00:00+07:00",
  "audit_log": [
    { "ts": "2026-06-22T11:00:00+07:00", "actor": "ref_pong", "action": "open_case" }
  ]
}
```

### Enforcement hooks
| Hook | Behaviour |
|---|---|
| **At registration** | Match `nid_hash` / `runner_id` against active entries. On match → **alert the organizer** (default: warn; hard-block only for T2/T3 competitive entry). The organizer, not the system, makes the final call. |
| **At ranking ingest** | Active T2/T3 → suspend the runner's Rank standing for the period. |
| **At award verify** | Active entry surfaces in the Winner Verify zone for extra scrutiny. |

---

## 5. PDPA & legal safeguards

| Area | Rule |
|---|---|
| **Lawful basis** | Consent at registration + legitimate interest in fair competition, disclosed in event T&C. |
| **National ID** | Stored only as a salted hash for matching. Raw ID is not retained in the blacklist. |
| **Minimization** | Store only what's needed to enforce: id keys, reason, evidence pointers, sanction window. |
| **No public disclosure** | The blacklist is never published or shown to the public. Naming a person publicly risks defamation (หมิ่นประมาท) and PDPA breach. |
| **Access control** | Role-gated to referees/organizer leads; every read/write is logged in `audit_log`. |
| **Data subject rights** | Runner can request access to their entry and object/appeal. Contactable channel required. |
| **Retention** | Entry data purged a defined period after `sanction_end` (recommend ≤ 24 months post-expiry), unless a repeat case keeps it live. |
| **Accuracy** | Overturned/cleared cases are purged, not merely deactivated. |

---

## 6. Governance

- **Standard criteria, not organizer whim.** The violation codes, evidence standard, and tiers
  in this document are the *single* ruleset; individual organizers cannot invent their own
  grounds for listing. This keeps the registry fair and defensible.
- **Permanent bans (T3)** require Checkrace management sign-off and a documented repeat or
  egregious case — never a first offence.
- **Annual review** of all active entries to expire or revalidate.
- **Quarterly audit** of access logs and a sample of cases for due-process compliance.
