Skip to content

id(app_manifest): the #4082 duplicate gate covers only capabilities.request — duplicate cli.commands pass, and padded capability entries evade the duplicate check and are stored untrimmed #4085

Closed

Description

@dezren39

Summary

The field-value gate added for #4063 (PR #4082, parse_app_manifest in pkgs/id/src/app_manifest.rs) rejects duplicate capabilities.request entries — with the stated rationale that a repeat is an authoring mistake the gate should name rather than silently absorb — but the same gate is inconsistent for the manifest's other list fields, and its own duplicate check is evadable by whitespace padding:

  1. Duplicate interfaces.cli.commands are accepted. commands = ["play", "play"] parses fine (app_manifest.rs:119-131 validates only non-empty + non-blank). The duplicate rule was applied to capabilities.request (lines 146-155) but not to the CLI command list in the same function.
  2. The capability duplicate check compares raw strings while the blank check trims. request = ["store.read", " store.read "] is accepted as two distinct requests (lines 133-155: blank check uses capability.trim(), the HashSet insert uses the raw capability), and the padded entry is stored verbatim in the parsed manifest — so the manifest's "strict record of what an app asks for" carries a capability name (" store.read ") that no exact-match capability check will ever match, silently granting nothing while looking granted. The same padding evasion works for commands: ["play", " play "] is accepted.

Evidence (verified this run)

Laptop probe ~/git/fleet/probe-2026-11-01-laneA-manifest/ — a crate that compiles the real app_manifest.rs from main 78b2bd26 (md5 d786541ff7045e599df9516605b129db, byte-identical to the repo file) and calls parse_app_manifest:

dup-cli-commands:    ACCEPTED cmds=["play", "play"]
ws-evaded-cli-dup:   ACCEPTED cmds=["play", " play "]
ws-evaded-cap-dup:   ACCEPTED caps=["store.read", " store.read "]
untrimmed-cap-entry: ACCEPTED caps=[" store.read "]   (stored verbatim, padding kept)
baseline-cli / baseline-web: ACCEPTED (unchanged)

Why it matters

#4082's gate is the strict authoring contract for app manifests; an app author who duplicates a command or pads a capability gets no error, and the padded capability silently never matches at enforcement time — the worst failure shape for a permission request (looks declared, never granted, no diagnostic anywhere). The inconsistency is also in the exact code the #4063 fix just touched, so the contract reads as deliberate where it is actually partial.

Acceptance criteria

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    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
    priority/lowNice to have; do when convenient
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 2, 2026
  2. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

  3. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · adopted as Phase 2 of design #4202

  4. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — holder: repo-worker-code (OpenChamber scheduled lane), at=2026-11-02T15:07:19Z. event: picked-up; task: 5981; queue: repo-health-code-pilot. Fresh main inspection at origin/main 2ab643e (source md5 matches the filed probe) confirms the duplicate/padded-entry gap; #4085 remains OPEN and adopted as Phase 2 of #4202. No issue refile/re-scope/split.

  5. 41 remaining items

  6. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — parked

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

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  9. added
    queue/claimedQueue worker lifecycle state
    and removed
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    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/sSmall: expected under 2 hours 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 jobsource/design-architectFiled by the repo design architect 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