Skip to main content

Platform Admin Service — Application Logic

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: DOMAIN_MODEL · API_CONTRACTS

1. Use cases (commands)

Use caseCommandTriggered byEmits
UpsertConfigUseCaseUpsertConfigCommandSuper Admin POSTplatform_admin.config.updated.v1
ArchiveConfigUseCaseArchiveConfigCommandSuper Admin DELETE
CreateFlagUseCaseCreateFlagCommandSuper Admin POSTplatform_admin.flag.created.v1
UpdateFlagUseCaseUpdateFlagCommandSuper Admin PATCHplatform_admin.flag.updated.v1
ArchiveFlagUseCaseArchiveFlagCommandSuper Admin DELETEplatform_admin.flag.archived.v1
SetTenantFlagOverrideUseCaseSetTenantOverrideCommandSuper Admin POSTplatform_admin.flag.updated.v1
RegisterHealthSourceUseCaseRegisterHealthSourceCommandService startup POSTplatform_admin.health_source.registered.v1

2. Use cases (queries)

QueryReturnsCache
GetConfigQuerySingle config KVRedis 60 s
ListConfigsQueryPaginated config listNo cache
GetConfigHistoryQueryChange history (cursor-paginated)No cache
GetFlagQueryFlag metadataRedis 60 s
ListFlagsQueryAll flags (optional tenant filter)No cache
EvaluateFlagQuery{ enabled: boolean, reason }Redis 60 s (flag:{key}:eval:{tenantId})
BootstrapFlagsQueryAll non-archived flags + decisions for tenantNo cache (startup only)
AggregateHealthQuery{ overall, services[] }Redis 10 s

3. Feature flag evaluation logic

Result cached at flag:{key}:eval:{tenantId} with 60 s TTL. Cache invalidated on flag mutation or override change.

4. Health aggregation flow

  1. AggregateHealthQuery checks Redis cache (platform:health:aggregate, 10 s TTL).
  2. On cache miss: iterate registered HealthSource records.
  3. For each source: check last HealthCheckResult (within staleness_threshold).
  4. Derive overall:
    • All healthy → healthy
    • Any unhealthy → unhealthy
    • Any stale or degraded → degraded
  5. Write result to Redis; return to caller.

Background HealthPollerJob polls each registered source every 15 s; stores result in HealthCheckResult; emits platform_admin.health_source.status_changed.v1 on transition.

5. Ports

PortImplementation
ConfigRepositoryDrizzleConfigRepository
ConfigHistoryRepositoryDrizzleConfigHistoryRepository
FeatureFlagRepositoryDrizzleFlagRepository
HealthSourceRepositoryDrizzleHealthSourceRepository
EventPublisherNatsOutboxEventPublisher
CachePortRedisCacheAdapter
HealthProbeClientHttpHealthProbeClient

6. Error codes

CodeHTTPMeaning
ADM_CONFIG_KEY_UNKNOWN400Key not in allow-list
ADM_CONFIG_VALUE_INVALID400Value type mismatch for key schema
ADM_FLAG_NOT_FOUND404Flag key does not exist
ADM_FLAG_KEY_DUPLICATE409Create attempted on existing active key
ADM_FLAG_ARCHIVED422Mutation attempted on archived flag