Skip to content

id(comms): operator block list by public key, with one-button block in the web UI (P0 of #2032) #2245

Open

Description

@dezren39

From the #2032 investigation (record). This is the control an operator actually reaches for during an incident.

Problem

There is no block list of any kind in pkgs/id — grep -i 'block|ban|deny' over peers, connectivity and petname returns nothing — and ServerConfig (server_config/mod.rs:58-70) has no key that could hold one.

Work

  • Persisted blocks table in the per-node store: {kind: peer_key | ip | topic_tag, value, added_at, reason, expires_at}; expires_at = null is the permanent block the issue asks for.
  • Public key (endpoint ID): refuse new sessions, refuse to serve blobs, drop gossip subscriptions, filter their objects out of views. Blocks change serving/subscribing/rendering — they must not reject already-signed objects, or the graph diverges between nodes (see id: investigate: trust/visibility model — servers accept all signed objects; views count only allowed writers #2030).
  • Web UI: Block / Mute on each peer row, a Blocks page with unblock, and a one-click action that writes the row.
  • IP and topic/tag kinds: IP enforced at the listener only (best-effort; a relayed peer has no visible IP), topic/tag composed with the existing PullPolicy.

Done when

An operator can block a peer from the peer list in one click, see it in the blocks page, and the peer's live frames and served objects stop without any signed object being discarded.

Parent: #2056 · Investigation: #2032 · Synthesis: #2033

Activity

  1. added
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  4. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done (triage)

    Claim-by-claim verdict (fresh at main 5b2eca7a1b5cd6adb84b7b319935118fa76ea32b)

    1. "There is no block list of any kind in pkgs/id" — CONFIRMED. Grep for block-list/blocked-peer machinery over pkgs/id/src returns nothing; block|ban|deny returns nothing in petname.rs or connectivity.rs. Nothing can refuse a peer today.
    2. ServerConfig has no key that could hold one — CONFIRMED. pkgs/id/src/server_config/mod.rs:58-67: ServerConfig { users, groups, create, policy, names, aliases } — no block/abuse field. (Design id: design: abuse-control primitives v1 for ID comms #2033's [abuse] config wiring is id(comms): budgets — app-wide, per-IP, per-ID, and per-counterparty overrides (P1 of #2032) #2247's P1 work, not this issue's.)
    3. Persistence home exists and has a pattern to follow — CONFIRMED. The per-node store is a redb Database in pkgs/id/src/event_store/mod.rs (imports at :56-57; TableDefinition constants events/hashes/chains at :86-91). A blocks table is a new TableDefinition in the same style — no new storage system needed. (store.rs is blob/keypair storage, not the node record store.)
    4. Enforcement seams exist — CONFIRMED. Sessions/pull serving already gate through policy seams (pull_policy.rs:1-19: PullPolicy is local serving policy; note id serve does not load it from config yet — that wiring gap is id(comms): budgets — app-wide, per-IP, per-ID, and per-counterparty overrides (P1 of #2032) #2247's, and Phase 3 must compose with PullPolicy as the issue says, not invent a parallel path); blob serving has its own gate (blob_gate, referenced in pull_policy.rs docs); gossip subscriptions live in the discovery/gossip layer (discovery.rs).
    5. Web UI surface exists — CONFIRMED. pkgs/id/src/web/routes.rs:265 (/peers), :274 (/api/peers), :379-399 (peers_handler → render_peers) — peer rows are rendered server-side, so Block/Mute actions and a Blocks page attach to an existing page, not a new app.
    6. The hard invariant is real — CONFIRMED as a design constraint. Per id: investigate: trust/visibility model — servers accept all signed objects; views count only allowed writers #2030 (cited by both the issue and design id: design: abuse-control primitives v1 for ID comms #2033): blocks change serving/subscribing/rendering only; they must not reject already-signed objects at ingest, or the object graph diverges between nodes. Any implementation that filters at ingest is wrong, however natural it looks.

    Route (design #2033 P0-C, split for the 45-minute packet timebox)

    Design #2033 maps this issue to its P0-C row ("may merge independently from P0-B; depends only on the rule model") and resolves the semantics: endpoint ID for transport admission, author identity for view muting, rules node-local and never federated, expires_at = null permanent. Phased on the standard fix key (one live fix packet per issue; later phases chained on completion, the #3448/#805 pattern):

    1. Phase 1 — ENQUEUED as task 5848 (dedupe repo-health:v1:fix:developing-today/code:issue:2245): typed rule model {kind: peer_key | ip | topic_tag, value, added_at, reason, expires_at} persisted as a redb table in the event store; peer_key enforcement (refuse new sessions, refuse blob serving, drop gossip subscriptions, filter its objects from local views); internal rule add/list/remove for the UI; tests incl. the no-ingest-rejection invariant, restart persistence, expiry.
    2. Phase 2 — web UI (enqueued by task 5848's worker on completion): Block / Mute on each peer row (separate explicit actions, per design id: design: abuse-control primitives v1 for ID comms #2033's endpoint-vs-author distinction), Blocks page with unblock, one-click write.
    3. Phase 3 — remaining kinds (chained after Phase 2): IP enforced at the listener only (best-effort; relayed peers have no visible IP — never inferred), topic/tag composed with the existing PullPolicy.

    Done-when mapping: the issue's "operator can block a peer from the peer list in one click, see it in the blocks page, and the peer's live frames and served objects stop without any signed object being discarded" is met at the end of Phase 2 (one-click + page) with Phase 1's enforcement underneath; Phase 3 completes the issue's remaining Work items.

    Questions for Drew

    None. Design #2033 states this explicitly for the whole primitive set ("no owner preference is needed to start implementation"), and nothing in #2245's scope raises a new one: permanence default, kind set, and the endpoint/author split are all already decided in the issue + design.

  5. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 1, 2026
  6. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: picked-up
    task: 5848 (repo-health-code-pilot, openchamber scheduled lane)
    state: claimed
    next: revalidate issue #2245 and design/PR #2033/#3834, then inspect current code and create the task worktree if the scope is still available.

  7. added
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  8. 134 remaining items

  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

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

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: handed-off
    queue: repo-health-code-pilot
    task: 8517 (small_fix, worker repo-worker-code, lane code-k), attempt 22
    by: repo-worker-code lane code-k
    at: 2026-11-04T21:22:00Z

    Handed off to the opencode execution lane (assigned_lane=opencode via repo-queue lane). Fresh check: issue #2245 OPEN, no hard-stop labels. The laptop claimant launches the bound opencode session for the block-list operator surface remainder; this lane does not work the task directly. Note: task 8517 is at attempt 22/24. Parked 1200s to release the claim for claimant binding. Labels synced: queue/parked + status/parked, work/assigned retained; queue/claimed + status/in-progress removed.

  13. 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 4, 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)queue/parkedQueue task is parked (waiting on CI, time, or an event)source/creatorFiled by the new-issue-creator jobstatus/parkedDeliberately paused with a recorded resume conditiontask/triageQueue packet kind: verify, reproduce, and route this itemwork/assignedQueue worker lifecycle state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions