feat(dev): DCNTRLIZED_DEV drives dev mode; dev fleet runs real mTLS

The single canonical dev flag is DCNTRLIZED_DEV=true, injected by every
docker-compose.debug/dev.yaml. Dev mode now selects endpoints and behaviors
without downgrading control-plane security:

- lib/env: IsDev()/GiteaURL(); registry BaseURL keys on DCNTRLIZED_DEV and
  DCNTRLIZED_GITEA_URL (renamed from GITEA_URL).
- authmgmt: Scheme()/PeerTransport() (satellite edges) key on DCNTRLIZED_DEV
  — dev satellites keep a plaintext RN-facing listener, production mTLS. The
  auth-management edge (New()) stays mTLS in both, preferring
  DCNTRLIZED_AUTH_URL in dev.
- Removed INSECURE_INTERNAL + propagateInsecureInternal from Maestro: the
  orchestrator no longer runs plaintext, and no longer injects the escape
  hatch into services it starts.
- lib/devboot: at boot (dev only) Maestro provisions the identities its
  compose-managed peers bind-mount at /dcntrlized/pki (before infra boots)
  and approves the known fleet in the auth trust store. Unknown peers still
  record a pending authorization and are refused (mechanisms active).
- Composes: prod docker-compose.yaml is clean (no DCNTRLIZED_DEV/GITEA_URL);
  the debug compose carries the dev flag + DCNTRLIZED_GITEA_URL only.
This commit is contained in:
2026-08-16 15:51:49 +01:00
parent e569466dc3
commit addaabc0a8
12 changed files with 178 additions and 96 deletions
-27
View File
@@ -18,7 +18,6 @@ package containers
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
@@ -70,15 +69,6 @@ func StartContainer(ctx context.Context, item types.RegistryContainer) error {
return err
}
// Dev escape hatch (M2 §2): when Maestro itself runs with
// INSECURE_INTERNAL=1, start services the dev way too — propagate the flag
// into the compose services so infra auto-started by Maestro (e.g. a
// resurrected dcntrlized-auth, see infra.go) keeps a plaintext listener
// instead of coming up as mTLS against the plaintext dev fleet.
if os.Getenv("INSECURE_INTERNAL") == "1" {
propagateInsecureInternal(project)
}
// The compose file may reference the image by a short name (e.g.
// "testservice") while install pulled it under its full registry reference.
// Make sure those short names exist so Up() can find them.
@@ -171,23 +161,6 @@ func injectServiceIdentity(ctx context.Context, project *composetypes.Project, s
return nil
}
// propagateInsecureInternal injects INSECURE_INTERNAL=1 into every non-oneoff
// compose service when Maestro itself runs in dev mode (the same flag the dev
// debug composes set). Mirroring those composes keeps peer edges plaintext, so
// a service auto-installed and started by Maestro (e.g. a resurrected
// dcntrlized-auth) matches the compose-managed plaintext dev fleet instead of
// binding an mTLS listener the satellites cannot reach.
func propagateInsecureInternal(project *composetypes.Project) {
for name, s := range project.Services {
if isOneoff(s) {
continue
}
s.Environment = mergeEnv(s.Environment, map[string]string{"INSECURE_INTERNAL": "1"})
project.Services[name] = s
}
logger.Info("Dev mode (INSECURE_INTERNAL=1): propagated plaintext escape hatch to %d service(s)", len(project.Services))
}
// pinAuthFingerprint returns the service's pinned auth fingerprint, fetching
// and persisting it when the install record does not have one yet (M2 §5).
// Best-effort: when the auth service is unreachable, it returns "" and the