Skip to content

feat(glitchtip): C1 — emit() infrastructure + DEV-trigger skeleton#12

Open
MANFahrer-GF wants to merge 2 commits into
mainfrom
claude/v0.9.3-c1-infrastructure
Open

feat(glitchtip): C1 — emit() infrastructure + DEV-trigger skeleton#12
MANFahrer-GF wants to merge 2 commits into
mainfrom
claude/v0.9.3-c1-infrastructure

Conversation

@MANFahrer-GF

Copy link
Copy Markdown
Owner

Erste Slice der v0.9.3 GlitchTip-Emit-Sites-Implementierung. Spec: docs/spec/v0.9.3-glitchtip-emit-sites.md (SPEC ACCEPTED R2). C1 = Plumbing ohne echte Site-Aufrufe. 8/8 sentry-Tests gruen, 56/56 vitest gruen, cargo check sauber. Detail siehe Commit-Message.

Spec: docs/spec/v0.9.3-glitchtip-emit-sites.md LE6 Slice C1 (SPEC ACCEPTED R2).

Erste der 9 C-Slices (C0=Spec, C1=Infra, C2..C8=Sites, C9=Release).
C1 baut die komplette emit()-Pipeline + DEV-Test-Infrastruktur, OHNE
einen einzigen echten Site-Aufruf in lib.rs. Damit ist die Akzeptanz-
Verifikation in C2..C8 (Live-Trigger gegen tip.kant.ovh) von Anfang
an moeglich (R2-P1-2-Fix: DEV-Panel kam in R1 zu spät).

Was kommt rein:

1. `sentry_init.rs` (+ ~380 Zeilen) — die EINZIGE öffentliche Schnitt-
   stelle für Custom-Events ab v0.9.3:

   - `pub(crate) mod tag_keys` — 13 Compile-Time-Konstanten 1:1 mit
     `allowed_tag_keys()`. Aufrufer müssen `tag_keys::ERROR_KIND` etc.
     statt roh-Strings nutzen → keine versehentlichen Underscore-vs-Dot-
     Drifts (Spec R0-P0). #[allow(dead_code)] solange C2..C8 noch nicht
     ergänzt haben.
   - `RATE_LIMIT_DEFAULTS` — 9 Sites mit Token-Bucket-Limits aus Spec LE2
     (1/min für update_check_failed, 10/min für hard_landing, etc.). Plus
     DEFAULT_LIMIT (10/60s) für unbekannte error_codes.
   - `try_consume_token(error_code, now: Instant)` — Clock-Injection
     macht Tests deterministisch ohne sleep(60s) (Spec R1-P2-2).
   - `pub(crate) fn emit(level, error_code, message, tags)` mit
     4-Gate-Sequenz (Spec R2-P1-1):
       Gate 1: Consent
       Gate 2: Client bound + is_enabled() — kein Token-Verbrauch
               wenn DSN fehlt oder nach Opt-Out
       Gate 3: Rate-Limit
       Gate 4: Send via sentry::with_scope mit explizitem
               `scope.set_fingerprint(Some(["aeroacars", error_code].as_slice()))`
               → Gruppierungs-Vertrag „1 Issue pro error_code" garantiert
                 (Spec R1-P1-3 + R2-P1-3).
   - Die 2 alten dead-code `capture_message`/`capture_error`-Wrapper
     wurden entfernt — die fehlende Verwendung war Teil des „GlitchTip
     ist Theorie"-Problems das v0.9.3 löst.

2. `sentry_init.rs#[cfg(test)] mod c1_rate_limit_tests` — 7 Schicht-1-
   Mechanik-Tests:
     - token_bucket_lets_first_n_through
     - token_bucket_drops_after_limit
     - token_bucket_resets_after_window_without_sleep (Clock-Injection)
     - known_error_code_uses_specific_limit (sim_disconnect = max 1)
     - unknown_error_code_gets_default_limit
     - emit_returns_false_when_no_client_bound (R2-P1-1-Regression-Guard)
     - consent_off_returns_false_without_consuming_token
   Alle nutzen `TEST_LOCK`-Mutex für Serialisierung (statisches BUCKETS
   geteilt zwischen parallel laufenden Tests sonst flaky).

3. `sentry_init.rs#[cfg(test)] mod c1_mock_transport_smoke` — 1 Schicht-
   2-Smoke-Test mit MockTransport-Helper:
     - smoke_emit_passes_all_gates_and_lands_in_mock_transport
   Beweist dass ein Envelope durch alle 4 Gates kommt + im MockTransport
   landet + die Tags die Allowlist (redact_event) überleben. Plus
   Fingerprint-Vertrag ["aeroacars", error_code] verifiziert.

