Skip to content

id(web): web_interface_from_app_toml accepts route/socket values that panic in create_router_for_app (no leading-slash or host-route collision check) #4779

Closed

Description

@dezren39

Problem

The binding-layer parser for a packaged app's [interfaces.web] section, web_interface_from_app_toml (pkgs/id/src/web/app_interface.rs:117), validates only mode. It accepts any route / socket string and hands it to create_router_for_app (pkgs/id/src/web/routes.rs:306), which feeds both straight into axum route registration:

  • route → .route(&world_route, get(world_page_handler)) at src/web/routes.rs:322
  • socket → world_routes_at(socket) at src/web/routes.rs:382, which does .route(socket, ...) at src/web/world_ws.rs:60

Axum panics on a path that does not start with / and on a path that collides with an already-registered route. So a packaged app whose app.toml carries a malformed or colliding binding crashes router construction (server startup / host binding) with an axum panic instead of a named WebInterfaceError.

This is the public flow the crate itself exercises in public_entry_point_honours_a_configured_binding (src/web/routes.rs): parse [interfaces.web] with web_interface_from_app_toml, then build the router with create_router_for_app. The host-discovery work (#2324) will feed real third-party app folders through exactly this path.

Verified (probe on laptop, origin/main cb190a3)

A probe test in a scratch worktree parsed each [interfaces.web] below with web_interface_from_app_toml (all parsed Ok) and built the router with create_router_for_app under catch_unwind:

route socket parse router
arena /ws/arena Ok panic at routes.rs:322 (path must start with /)
/ /ws/arena Ok panic at routes.rs:322 (collides with the index route)
/files /ws/arena Ok panic at routes.rs:322 (collides with the files page route)
/arena ws/arena Ok panic at world_ws.rs:60 (path must start with /)
/arena /ws/tags Ok panic at routes.rs:382 merge (collides with the live-tags channel)
/arena /ws/arena Ok no panic (control)

Why this is not #4060

#4060 covers parse_app_manifest / discover_apps in src/app_manifest.rs (segment sanity for route, any validation at all for socket, cross-app duplicate routes at discovery). This issue is the other parser — the binding layer in src/web/app_interface.rs, which #4060 does not name — and a different failure mode: even values that pass app_manifest's only web check (route.starts_with('/'), app_manifest.rs:174) and all of #4060's proposed segment-sanity criteria (/, /files: leading slash, no .., no whitespace, no ?/#) still panic the router, because the host's own route table is never consulted.

Why it matters

A packaged app is data, not code the host author wrote. One bad app.toml in an apps folder turns a recoverable configuration error into a process panic at startup, with an axum/matchit message that names neither the app nor the field. Every other malformed-manifest path in this codebase returns a named error (WebInterfaceError::UnknownMode is the existing precedent in the same function).

Acceptance criteria

  • web_interface_from_app_toml rejects a route or socket that does not start with /, returning a WebInterfaceError variant that names the field and the value.
  • A route or socket that collides with a route the host router always registers (at minimum /, /files, /settings, /peers, /ws/tags, /ws/collab/{doc_id}, the /api/world/* surface, and the other side of the same binding) cannot panic router construction: it is rejected at parse/bind time with a named error, or router construction validates and reports it.
  • Unit tests cover the five verified cases above (no-slash route, /, /files, no-slash socket, /ws/tags socket) plus the /arena + /ws/arena control still building a working router.
  • The world app's own binding (/world, /ws/world) and the checked-in pkgs/id/apps/tic-tac-toe/app.toml binding are unchanged.

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)
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Nov 3, 2026
  2. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator (lane B, new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b run, 2026-11-03T06:50Z
    • Found via: filed this run
    • Task: Filed after verifying on the laptop at origin/main cb190a3: a probe test (pkgs/id/src/web/routes.rs, cargo test --lib --features web, probe worktree removed after the run) showed web_interface_from_app_toml parses route="arena", route="/", route="/files", socket="ws/arena" and socket="/ws/tags" all Ok, and create_router_for_app panics on every one (routes.rs:322, routes.rs:382, world_ws.rs:60); the /arena + /ws/arena control builds fine. Distinct from id(app_manifest): interfaces.web route/socket are barely validated and discovery accepts duplicate routes #4060, which covers parse_app_manifest/discover_apps in app_manifest.rs — route="/" and "/files" pass even its proposed criteria.
    • Expectation: effort/s — reject non-/-prefixed and host-colliding route/socket values at parse/bind time with a named WebInterfaceError, with regression tests for the five verified cases.
    • Links: queue packet packet-4779-fix.json (repo-health-code-pilot)
  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 3, 2026
  4. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  5. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · PR opened

  6. added a commit that references this issue on Nov 3, 2026
  7. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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)effort/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