get2knowio / get2knowio/remo

Implement Approach B: socket-watching controller (Docker-event source enrollment)

Open
#46 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2
Forks
0
Avg merge
15h 59m
Merged PRs (30d)
9

Description

## Summary

Implement the **socket-watching controller** enrollment model (Approach B, decided in #42). A privileged controller watches the Docker event stream and drives source enrollment, network attach, and liveness — replacing the in-container connector + presence protocol. The proven spec-009 core (registry / per-source pollers / delivery / grants) is **reused unchanged**: the controller calls the existing `POST /v1/sources` on behalf of each discovered container.

Parent decision: #42. Key conveyance: **host-managed per-project key mount** (decided).

## Architecture

```
docker socket
│ (method+path allowlist)
┌───────▼────────┐
│ socket-proxy │ GET /events,/containers,/networks
└───────┬────────┘ POST /networks/*/connect|disconnect (nothing else)
events/inspect/ │
network connect │
┌───────▼────────┐ internal API ┌──────────────────────┐
│ controller │ ──register/drain──▶ │ notifier core (spec │
│ (privileged) │ POST /v1/sources │ 009): registry, │
└───────┬────────┘ │ pollers, delivery, │
reads key ───▶│ │ grants, channel+bot │
/run/remo/keys/│ │ (UNPRIVILEGED) │
└──────────────────────┘
```

The split is the point: only the controller touches Docker (via the proxy); the
internet-facing notifier + Telegram bot stay unprivileged.

## Key conveyance — host-managed per-project mount (decided)

- Host (Ansible/launch) generates a per-project approver key at `/run/remo/keys/` (0400).
- Mounted read-only into **that project's agentsh container** (agentsh uses it) **and** into the **controller** (reads it on discovery).
- Per-project isolation; key never in container labels/inspect; host is the trust root.
- The mount is a volume, not socket power — survives the proxy guardrail.

## Tasks

- [ ] **Spike (do first): socket-proxy allowlist.** Validate a proxy can express *GET containers/networks + events + POST network connect/disconnect, deny all else*. Coarse proxies (tecnativa) gate by section + a global POST toggle and likely **cannot** express this → expect a small bespoke method+path-allowlist proxy (Caddy/nginx/Go). Output: the chosen proxy + config.
- [ ] **Controller**: Docker `events` watch (reconnect/replay-safe); on container `start` → resolve `sourceId` (label/hostname convention), read key from `/run/remo/keys/`, derive `api_url` from the project network name, `network connect` notifier→project net (reuse PR #45 `netwire` logic), register via `/v1/sources`. On `die`/`stop` → deregister + drain + `network disconnect` (disconnect-when-last).
- [ ] **Discovery convention**: container label(s) that mark "this runs agentsh" + port (e.g. `remo.agentsh.enabled`, `remo.agentsh.port`). Containers without it are ignored.
- [ ] **Host key provisioning**: Ansible generates per-project keys, places at `/run/remo/keys/`, wires the agentsh + controller mounts.
- [ ] **Split deployment**: controller + socket-proxy as their own units/containers; notifier keeps no Docker access. Update the `remo_notifier` role.
- [ ] **Compose-aware**: a project = N containers on one project network; controller targets the workspace/agentsh container and joins the notifier to its net. Other services on the net don't trigger separate sources.
- [ ] **Tests**: controller driven by a fake event stream + fake `/v1/sources` + fake proxied docker (mirror the `netwire`/feature test style — no live daemon needed).

## Supersedes / reuses
- **Supersedes** the in-container connector + devcontainer Feature `remo-notifier-source` (Approach A). Once B lands, the Feature can be deprecated.
- **Reuses**: spec-009 registry/pollers/delivery/grants unchanged; PR #45 `netwire` logic (moves into controller) and wildcard grants (orthogonal, kept).
- PR #45's connector-derivation is now mostly moot under B, but harmless to leave; the Feature stays until B is proven.

## Still required regardless
- agentsh in the container — **#43** (agentsh-as-a-Feature).
- network-aware rendering — **#44** (after payload capture).

## Open questions
- Bespoke proxy choice + exact allowlist (spike output).
- Event replay/missed-event handling on controller restart (re-scan `containers` on startup to rebuild state).
- Exact discovery label schema.

## Links
- Parent: #42 · Related: #41, #43, #44 · Builds on: PR #45

Contributor guide

Open the contributing guide

Research direction

Start with the socket-proxy allowlist spike and document the chosen proxy and configuration. Then read PR #45's netwire logic, the remo_notifier role, and the spec-009 interfaces before defining the controller boundaries. Done means event-driven enrollment and draining, host key mounts, split deployment, Compose-aware discovery, and fake-stream/proxy tests without a live Docker daemon.

Written by the indexing model from the issue text.

Assessment

Tech stack
ansible, docker, python
Domain
backend, devops, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.