Skip to content

[mesh] Security hardening (Zenoh-native): umbrella tracker for split of #195 #219

@cagataycali

Description

@cagataycali

Umbrella tracker — splitting #195 into 9 child PRs

#195 is the canonical 'mesh security hardening' PR (77 files changed, +15,965/-216, 213 review threads, 24 R-rounds). It is correct as a single piece of work but operationally hostile to review. Splitting it into 9 dependency-ordered child PRs lets reviewers focus on one subsystem at a time, lets CI signal stay sharp, and keeps git bisect useful in the future.

The full split plan with dependency graph, file mappings, and reviewer focus per slice lives in PR_LIST.md on my fork. This issue is the live tracker.

Threat surface (recap from #195)

11 attack vectors across 3 attacker tiers (LAN device, stolen IoT cert, prompt injection): unauth /cmd publish, replay, fake policy_host, dual-path double-exec, prompt-injected emergency_stop, audit tampering, camera URL capture, command-after-Estop, presence spoofing, /cmd flood, CA-substitution MITM.

Solution architecture (recap)

Defence-in-depth in three layers:

  1. Wire layer (Zenoh built-ins) — mTLS, per-key-expr ACL, downsampling rate caps, low_pass_filter byte caps, namespace isolation, gossip-only scouting, session-count bound, safety-topic caps.
  2. Payload layer (mesh/security.py, ~786 LOC) — action allowlist + bounds, VLA host allowlist, HF repo gate, policy class registry gate.
  3. LLM tool layer (tools/robot_mesh.py) — HITL via tool_context.interrupt, per-action rate limit, declined-doesn't-consume.
  4. Audit (mesh/audit.py) — per-record HMAC + per-peer monotonic seq + bounded rotation + tamper-aware cursor + symlink-resistant inode writes.

Child PRs (in landing order)

Dependency graph

PR-1 (#220, test infra) ──┐
                          ├──► PR-2 (#223 security) ───────────────┐
                          ├──► PR-3 (#224 wire)     ──┐                    ├──► PR-6 (#225 core) ──► PR-7 (#227 tools) ─────┐
                          ├──► PR-4 (#221 audit)   ──┤                                                              ├──► PR-9 (#226 docs)
                          │                          ├──► PR-8 (#228 iot) ────────────────────────────────┘
                          └──► PR-5 (#222 bridge)  ──┘

PR-1 (#220) → 2/3/4/5 can land in parallel after #220.
PR-6 (#225) needs all of #223 / #224 / #221 / #222 merged.
PR-7 (#227) needs #223 + #225.
PR-8 (#228) needs #223 + #221 (parallel with #225 / #227).
PR-9 (#226) lands last.

Note: GitHub assigned PR numbers in API call order, not slot order — hence the apparent jumble (#226=docs, #227=tools, #228=iot). The slot-to-PR-number mapping above is the source of truth.

Closing condition

This issue closes when PR-9 (#226) lands and #195 is closed with a redirect comment.

Review-thread bookkeeping

The 213 review threads on #195 stay open until the corresponding child PR closes them; child PRs cite the original #195 thread URL when resolving. The R-round changelog table on #195 is the forensic source of truth.

CI expectations

  • PR-1 / PR-2 / PR-3 / PR-4 / PR-5 — CI green standalone after each one merges (or against main).
  • PR-6 / PR-7 / PR-8 / PR-9 — CI red in isolation. They will go green as their dependencies land. This is intentional: the diffs are reviewable now, but the integration only compiles once the leaves are in.

Tracking child of #195. Generated by DevDuck 2026-05-25.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions