# Phoenix Operating Model - API Specification

**Complete API specification for all five control planes**

This document provides detailed API specifications for the Phoenix operating model, including GraphQL schemas, REST endpoints, and integration patterns.

---

## Executive Summary

The Phoenix operating model exposes APIs for all five control planes:
1. **Commercial Plane API** - Client and billing operations
2. **Tenancy Plane API** - Tenant and identity operations
3. **Subscription Plane API** - Subscription and quota operations
4. **Environment Plane API** - Environment and deployment operations
5. **Content & DevOps Plane API** - Content and Git operations

All APIs support:
- GraphQL interface (primary)
- REST interface (alternative)
- Authentication via Keycloak
- Authorization via RBAC
- Audit logging
- Multi-region support

---

## I. Commercial Plane API

### GraphQL Schema

```graphql
# Client Management
type Client {
  id: ID!
  name: String!
  legalEntity: LegalEntity!
  contract: Contract
  msa: MSA
  invoicingConfig: InvoicingConfig!
  paymentInstruments: [PaymentInstrument!]!
  costCenters: [CostCenter!]!
  tenants: [Tenant!]!
  usageAggregation: UsageAggregation
  chargebackRules: [ChargebackRule!]!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type LegalEntity {
  name: String!
  registrationNumber: String
  jurisdiction: String!
  taxId: String
  address: Address!
}

type InvoicingConfig {
  format: InvoiceFormat!
  frequency: InvoiceFrequency!
  currency: String!
  paymentTerms: String!
  billingAddress: Address!
  emailRecipients: [String!]!
}

enum InvoiceFormat {
  PDF
  XML
  JSON
}

enum InvoiceFrequency {
  MONTHLY
  QUARTERLY
  ANNUAL
}

# Queries
type Query {
  client(id: ID!): Client
  clients(filter: ClientFilter): [Client!]!
  billing(clientId: ID!, timeRange: TimeRange!): BillingData!
  invoices(clientId: ID!, filter: InvoiceFilter): [Invoice!]!
  costCenters(clientId: ID!): [CostCenter!]!
}

# Mutations
type Mutation {
  createClient(input: CreateClientInput!): Client!
  updateClient(id: ID!, input: UpdateClientInput!): Client!
  deleteClient(id: ID!): Boolean!
  createInvoice(clientId: ID!, period: BillingPeriod!): Invoice!
  processPayment(invoiceId: ID!, payment: PaymentInput!): Payment!
  addPaymentInstrument(clientId: ID!, instrument: PaymentInstrumentInput!): PaymentInstrument!
  removePaymentInstrument(clientId: ID!, instrumentId: ID!): Boolean!
  createCostCenter(clientId: ID!, input: CreateCostCenterInput!): CostCenter!
  updateCostCenter(clientId: ID!, costCenterId: ID!, input: UpdateCostCenterInput!): CostCenter!
  deleteCostCenter(clientId: ID!, costCenterId: ID!): Boolean!
}

# Input Types
input CreateClientInput {
  name: String!
  legalEntity: LegalEntityInput!
  invoicingConfig: InvoicingConfigInput!
  contract: ContractInput
  msa: MSAInput
}

input ClientFilter {
  name: String
  jurisdiction: String
  status: ClientStatus
}

input TimeRange {
  start: DateTime!
  end: DateTime!
}
```

### REST Endpoints

```
# Client Management
POST   /api/v1/commercial/clients
GET    /api/v1/commercial/clients
GET    /api/v1/commercial/clients/{id}
PUT    /api/v1/commercial/clients/{id}
DELETE /api/v1/commercial/clients/{id}

# Billing
GET    /api/v1/commercial/clients/{id}/billing
GET    /api/v1/commercial/clients/{id}/invoices
POST   /api/v1/commercial/clients/{id}/invoices
GET    /api/v1/commercial/invoices/{id}
POST   /api/v1/commercial/invoices/{id}/payments

# Cost Centers
POST   /api/v1/commercial/clients/{id}/cost-centers
GET    /api/v1/commercial/clients/{id}/cost-centers
PUT    /api/v1/commercial/clients/{id}/cost-centers/{costCenterId}
DELETE /api/v1/commercial/clients/{id}/cost-centers/{costCenterId}
```

### Example Queries

#### Create Client

