-
Notifications
You must be signed in to change notification settings - Fork 0
Description
RFC: Network Topology Extension for SCP
Status: Draft
Author: SCP Core Team
Created: 2026-01-14
Last Updated: 2026-01-14
Abstract
This RFC proposes extending SCP dependencies with minimal, vendor-neutral network metadata (protocol and port). This enables integrations to generate platform-specific firewall policies, validate drift, and automate network security configuration.
Motivation
Problem: Port Drift
depends:
- system: "urn:scp:fraud-service"
capability: "fraud-check"
# No way to know:
# - What port is used?
# - Is the firewall rule correct?
# - Did someone open port 8080 when it should be 8443?Impact: Security vulnerabilities, failed deployments, manual port management
Current Gap
SCP models logical dependencies but lacks network-level detail needed to:
- Validate firewall rules match declared dependencies
- Auto-generate NetworkPolicies/Security Groups
- Detect drift between declared architecture and deployed infrastructure
Goals
- Enable network validation - Validate firewall rules match declared dependencies
- Maintain simplicity - Store only port/protocol, not cloud-specific configs
- Vendor-neutral - Works with AWS, GCP, Azure, Kubernetes, etc.
Non-Goals
- Replace IaC - Not building Terraform/CloudFormation competitor
- Store cloud identifiers - No ARNs, Security Group IDs, etc. in SCP
Proposed Solution
Core Principle: "Just Enough Information"
SCP stores generic connectivity requirements. Platform-specific integrations translate this to infrastructure policies.
flowchart LR
scp["scp.yaml<br/>(Generic Data)<br/>URN A → URN B<br/>tcp:8443"]
json[Unified JSON Graph]
subgraph integrations["Vendor-Specific Integrations"]
aws["AWS Integration"]
k8s["K8s Integration"]
gcp["GCP Integration"]
end
scp -->|export| json
json -->|reads| aws
json -->|reads| k8s
json -->|reads| gcp
aws -->|creates| awssg[AWS Security Group]
k8s -->|creates| k8spol[K8s NetworkPolicy]
gcp -->|creates| gcpfw[GCP Firewall Rule]
Design Details
Schema Addition
# Extend dependency with network config
network:
direction: "outbound" | "inbound" # Which way the connection flows
protocol: "tcp" | "udp"
port: 8443
port_range: [8000, 8100] # OptionalDirection semantics:
outbound(default): This service initiates connection TO the dependencyinbound: The dependency initiates connection TO this service
[!IMPORTANT] > Use
inboundsparingly. It should only be used for:
- External dependencies with callbacks - e.g., Stripe webhooks, PSP notifications
- Generic listening ports - e.g., an FTP service accepting connections from unmodelled clients
Do NOT use
inboundfor internal services. If Service A calls Service B, then Service A's SCP declaresoutboundto B. The integration will automatically infer that B needs an ingress rule from A when parsing the unified graph. Declaringinboundon B would duplicate information and create maintenance burden.
Pydantic Model
class NetworkConfig(BaseModel):
"""Generic network connectivity configuration."""
direction: Literal["outbound", "inbound"] = "outbound"
protocol: Literal["tcp", "udp"] | None = None
port: int | None = None
port_range: tuple[int, int] | None = None
class Dependency(BaseModel):
# ... existing fields ...
network: NetworkConfig | None = None # NEWExample
depends:
# Outbound: We call the fraud service
- system: "urn:scp:acmepay-fraud"
capability: "fraud-check"
type: "rest"
criticality: "degraded"
network:
direction: "outbound" # We initiate connection (default)
protocol: "tcp"
port: 8443
# Outbound: We connect to database
- system: "urn:scp:acmepay-db"
type: "data"
criticality: "required"
network:
protocol: "tcp"
port: 5432
# Inbound: PSP sends webhooks TO us
- system: "urn:scp:external:stripe"
capability: "payment-webhooks"
type: "rest"
criticality: "degraded"
network:
direction: "inbound" # External service connects to us
protocol: "tcp"
port: 443How Integrations Use This
| Integration | Outbound Action | Inbound Action |
|---|---|---|
| AWS | Creates egress Security Group rule | Creates ingress Security Group rule |
| K8s | Creates NetworkPolicy egress rule | Creates NetworkPolicy ingress rule |
| GCP | Creates egress Firewall rule | Creates ingress Firewall rule |
JSON Graph Output
{
"edges": [
{
"from": "urn:scp:acmepay-payment",
"to": "urn:scp:acmepay-fraud",
"type": "DEPENDS_ON",
"capability": "fraud-check",
"criticality": "degraded",
"network": {
"direction": "outbound",
"protocol": "tcp",
"port": 8443
}
},
{
"from": "urn:scp:acmepay-payment",
"to": "urn:scp:external:stripe",
"type": "DEPENDS_ON",
"capability": "payment-webhooks",
"criticality": "degraded",
"network": {
"direction": "inbound",
"protocol": "tcp",
"port": 443
}
}
]
}Use Cases
Use Case 1: Generate Firewall Rules
# Generate K8s NetworkPolicies from SCP
scp-integrations generate --platform k8s --output ./k8s/
# Generate AWS Security Groups
scp-integrations generate --platform aws --output ./terraform/Use Case 2: Validate Drift
scp-integrations validate --platform aws
# Output:
# ✅ payment → fraud: tcp:8443 matches Security Group
# ❌ DRIFT: payment → ledger: SCP declares tcp:5432, SG allows tcp:5433Use Case 3: Security Audit
# Find all tier-1 systems and their open ports
scp-integrations query "SELECT * FROM edges WHERE tier=1 AND network.port IS NOT NULL"Alternatives Considered
Store cloud-specific identifiers
network:
aws_security_group: "sg-123"
k8s_networkpolicy: "./policies/fraud.yaml"Rejected: Violates vendor-neutral principle, creates maintenance burden.
Store full firewall rules
network:
egress:
- cidr: "10.0.0.0/8"
port: 8443Rejected: Too complex, duplicates IaC tools.
Open Questions
Q1: Multi-port services?
Recommendation: Create multiple dependency entries for clarity.
Q2: Port ranges vs explicit ports?
Recommendation: Support both - port: 8443 for single, port_range: [8000, 8100] for ranges.