Skip to content

id(world-manifest): validate() never checks the execution profile or the schedule count — manifests parse and plan clean, then fail partway through a live apply #3015

Closed

Description

@dezren39

id(world-manifest): validate() never checks the execution profile or the schedule count — manifests parse and plan clean, then fail partway through a live apply

Evidence (main 6bbb065b, verified this run)

WorldManifest::validate() (pkgs/id/src/world_manifest.rs:164-196) — the only gate parse() runs (:151-155) — checks grant names, ceiling names, schedule ids and positive fire times, module-hash shape, and hash/source exclusivity. It never looks at two fields it carries:

  1. The execution profile. Every bound WorldExecutionProfile::resolve() refuses (pkgs/id/src/world_limits.rs:71-92) sails through parse():

    • wasm_fuel = 0, wasm_message_bytes = 0, native_cpu_seconds = 0, native_call_deadline_ms = 0
    • wasm_memory_bytes = 1024 (below the 64 KiB one-page minimum)
    • native_memory_bytes = 1024 (below the 16 MiB minimum)

    plan() then emits a SetProfile step for each (any non-default profile that differs from current, world_manifest.rs:285-289). The live apply reaches WorldService::set_execution_profile, which resolves first and refuses (pkgs/id/src/world_session/mod.rs:266: profile.resolve(self.runtime)?). world doctor's check_profile (world_doctor.rs:326-366) flags exactly these values — the doctor and the manifest validator disagree about what a valid profile is.

  2. The schedule count. A present schedules map is reconciled exactly (world_manifest.rs:293-308: add missing, cancel undeclared), so the desired end state has exactly len(schedules) pending. validate() accepts 65 entries — one past MAX_PENDING_SCHEDULES = 64 (world_caps.rs:95), the cap WorldCore::check_schedule enforces on every live set (world/core.rs:613-617, called from world/actor.rs:759). No live world can ever hold the state the manifest declares.

Verified with a probe (laptop, this run)

Probe crate ~/git/fleet/probe-2026-10-31-laneA-manifestvalidate/ (laptop) built from verbatim world_manifest.rs (md5 7b3e4e0a…), the verbatim validators/constants of world_caps.rs (md5 ac9d6bd5…), and the verbatim WorldExecutionProfile + resolve() of world_limits.rs (md5 94fccbd8…) — both clones at 6bbb065b:

  • All six profile values above: parse() → Ok, plan() → exactly one SetProfile step, resolve(RuntimeLimits::default()) → Err.
  • A 65-entry schedules map: parse() → Ok, plan() against an empty state → 65 ScheduleAt steps.

Why it matters

id world apply is not atomic: apply_steps runs the steps in reachability order (commands/world.rs ordered_steps: cancels → profile → grants → ceiling → module → schedule additions) and stops at the first error. So a manifest that parse() blessed can:

  • fail at the SetProfile step after schedule cancels have already landed, or
  • fail on the 65th ScheduleAt step after the profile, grants, ceiling and module install have all been applied and journaled —

leaving the world half-reconciled to a manifest that can never be fully applied, with diff still promising the remaining steps will converge. Validation is the manifest's contract ("a manifest should be validated first; this is a defensive re-check", world_manifest.rs:311-314 on apply()) — the two fields it skips are exactly the two whose live refusals arrive mid-apply.

Distinct from #2876 (unknown/misspelled keys silently ignored — serde-level) and #2166 (module_hash blake3:<hex> doc mismatch): this is about declared, known fields whose values validate() never checks. The schedule horizon (30 days, check_schedule) is deliberately not part of this issue: it is relative to the apply-time clock, so a pure validate() cannot judge it — only the count is time-free.

Acceptance criteria

  • WorldManifest::validate() (or parse()) refuses a profile that resolve() would refuse: zero wasm_fuel / wasm_message_bytes / native_cpu_seconds / native_call_deadline_ms, wasm_memory_bytes < 64 KiB, native_memory_bytes < 16 MiB — naming the offending bound, consistent with check_profile's problem list.
  • validate() refuses a schedules map with more than MAX_PENDING_SCHEDULES (64) entries, naming the cap.
  • Regression tests in world_manifest.rs's test module (extending validation_rejects_unknown_names_and_bad_hashes or new tests): each bad profile bound fails parse(); a 65-entry schedule map fails parse(); a 64-entry map and a boundary-valid profile (exactly 64 KiB / 16 MiB) still parse.
  • Existing manifest tests keep passing (parses_and_round_trips uses wasm_fuel = 5_000_000 and one schedule — both stay valid).

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/lowNice to have; do when convenient
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  3. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed (verification correction)

  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 Nov 1, 2026
  5. 38 remaining items

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

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  9. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    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/idPackage/app: id (pkgs/ or apps/ 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