```graphql
mutation {
  createClient(input: {
    name: "Government Agency A"
    legalEntity: {
      name: "Government Agency A"
      jurisdiction: "Nation A"
      address: {
        street: "123 Main St"
        city: "Capital City"
        country: "Nation A"
      }
    }
    invoicingConfig: {
      format: PDF
      frequency: MONTHLY
      currency: "USD"
      paymentTerms: "Net 30"
      billingAddress: {
        street: "123 Main St"
        city: "Capital City"
        country: "Nation A"
      }
      emailRecipients: ["billing@agency.gov"]
    }
  }) {
    id
    name
    legalEntity {
      name
      jurisdiction
    }
  }
}
```

#### Get Billing Data

```graphql
query {
  billing(
    clientId: "client-id"
    timeRange: {
      start: "2025-01-01T00:00:00Z"
      end: "2025-01-31T23:59:59Z"
    }
  ) {
    totalCost
    currency
    bySubscription {
      subscription {
        id
        name
      }
      cost
      percentage
    }
    byCostCenter {
      costCenter {
        id
        name
      }
      cost
      percentage
    }
  }
}
```

---

## II. Tenancy Plane API

### GraphQL Schema

```graphql
# Tenant Management
type Tenant {
  id: ID!
  name: String!
  primaryDomains: [String!]!
  identityProvider: IdentityProvider!
  rbacNamespace: String!
  dataResidencyFlags: [DataResidencyFlag!]!
  complianceProfile: ComplianceProfile!
  client: Client!
  subscriptions: [Subscription!]!
  environments: [Environment!]!
  regions: [Region!]!
  keycloakRealmId: String
  multiRegionEnabled: Boolean!
  regionalDataResidency: [RegionalDataResidency!]!
  crossBorderGovernance: CrossBorderGovernance
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type IdentityProvider {
  type: IdentityProviderType!
  config: JSON!
  ssoEnabled: Boolean!
  mfaRequired: Boolean!
}

enum IdentityProviderType {
  KEYCLOAK
  AZURE_AD
  OKTA
  GOOGLE_WORKSPACE
  CUSTOM_SAML
  CUSTOM_OIDC
}

# Queries
type Query {
  tenant(id: ID!): Tenant
  tenants(filter: TenantFilter): [Tenant!]!
  tenantByDomain(domain: String!): Tenant
  identityProvider(tenantId: ID!): IdentityProvider
  complianceProfile(tenantId: ID!): ComplianceProfile
}

# Mutations
type Mutation {
  createTenant(input: CreateTenantInput!): Tenant!
  updateTenant(id: ID!, input: UpdateTenantInput!): Tenant!
  deleteTenant(id: ID!): Boolean!
  configureIdentityProvider(tenantId: ID!, provider: IdentityProviderInput!): IdentityProvider!
  syncKeycloakRealm(tenantId: ID!): KeycloakRealm!
  updateComplianceProfile(tenantId: ID!, profile: ComplianceProfileInput!): ComplianceProfile!
  addDataResidencyFlag(tenantId: ID!, flag: DataResidencyFlagInput!): DataResidencyFlag!
  removeDataResidencyFlag(tenantId: ID!, flagId: ID!): Boolean!
}

# Input Types
input CreateTenantInput {
  name: String!
  clientId: ID!
  primaryDomains: [String!]!
  identityProvider: IdentityProviderInput!
  rbacNamespace: String!
  complianceProfile: ComplianceProfileInput!
  dataResidencyFlags: [DataResidencyFlagInput!]
  multiRegionEnabled: Boolean
}
```

### REST Endpoints

```
# Tenant Management
POST   /api/v1/tenancy/tenants
GET    /api/v1/tenancy/tenants
GET    /api/v1/tenancy/tenants/{id}
PUT    /api/v1/tenancy/tenants/{id}
DELETE /api/v1/tenancy/tenants/{id}
GET    /api/v1/tenancy/tenants/by-domain/{domain}

# Identity Provider
GET    /api/v1/tenancy/tenants/{id}/identity-provider
PUT    /api/v1/tenancy/tenants/{id}/identity-provider
POST   /api/v1/tenancy/tenants/{id}/keycloak/sync

# Compliance
GET    /api/v1/tenancy/tenants/{id}/compliance
PUT    /api/v1/tenancy/tenants/{id}/compliance
```

### Example Queries

#### Create Tenant

