Repository navigation
Conversation
maple_ik_ keys resolve from org_ingest_custom_keys. After auth and before decode the gateway rejects expired keys (401), signals outside the key's allow-list (403) and requests over the key's rate limit (429, Retry-After). The limit is split across INGEST_RATE_LIMIT_FLEET_SIZE tasks. Resource attribute overrides apply before the maple_* stamps, and telemetry is stamped with maple_ingest_key_id.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…om-gateway # Conflicts: # apps/ingest/alchemy.run.ts # apps/ingest/src/main.rs
Maple review🟢 Confidence 7/10 · likely safe to merge The gateway now resolves
Before merge
Findings🟠 Warning · F1 ·
|
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/main.rs |
228k | POST /v1/logs 130k/day, 0.0% errPOST /v1/logs 66k/day, 0.0% errPOST /v1/sessionEvents 32k/day, 0.0% err |
apps/ingest/src/custom_keys.rs |
32k | POST /v1/sessionEvents 32k/day, 0.0% errPOST /v1/events 14/day, 0.0% errPOST /v1/events 10/day, 0.0% err |
What was checked
- Expiry units: the store selects
EXTRACT(EPOCH FROM expires_at) * 1000(main.rs:7046), matchingis_expired's ms comparison - Tenancy: overrides drop
org_id/maple_*andenrich_resource_attributesretains those keys out before stamping (main.rs:5869) - gRPC admission rejects before the service runs, mapping 401/403/429 to Unauthenticated/PermissionDenied/ResourceExhausted (main.rs:2947)
Observability coverage: 4 of 4 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
| Custom-key policy check (expiry, allow-list, rate limit) on HTTP OTLP, replay/session/events endpoints | request handler | yes | existing server spans record error.type/maple.ingest.reject_reason; maple.ingest.custom_key_id recorded at main.rs:4644 and declared at main.rs:4432 |
| Custom-key policy check in the gRPC admission middleware | rpc middleware | yes | grpc_server_span + record_grpc_identity/record_grpc_outcome (main.rs:2910-2924, 2003-2005) |
Postgres read of org_ingest_custom_keys |
db query | yes | postgres_client_span "fetch_custom_ingest_key" (main.rs:7056) |
| Resource-attribute overrides applied to the payload | enrichment | yes | resulting attributes ride the exported resource (main.rs:5875-5888), not a separate span |
b6b278f · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
A /v1/sessionEvents batch is admitted when the custom key allows sessions or events; custom (track) rows are kept only with events, the rest only with sessions, and dropped rows are counted on the span.
Maple review🟢 Confidence 8/10 · likely safe to merge Fixes the previously flagged hole:
Before merge
Fixed since the last review
Production impactProduction traffic of the changed files (last 7 days)
What was checked
Observability coverage: 5 of 5 changes observable
|
Maple review🟢 Confidence 8/10 · likely safe to merge The gateway now enforces custom
Before merge
Findings🔵 Note · F2 · A default key can spoof
|
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/main.rs |
229k | POST /v1/logs 131k/day, 0.0% errPOST /v1/logs 66k/day, 0.0% errPOST /v1/sessionEvents 32k/day, 0.0% err |
apps/ingest/src/custom_keys.rs |
32k | POST /v1/sessionEvents 32k/day, 0.0% errPOST /v1/events 14/day, 0.0% errPOST /v1/events 10/day, 0.0% err |
What was checked
- The new
org_ingest_custom_keyslookup is a Client span withdb.system/peer.service(apps/ingest/src/main.rs:7083) - Fleet split uses the scaling floor (prd min 2 vs ASG max 12,
apps/ingest/alchemy.run.ts:621), so a scaled-out fleet admits above the configured rps — deliberate per the code comment - Reserved keys are guarded twice: the API rejects
maple_*/org_idcase-insensitively, andcustom_keys::is_protected_attributere-checks at the gateway
Observability coverage: 2 of 2 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
Postgres lookup of org_ingest_custom_keys per uncached custom key |
client DB query | yes | postgres_client_span("fetch_custom_ingest_key", "SELECT", "org_ingest_custom_keys") at apps/ingest/src/main.rs:7083 |
| Expiry / allow-list / rate-limit enforcement for custom keys on HTTP, gRPC, replay and session/event routes | inbound enforcement on existing Server spans | yes | custom key id recorded on ingest.authenticate (main.rs:4670) and gRPC spans (main.rs:1989); metrics::org_throttled(org, "key_rate_limit") at main.rs:3492 |
9227fe5 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
The key id is gateway-owned: drop it with org_id and maple_org_id so a default-key sender cannot spoof which custom key sent its telemetry.
|
Re F2: fixed in e9dca51. |
Maple review🟢 Confidence 9/10 · safe to merge This head only changes
Before merge
Fixed since the last review
Production impactProduction traffic of the changed files (last 7 days)
What was checked
|
|
Preview check of F2 on |
… use A paused custom key is admitted after the expiry and signal checks but its data is dropped: OTLP gets 200, gRPC gets OK and the replay and session endpoints return early, so senders do not retry and nothing is billed. Timed pauses end at paused_until without a cache refresh. Admitted keys stamp last_used_at at most once a minute per key and instance, the same throttle the connector health writes use.
…path last_used_at is now stamped after a payload is enqueued or forwarded, on a spawned task, so a key whose requests all fail (402, 413, 429) no longer reads as live and the write never holds up a request. gRPC carries the admission decision to the export instead of re-reading the clock, and a paused key's 0-byte requests no longer reach billing.
Maple review🟢 Confidence 8/10 · likely safe to merge The ingest gateway now enforces custom
Before merge
Findings🟠 Warning · F3 · A paused key's dropped payload leaves no trace in productionobservability · MET-02 · A paused custom key answers 200 and discards the payload, and nothing in telemetry records it: the only line is this 🤖 Prompt to fix this finding with an AI agentProduction impactProduction traffic of the changed files (last 7 days)
What was checked
|
…ches A throttled key no longer spawns a task, the write runs under a root span linked to the request so request traces do not wait on it, and a collector 4xx no longer counts as use.
Maple review🔴 Confidence 4/10 · risky as written Enforces
Before merge
Findings🔵 Note · F4 · The
|
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/main.rs |
641k | ingest.authenticate 409k/day, 0.0% errPOST /v1/logs 133k/day, 0.0% errPOST /v1/logs 67k/day, 0.0% err |
apps/ingest/src/custom_keys.rs |
31k | POST /v1/sessionEvents 31k/day, 0.0% errPOST /v1/events 15/day, 0.0% errPOST /v1/events 9/day, 0.0% err |
What was checked
- A failed forward returns non-2xx (
forward_to_collector, main.rs:6108), so the new gate drops exactly the unaccepted batches - Per-instance throttling reuses the
entry().or_insert().is_fresh()idiom ofrecord_health(main.rs:6722) information_schemascoping matches thepublicschema every other drizzle statement and the parity harness use
Observability coverage: 3 of 4 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
HTTP OTLP and gRPC export admission (authorize_custom_key) |
inbound entrypoint | yes | existing handle_signal/grpc_server_span record maple.ingest.custom_key_id (main.rs:4523, otel.rs:310) |
Custom key lookup fetch_custom_ingest_key (Postgres SELECT) |
outbound call | yes | postgres_client_span("fetch_custom_ingest_key", "SELECT", "org_ingest_custom_keys", …) |
record_custom_key_used (Postgres UPDATE on a spawned task) |
background work | yes | root span record_custom_key_use linking the request, wrapping postgres_client_span(… "UPDATE" …) (main.rs:6368) |
| Paused key's dropped payload | outcome of an inbound entrypoint | no | only a debug! (main.rs:3530) under the production maple_ingest=warn filter; span stays Ok with no drop attribute |
799a2ec · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
ingest_custom_key_paused_drops_total (org_id, signal) moves on each drop and the request span records maple.ingest.reject_reason=custom_key_paused, so a paused key's traffic is visible instead of looking like an empty export.
Pins the 2xx gate on last_used_at: a collector 400 is relayed and records nothing, and the end-to-end test now asserts an accepted batch records the key id.
|
Re the review at
|
Maple review🟢 Confidence 9/10 · safe to merge The delta makes a paused custom key's discarded payload visible: a per-org/signal counter and a reason on the request span, plus tests pinning the pause drop and the 2xx gate on
Before merge
Fixed since the last review
Production impactProduction traffic of the changed files (last 7 days)
What was checked
Observability coverage: 1 of 1 changes observable
|
Maple review🟢 Confidence 8/10 · likely safe to merge No source changed since the last review: Before merge
Production impactProduction traffic of the changed files (last 7 days)
What was checked
Observability coverage: 2 of 2 changes observable
|
Part 2 of 3: the ingest gateway enforces custom ingest keys (
maple_ik_). Base: #1518.Behavior
maple_ik_keys resolve only fromorg_ingest_custom_keys(same 60s cache as default keys). Default keys are unchanged.PermissionDenied.paused_untilwithout waiting for a cache refresh.Retry-After, or gRPCResourceExhausted. The per-key token bucket isceil(rps / INGEST_RATE_LIMIT_FLEET_SIZE)per task.last_used_atis written on a spawned task, at most once a minute per key and instance. A key whose requests all fail never reads as live.maple_*stamps and can never writeorg_id/maple_*. Telemetry getsmaple_ingest_key_id = ingk_…, and a sender cannot spoof it.Verified
cargo test: 245 + 123 tests pass. New tests cover:🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.