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> - update_vpc(&self, org_id: &str, project_id: &str, id: &VpcId, ...) -> Result> OR alternate: delete_vpc(&self, vpc: &Vpc) to match FiberLB/FlashDNS pattern 3. Make *_by_id methods private (internal helpers only) 4. Add test: cross-tenant Get/Delete with wrong org/project returns NotFound/PermissionDenied OPTION B (Auth Layer Validation): - gRPC services extract caller org_id/project_id from auth context - After *_by_id fetch, validate object.org_id == caller.org_id - Return PermissionDenied on mismatch - Still lacks defense-in-depth at data layer DECISION: Option A required (defense-in-depth + pattern consistency) progress: | 2025-12-08 20:15 - Proto+metadata + service layer updated to enforce tenant context on Get/Update/Delete/List for VPC/Subnet/Port; SecurityGroup list now takes org/project. - cross-tenant delete denial test added (metadata::tests::test_cross_tenant_delete_denied) - cargo test -p novanet-server passes (tenant isolation coverage) next: "Proceed to S3 gRPC control-plane wiring" evidence: - "2025-12-08: cargo test -p novanet-server :: ok (tenant isolation tests passing)" - "2025-12-08: proto updated for tenant-scoped Get/Update/Delete/List (novanet/crates/novanet-api/proto/novanet.proto)" notes: | NovaNET naming: Nova (star) + NET (network) = bright network Risk: OVN complexity requires real infrastructure for full testing. Mitigation: Use mock/stub mode for CI; document manual OVN testing. Risk: PlasmaVMC changes may break existing functionality. Mitigation: Add network_ports as optional field; existing tests unchanged.