---
id: STATE-PFM-SEC-009
title: Service principal
object: DOM-PFM-SEC-003
product_area: platform
module: security
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
states:
- name: active
  meaning: The registered machine caller can act under its cloud role and declared service operations.
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
- name: suspended
  meaning: Registry-aware receivers refuse this caller once their one-minute status cache expires.
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
transitions:
- from: active
  to: suspended
  trigger: An authorized Rhythm Administrator suspends the registered caller.
  guard: The principal exists and the caller has service-principal management authority.
  side_effects:
  - Record a narrowing event in the status transaction
  who: Rhythm Administrator
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
- from: suspended
  to: active
  trigger: An authorized Rhythm Administrator resumes the caller.
  guard: The caller has service-principal management authority.
  side_effects:
  - Record a widening event
  who: Rhythm Administrator
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
invalid:
- from: suspended
  to: active
  why: Deployment inserts missing principals but never resumes a suspended existing principal.
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
- from: active
  to: suspended
  why: An unknown principal is returned as not found and the refused change is audited.
  provenance: observed
  source: services-platform:modules/security/services/service-principals/principal-status.ts
concurrency: Status changes lock the principal row and append history in the same transaction. Repeating the
  existing status writes no change event. The observed administration API offers no principal-deletion operation.
evidence:
- 'services-platform at ad3f6a65: modules/security/db/service-principals.table.ts; services/service-principals/principal-status.ts,
  registered-principals.ts; services/provisioning/ensure-service-principals.ts; docs/proposals/service-principals.md
  §8.1.'
examined_at: '2026-10-23'
examiner: codex
---

# Service principal

## The Lifecycle

```mermaid
stateDiagram-v2
    state "Active" as active
    state "Suspended" as suspended
    active --> suspended
    suspended --> active
```

The diagram summarizes the observed transition rows; declared edges without an observed writer remain outside the operational graph.

## Transitions Explained

Principal status governs machine callers independently of human membership. Suspension takes effect through the receiving service’s registry-aware cache; it is not a cloud-role revocation.

Deployment preserves a deliberate suspension. The state model makes no claim of a supported deletion path.

## What Cannot Happen

Deployment inserts missing principals but never resumes a suspended existing principal.

An unknown principal is returned as not found and the refused change is audited.

## Concurrency and Timing

Status changes lock the principal row and append history in the same transaction. Repeating the existing status writes no change event. The observed administration API offers no principal-deletion operation.
