PrimeBrickPrimeBrick
  • Docs
  • Contact
  • MIT License
  • Documentation
  • MCP Server
  • API Catalog
  • Services
  • Libraries
PrimeBrickPrimeBrick

© 2026 PrimeBrick. MIT License. v3.11.2

github
Backend
    Roles and PermissionsWorking Together on the Same RecordManaging ModulesSigning In and MFA
    Generated
    Manual
    Developer Guide
      OverviewArchitectureAPI ConventionsEntity metadata contractEntity CRUD PipelineEntities and CRUD conventionsModule Navigation MetadataService RegistryMCP GatewayThe Service ProxyRotating Secrets EngineTranslationsAuthenticationRBACEnvironment ConfigurationCollaboration & Visual Merge
Frontend
Microservices
powered by Zudoku
Developer Guide

Rotating Secrets Engine

Service-to-service authentication does not rely on a static shared secret. The BE runs a RotatingSecretEngine (SDK secrets/rotating-secret.ts) that owns every s2s secret and rotates it on a timer.

The slot model

Each secret lives in Redis as a slot { current, previous, rotated_at }:

  • Rotation: every rotationMs (default 60 min) a fresh secret replaces current; the old one becomes previous. The Redis key expires after rotationMs + graceMs.
  • Grace window: for graceMs (default 5 min) after rotation, verifiers accept both current and previous (validClientShieldSecrets) — so an in-flight request signed just before rotation never fails.
  • Broadcast: each rotation publishes the shielded secret.rotated event; consumers refresh their cached slot immediately instead of waiting for a miss.

Serving secrets — governed, allowlisted

Consumers fetch a secret over the NATS secret.get correlation route. The route is:

  • publisher-verified — only registered services may call it
  • allowlisted — SERVED_SECRETS in modules/secrets/secret-engine.ts declares exactly which (scope, name) refs exist; anything else is refused with an error log. A service can never fetch an arbitrary secret.

Currently served: service_client_shield_secret — the secret stamped on every s2s call (x-client-shield-secret header) and verified by the client-shield middleware on every inbound internal route.

Fallbacks and failure modes

  • The config_entries row service_client_shield_secret (type secret, __ROTATED_BY_SECRET_ENGINE__ placeholder) is the static fallback only — it exists so the config loader can boot services before the engine's first rotation. It is never the production value.
  • If Redis is unavailable the engine logs an explicit error and rotation simply does not happen — consumers keep accepting the last slot.
  • The engine also keeps the BE's own outbound slot warm, so BE→US calls (proxy, NATS auth headers) always stamp current.

Why rotation matters

A leaked s2s secret expires within the hour by design — no deploy, no config change, no coordination. Combined with the allowlist and the publisher verifier, the blast radius of a compromised service identity is bounded to one rotation window.

Last modified on October 28, 2026
The Service ProxyTranslations
On this page
  • The slot model
  • Serving secrets — governed, allowlisted
  • Fallbacks and failure modes
  • Why rotation matters