4. `lib.rs` — `#[cfg(debug_assertions)] fn dev_trigger_glitchtip_event(
   site: String)` Tauri-Command mit Catch-All-Match (Err(unknown_site)).
   Match-Arms werden in C2..C8 pro Site ergänzt. Plus cfg-gated
   Registration im invoke_handler-Set. Production-Build hat den Command
   NICHT (doppelter Schutz: cfg + import.meta.env.DEV).

5. `SettingsPanel.tsx` — `<GlitchTipDevTriggerPanel />` nur unter
   `import.meta.env.DEV`. 9 Buttons in Grid-Layout (S1..S9), pro Button
   wird der letzte Status als `<small>` daneben angezeigt (R2-Frage-10:
   unknown-site-Errors sauber zeigen statt crashen). Tree-shaked in
   Production-Bundle.

Tests + Verify:
- `cargo check --all-targets` ✓
- `cargo test -p aeroacars-app --lib sentry_init` → 8/8 ✓
- `tsc -b` ✓
- `npm test` → 56/56 ✓ (47 SinkrateForensik + 9 UpdateButton-Guards)

KEIN echter Site-Aufruf in lib.rs in C1 — emit() wird in Production-
Code-Pfaden erst ab C2 (S1+S2: PIREP-Submit-Fail) gerufen. #[allow(
dead_code)] an emit() bleibt — schadet nicht.

KEINE Wire-Format-Änderung. KEINE Privacy-Allowlist-Erweiterung
(LE7). KEINE neue NPM-Dependency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 646695c63f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src-tauri/src/sentry_init.rs Outdated
Comment on lines +689 to +695
static SMOKE_LOCK: StdMutex<()> = StdMutex::new(());

#[test]
fn smoke_emit_passes_all_gates_and_lands_in_mock_transport() {
// Test-Isolation: SMOKE_LOCK + frischer Bucket + frischer Hub.
let _g = SMOKE_LOCK.lock().unwrap_or_else(|p| p.into_inner());
BUCKETS

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Serialize all sentry_init tests with one shared lock

The smoke test uses its own SMOKE_LOCK, but c1_rate_limit_tests uses a different TEST_LOCK while both modules mutate the same globals (BUCKETS, CONSENT, and hub binding). Because Rust tests run in parallel by default, these tests can interleave and clear/flip shared state underneath each other, causing nondeterministic failures (for example, token-bucket assertions racing with BUCKETS.clear()). Use a single lock shared across both test modules (or move all shared-state tests into one serialized module) to avoid flakiness.

Useful? React with 👍 / 👎.

Thomas-Code-QS-R1 fand P2 (kein P0/P1): die zwei lokalen Test-Locks
(TEST_LOCK in c1_rate_limit_tests, SMOKE_LOCK in c1_mock_transport_smoke)
schuetzten nur INNERHALB ihres jeweiligen Moduls. Beide Module teilen
aber drei globale Statics: CONSENT (Atomic), BUCKETS (Static-Mutex),
und den Sentry-Hub. Ein Test aus Modul A konnte parallel zu einem
Test aus Modul B laufen und CONSENT umkippen → flaky CI moeglich.

Fix:

1. Shared file-level `SENTRY_TEST_LOCK` (#[cfg(test)]) — serialisiert
   ALLE Sentry-Init-Tests modul-uebergreifend.

2. `SentryTestEnv`-Drop-Guard mit Pre-Clean + Post-Clean:
   - `lock()`: holt den shared lock + setzt CONSENT=false +
     bind_client(None) + leert BUCKETS-Map. Recover-from-poisoned-Mutex
     damit ein Panic-Test nicht alle folgenden Sentry-Tests blockiert.
   - `drop()`: gleicher Cleanup wieder. Naechster Test bekommt
     garantiert sauberen Default-Zustand.

3. Alle 7 Tests in c1_rate_limit_tests + den 1 Smoke-Test in
   c1_mock_transport_smoke umgestellt von `let _g = LOCAL_LOCK.lock()...
   ; fresh_buckets();` auf `let _env = super::SentryTestEnv::lock();`.
   8 Stellen ersetzt.

4. Lokale `TEST_LOCK` + `SMOKE_LOCK` Statics + `fresh_buckets()`-Helper
   entfernt — nicht mehr noetig.

5. Manuelles `sentry::Hub::current().bind_client(None)`-Cleanup am Ende
   vom Smoke-Test entfernt (war nicht genug — resettete nur Hub aber
   nicht CONSENT/BUCKETS) → Drop-Guard macht das jetzt vollstaendig.

Tests:
- cargo test -p aeroacars-app --lib sentry_init → 8/8 ✓
- cargo check --all-targets ✓

Macht den Pfad sauber bevor C2 (S1+S2 PIREP-Sites) kommt — die werden
weitere MockTransport-Tests in c1_mock_transport_smoke ergaenzen, alle
nutzen jetzt automatisch die saubere Test-Isolation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant