# NemoClaw policy preset that allows the AgenticROS plugin (running inside
# the OpenShell sandbox) to reach a rosbridge_server on the host machine.
#
# Apply with::
#
#   nemoclaw <sandbox> policy-add --from-file scripts/agenticros-rosbridge.policy.yaml --yes
#
# The plugin connects via ws://host.docker.internal:9090 (which resolves to
# the Docker bridge gateway IP — usually 172.19.0.1). host.openshell.internal
# is the alias NemoClaw injects with the same IP.
#
# Why ``access: full`` / ``tls: skip`` (raw L4 CONNECT tunnel) instead of
# ``protocol: websocket`` with allow rules:
#
#   * The OpenShell proxy MITM that backs ``protocol: websocket`` negotiates
#     HTTP/2 ALPN by default when it terminates TLS. rosbridge_server is
#     plain HTTP/1.1 ws://, not wss://, but the proxy still tries to do
#     HTTP-level routing which breaks the WebSocket upgrade for some clients
#     (Node ``ws`` library connect attempts disappear without an OPA log
#     entry).
#   * Declaring the endpoint as a raw L4 CONNECT tunnel (``access: full``)
#     tells the proxy to pass the encrypted/cleartext bytes through
#     unmodified, so the WebSocket upgrade survives intact. The whatsapp
#     built-in preset uses the same trick for the same underlying reason.
#   * ``tls: skip`` is needed because the upstream is plain HTTP — there's
#     no TLS for the proxy to terminate.

preset:
  name: agenticros-rosbridge
  description: "AgenticROS plugin -> host rosbridge_server WebSocket on :9090"

network_policies:
  agenticros_rosbridge:
    name: agenticros_rosbridge
    endpoints:
      - host: host.docker.internal
        port: 9090
        access: full
        tls: skip
        # Without an explicit allowed_ips block the OPA proxy's SSRF guard
        # rejects this connection with "resolves to internal address
        # 172.19.0.1, connection rejected" — because host.docker.internal
        # is a docker-bridge gateway IP in the RFC1918 range and the guard
        # default-denies private IPs. Listing the three private CIDRs is
        # the documented way to tell the guard "yes, I really do want to
        # talk to a host on a private network here".
        allowed_ips:
          - 10.0.0.0/8
          - 172.16.0.0/12
          - 192.168.0.0/16
      - host: host.openshell.internal
        port: 9090
        access: full
        tls: skip
        allowed_ips:
          - 10.0.0.0/8
          - 172.16.0.0/12
          - 192.168.0.0/16
    binaries:
      - { path: /usr/local/bin/openclaw }
      - { path: /usr/local/bin/node }
      - { path: /usr/bin/node }