```graphql
mutation {
  createTenant(input: {
    name: "agency-tenant"
    clientId: "client-id"
    primaryDomains: ["agency.gov", "agency.sankofa.nexus"]
    identityProvider: {
      type: KEYCLOAK
      config: {}
      ssoEnabled: true
      mfaRequired: true
    }
    rbacNamespace: "agency-namespace"
    complianceProfile: {
      standards: [ISO_27001, SOC_2, FEDRAMP]
    }
    dataResidencyFlags: [{
      region: "region-a"
      requirement: REQUIRED
      enforcement: HARD
    }]
    multiRegionEnabled: true
  }) {
    id
    name
    primaryDomains
    keycloakRealmId
  }
}
```

#### Configure Identity Provider

```graphql
mutation {
  configureIdentityProvider(
    tenantId: "tenant-id"
    provider: {
      type: AZURE_AD
      config: {
        tenantId: "azure-tenant-id"
        clientId: "azure-client-id"
        clientSecret: "azure-client-secret"
      }
      ssoEnabled: true
      mfaRequired: true
    }
  ) {
    type
    ssoEnabled
    mfaRequired
  }
}
```

---

## III. Subscription Plane API

### GraphQL Schema

```graphql
# Subscription Management
type Subscription {
  id: ID!
  name: String!
  tenant: Tenant!
  client: Client!
  type: SubscriptionType!
  serviceBundles: [ServiceBundle!]!
  quotas: Quotas!
  limits: Limits!
  costTracking: CostTracking!
  policyPacks: [PolicyPack!]!
  featureEntitlements: [FeatureEntitlement!]!
  environments: [Environment!]!
  regions: [Region!]!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

enum SubscriptionType {
  SHARED_PLATFORM
  PRODUCT
  SANDBOX
  INNOVATION
}

type ServiceBundle {
  service: ServiceType!
  enabled: Boolean!
  quotas: ServiceQuotas
  limits: ServiceLimits
}

enum ServiceType {
  COMPUTE
  STORAGE
  NETWORKING
  DATABASE
  AI_ML
  ANALYTICS
  SECURITY
  MONITORING
  BACKUP
}

# Queries
type Query {
  subscription(id: ID!): Subscription
  subscriptions(filter: SubscriptionFilter): [Subscription!]!
  quotas(subscriptionId: ID!): Quotas!
  checkQuota(subscriptionId: ID!, resource: ResourceType!): QuotaStatus!
}

# Mutations
type Mutation {
  createSubscription(input: CreateSubscriptionInput!): Subscription!
  updateSubscription(id: ID!, input: UpdateSubscriptionInput!): Subscription!
  deleteSubscription(id: ID!): Boolean!
  updateQuotas(subscriptionId: ID!, quotas: QuotasInput!): Quotas!
  addServiceBundle(subscriptionId: ID!, bundle: ServiceBundleInput!): ServiceBundle!
  removeServiceBundle(subscriptionId: ID!, service: ServiceType!): Boolean!
  addPolicyPack(subscriptionId: ID!, pack: PolicyPackInput!): PolicyPack!
  removePolicyPack(subscriptionId: ID!, packId: ID!): Boolean!
}
```

### REST Endpoints

```
# Subscription Management
POST   /api/v1/subscription/subscriptions
GET    /api/v1/subscription/subscriptions
GET    /api/v1/subscription/subscriptions/{id}
PUT    /api/v1/subscription/subscriptions/{id}
DELETE /api/v1/subscription/subscriptions/{id}

# Quotas
GET    /api/v1/subscription/subscriptions/{id}/quotas
PUT    /api/v1/subscription/subscriptions/{id}/quotas
GET    /api/v1/subscription/subscriptions/{id}/quotas/check

# Service Bundles
POST   /api/v1/subscription/subscriptions/{id}/service-bundles
DELETE /api/v1/subscription/subscriptions/{id}/service-bundles/{service}

# Policy Packs
POST   /api/v1/subscription/subscriptions/{id}/policy-packs
DELETE /api/v1/subscription/subscriptions/{id}/policy-packs/{packId}
```

### Example Queries

#### Create Subscription

```graphql
mutation {
  createSubscription(input: {
    name: "production-subscription"
    tenantId: "tenant-id"
    type: PRODUCT
    serviceBundles: [{
      service: COMPUTE
      enabled: true
      quotas: {
        vcpu: 100
        memory: 512
        instances: 50
      }
    }, {
      service: STORAGE
      enabled: true
      quotas: {
        total: 10000
        perInstance: 500
      }
    }]
    quotas: {
      compute: {
        vcpu: 100
        memory: 512
        instances: 50
      }
      storage: {
        total: 10000
        perInstance: 500
      }
    }
    policyPacks: [{
      name: "security-policy"
      type: SECURITY
      policies: []
      enforcement: HARD
    }]
  }) {
    id
    name
    type
    serviceBundles {
      service
      enabled
    }
  }
}
```

---

## IV. Environment Plane API

### GraphQL Schema

```graphql
# Environment Management
type Environment {
  id: ID!
  name: String!
  type: EnvironmentType!
  subscription: Subscription!
  networkIsolation: NetworkIsolation!
  dataIsolation: DataIsolation!
  deploymentPolicies: [DeploymentPolicy!]!
  runtimeSecrets: [Secret!]!
  complianceOverlays: [ComplianceOverlay!]!
  region: Region
  promotionFlow: PromotionFlow
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

enum EnvironmentType {
  DEV
  INT
  UAT
  STAGING
  PROD
  REGULATED
  SOVEREIGN
  AIR_GAPPED
}

# Queries
type Query {
  environment(id: ID!): Environment
  environments(filter: EnvironmentFilter): [Environment!]!
  promotionFlow(environmentId: ID!): PromotionFlow
  deploymentPolicies(environmentId: ID!): [DeploymentPolicy!]!
}

# Mutations
type Mutation {
  createEnvironment(input: CreateEnvironmentInput!): Environment!
  updateEnvironment(id: ID!, input: UpdateEnvironmentInput!): Environment!
  deleteEnvironment(id: ID!): Boolean!
  promoteArtifact(input: PromoteArtifactInput!): PromotionResult!
  approvePromotion(promotionId: ID!, approved: Boolean!): PromotionResult!
  configurePromotionFlow(environmentId: ID!, flow: PromotionFlowInput!): PromotionFlow!
  addDeploymentPolicy(environmentId: ID!, policy: DeploymentPolicyInput!): DeploymentPolicy!
  removeDeploymentPolicy(environmentId: ID!, policyId: ID!): Boolean!
}
```

### REST Endpoints

```
# Environment Management
POST   /api/v1/environment/environments
GET    /api/v1/environment/environments
GET    /api/v1/environment/environments/{id}
PUT    /api/v1/environment/environments/{id}
DELETE /api/v1/environment/environments/{id}

# Promotion
POST   /api/v1/environment/promotions
GET    /api/v1/environment/promotions/{id}
POST   /api/v1/environment/promotions/{id}/approve
POST   /api/v1/environment/promotions/{id}/reject

# Deployment Policies
POST   /api/v1/environment/environments/{id}/deployment-policies
GET    /api/v1/environment/environments/{id}/deployment-policies
DELETE /api/v1/environment/environments/{id}/deployment-policies/{policyId}
```

### Example Queries

#### Create Environment

```graphql
mutation {
  createEnvironment(input: {
    name: "production-env"
    subscriptionId: "subscription-id"
    type: PROD
    networkIsolation: {
      vpcId: "vpc-id"
      subnetIds: ["subnet-1", "subnet-2"]
      firewallRules: []
    }
    dataIsolation: {
      encryptionAtRest: true
      encryptionInTransit: true
      accessControls: []
    }
    deploymentPolicies: [{
      name: "production-policy"
      type: POLICY_DRIVEN
      approvalRequired: true
      approvers: ["release-manager-1", "release-manager-2"]
    }]
    region: "region-a"
  }) {
    id
    name
    type
    region {
      id
      name
    }
  }
}
```

#### Promote Artifact

```graphql
mutation {
  promoteArtifact(input: {
    artifactId: "artifact-id"
    fromEnvironmentId: "staging-env-id"
    toEnvironmentId: "prod-env-id"
    metadata: {
      version: "1.2.3"
      changelog: "Production release"
    }
  }) {
    id
    status
    approvalRequired
    approvers
  }
}
```

---

## V. Content & DevOps Plane API

### GraphQL Schema

```graphql
# Content Hierarchy
type Enterprise {
  id: ID!
  name: String!
  portfolios: [Portfolio!]!
  ownership: Ownership!
  governance: Governance!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type Portfolio {
  id: ID!
  name: String!
  enterprise: Enterprise!
  products: [Product!]!
  ownership: Ownership!
  governance: Governance!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type Product {
  id: ID!
  name: String!
  portfolio: Portfolio!
  applications: [Application!]!
  ownership: Ownership!
  governance: Governance!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type Application {
  id: ID!
  name: String!
  product: Product!
  components: [Component!]!
  gitRepos: [GitRepo!]!
  ownership: Ownership!
  governance: Governance!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

type Component {
  id: ID!
  name: String!
  application: Application!
  contentType: ContentType!
  content: Content!
  ownership: Ownership!
  governance: Governance!
  version: String!
  lineage: [LineageEntry!]!
  createdAt: DateTime!
  updatedAt: DateTime!
  metadata: JSON
}

enum ContentType {
  SOURCE_CODE
  IAC
  PIPELINE
  CONFIG_TEMPLATE
  DOCUMENTATION
  DATA_SCHEMA
  AI_MODEL
  PROMPT
}

# Queries
type Query {
  enterprise(id: ID!): Enterprise
  enterprises: [Enterprise!]!
  portfolio(id: ID!): Portfolio
  product(id: ID!): Product
  application(id: ID!): Application
  component(id: ID!): Component
  gitRepo(id: ID!): GitRepo
  gitRepos(filter: GitRepoFilter): [GitRepo!]!
}

# Mutations
type Mutation {
  createEnterprise(input: CreateEnterpriseInput!): Enterprise!
  createPortfolio(input: CreatePortfolioInput!): Portfolio!
  createProduct(input: CreateProductInput!): Product!
  createApplication(input: CreateApplicationInput!): Application!
  createComponent(input: CreateComponentInput!): Component!
  createGitRepo(input: CreateGitRepoInput!): GitRepo!
  configureBranchProtection(repoId: ID!, branch: String!, protection: BranchProtectionInput!): BranchProtection!
}
```

### REST Endpoints

```
# Content Hierarchy
POST   /api/v1/content/enterprises
GET    /api/v1/content/enterprises
GET    /api/v1/content/enterprises/{id}

POST   /api/v1/content/portfolios
GET    /api/v1/content/portfolios/{id}

POST   /api/v1/content/products
GET    /api/v1/content/products/{id}

POST   /api/v1/content/applications
GET    /api/v1/content/applications/{id}

POST   /api/v1/content/components
GET    /api/v1/content/components/{id}

# Git Integration
POST   /api/v1/content/git-repos
GET    /api/v1/content/git-repos
GET    /api/v1/content/git-repos/{id}
POST   /api/v1/content/git-repos/{id}/branch-protection
```

### Example Queries

#### Create Application

```graphql
mutation {
  createApplication(input: {
    name: "web-application"
    productId: "product-id"
    ownership: {
      owner: "dev-team"
      team: "engineering"
      contact: "dev-team@agency.gov"
    }
    governance: {
      approvalWorkflows: [{
        name: "code-review"
        steps: [{
          approver: "tech-lead"
          role: "TECH_LEAD"
        }]
        required: true
      }]
      complianceTags: ["HIPAA", "SOC_2"]
    }
  }) {
    id
    name
    product {
      id
      name
    }
  }
}
```

#### Create Git Repository

```graphql
mutation {
  createGitRepo(input: {
    name: "web-application-repo"
    applicationId: "application-id"
    url: "https://git.sankofa.nexus/web-application"
    branchStrategy: {
      main: "main"
      develop: "develop"
      protectedBranches: ["main", "release/*"]
    }
  }) {
    id
    name
    url
    application {
      id
      name
    }
  }
}
```

---

## VI. Authentication and Authorization

### Authentication

All APIs use Keycloak for authentication:

```graphql
# Authentication via Keycloak
# Token obtained from Keycloak OAuth2/OIDC flow
# Include in Authorization header: Bearer <token>
```

### Authorization

Authorization is enforced via RBAC:

```graphql
# RBAC roles per plane:
# Commercial: Finance Admin, Billing Viewer, Cost Center Owner
# Tenancy: Tenant Owner, Security Admin, Identity Admin, Compliance Officer
# Subscription: Subscription Owner, Platform Admin, Service Operator, Auditor
# Environment: Environment Owner, Release Manager, Operator, Observer
# Content: Enterprise Architect, Portfolio Lead, Product Owner, Dev Lead, Contributor, Reviewer, Release Approver
```

### Example: Authenticated Request

```bash
curl -X POST https://api.phoenix.sankofa.nexus/graphql \
  -H "Authorization: Bearer <keycloak-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { tenant(id: \"tenant-id\") { id name } }"
  }'
```

---

## VII. Error Handling

### Error Response Format

```json
{
  "errors": [
    {
      "message": "Error message",
      "extensions": {
        "code": "ERROR_CODE",
        "field": "fieldName",
        "resource": "ResourceType",
        "resourceId": "resource-id"
      }
    }
  ],
  "data": null
}
```

### Common Error Codes

- `UNAUTHORIZED` - Authentication required
- `FORBIDDEN` - Insufficient permissions
- `NOT_FOUND` - Resource not found
- `VALIDATION_ERROR` - Input validation failed
- `QUOTA_EXCEEDED` - Quota limit exceeded
- `POLICY_VIOLATION` - Policy violation
- `CONFLICT` - Resource conflict
- `INTERNAL_ERROR` - Internal server error

---

## VIII. Rate Limiting

### Rate Limits

- **GraphQL**: 1000 requests per minute per tenant
- **REST**: 500 requests per minute per tenant
- **Billing Queries**: 100 requests per minute per client
- **Promotion Operations**: 50 requests per minute per environment

### Rate Limit Headers

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1640995200
```

---

## IX. Pagination

### GraphQL Pagination

```graphql
type Query {
  tenants(
    filter: TenantFilter
    pagination: PaginationInput
  ): TenantConnection!
}

type TenantConnection {
  edges: [TenantEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type TenantEdge {
  node: Tenant!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}

input PaginationInput {
  first: Int
  after: String
  last: Int
  before: String
}
```

### REST Pagination

```
GET /api/v1/tenancy/tenants?page=1&pageSize=50
```

Response:
```json
{
  "data": [...],
  "pagination": {
    "page": 1,
    "pageSize": 50,
    "totalPages": 10,
    "totalCount": 500,
    "hasNext": true,
    "hasPrevious": false
  }
}
```

---

## X. Webhooks and Subscriptions

### GraphQL Subscriptions

```graphql
type Subscription {
  clientUpdated(clientId: ID!): Client!
  tenantUpdated(tenantId: ID!): Tenant!
  subscriptionUpdated(subscriptionId: ID!): Subscription!
  environmentUpdated(environmentId: ID!): Environment!
  promotionStatusChanged(promotionId: ID!): PromotionResult!
  quotaExceeded(subscriptionId: ID!): QuotaAlert!
}
```

### REST Webhooks

```
POST /api/v1/webhooks
GET  /api/v1/webhooks
PUT  /api/v1/webhooks/{id}
DELETE /api/v1/webhooks/{id}
```

Webhook Events:
- `client.created`
- `client.updated`
- `tenant.created`
- `tenant.updated`
- `subscription.created`
- `subscription.updated`
- `environment.created`
- `environment.updated`
- `promotion.started`
- `promotion.approved`
- `promotion.rejected`
- `quota.exceeded`

---

## XI. Multi-Region Support

### Regional API Endpoints

```
# Primary region
https://api.phoenix.sankofa.nexus

# Regional endpoints
https://api-region-a.phoenix.sankofa.nexus
https://api-region-b.phoenix.sankofa.nexus
https://api-region-c.phoenix.sankofa.nexus
```

### Cross-Region Operations

```graphql
mutation {
  createCrossRegionSubscription(input: {
    name: "multi-region-sub"
    tenantId: "tenant-id"
    regions: ["region-a", "region-b"]
    regionalQuotas: {
      "region-a": {
        compute: { vcpu: 50, memory: 256 }
      }
      "region-b": {
        compute: { vcpu: 50, memory: 256 }
      }
    }
  }) {
    id
    name
    regions {
      id
      name
    }
  }
}
```

---

## References

- **[Operating Model](./OPERATING_MODEL.md)** - Complete operating model documentation
- **[MVP Control Plane](./MVP_CONTROL_PLANE.md)** - MVP API requirements
- **[Architecture Diagrams](./OPERATING_MODEL_DIAGRAMS.md)** - API integration diagrams

---

**Last Updated**: 2025-01-09  
**Version**: 1.0  
**Status**: Complete API Specification

