Files
synapbus/specs/006-admin-cli-docker-fixes/research.md
T
Algis DumbrisandClaude Opus 4.6 9dd27c4b9b feat: admin CLI & Docker fixes — alpine base, channels create/join, absolute socket path
Switch Docker runtime from scratch to alpine:3.19 so kubectl exec works
for admin CLI operations. Add `synapbus channels create` and
`synapbus channels join` CLI commands with corresponding admin socket
handlers. Change default socket path to /data/synapbus.sock (absolute).
Also add Helm envFrom support and NodePort configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 14:54:13 +02:00

50 lines
3.4 KiB
Markdown

# Research: Admin CLI & Docker Fixes
**Feature**: 006-admin-cli-docker-fixes
**Date**: 2026-03-15
## R1: Alpine vs Scratch Docker Base Image
**Decision**: Use `alpine:3.19` as the runtime base image.
**Rationale**: The `scratch` image has no shell, no `/bin/sh`, no filesystem utilities. This means `kubectl exec` cannot spawn any process other than the entrypoint binary itself. Since admin CLI commands need to connect to the Unix socket created by the running server process, exec'd processes need a working environment. Alpine adds ~7MB but provides `/bin/sh`, basic filesystem operations, and a working process environment.
**Alternatives considered**:
- `distroless/static` (Google): No shell, same problem as scratch.
- `busybox`: Works but no package manager. Alpine is the standard minimal base.
- `debian-slim`: ~80MB, unnecessarily large.
## R2: Admin Socket Protocol for Channel Operations
**Decision**: Add `channels.create` and `channels.join` commands to the existing admin socket dispatch table, following the exact pattern of existing commands (e.g., `agent.create`, `webhook.register`).
**Rationale**: The admin socket already has a well-established request/response pattern: JSON-RPC style `{command, args}` → `{ok, data, error}`. The channel service already exposes `CreateChannel` and `JoinChannel` methods. The admin server already holds a reference to the channel service via `Services.Channels`. No new wiring needed.
**Alternatives considered**:
- HTTP admin API endpoint: Would require API key protection (user explicitly rejected this approach).
- Direct database manipulation via CLI: Bypasses service layer validation, unsafe.
## R3: Default Socket Path
**Decision**: Change default from `./data/synapbus.sock` to `/data/synapbus.sock` (absolute).
**Rationale**: In containers, the working directory is `/` and the data volume is mounted at `/data`. The relative path `./data/synapbus.sock` resolves to `/data/synapbus.sock` from `/`, but this is confusing and fragile. An absolute default matches the Dockerfile's `--data /data` argument and the Helm chart's `volumeMount` at `/data`.
The `SYNAPBUS_SOCKET` environment variable and `--socket` flag still allow overriding for development (e.g., `--socket ./data/synapbus.sock` for local dev).
**Alternatives considered**:
- Keep relative path: Works in containers but confusing for users.
- Use `$SYNAPBUS_DATA_DIR/synapbus.sock` as default: Over-engineered; the socket path flag already exists.
## R4: `channels.create` Admin Handler Design
**Decision**: The `channels.create` handler accepts `{name, description}` args, calls `channelService.CreateChannel` with `created_by: "system"`, and returns the created channel as JSON.
**Rationale**: Admin socket commands are implicitly trusted (localhost-only, process-level access). Using `"system"` as the creator matches the pattern used for the default `#general` channel. The `description` field is optional (defaults to empty string).
## R5: `channels.join` Admin Handler Design
**Decision**: The `channels.join` handler accepts `{channel, agent}` args, looks up the channel by name via `GetChannelByName`, then calls `JoinChannel(channelID, agentName)`. Returns success message.
**Rationale**: The CLI uses channel names (not IDs) because operators work with names. The service's `JoinChannel` already handles idempotency (re-joining is a no-op) and private channel invite checks.