Skip to content

Middleware silently drops windows on 401, no escalation path #16

@AndresL230

Description

@AndresL230

Middleware silently drops windows on 401, no escalation path

Severity: High
Affected repos: middleware-node, middleware-python
Component boundary: middleware cloud transport ↔ API

Symptom

When the API returns 401 (invalid or revoked API key), both SDKs correctly skip retry (4xx is non-retriable), then drop the window and log a console warning. There is no mechanism to:

  • Stop trying after N consecutive 401s (each subsequent flush eats the same 401 and discards more data).
  • Notify the host application that authentication is failing.
  • Surface a clear "your key was revoked" message to the developer.

The integration appears to work — the SDK keeps spinning — but no data ever reaches the API.

Evidence

  • middleware-node/src/core/transport.ts_postCloud() returns { ok: false, status: 401 } on a 401, the window is dropped, optional onError callback is fired with a generic error.
  • middleware-python/recost/_transport.py — same shape.

Impact

  • A user rotates their API key, forgets to update the SDK config. The new key is valid, the old key 401s forever. SDK keeps running, dashboard goes flat. Customer assumes the dashboard is broken.
  • An invalidated key (e.g., security incident) silently disconnects every running deployment with no signal.

Fix recommendation

  1. Stop after N consecutive auth failures. After 5 consecutive 401s, suspend the cloud transport, emit a high-severity onError with explicit text, and stop retrying. Resume only on explicit handle.reconfigure(...) or process restart.
  2. Distinguish auth errors in onError. Pass a discriminator ({ kind: "auth_failure", status: 401 }) so host applications can route to alerting.
  3. One-time stdout warning. On the first 401, log to stderr (not the debug logger that's silent by default) with a clear message: "ReCost: API rejected key (401). Telemetry will be dropped. Check your apiKey at https://recost.dev/dashboard/account."

Mirror in both SDKs.

Verification

  • Configure an invalid key, run for 5 flush intervals, confirm the SDK stops trying after 5 attempts and the onError callback fires with the auth discriminator.
  • Confirm a single warning is printed to stderr on first failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions