Skip to content

aggregator(health): dns/aa section stamps are never validated — a garbage dns generatedAt renders ageMs NaN/null, a future aa generatedAt renders age 0 (maximally fresh) for as long as the skew lasts #2242

Closed

Description

@dezren39

aggregator(health): dns/aa section stamps are never validated — garbage dns generatedAt renders ageMs NaN, future aa generatedAt renders age 0

Evidence (verified this run, main 24901e7b)

The /health view is the stack's honesty surface: feedSections in pm-stack/aggregator/src/health.ts:184-207 reports each feed section's generatedAt and ageMs. Three sections carry their own stamps — orchestration, dns, aa (the rest inherit the feed's top-level stamp). Only the orchestration stamp is ever validated:

  • Top-level feed stamp: isFleetFeed (feed.ts:213-222) requires Number.isFinite(Date.parse(generatedAt)), and buildHealth itself flags a top-level stamp >60s in the future as "never fresh" (health.ts:234-235, :254-262, GENERATED_AT_FUTURE_SKEW_MS).
  • Orchestration stamp: orchestrationSectionProblem (feed.ts:131) requires a finite parse, and diagnoseOrchestrationSection (feed.ts:180-186) rejects >60s future stamps as invalid.
  • dns stamp: DnsSection.generatedAt (model.ts:644-646) has no validator on the read path — isFleetFeed never inspects the dns section.
  • aa stamp: isAaSection (aa.ts:1070-1084) checks only typeof generatedAt === "string" — no parse, no finiteness, no future bound. isFleetFeed doesn't inspect the aa section either.

feedSections' helper (health.ts:186-189) computes the age blindly:

const ts = generatedAt ?? feed.generatedAt;
return { present, generatedAt: ts, ageMs: Math.max(0, now - Date.parse(ts)), ... };

Date.parse of a garbage stamp is NaN, and Math.max(0, NaN) is NaN. A future stamp gives a negative age, clamped to 0 — maximally fresh — and stays 0 until the stamped date passes.

Probe (Bun, real buildHealth, fixtures mode)

Feed with a valid top-level stamp, dns.generatedAt = "not-a-date", aa.generatedAt = now + 30 days:

orchestration: present=false generatedAt="2026-10-29T10:47:56.678Z" ageMs=0 isNaN=false json=0   (control: absent → feed stamp)
dns: present=true generatedAt="not-a-date" ageMs=NaN isNaN=true json=null
aa:  present=true generatedAt="2026-11-28T10:47:56.678Z" ageMs=0 isNaN=false json=0

So the health JSON says the dns section is present with ageMs: null and no invalid/stale signal, and the aa section looks just-collected (ageMs: 0) for the next 30 days.

Why it matters

The health page exists so a stale or broken section is diagnosable instead of silently "absent" or silently fresh (#1139/#1140, and #1564 established the finite + 60s-future-skew convention for the orchestration section and the top-level stamp). The dns and aa sections escaped that pass: a collector bug or clock skew that corrupts either stamp is invisible on the one surface meant to catch it — garbage reads as "present, age unknown", and a future stamp reads as "freshest possible" for as long as the skew lasts.

Acceptance criteria

  • feedSections (or the section gates feeding it) applies the house convention to the dns and aa stamps: an unparseable stamp does not produce ageMs: NaN — the section is reported with a legible invalid/absent-style signal instead of present + ageMs: null.
  • A section stamp more than GENERATED_AT_FUTURE_SKEW_MS (60s) in the future is not reported as ageMs: 0 fresh; it gets the same treatment the top-level stamp gets ("never fresh" / invalid).
  • Valid stamps render exactly as today; a regression test (health tests) covers garbage and future dns/aa stamps alongside the existing top-level/orchestration cases.

Notes

Filed by new-issue-creator-code-a (agent-note follows).

Activity

  1. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 29, 2026
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 31, 2026
  5. 9 remaining items

  6. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  7. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  8. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 31, 2026
  9. added a commit that references this issue on Oct 31, 2026
  10. removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    work/assignedQueue worker lifecycle state
    on Oct 31, 2026
  11. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: done
    task: 4321 (lane E resume)
    pr: #3091 MERGED @ 201e0c3
    note: Codex review on df2ea24 completed clean ("Didn't find any major issues", no threads). No PR CI covers pm-stack/** (per #2936); verification was the laptop suite from the opening lane (health 18/18, full-suite fail set identical to clean main). Diff = exactly the 4 packet files (health.ts, dns.ts, aa.ts, test/health.test.ts). Issue auto-closed by the merge; stale queue/status/work labels removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)effort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions