Skip to content

orb_signals.gate_verdict has no length cap, unlike every sibling string field in the same insert #8333

Description

@JSONbored

Context

src/orb/ingest.ts's per-event validation/insert loop for orb_signals caps every other string field it writes: repo_hash/pr_hash at MAX_HASH_CHARS (128), gate_reasoncode_bucket at MAX_BUCKET_CHARS (64), and instance_id at MAX_INSTANCE_ID_CHARS (64) elsewhere in the same file. gate_verdict, however, is inserted with only a type check and no length cap:

typeof event.gate_verdict === "string" ? event.gate_verdict : null,

The column is documented in migration 0060_orb_fleet_collector.sql (line 20) as a low-cardinality enum-shaped field ('merge' | 'close' | 'hold'), matching every sibling string field's tight cap in intent — but nothing in the ingest path actually enforces a size limit on it. test/integration/orb-ingest.test.ts has explicit oversized-value rejection tests for instance_id (line 29), repo_hash/pr_hash (lines 35, 38), and gate_reasoncode_bucket (line 63) — but only a plain string-vs-null test for gate_verdict (lines 42-46), confirming no cap was ever added for this field even though its siblings all have one.

Since this collector accepts anonymized batches from self-hosted instances (see the file's own header comment: "Accepts anonymized, reversal-aware outcome batches from self-hosted instances"), an unbounded string field is an easy way for a malformed or hostile instance to push oversized rows into orb_signals.

Requirements

  • Add a MAX_VERDICT_CHARS constant (32 is a reasonable ceiling given the three documented enum values) alongside the file's existing MAX_HASH_CHARS/MAX_BUCKET_CHARS/MAX_INSTANCE_ID_CHARS constants.
  • Gate the gate_verdict bind the same way gate_reasoncode_bucket already is: typeof event.gate_verdict === "string" && event.gate_verdict.length <= MAX_VERDICT_CHARS ? event.gate_verdict : null.
  • Do not change validation for any other field in this loop.

Deliverables

  • MAX_VERDICT_CHARS constant added to src/orb/ingest.ts.
  • gate_verdict's bind expression updated to enforce the new cap, following the exact pattern already used for gate_reasoncode_bucket.
  • A test in test/integration/orb-ingest.test.ts mirroring the existing oversized-value tests (e.g. line 63's gate_reasoncode_bucket test) for gate_verdict: an event with a gate_verdict longer than MAX_VERDICT_CHARS is accepted into the batch but stored as null for that field (matching the existing coercion behavior for other capped fields), not rejected outright.

Test Coverage Requirements

This repo's Codecov patch gate requires 99%+ coverage of changed lines and branches. Cover both the within-cap (value stored) and over-cap (coerced to null) branches of the new condition.

Expected Outcome

gate_verdict is bounded the same way every sibling string field in the orb_signals insert already is — an oversized value from a malformed or hostile self-hosted instance is coerced to null instead of being written unbounded.

Links & Resources

  • src/orb/ingest.ts — the orb_signals insert loop, gate_verdict bind around line 166-170; existing caps MAX_HASH_CHARS/MAX_BUCKET_CHARS/MAX_INSTANCE_ID_CHARS near the top of the file
  • migrations/0060_orb_fleet_collector.sql — line 20, gate_verdict column documentation
  • test/integration/orb-ingest.test.ts — existing oversized-value tests, lines 29, 35, 38, 63; existing gate_verdict string-vs-null test, lines 42-46

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions