Outcall
SpecificationsS002 · Network Management

S002 · Network Management

Specification module 002-network-management

S002: Network Management

FieldValue
SpecS002
FeatureNetwork Management
Date2026-04-22
StatusDraft
Author@marktopper

Overview

Manage the isolated networks that agent containers run on. Every agent container connects to an outcall-managed network where all outbound traffic is governed by the bridge and nftables policy layer. The host operator creates, inspects, and destroys these networks through the outcall CLI and the outcalld host API.

A default network (outcall-default) is created on first use and can be destroyed and recreated at any time. Additional named networks can be created for workload isolation — each network shares the same bridge and nftables policy, but provides a separate address space and container group.

Subnet allocation

Outcall reserves the 10.200.0.0/16 block. This range was chosen because it avoids collisions with Docker (172.17+), Kubernetes (10.96, 10.244), AWS VPCs (10.0-10.10), k3s (10.42-10.43), OpenVPN (10.8), home routers (10.0, 192.168), and Podman (10.88). Each network gets a /24 subnet auto-allocated from this block:

outcall-default    → 10.200.0.0/24   (first available)
outcall-staging    → 10.200.1.0/24   (next available)
outcall-prod       → 10.200.2.0/24   (next available)
...up to 255 networks

Before allocating, outcalld checks both its own records and Docker's live network list to avoid collisions. A specific subnet can be requested with --subnet to override auto-allocation.

User Scenarios

S002-US-001 [P1] As a host operator, I want to create isolated networks for agent containers so that each workload group has its own address space.

S002-US-002 [P1] As a host operator, I want to inspect which containers are connected to each network so that I can manage workload placement.

S002-US-003 [P1] As a host operator, I want to destroy networks I no longer need so that resources are cleaned up.

Requirements Summary

IDTypePriorityTitleStatus
S002-FR-001FunctionalP1Docker Engine API onlyDraft
S002-FR-002FunctionalP1Network creation parametersDraft
S002-FR-003FunctionalP1Idempotent createDraft
S002-FR-004FunctionalP1Bridge-up prerequisiteDraft
S002-FR-005FunctionalP2Post-create bridge verificationDraft
S002-FR-006FunctionalP1Default network definitionDraft
S002-FR-007FunctionalP1Default network on bare createDraft
S002-FR-008FunctionalP1Default network destroyableDraft
S002-FR-009FunctionalP1Named network prefixDraft
S002-FR-010FunctionalP1Shared bridge interfaceDraft
S002-FR-011FunctionalP2Name validationDraft
S002-FR-012FunctionalP1Subnet auto-allocationDraft
S002-FR-013FunctionalP1Collision detectionDraft
S002-FR-014FunctionalP2Subnet exhaustion errorDraft
S002-FR-015FunctionalP1Explicit subnet collision checkDraft
S002-FR-016FunctionalP1Status response contentDraft
S002-FR-017FunctionalP1No state cachingDraft
S002-FR-018FunctionalP1List endpoint discoveryDraft
S002-FR-019FunctionalP1Destroy refuses when connectedDraft
S002-FR-020FunctionalP2Idempotent destroyDraft
S002-FR-021FunctionalP1No force-disconnectDraft
S002-FR-022FunctionalP1In-process Docker managementDraft
S002-FR-023FunctionalP2Docker client startup resilienceDraft
S002-FR-024FunctionalP1Host socket onlyDraft
S002-FR-025FunctionalP1CLI subcommandsDraft
S002-FR-026FunctionalP1CLI transport mechanismDraft
S002-FR-027FunctionalP1CLI error handlingDraft
S002-FR-028FunctionalP1Constants in outcall-apiDraft
S002-FR-029FunctionalP2Configurable subnet blockDraft
S002-FR-030FunctionalP2RFC 1918 validationDraft
S002-FR-031FunctionalP2Config query endpointDraft
S002-FR-032FunctionalP1Network rediscovery on startupDraft
S002-AS-001AcceptanceP1Create default networkDraft
S002-AS-002AcceptanceP1Create named network (auto-subnet)Draft
S002-AS-003AcceptanceP1Create already existsDraft
S002-AS-004AcceptanceP1Create bridge not upDraft
S002-AS-005AcceptanceP1Status with containersDraft
S002-AS-006AcceptanceP1Status named networkDraft
S002-AS-007AcceptanceP1Status does not existDraft
S002-AS-008AcceptanceP1List multiple networksDraft
S002-AS-009AcceptanceP1Destroy named networkDraft
S002-AS-010AcceptanceP1Destroy default networkDraft
S002-AS-011AcceptanceP1Destroy containers connectedDraft
S002-AS-012AcceptanceP2Destroy does not existDraft
S002-AS-013AcceptanceP1Daemon not runningDraft
S002-AS-014AcceptanceP1Docker not availableDraft
S002-IF-001InterfaceP1POST /api/v1/network/createDraft
S002-IF-002InterfaceP1GET /api/v1/networkDraft
S002-IF-003InterfaceP1GET /api/v1/networksDraft
S002-IF-004InterfaceP1POST /api/v1/network/destroyDraft
S002-IF-005InterfaceP1CLI commandsDraft
S002-IF-006InterfaceP1CLI output formatDraft
S002-EC-001Edge CaseP1Network already existsDraft
S002-EC-002Edge CaseP1Bridge not upDraft
S002-EC-003Edge CaseP1Docker unreachableDraft
S002-EC-004Edge CaseP1Status for missing networkDraft
S002-EC-005Edge CaseP2Destroy missing networkDraft
S002-EC-006Edge CaseP1Containers connected on destroyDraft
S002-EC-007Edge CaseP1Destroy default networkDraft
S002-EC-008Edge CaseP2Bridge mismatchDraft
S002-EC-009Edge CaseP2Rapid create callsDraft
S002-EC-010Edge CaseP2Daemon shutdown with networksDraft
S002-EC-011Edge CaseP2Docker disappears at runtimeDraft
S002-EC-012Edge CaseP1Subnet collisionDraft
S002-EC-013Edge CaseP2Subnets exhaustedDraft
S002-EC-014Edge CaseP2Invalid network nameDraft
S002-SC-001SuccessP1Default network creation verifiedDraft
S002-SC-002SuccessP1Named network auto-allocationDraft
S002-SC-003SuccessP1Status accuracyDraft
S002-SC-004SuccessP1List completenessDraft
S002-SC-005SuccessP1Named network destroyDraft
S002-SC-006SuccessP1Default network destroy+recreateDraft
S002-SC-007SuccessP1Connected container rejectionDraft
S002-SC-008SuccessP1IdempotencyDraft
S002-SC-009SuccessP1Collision-aware allocationDraft
S002-SC-010SuccessP1No docker CLI shellingDraft
S002-SC-011SuccessP1Bridge commands unaffectedDraft

Out of Scope

  • Container lifecycle management (start, stop, attach, exec)
  • Connecting/disconnecting individual containers to/from a network
  • Agent-side API exposure — network management endpoints are host-only
  • TLS or authentication on the host socket
  • Network policy rules (per-container allow/deny) — handled by bridge + nftables
  • DNS configuration within networks
  • IPv6 support
  • Automated bridge-up before network create

Cross-Spec Dependencies

  • Depends on: S001 (bridge must be up before network creation — S002-FR-004)
  • Required by: S006, S007, S008

Shared Types (outcall-api)

Constants

pub const NETWORK_PREFIX: &str = "outcall-";
pub const DEFAULT_NETWORK_NAME: &str = "outcall-default";
pub const SUBNET_BLOCK: &str = "10.200.0.0/16";
pub const DEFAULT_SUBNET: &str = "10.200.0.0/24";
pub const DEFAULT_GATEWAY: &str = "10.200.0.1";

Types

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkCreateRequest {
    pub name: Option<String>,
    pub subnet: Option<String>,
    pub gateway: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkCreateResult {
    pub network_id: String,
    pub name: String,
    pub created: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkStatus {
    pub exists: bool,
    pub network_id: Option<String>,
    pub name: String,
    pub subnet: Option<String>,
    pub gateway: Option<String>,
    pub containers: Vec<NetworkContainer>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkContainer {
    pub name: String,
    pub ipv4_address: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkDestroyRequest {
    pub name: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkDestroyResult {
    pub name: String,
    pub destroyed: bool,
}

On this page