#6 Decision: GitHub labels + abuse/rate-limit policy #18

Merged
JMR-dev merged 1 commits from ticket-6-labels-abuse-adr into main 2026-07-02 18:13:40 +00:00
JMR-dev commented 2026-07-02 18:12:05 +00:00 (Migrated from github.com)

Adds docs/decisions/labels-and-abuse.md — a documented decision (ADR) with concrete, implementable values. Doc-only; no code or labels created (creating the labels is #14's implementation job).

Decisions

GitHub labels applied to every auto-published issue on JMR-dev/LibreMail (all three; #14 must create any that are missing — none exist today):

  • bug-report — origin marker: came from the app's opt-in debug ingest pipeline (distinct from the human-triaged bug).
  • automated — provenance: created by the weekly publish job, not a human.
  • needs-triage — workflow state: not yet reviewed; maintainer clears it.

Ingest endpoint (informs #7):

  • Payload cap 256 KiB (Content-Length fast-path + streamed hard cap) → 413.
  • Per-IP rate limit: >15 req/60s (block 10 min) and >100 req/1h (block 1h) → 429 + Retry-After; optional global 1,000/h shed → 503.
  • Mechanism: Cloudflare Rate Limiting rules via Pulumi (edge, pre-Worker, fits existing IaC); DO token-bucket / Workers rate-limit binding documented as alternatives; KV rejected (eventually consistent). Worker still owns size + schema checks.
  • Response contract: 202 accepted / 400 malformed / 413 too large / 415 wrong type / 405 wrong method / 429 rate-limited / 500 / 503, plus client retry rules.

Weekly publish job (#14):

  • 50 issues/run cap, oldest-first, alert on cap hit.
  • Serial creation, 1s spacing, honour Retry-After, exponential backoff (base 1s, cap 60s, full jitter, max 5 attempts/issue), mark-published-only-on-confirmed-201 for de-dup. Sits well under GitHub primary (5k/h) and secondary content-creation limits.

Plus a "Consequences" section and a short list of values for the maintainer to confirm at review (three labels vs. leaner set; 256 KiB; per-IP numbers; 50/run cap + alert destination).

Closes #6

Adds `docs/decisions/labels-and-abuse.md` — a documented decision (ADR) with concrete, implementable values. Doc-only; no code or labels created (creating the labels is #14's implementation job). ## Decisions **GitHub labels** applied to every auto-published issue on `JMR-dev/LibreMail` (all three; #14 must create any that are missing — none exist today): - `bug-report` — origin marker: came from the app's opt-in debug ingest pipeline (distinct from the human-triaged `bug`). - `automated` — provenance: created by the weekly publish job, not a human. - `needs-triage` — workflow state: not yet reviewed; maintainer clears it. **Ingest endpoint (informs #7):** - Payload cap **256 KiB** (`Content-Length` fast-path + streamed hard cap) → **413**. - Per-IP rate limit: **>15 req/60s** (block 10 min) and **>100 req/1h** (block 1h) → **429 + `Retry-After`**; optional global 1,000/h shed → 503. - Mechanism: **Cloudflare Rate Limiting rules via Pulumi** (edge, pre-Worker, fits existing IaC); DO token-bucket / Workers rate-limit binding documented as alternatives; KV rejected (eventually consistent). Worker still owns size + schema checks. - Response contract: 202 accepted / 400 malformed / 413 too large / 415 wrong type / 405 wrong method / 429 rate-limited / 500 / 503, plus client retry rules. **Weekly publish job (#14):** - **50 issues/run** cap, oldest-first, alert on cap hit. - Serial creation, **1s spacing**, honour `Retry-After`, exponential backoff (base 1s, cap 60s, full jitter, **max 5 attempts/issue**), mark-published-only-on-confirmed-201 for de-dup. Sits well under GitHub primary (5k/h) and secondary content-creation limits. Plus a "Consequences" section and a short list of values for the maintainer to confirm at review (three labels vs. leaner set; 256 KiB; per-IP numbers; 50/run cap + alert destination). Closes #6
Sign in to join this conversation.