Security Architecture Overview

Security Principles

PrincipleImplementation
Defense in depthMultiple layers: network, auth, authz, audit
Least privilegeRole-based access; minimal permissions
Zero trustAll requests authenticated; mTLS for agents
Secrets hygieneSecrets in vault; never in DB; ephemeral injection
Audit everythingAll mutations logged; evidence trail
Immutable evidenceEvidence packets append-only; cryptographically signed

Authentication Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                    AUTHENTICATION ARCHITECTURE                              │
│                                                                             │
│  Human Users                            Service/Agent                       │
│  ┌──────────┐                          ┌──────────┐                        │
│  │ Browser  │                          │ Agent    │                        │
│  └────┬─────┘                          └────┬─────┘                        │
│       │                                     │                               │
│       │ OAuth 2.0                           │ mTLS + JWT                    │
│       │ Authorization Code                  │                               │
│       ▼                                     ▼                               │
│  ┌──────────────────────────────────────────────────────────────────┐      │
│  │                         AUTHORITY MODULE                          │      │
│  │                                                                   │      │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐              │      │
│  │  │ OAuth 2.0   │  │   mTLS      │  │ API Key     │              │      │
│  │  │ Provider    │  │ Validator   │  │ Validator   │              │      │
│  │  └─────────────┘  └─────────────┘  └─────────────┘              │      │
│  │                                                                   │      │
│  │  ┌─────────────────────────────────────────────────────────────┐ │      │
│  │  │                    TOKEN ISSUER                              │ │      │
│  │  │  - Short-lived JWT (15 min)                                 │ │      │
│  │  │  - Contains: user_id, tenant_id, roles, permissions         │ │      │
│  │  │  - Signed with RS256                                        │ │      │
│  │  └─────────────────────────────────────────────────────────────┘ │      │
│  └──────────────────────────────────────────────────────────────────┘      │
│       │                                                                     │
│       ▼                                                                     │
│  ┌──────────────────────────────────────────────────────────────────┐      │
│  │                         API GATEWAY                               │      │
│  │                                                                   │      │
│  │  - Validate JWT signature                                        │      │
│  │  - Check token expiration                                        │      │
│  │  - Extract tenant context                                        │      │
│  │  - Enforce rate limits                                           │      │
│  └──────────────────────────────────────────────────────────────────┘      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Authorization Model

Permission Structure

interface Permission {
  resource: ResourceType;
  action: ActionType;
  scope?: ScopeType;
  conditions?: Condition[];
}

type ResourceType =
  | "environment"
  | "release"
  | "promotion"
  | "target"
  | "agent"
  | "workflow"
  | "plugin"
  | "integration"
  | "evidence";

type ActionType =
  | "create"
  | "read"
  | "update"
  | "delete"
  | "execute"
  | "approve"
  | "deploy"
  | "rollback";

type ScopeType =
  | "*"                              // All resources
  | { environmentId: UUID }          // Specific environment
  | { labels: Record<string, string> };  // Label-based

Role Definitions

RolePermissions
adminAll permissions on all resources
release-managerFull access to releases, promotions; read environments/targets
deployerRead releases; create/read promotions; read targets
approverRead/approve promotions
viewerRead-only access to all resources

Environment-Scoped Roles

Roles can be scoped to specific environments:

// Example: Production deployer can only deploy to production
const prodDeployer = {
  role: "deployer",
  scope: { environmentId: "prod-environment-uuid" }
};

Policy Enforcement Points

┌─────────────────────────────────────────────────────────────────────────────┐
│                    POLICY ENFORCEMENT POINTS                                │
│                                                                             │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                         API LAYER (PEP 1)                            │   │
│  │  - Authenticate request                                             │   │
│  │  - Check resource-level permissions                                  │   │
│  │  - Enforce tenant isolation                                          │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                      SERVICE LAYER (PEP 2)                           │   │
│  │  - Check business-level permissions                                  │   │
│  │  - Validate separation of duties                                     │   │
│  │  - Enforce approval policies                                         │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                    DECISION ENGINE (PEP 3)                           │   │
│  │  - Evaluate security gates                                          │   │
│  │  - Evaluate custom OPA policies                                     │   │
│  │  - Produce signed decision records                                  │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                    │                                        │
│                                    ▼                                        │
│  ┌─────────────────────────────────────────────────────────────────────┐   │
│  │                     DATA LAYER (PEP 4)                               │   │
│  │  - Row-level security (tenant_id)                                   │   │
│  │  - Append-only enforcement (evidence)                               │   │
│  │  - Encryption at rest                                               │   │
│  └─────────────────────────────────────────────────────────────────────┘   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Agent Security Model

See Agent Security for detailed agent security architecture.

Key features:

Secrets Management

┌─────────────────────────────────────────────────────────────────────────────┐
│                    SECRETS FLOW (NEVER STORED IN DB)                        │
│                                                                             │
│  ┌──────────────┐        ┌──────────────┐        ┌──────────────┐          │
│  │    VAULT     │        │  STELLA CORE │        │    AGENT     │          │
│  │  (Source)    │        │  (Broker)    │        │  (Consumer)  │          │
│  └──────┬───────┘        └──────┬───────┘        └──────┬───────┘          │
│         │                       │                       │                   │
│         │                       │ Task requires secret  │                   │
│         │                       │                       │                   │
│         │ Fetch with service   │                       │                   │
│         │ account token        │                       │                   │
│         │◄───────────────────────                       │                   │
│         │                       │                       │                   │
│         │ Return secret        │                       │                   │
│         │ (wrapped, short TTL) │                       │                   │
│         │───────────────────────►                       │                   │
│         │                       │                       │                   │
│         │                       │ Embed in task payload │                   │
│         │                       │ (encrypted)          │                   │
│         │                       │───────────────────────►                   │
│         │                       │                       │                   │
│         │                       │                       │ Decrypt           │
│         │                       │                       │ Use for task      │
│         │                       │                       │ Discard           │
│                                                                             │
│  Rules:                                                                     │
│  - Secrets NEVER stored in Stella database                                 │
│  - Only Vault references stored                                            │
│  - Secrets fetched at execution time only                                  │
│  - Secrets not logged (masked in logs)                                     │
│  - Secrets not persisted in agent memory beyond task scope                 │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

As-built credential handling (2026-07-04, SPRINT_20260703_002 / DTC-12)

The diagram above is the design-time contract; this subsection is the verified as-built state of target credentials in src/ (updated when the implementation changes).

Target connection configs are encrypted at rest. The release.targets column connection_config_encrypted historically stored plain UTF-8 JSON despite its name. It now stores an AEAD-sealed envelope produced by AeadTargetConnectionConfigProtector (src/ReleaseOrchestrator/__Libraries/StellaOps.ReleaseOrchestrator.Environment/Target/TargetConnectionConfigProtector.cs):

API reads mask inline secrets. Secret-bearing connection-config fields are canonical secret references. Pointer schemes (vault://, builtin://, openbao://, authref://, file://) are non-secret pointers and return verbatim so operators can view/edit them; inline values (plain:, base64:, raw literals) are replaced with the *** sentinel on every target read, and the update path substitutes the stored value back when a client echoes the sentinel (TargetConnectionSecretMasking, applied in ReleaseOrchestratorEnvironmentEndpoints).

Deploy-time secretRef resolution is fail-closed. All per-transport resolvers (SSH, WinRM, Ansible, ECS, Nomad) route through the unified ISecretProvider (builtin | Vault | OpenBao) with tenant scope — including WinRM, which was previously the one resolver never provider-routed (a vault:// WinRM password silently resolved to null). A configured reference that fails to resolve throws DeploymentSecretResolutionException and fails that target’s deployment with a clear per-target error (message carries only target name, field, and scheme — never the path or value) instead of dispatching a credential-less task (TargetExecutor.ResolveConfiguredSecretAsync). Broker-mode (pull) resolution is separately fail-closed per ADR-034 (DeploymentSecretBrokerService).

Decision audit trail is written. Approval decisions (grant/reject, single and batch) and deployment lifecycle decisions (create, pause, resume, cancel, rollback, target retry) append to the tamper-evident release_orchestrator.audit_entries hash chain via ReleaseOrchestratorDecisionAuditTrail (src/ReleaseOrchestrator/__Apps/StellaOps.ReleaseOrchestrator.WebApi/Services/). The chain (per-tenant sequence + previous-hash link through release_orchestrator.audit_sequences, verified by verify_audit_chain) existed since migration 001 but had no writers before this sprint. Ledger writes never carry secret material and never fail the user action (failures are logged and swallowed; the primary approval/deployment row has already committed).

Threat Model

ThreatAttack VectorMitigation
Credential theftDatabase breachSecrets never in DB; only vault refs
Token replayStolen JWTShort-lived tokens (15 min); refresh tokens rotated
Agent impersonationFake agentmTLS with CA-signed certs; registration token one-time
Digest tamperingModified imageDigest verification at pull time; mismatch = failure
Evidence tamperingModified audit recordsAppend-only table; cryptographic signing
Privilege escalationCompromised accountRole-based access; SoD enforcement; audit logs
Supply chain attackMalicious pluginPlugin sandbox; capability declarations; review process
Lateral movementCompromised targetShort-lived task credentials; scoped permissions
Data exfiltrationLog/artifact theftEncryption at rest; network segmentation
Denial of serviceResource exhaustionRate limiting; resource quotas; circuit breakers

Audit Trail

Audit Event Structure

interface AuditEvent {
  id: UUID;
  timestamp: DateTime;
  tenantId: UUID;

  // Actor
  actorType: "user" | "agent" | "system" | "plugin";
  actorId: UUID;
  actorName: string;
  actorIp?: string;

  // Action
  action: string;              // "promotion.approved", "deployment.started"
  resource: string;            // "promotion"
  resourceId: UUID;

  // Context
  environmentId?: UUID;
  releaseId?: UUID;
  promotionId?: UUID;

  // Details
  before?: object;             // State before (for updates)
  after?: object;              // State after
  metadata?: object;           // Additional context

  // Integrity
  previousEventHash: string;   // Hash chain for tamper detection
  eventHash: string;
}

Audited Operations

CategoryOperations
AuthenticationLogin, logout, token refresh, failed attempts
AuthorizationPermission denied events
EnvironmentsCreate, update, delete, freeze window changes
ReleasesCreate, deprecate, archive
PromotionsRequest, approve, reject, cancel
DeploymentsStart, complete, fail, rollback
TargetsRegister, update, delete, health changes
AgentsRegister, heartbeat gaps, capability changes
IntegrationsCreate, update, delete, test
PluginsEnable, disable, config changes
EvidenceCreate (never update/delete)

References