The dashboard sees containers Maestro did not create (each repo dev debug compose), and treating them as installs made start/uninstall/config act on a project file that never created them. Mark them external, refuse start/update/uninstall with a message pointing at their own compose project, and let stop work at the container level. Inject runtime env (config-signing public key, plaintext shared-DB DSN) on the managed start path, and keep the external flag a property of the service so a debug sibling cannot flip a managed service.
Fresh boots opened the owner/token/session stores before EnsureDataRoot
dropped to the host user, leaving a root-owned maestro/ state dir whose
EACCES surfaced as a bogus ERR_INVALID_CREDENTIALS on /api/auth/setup.
main() now runs the handoff first; EnsureDataRoot heals pre-existing
root-owned state dirs while still root (healOwnerState).
Storage failures from the owner store now answer 500 ERR_INTERNAL
everywhere (status/setup/login/change-password/RequireSession/
GateWebSocket) instead of blaming credentials or re-advertising setup
mode; SetupRequired returns the store error instead of swallowing it,
and FileOwnerStore.Verify propagates read errors rather than masking
them as unknown-user.
Fetch the auth service's key attestation over mTLS at install time and
persist the fingerprint (plus kid/issued-at) in the install record. At
start, inject AUTH_PINNED_FINGERPRINT into every non-oneoff service so
the shared authclient refuses a substituted key instead of silently
trusting it (TOFU/D3). Best-effort: installs that cannot reach the auth
service backfill the pin on the next start. Skip pinning for the auth
service itself (it is the attester).
- lib/pki: root CA provisioning on first run (~/.dcntrlized/pki/), per-service
leaf identity issuance (90d, refreshed at start), revocation with CRL
- main: EnsureCA on startup
- start: inject CA + identity mounts and AUTH_* mTLS env into compose services
- uninstall: revoke the service's cert (CRL entry published)