Skip to content

pkarr-worker(retention): RETENTION_SECONDS is parsed with a bare Number() and no guard — '0'/'7d'/' ' schedule the deletion alarm at/before now (or NaN), so stored packets vanish right after a 204, and '1e9' never expires #3261

Closed

Description

@dezren39

Summary

pkgs/pkarr-worker: RETENTION_SECONDS is parsed with a bare Number(...) and no validity guard in PkarrStore.putPacket (src/index.ts:67-68), and the resulting timestamp is handed straight to setAlarm, whose handler unconditionally deletes the stored record. Any value that is not a plain positive decimal silently breaks retention for every record in that object:

  • "0", "-1", or a whitespace-only " " (truthy, so the || "604800" fallback does not fire; Number(" ") is 0) → the deletion alarm is scheduled at or before now, so the record a PUT just stored (and returned 204 for) is deleted again almost immediately; later GETs 404.
  • "7d" or any non-numeric spelling → retentionMs is NaN and the alarm time is NaN — the expiry behaviour is whatever the runtime does with an invalid alarm time, instead of the documented 7 days.
  • "1e9" → silently reinterpreted as 1,000,000,000 seconds (~31,700 years): records effectively never expire, contradicting the header contract that "records expire after RETENTION_SECONDS without refresh".

The same file already shows the house pattern for exactly this: DNS_TTL is parsed in handleDoh (src/index.ts:224-226) with Number.isFinite(ttl) && ttl > 0 ? ttl : 30 — a guarded parse with a sane fallback. The retention parse has no equivalent guard.

Evidence (main f4f800e7)

Verified (laptop probe, exact expressions from index.ts:67)

Probe: ~/git/fleet/probe-2026-10-31-laneA-pkarr-retention/ on the laptop — src/index.ts sha256 a751bb4d… identical in the laptop clone and the sandbox checkout at main f4f800e7; the probe evaluates the verbatim :67 expression:

undefined  -> retentionMs = 604800000     | alarm in past / invalid: false
"604800"   -> retentionMs = 604800000     | alarm in past / invalid: false
"0"        -> retentionMs = 0             | alarm in past / invalid: true
"-1"       -> retentionMs = -1000         | alarm in past / invalid: true
"7d"       -> retentionMs = NaN           | alarmAt = NaN
"  "       -> retentionMs = 0             | alarm in past / invalid: true
"1e9"      -> retentionMs = 1000000000000 | ~31,700-year retention
"3600.5"   -> retentionMs = 3600500       | fractional seconds accepted silently

(The Durable Object alarm itself was not executed — no node_modules on the laptop for the workers vitest pool; the claim verified here is the parse layer plus the unconditional-delete alarm handler in the source. A past-due setAlarm firing promptly is documented Durable Object behaviour.)

Why it matters

Retention is the only expiry mechanism for stored pkarr packets: the store has one row per key and getPacket performs no age check, so the alarm is the whole contract. A config slip therefore fails in the worst two directions at once — live records vanishing right after a successful publish (clients see 204, then 404), or records never expiring at all — with no error anywhere: putPacket returns "stored" in every case above except a possible runtime throw on the NaN alarm.

Acceptance criteria

  • RETENTION_SECONDS is parsed with the same discipline as DNS_TTL: a non-finite, non-positive, or non-plain-decimal value falls back to the 604800s default (or is rejected loudly at startup), never reaching setAlarm as 0/negative/NaN.
  • With RETENTION_SECONDS set to "0", "7d", and " " (one test each), a PUT still stores the packet and a subsequent GET returns it, with the alarm scheduled ~7 days out.
  • Scientific/fractional spellings ("1e9", "3600.5") are either rejected-to-default or explicitly documented as accepted — not silently reinterpreted.
  • Regression tests in the workers vitest suite cover the bad-value cases alongside the existing "604800" behaviour, which is unchanged.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    effort/sSmall: expected under 2 hours of work
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: filed

    • Agent: new-issue-creator (new-issue-creator-code-a)
    • Session / ID: cron new-issue-creator-code-a, 2026-10-31 18:35 CDT run
    • Found via: filed this run
    • Task: Filed after verifying on the laptop (sha-matched src/index.ts) that the RETENTION_SECONDS parse at index.ts:67 has no guard — '0'/'-1'/' ' put the deletion alarm at/before now, '7d' yields NaN, '1e9' stretches retention to ~31,700 years — while DNS_TTL in the same file is guarded with a fallback
    • Expectation: effort/s — parse RETENTION_SECONDS with the DNS_TTL discipline (finite, positive, plain decimal, else the 604800 default); vitest cases for '0', '7d', ' ' alongside the unchanged '604800' behaviour
    • Links: pkgs/pkarr-worker/src/index.ts:67-68,86-88,224-226; probe ~/git/fleet/probe-2026-10-31-laneA-pkarr-retention/ (laptop)
  3. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  4. 9 remaining items

  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    status/readyTriaged and ready for queued implementation work
    on Nov 2, 2026
  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1

  7. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1

    • state: handed-off (PR opened)
    • agent: repo-worker-code (OpenChamber scheduled lane)
    • session: ses_e5e63de7762ffeTdiKRyeQb1wZ; task 5686
    • result: guarded RETENTION_SECONDS as positive whole decimal seconds; invalid, unsafe, or out-of-range values use the 604800-second default. Added PUT/GET and alarm regressions and documented the setting.
    • verification: Workers Vitest 28/28 passed; typecheck passed.
    • next: inspect PR checks and merge only after checks are green.
    • links: fix(pkarr-worker): guard retention alarm values (#3261) #4352
  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1

    • state: done (queue outcome: pr_opened)
    • agent: repo-worker-code (OpenChamber scheduled lane)
    • session: ses_e5e63de7762ffeTdiKRyeQb1wZ; task 5686
    • result: PR fix(pkarr-worker): guard retention alarm values (#3261) #4352 is open with the retention guard, docs, and regressions. Local Workers tests (28/28), typecheck, and diff check pass.
    • CI: no project checks are configured/running; CodeRabbit is neutral/skipped. Unrelated daily automation workflows failed before creating jobs. Left the PR open for review rather than merging without a green project check.
    • links: fix(pkarr-worker): guard retention alarm values (#3261) #4352
  10. added a commit that references this issue on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/pkarr-workerpkgs/pkarr-workereffort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions