Skip to content

id(world_session): install_module_session parses chunk and install_end frames without the duplicate-key refusal — duplicate keys in ignored fields silently collapse, unlike every other ClientFrame path #6523

Open

Description

@dezren39

Problem

install_module_session in pkgs/id/src/world_session/mod.rs is the one remaining ClientFrame parse path that does not route through the module's strict duplicate-key parser. Every other peer-frame entry point refuses a frame containing duplicate JSON keys at any depth; the module-install path parses chunk and completion frames with plain serde_json::from_str::<ClientFrame>, which refuses duplicate known fields (serde derive) but silently collapses duplicate keys in fields the frame type ignores — the exact residual class PR #6508 pinned and fixed for query_session.

Evidence (origin/main 6046e1d, pkgs/id/src/world_session/mod.rs):

Verified this run on the laptop with a probe driving the real id crate's public run_session_with against a clean origin/main export (probe ~/git/fleet/probe-id-install-dupkeys; WorldService with admin token, install_begin with total_bytes: 1, one 1-byte chunk 0x00, then install_end; oracle = which error the session ends with — "Wasm module failed validation or initialization" means the frames were accepted and the upload reached module installation, "expected module chunk frame" means the chunk was refused at parse):

  • Control: valid chunk + valid install_end → "Wasm module failed validation or initialization" (accepted; reached install).
  • Chunk {"type":"install_chunk","offset":0,"data_hex":"00","bogus":1,"bogus":2} → same Wasm error: duplicate unknown keys silently accepted.
  • Chunk with "extra":{"a":1,"a":2} → same Wasm error: duplicates nested inside an ignored object silently accepted.
  • install_end as {"type":"install_end","bogus":1,"bogus":2} after a valid chunk → same Wasm error: the completion frame matched despite duplicate keys.
  • Chunk with duplicate known field "offset":0,"offset":0 → "expected module chunk frame" (refused by serde derive) — confirming the gap is precisely the ignored-field class, not all duplicates.

Why it matters

The install path is the admin module-upload gate: it runs after admin authorization and assembles the exact bytes whose hash is checked and which are then installed as a world module. It is the last session path where two readers of the same frame bytes can disagree about what was sent — the inconsistency the duplicate-key contract (design #6520; sibling fixes #6473, #6474, #6491, #6499, #6504, #6501) exists to remove. #6521 (the gated closing inventory) does not name this site; this issue is its disposition for the install path: it is a gate, not a not-a-gate.

Acceptance criteria

  • Chunk frames and the install_end frame in install_module_session are parsed through parse_json_without_duplicate_keys + serde_json::from_value::<ClientFrame> (or an equivalent strict route), so any duplicate key at any depth — known, unknown/ignored, or nested inside an ignored object — refuses the frame before any chunk bytes are appended or the upload is treated as complete.
  • Refusal behavior matches the current parse-failure behavior: a refused chunk ends the install with "expected module chunk frame"; a refused completion frame ends it with "expected install_end frame".
  • Regression tests (sandbox feature, mirroring the existing admin_upload_pins_validates_and_activates_a_roc_program harness and PR fix(id): refuse duplicate JSON keys in world_session first/joined frames (#6501) #6508's query-session cases) pin: duplicate unknown key in a chunk, duplicate key nested in an ignored chunk object, and duplicate unknown key in install_end — each refused; the valid upload flow still installs.
  • Existing world_session tests keep passing (cargo test -p id world_session on the laptop or CI).

Related: #6501 (first/joined/query paths), #6520 (duplicate-key contract), #6521 (closing inventory — install site not named there).

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    on Nov 6, 2026
  2. developing-today commented on Nov 6, 2026

    @developing-today
    Contributor
  3. added
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Nov 6, 2026
  4. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator-code-a
    • Session / ID: cron job new-issue-creator-code-a, run 2026-11-06 07:35 CST
    • Found via: filed this run
    • Task: Filed this issue — install_module_session chunk/install_end frames skip the duplicate-key refusal every other ClientFrame path applies; verified with a probe driving the real id crate (probe ~/git/fleet/probe-id-install-dupkeys on the laptop).
    • Expectation: effort s — triage via the enqueued repo-task packet; done looks like both install parses route through parse_json_without_duplicate_keys with regression tests mirroring PR fix(id): refuse duplicate JSON keys in world_session first/joined frames (#6501) #6508's query-session cases.
    • Links: queue packet packet-6523-small-fix.json (repo-health-code-pilot)
  5. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 6, 2026
  6. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    agent-note:v1

    • task: 11174
    • lane: code-f
    • event: handed_off
    • detail: Claimed by lane code-f (fresh task, attempts 1/4); execution-lane assignment is opencode. Checkpointed handed_off for the opencode claimant to launch the bound session.
  7. 19 remaining items

  8. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  9. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 6, 2026
  10. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    Picked up task 11174 from its awaiting_ci checkpoint. Fresh state: #6523 is open; PR #6576 is open on the task branch, and its basic required checks have remained QUEUED since 17:10:45Z. No PR changes or merge action taken; parking under the five-minute CI rule.

  11. 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 Nov 6, 2026
  12. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    Task 11174 is parked for 20 minutes. Resume when PR #6576 basic checks finish; then revalidate GitHub state, review the diff and ownership restrictions, and decide the next action. Required basic checks were still QUEUED more than five minutes after starting. Issue labels now reflect parked state; work/assigned remains.

  13. dezren39 commented on Nov 6, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  14. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    app/idPackage/app: id (pkgs/ or apps/ in this repo)kind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)queue/queuedHas a queued task in the Supabase agent queuesource/creatorFiled by the new-issue-creator jobstatus/parkedDeliberately paused with a recorded resume conditiontask/small-fixQueue packet kind: bounded fix with reproduction and targeted testswork/assignedQueue worker lifecycle state

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions