id: T019
name: Overlay Network Implementation (NovaNET)
status: complete
goal: Implement multi-tenant overlay networking with OVN integration for PlasmaVMC
priority: P0
owner: peerA (strategy) + peerB (implementation)
created: 2025-12-08
depends_on: [T015]
context: |
PROJECT.md item 11 specifies overlay networking for multi-tenant isolation.
T015 completed specification work:
- research-summary.md: OVN recommended over Cilium/Calico
- tenant-network-model.md: VPC/subnet/port/security-group model
- plasmavmc-integration.md: VM-port attachment flow
NovaNET will be a new component providing:
- Tenant network isolation (VPC model)
- OVN integration layer (ovsdb, ovn-controller)
- Security groups (firewall rules)
- PlasmaVMC integration hooks
acceptance:
- novanet workspace created (novanet-api, novanet-server, novanet-types)
- gRPC services for VPC, Subnet, Port, SecurityGroup CRUD
- OVN integration layer (ovsdb client)
- PlasmaVMC hook for VM-port attachment
- Integration test showing VM network isolation
steps:
- step: S1
action: NovaNET workspace scaffold
priority: P0
status: complete
owner: peerB
notes: |
Create novanet workspace structure:
- novanet/Cargo.toml (workspace)
- novanet/crates/novanet-api (proto + generated code)
- novanet/crates/novanet-server (gRPC server)
- novanet/crates/novanet-types (domain types)
Pattern: follow fiberlb/flashdns structure
deliverables:
- Workspace compiles
- Proto for VPC, Subnet, Port, SecurityGroup services
outputs:
- path: novanet/crates/novanet-server/src/services/vpc.rs
note: VPC gRPC service implementation
- path: novanet/crates/novanet-server/src/services/subnet.rs
note: Subnet gRPC service implementation
- path: novanet/crates/novanet-server/src/services/port.rs
note: Port gRPC service implementation
- path: novanet/crates/novanet-server/src/services/security_group.rs
note: SecurityGroup gRPC service implementation
- path: novanet/crates/novanet-server/src/main.rs
note: Server binary entry point
- step: S2
action: NovaNET types and metadata store
priority: P0
status: complete
owner: peerB
notes: |
Define domain types from T015 spec:
- VPC (id, org_id, project_id, cidr, name)
- Subnet (id, vpc_id, cidr, gateway, dhcp_enabled)
- Port (id, subnet_id, mac, ip, device_id, device_type)
- SecurityGroup (id, org_id, project_id, name, rules[])
- SecurityGroupRule (direction, protocol, port_range, remote_cidr)
Create NetworkMetadataStore with ChainFire backend.
Key schema:
/novanet/vpcs/{org_id}/{project_id}/{vpc_id}
/novanet/subnets/{vpc_id}/{subnet_id}
/novanet/ports/{subnet_id}/{port_id}
/novanet/security_groups/{org_id}/{project_id}/{sg_id}
Progress (2025-12-08 20:51):
- ✓ Proto: All requests (Get/Update/Delete/List) include org_id/project_id for VPC/Subnet/Port/SecurityGroup
- ✓ Metadata: Tenant-validated signatures implemented with cross-tenant delete denial test
- ✓ Service layer aligned to new signatures (vpc/subnet/port/security_group) and compiling
- ✓ SecurityGroup architectural consistency: org_id added to type/proto/keys (uniform tenant model)
- ✓ chainfire-proto decoupling completed; novanet-api uses vendored protoc
deliverables:
- Types defined
- Metadata store with CRUD
- Unit tests
outputs:
- path: novanet/crates/novanet-server/src/metadata.rs
note: Async metadata store with ChainFire backend
- step: S3
action: gRPC control plane services
priority: P0
status: complete
owner: peerB
notes: |
Implement gRPC services:
- VpcService: Create, Get, List, Delete
- SubnetService: Create, Get, List, Delete
- PortService: Create, Get, List, Delete, AttachDevice, DetachDevice
- SecurityGroupService: Create, Get, List, Delete, AddRule, RemoveRule
deliverables:
- All services functional
- cargo check passes
- step: S4
action: OVN integration layer
priority: P1
status: complete
owner: peerB
notes: |
Create OVN client for network provisioning:
- OvnClient struct connecting to ovsdb (northbound)
- create_logical_switch(vpc) -> OVN logical switch
- create_logical_switch_port(port) -> OVN LSP
- create_acl(security_group_rule) -> OVN ACL
Note: Initial implementation can use mock/stub for CI.
Real OVN requires ovn-northd, ovsdb-server running.
deliverables:
- OvnClient with basic operations
- Mock mode for testing
outputs:
- path: novanet/crates/novanet-server/src/ovn/client.rs
note: OvnClient mock/real scaffold with LS/LSP/ACL ops, env-configured
- path: novanet/crates/novanet-server/src/services
note: VPC/Port/SG services invoke OVN provisioning hooks post-metadata writes
- step: S5
action: PlasmaVMC integration hooks
priority: P1
status: complete
owner: peerB
notes: |
Add network attachment to PlasmaVMC:
- Extend VM spec with network_ports: [PortId]
- On VM create: request ports from NovaNET
- Pass port info to hypervisor (tap device name, MAC)
- On VM delete: release ports
deliverables:
- PlasmaVMC network hooks
- Integration test
outputs:
- path: plasmavmc/crates/plasmavmc-types/src/vm.rs
note: NetworkSpec extended with subnet_id and port_id fields
- path: plasmavmc/crates/plasmavmc-server/src/novanet_client.rs
note: NovaNET client wrapper for port management (82L)
- path: plasmavmc/crates/plasmavmc-server/src/vm_service.rs
note: VM lifecycle hooks for NovaNET port attach/detach
- step: S6
action: Integration test
priority: P1
status: complete
owner: peerB
notes: |
End-to-end test:
1. Create VPC, Subnet via gRPC
2. Create Port
3. Create VM with port attachment (mock hypervisor)
4. Verify port status updated
5. Test security group rules (mock ACL check)
deliverables:
- Integration tests passing
- Evidence log
outputs:
- path: plasmavmc/crates/plasmavmc-server/tests/novanet_integration.rs
note: E2E integration test (246L) - VPC/Subnet/Port creation, VM attach/detach lifecycle
blockers:
- description: "CRITICAL SECURITY: Proto+metadata allow Get/Update/Delete by ID without tenant validation (R6 escalation)"
owner: peerB
status: resolved
severity: critical
discovered: "2025-12-08 18:38 (peerA strategic review of 000170)"
details: |
Proto layer (novanet.proto:50-84):
- GetVpcRequest/UpdateVpcRequest/DeleteVpcRequest only have 'id' field
- Missing org_id/project_id tenant context
Metadata layer (metadata.rs:220-282):
- get_vpc_by_id/update_vpc/delete_vpc use ID index without tenant check
- ID index pattern (/novanet/vpc_ids/{id}) bypasses tenant scoping
- Same for Subnet, Port, SecurityGroup operations
Pattern violation:
- FiberLB/FlashDNS/LightningSTOR: delete methods take full object
- NovaNET: delete methods take only ID (allows bypass)
Attack vector:
- Attacker learns VPC ID via leak/guess
- Calls DeleteVpc(id) without org/project
- Retrieves and deletes victim's VPC
Violates: Multi-tenant isolation hard guardrail (PROJECT.md)
fix_required: |
OPTION A (Recommended - Pattern Match + Defense-in-Depth):
1. Proto: Add org_id/project_id to Get/Update/Delete requests for all resources
2. Metadata signatures:
- delete_vpc(&self, org_id: &str, project_id: &str, id: &VpcId) -> Result