# MVP-Beta Tenant Path Architecture

## Overview

This document describes the architecture of the PlasmaCloud MVP-Beta tenant path, which enables end-to-end multi-tenant cloud infrastructure provisioning with complete isolation between tenants.

The tenant path spans three core components:
1. **IAM** (Identity and Access Management): User authentication, RBAC, and tenant scoping
2. **PrismNET**: Network virtualization with VPC overlay and tenant isolation
3. **PlasmaVMC**: Virtual machine provisioning and lifecycle management

## Architecture Diagram

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           User / API Client                                  │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ↓ Authentication Request
┌─────────────────────────────────────────────────────────────────────────────┐
│                          IAM (Identity & Access)                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                               │
│  ┌────────────────────┐         ┌──────────────────┐                        │
│  │  IamTokenService   │────────▶│  IamAuthzService │                        │
│  │                    │         │                  │                        │
│  │ • Authenticate     │         │ • RBAC Eval      │                        │
│  │ • Issue JWT Token  │         │ • Permission     │                        │
│  │ • Scope: org+proj  │         │   Check          │                        │
│  └────────────────────┘         └──────────────────┘                        │
│                                                                               │
│  Data Stores:                                                                │
│  • PrincipalStore (users, service accounts)                                 │
│  • RoleStore (system, org, project roles)                                   │
│  • BindingStore (principal → role assignments)                              │
│                                                                               │
│  Tenant Scoping:                                                             │
│  • Principals belong to org_id                                              │
│  • Tokens include org_id + project_id                                       │
│  • RBAC enforces resource.org_id == token.org_id                            │
│                                                                               │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ↓ JWT Token {org_id, project_id, permissions}
┌─────────────────────────────────────────────────────────────────────────────┐
│                          API Gateway / Service Layer                         │
│  • Validates JWT token                                                       │
│  • Extracts org_id, project_id from token                                   │
│  • Passes tenant context to downstream services                             │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                    ┌───────────────┴───────────────┐
                    ↓                               ↓
┌─────────────────────────────────┐   ┌─────────────────────────────────┐
│         PrismNET                 │   │        PlasmaVMC                │
│   (Network Virtualization)      │   │   (VM Provisioning)             │
├─────────────────────────────────┤   ├─────────────────────────────────┤
│                                 │   │                                 │
│  ┌────────────────────────┐     │   │  ┌────────────────────────┐     │
│  │  VpcServiceImpl        │     │   │  │  VmServiceImpl         │     │
│  │  • Create VPC          │     │   │  │  • Create VM           │     │
│  │  • Scope: org_id       │     │   │  │  • Scope: org_id,      │     │
│  │  • VPC ID generation   │     │   │  │    project_id          │     │
│  └────────────────────────┘     │   │  │  • Network attach      │     │
│              ↓                  │   │  └────────────────────────┘     │
│  ┌────────────────────────┐     │   │              │                  │
│  │  SubnetServiceImpl     │     │   │              │                  │
│  │  • Create Subnet       │     │   │  ┌────────────────────────┐     │
│  │  • CIDR allocation     │     │   │  │  NetworkAttachment     │     │
│  │  • DHCP config         │     │   │  │  • Attach port to VM   │     │
│  │  • Gateway config      │     │   │  │  • Update port.device  │     │
│  └────────────────────────┘     │   │  │  • TAP interface       │     │
│              ↓                  │   │  └────────────────────────┘     │
│  ┌────────────────────────┐     │   │              ↑                  │
│  │  PortServiceImpl       │◀────┼───┼──────────────┘                  │
│  │  • Create Port         │     │   │   port_id in NetworkSpec        │
│  │  • IP allocation       │     │   │                                 │
│  │  • MAC generation      │     │   │  Hypervisor:                    │
│  │  • Port status         │     │   │  • KvmBackend                   │
│  │  • device_id tracking  │     │   │  • FirecrackerBackend           │
│  └────────────────────────┘     │   │                                 │
│                                 │   │  Storage:                       │
│  Metadata Store:                │   │  • NetworkMetadataStore         │
│  • NetworkMetadataStore         │   │  • ChainFire (planned)          │
│  • In-memory (dev)              │   │                                 │
│  • FlareDB (production)         │   └─────────────────────────────────┘
│                                 │
│  Data Plane (OVN):              │
│  • Logical switches per VPC     │
│  • Logical routers per subnet   │
│  • Security groups              │
│  • DHCP server                  │
│                                 │
└─────────────────────────────────┘
```

## Component Boundaries

### IAM: Tenant Isolation + RBAC Enforcement

**Responsibilities**:
- User authentication and token issuance
- Organization and project hierarchy management
- Role-based access control (RBAC) enforcement
- Cross-tenant access denial

**Tenant Scoping**:
- Each `Principal` (user/service account) belongs to an `org_id`
- Tokens include both `org_id` and `project_id` claims
- Resources are scoped as: `org/{org_id}/project/{project_id}/{resource_type}/{id}`

**Key Types**:
```rust
struct Principal {
    id: String,
    org_id: Option<String>,      // Primary tenant boundary
    project_id: Option<String>,  // Sub-tenant boundary
    // ...
}

struct Scope {
    System,                       // Global access
    Org(String),                  // Organization-level
    Project { org, project },     // Project-level
}

struct Permission {
    action: String,               // e.g., "compute:instances:create"
    resource_pattern: String,     // e.g., "org/acme-corp/project/*/instance/*"
    conditions: Vec<Condition>,   // e.g., resource.owner == principal.id
}
```

**Integration Points**:
- Issues JWT tokens consumed by all services
- Validates authorization before resource creation
- Enforces `resource.org_id == token.org_id` at policy evaluation time

### PrismNET: Network Isolation per Tenant VPC

**Responsibilities**:
- VPC (Virtual Private Cloud) provisioning
- Subnet management with CIDR allocation
- Port creation and IP/MAC assignment
- Security group enforcement
- Port lifecycle management (attach/detach)

**Tenant Scoping**:
- Each VPC is scoped to an `org_id`
- VPC provides network isolation boundary
- Subnets and ports inherit VPC tenant scope
- Port device tracking links to VM IDs

**Key Types**:
```rust
struct Vpc {
    id: String,
    org_id: String,               // Tenant boundary
    project_id: String,
    cidr: String,                 // e.g., "10.0.0.0/16"
    // ...
}

struct Subnet {
    id: String,
    vpc_id: String,               // Parent VPC (inherits tenant)
    cidr: String,                 // e.g., "10.0.1.0/24"
    gateway: String,
    dhcp_enabled: bool,
    // ...
}

struct Port {
    id: String,
    subnet_id: String,            // Parent subnet (inherits tenant)
    ip_address: String,
    mac_address: String,
    device_id: String,            // VM ID when attached
    device_type: DeviceType,      // Vm, LoadBalancer, etc.
    // ...
}
```

**Integration Points**:
- Accepts org_id/project_id from API tokens
- Provides port IDs to PlasmaVMC for VM attachment
- Receives port attachment/detachment events from PlasmaVMC
- Uses OVN (Open Virtual Network) for overlay networking data plane

### PlasmaVMC: VM Scoping by org_id/project_id

**Responsibilities**:
- Virtual machine lifecycle management (create, start, stop, delete)
- Hypervisor abstraction (KVM, Firecracker)
- Network interface attachment to PrismNET ports
- VM metadata persistence (ChainFire)

**Tenant Scoping**:
- Each VM belongs to an `org_id` and `project_id`
- VM metadata includes tenant identifiers
- Network attachments validated against tenant scope

**Key Types**:
```rust
struct Vm {
    id: String,
    name: String,
    org_id: String,               // Tenant boundary
    project_id: String,
    spec: VmSpec,
    state: VmState,
    // ...
}

struct NetworkSpec {
    id: String,                   // Interface name (e.g., "eth0")
    network_id: String,           // VPC ID from PrismNET
    subnet_id: String,            // Subnet ID from PrismNET
    port_id: String,              // Port ID from PrismNET
    mac_address: String,
    ip_address: String,
    // ...
}
```

**Integration Points**:
- Accepts org_id/project_id from API tokens
- Fetches port details from PrismNET using port_id
- Notifies PrismNET when VM is created (port attach)
- Notifies PrismNET when VM is deleted (port detach)
- Uses hypervisor backends (KVM, Firecracker) for VM execution

## Data Flow: Complete Tenant Path

### Scenario: User Creates VM with Network

```
Step 1: User Authentication
──────────────────────────────────────────────────────────────
User                    IAM
  │                      │
  ├──── Login ──────────▶│
  │                      ├─ Validate credentials
  │                      ├─ Lookup Principal (org_id="acme")
  │                      ├─ Generate JWT token
  │◀─── JWT Token ───────┤   {org_id: "acme", project_id: "proj-1"}
  │                      │


Step 2: Create Network Resources
──────────────────────────────────────────────────────────────
User                 PrismNET
  │                      │
  ├── CreateVPC ────────▶│ (JWT token in headers)
  │  {org: acme,         ├─ Validate token
  │   project: proj-1,   ├─ Extract org_id="acme"
  │   cidr: 10.0.0.0/16} ├─ Create VPC(id="vpc-123", org="acme")
  │◀─── VPC ─────────────┤   {id: "vpc-123"}
  │                      │
  ├── CreateSubnet ─────▶│
  │  {vpc: vpc-123,      ├─ Validate VPC belongs to token.org_id
  │   cidr: 10.0.1.0/24} ├─ Create Subnet(id="sub-456")
  │◀─── Subnet ──────────┤   {id: "sub-456"}
  │                      │
  ├── CreatePort ───────▶│
  │  {subnet: sub-456,   ├─ Allocate IP: 10.0.1.10
  │   ip: 10.0.1.10}     ├─ Generate MAC: fa:16:3e:...
  │◀─── Port ────────────┤   {id: "port-789", device_id: ""}
  │                      │


Step 3: Create VM with Network Attachment
──────────────────────────────────────────────────────────────
User              PlasmaVMC                PrismNET
  │                  │                        │
  ├─ CreateVM ──────▶│ (JWT token)            │
  │  {name: "web-1", ├─ Validate token        │
  │   network: [     ├─ Extract org/project   │
  │     {port_id:    │                        │
  │      "port-789"} ├─ GetPort ─────────────▶│
  │   ]}             │                        ├─ Verify port.subnet.vpc.org_id
  │                  │                        │    == token.org_id
  │                  │◀─── Port ──────────────┤ {ip: 10.0.1.10, mac: fa:...}
  │                  │                        │
  │                  ├─ Create VM             │
  │                  ├─ Attach network:       │
  │                  │   TAP device → port    │
  │                  │                        │
  │                  ├─ AttachPort ──────────▶│
  │                  │   {device_id: "vm-001"}│
  │                  │                        ├─ Update port.device_id="vm-001"
  │                  │                        ├─ Update port.device_type=Vm
  │                  │◀─── Success ───────────┤
  │                  │                        │
  │◀─── VM ──────────┤ {id: "vm-001", state: "running"}
  │                  │


Step 4: Cross-Tenant Access Denied
──────────────────────────────────────────────────────────────
User B           PlasmaVMC                IAM
(org: "other")      │                      │
  │                 │                      │
  ├─ GetVM ────────▶│ (JWT token: org="other")
  │  {vm_id:        ├─ Authorize ─────────▶│
  │   "vm-001"}     │  {action: "vm:read", ├─ Evaluate RBAC
  │                 │   resource: "org/acme/..."}
  │                 │                      ├─ Check resource.org_id="acme"
  │                 │                      ├─ Check token.org_id="other"
  │                 │                      ├─ DENY: org mismatch
  │                 │◀─── Deny ────────────┤
  │◀── 403 Forbidden ┤
  │                 │
```

## Tenant Isolation Mechanisms

### Layer 1: IAM Policy Enforcement

**Mechanism**: Resource path matching with org_id validation

**Example**:
```
Resource: org/acme-corp/project/proj-1/instance/vm-001
Token:    {org_id: "acme-corp", project_id: "proj-1"}
Policy:   Permission {action: "compute:*", resource: "org/acme-corp/*"}

Result: ALLOW (org_id matches)
```

**Cross-Tenant Denial**:
```
Resource: org/acme-corp/project/proj-1/instance/vm-001
Token:    {org_id: "other-corp", project_id: "proj-2"}

Result: DENY (org_id mismatch)
```

### Layer 2: Network VPC Isolation

**Mechanism**: VPC provides logical network boundary

- Each VPC has a unique overlay network (OVN logical switch)
- Subnets within VPC can communicate
- Cross-VPC traffic requires explicit routing (not implemented in MVP-Beta)
- VPC membership enforced by org_id

**Isolation Properties**:
- Tenant A's VPC (10.0.0.0/16) is isolated from Tenant B's VPC (10.0.0.0/16)
- Even with overlapping CIDRs, VPCs are completely isolated
- MAC addresses are unique per VPC (no collision)

### Layer 3: VM Scoping

**Mechanism**: VMs are scoped to org_id and project_id

- VM metadata includes org_id and project_id
- VM list operations filter by token.org_id
- VM operations validated against token scope
- Network attachments validated against VPC tenant scope

## Service Communication

### gRPC APIs

All inter-service communication uses gRPC with Protocol Buffers:

```
IAM:         :50080 (IamAdminService, IamAuthzService)
PrismNET:     :50081 (VpcService, SubnetService, PortService, SecurityGroupService)
PlasmaVMC:   :50082 (VmService)
FlashDNS:    :50083 (DnsService) [Future]
FiberLB:     :50084 (LoadBalancerService) [Future]
LightningStor: :50085 (StorageService) [Future]
```

### Environment Configuration

Services discover each other via environment variables:

```bash
# PlasmaVMC configuration
NOVANET_ENDPOINT=http://prismnet:50081
IAM_ENDPOINT=http://iam:50080

# PrismNET configuration
IAM_ENDPOINT=http://iam:50080
FLAREDB_ENDPOINT=http://flaredb:50090  # Metadata persistence
```

## Metadata Persistence

### Development: In-Memory Stores

```rust
// NetworkMetadataStore (PrismNET)
let store = NetworkMetadataStore::new_in_memory();

// Backend (IAM)
let backend = Backend::memory();
```

### Production: FlareDB

```
IAM:      PrincipalStore, RoleStore, BindingStore → FlareDB
PrismNET:  NetworkMetadataStore → FlareDB
PlasmaVMC: VmMetadata → ChainFire (immutable log) + FlareDB (mutable state)
```

## Future Extensions (Post MVP-Beta)

### S3: FlashDNS Integration

```
User creates VM → PlasmaVMC creates DNS record in tenant zone
VM hostname: web-1.proj-1.acme-corp.cloud.internal
DNS resolution within VPC
```

### S4: FiberLB Integration

```
User creates LoadBalancer → FiberLB provisions LB in tenant VPC
LB backend pool: [vm-1, vm-2, vm-3] (all in same project)
LB VIP: 10.0.1.100 (allocated from subnet)
```

### S5: LightningStor Integration

```
User creates Volume → LightningStor allocates block device
Volume attachment to VM → PlasmaVMC attaches virtio-blk
Snapshot management → LightningStor + ChainFire
```

## Testing & Validation

**Integration Tests**: 8 tests validating complete E2E flow

| Test Suite | Location | Tests | Coverage |
|------------|----------|-------|----------|
| IAM Tenant Path | iam/.../tenant_path_integration.rs | 6 | Auth, RBAC, isolation |
| Network + VM | plasmavmc/.../prismnet_integration.rs | 2 | VPC lifecycle, VM attach |

**Key Validations**:
- ✅ User authentication and token issuance
- ✅ Organization and project scoping
- ✅ RBAC policy evaluation
- ✅ Cross-tenant access denial
- ✅ VPC, subnet, and port creation
- ✅ Port attachment to VMs
- ✅ Port detachment on VM deletion
- ✅ Tenant-isolated networking

See [E2E Test Documentation](../por/T023-e2e-tenant-path/e2e_test.md) for detailed test descriptions.

## Conclusion

The MVP-Beta tenant path provides a complete, production-ready foundation for multi-tenant cloud infrastructure:

- **Strong tenant isolation** at IAM, network, and compute layers
- **Flexible RBAC** with hierarchical scopes (System → Org → Project)
- **Network virtualization** with VPC overlay using OVN
- **VM provisioning** with seamless network attachment
- **Comprehensive testing** validating all integration points

This architecture enables secure, isolated cloud deployments for multiple tenants on shared infrastructure, with clear boundaries and well-defined integration points for future extensions (DNS, load balancing, storage).
