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>
8.1 KiB
Feature Specification: Admin CLI & Docker Fixes
Feature Branch: 006-admin-cli-docker-fixes
Created: 2026-03-15
Status: Draft
Input: User description: "Fix admin socket accessibility in Docker, add channels create/join CLI commands, fix default socket path"
User Scenarios & Testing (mandatory)
User Story 1 - Admin CLI Works in Kubernetes Pods (Priority: P1)
An operator needs to run admin CLI commands inside a Kubernetes pod (e.g., kubectl exec -n synapbus deploy/synapbus -- /synapbus channels list). With the current scratch base image, there is no shell and the admin socket is unreachable via exec'd processes. Switching to alpine allows kubectl exec with a shell and gives the admin CLI a working environment.
Why this priority: This is a blocker — without this fix, all admin CLI operations fail after pod restart in production.
Independent Test: Build Docker image with alpine base, deploy to a test pod, run kubectl exec ... -- /synapbus channels list and verify it returns results.
Acceptance Scenarios:
- Given a SynapBus pod running with the alpine-based image, When an operator runs
kubectl exec deploy/synapbus -- /synapbus channels list, Then the command executes and returns channel data over the admin socket. - Given a SynapBus pod running with the alpine-based image, When an operator runs
kubectl exec deploy/synapbus -- sh, Then they get an interactive shell.
User Story 2 - Create Channels via CLI (Priority: P1)
An operator needs to create channels without using the Web UI or REST API with session cookies. The synapbus channels create command should create a channel via the admin socket.
Why this priority: Required for automated provisioning scripts and headless setups.
Independent Test: Start SynapBus server, run synapbus channels create --name test-channel --description "A test channel", then verify with synapbus channels list.
Acceptance Scenarios:
- Given a running SynapBus server, When an operator runs
synapbus channels create --name news-feed --description "News feed channel", Then the channel is created and a success response with channel details is printed. - Given a running SynapBus server, When an operator runs
synapbus channels create --name news-feedwithout--description, Then the channel is created with an empty description. - Given a channel named "news-feed" already exists, When an operator runs
synapbus channels create --name news-feed, Then an appropriate error message is displayed.
User Story 3 - Join Agents to Channels via CLI (Priority: P1)
An operator needs to add agents to channels via the admin CLI so agents can post messages. The synapbus channels join command should add an agent to a channel's membership.
Why this priority: Agents cannot post to channels they haven't joined; this is required for initial agent setup and automation.
Independent Test: Create a channel and an agent, run synapbus channels join --channel test-channel --agent my-agent, then verify with synapbus channels show --name test-channel.
Acceptance Scenarios:
- Given a channel "test-channel" and agent "my-agent" exist, When an operator runs
synapbus channels join --channel test-channel --agent my-agent, Then the agent is added as a member and a success response is printed. - Given an agent is already a member of "test-channel", When an operator runs
synapbus channels join --channel test-channel --agent my-agent, Then the operation succeeds idempotently (no error). - Given channel "nonexistent" does not exist, When an operator runs
synapbus channels join --channel nonexistent --agent my-agent, Then an error message indicates the channel was not found.
User Story 4 - Absolute Default Socket Path (Priority: P2)
The default socket path for admin CLI commands is currently ./data/synapbus.sock (relative). In containers where CWD varies, this is confusing. The default should be /data/synapbus.sock (absolute) to match the container layout.
Why this priority: Quality-of-life improvement; the current relative path works but is confusing.
Independent Test: Run synapbus --help and verify the default socket path shows /data/synapbus.sock.
Acceptance Scenarios:
- Given the
--socketflag is not provided, When the CLI resolves the admin socket path, Then it defaults to/data/synapbus.sock. - Given the
SYNAPBUS_SOCKETenvironment variable is set, When the CLI resolves the admin socket path, Then it uses the environment variable value. - Given the
--socketflag is provided with a custom path, When the CLI resolves the admin socket path, Then it uses the custom path.
Edge Cases
- What happens when channel name contains invalid characters? The existing
ValidateChannelNamerules apply, and the CLI reports the validation error. - What happens when the admin socket is not reachable? The CLI prints a connection error with "is synapbus serve running?" hint.
- What happens when an agent name doesn't exist during channel join? The operation fails with a clear error message from the channel service.
- What happens when the
--nameflag is missing onchannels create? Cobra enforces the required flag and prints usage.
Requirements (mandatory)
Functional Requirements
- FR-001: The Docker image MUST use
alpine:3.19as the runtime base image instead ofscratch. - FR-002: The system MUST provide a
synapbus channels createCLI command with--name(required) and--description(optional) flags. - FR-003: The
channels createcommand MUST send achannels.createrequest over the admin socket and display the result. - FR-004: The admin socket server MUST handle
channels.createcommands by creating a channel via the channel service. - FR-005: The system MUST provide a
synapbus channels joinCLI command with--channel(required) and--agent(required) flags. - FR-006: The
channels joincommand MUST send achannels.joinrequest over the admin socket and display the result. - FR-007: The admin socket server MUST handle
channels.joincommands by looking up the channel by name and adding the agent as a member. - FR-008: The default value of the
--socketpersistent flag MUST be/data/synapbus.sock(absolute path). - FR-009: The
SYNAPBUS_SOCKETenvironment variable MUST override the default socket path when the flag is not explicitly set. - FR-010: The Docker image MUST remain minimal — only the binary, TLS certs, and timezone data should be included from the build stage.
Key Entities
- Channel: Named communication space with type, description, privacy flag, and member list.
- Agent: Named entity (AI or human) that can be a member of channels.
- Admin Socket: Unix domain socket at a known path, used by CLI commands to communicate with the running server.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: Operators can execute all admin CLI commands inside a Kubernetes pod via
kubectl execwithout errors. - SC-002:
synapbus channels create --name <name>successfully creates a channel and returns channel details within 1 second. - SC-003:
synapbus channels join --channel <name> --agent <name>successfully adds an agent to a channel within 1 second. - SC-004: The default socket path displayed in help text is
/data/synapbus.sock. - SC-005: The Docker image size remains under 50MB (alpine adds minimal overhead vs scratch).
Assumptions
- Alpine 3.19 is acceptable as the runtime base image (adds ~7MB over scratch).
- The
channels.createadmin command uses"system"as thecreated_byfield since admin socket operations are implicitly trusted. - The
channels.joinadmin command adds the agent with the"member"role (not owner). - Channel type defaults to
"standard"if not specified. - No
--privateor--typeflags are needed for the initialchannels createcommand — they can be added later. - The Helm chart deployment.yaml does not need changes since it already passes
--data /data.