For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /reference/docs/dd/0043-themelio-compat-service.md.

DD-0043 — The retained Themelio as the themelio-compat service

Related ADR: ADR-0043.

Status: Draft for review. Qualified on the authorised dev-ikons dev box; other dev boxes remain pending. Staging and production do not run it.

Date: 2026-10-14.

Scope and responsibilities

This is infrastructure configuration, stage 4 of decision 0040, for the legacy source relocated under decision 0042. There is no new business context, aggregate, command API, event or subscription.

OwnerResponsibility
Ansible bootstrapThe themelio-compat namespace, its Pod Security labels and the controller's Role in it
Argo CDThe web, both actors, PostgreSQL, Valkey, generated Secrets, the database Jobs and the network policies; Waldur's Identity Bridge setting
make deployThe images and their digests, the AAI client Secret and the GitLab and Waldur tokens

Application and manifests

Every dev box installs the themelio-compat Application (gitops/apps/base/themelio-compat.yaml) on wave 4, after GitLab and Waldur. apps/overlays/devbox sets its path, and apps/base patches Waldur's Application with the Identity Bridge setting. When the new Themelio replaces it, it becomes an optional component again (ADR-0045). An earlier saved themelio-compat profile is still accepted and has no effect.

The Application installs gitops/manifests/themelio-compat/overlays/devbox:

  • base/ holds plain manifests, one file per workload or concern, as legacy/gitops/manifests/themelio does. Its configMapGenerator names the configuration with a content hash, so a change rolls the pods that read it at start. Superseded ConfigMaps carry IgnoreExtraneous, so they stay (the root does not prune) without marking the service OutOfSync.
  • overlays/devbox/ merges the dev box's public origins into that configuration.

check_platform_gitops.py builds the service as Argo does with the root's images. Every container image must be a digest, and the docker.io/pharos/themelio-compat-* ones must be the digests of the in-cluster builds. Without them the build fails the check. model.application_errors accepts only kustomize.images on this Application.

Images

The web, gitlab-root-actor and k8s-root-actor targets are entries of the image catalogue, built in the cluster from the delivered commit (DD-0045). The Dockerfile copies all of compat/themelio, so a change anywhere in it rebuilds all three. The root passes their digests as the Application's kustomize.images.

The web pins Next.js 15.5.7. Its loopback rewrite matches 127.x.x.x anywhere in a URL, so themelio-compat.pharos.127.0.0.1.sslip.io became ...pharos.localhost.sslip.io and the OIDC redirect URI no longer matched. Next.js 16 anchors the rule to the host. No 15.5 release does. compat/themelio/next-loopback.cjs applies the anchored rule to the 27 affected files before the build and fails on any other version or count, so an upgrade is reviewed.

Data and credentials

PostgreSQL 17 and Valkey 8.1 run in the namespace on Ceph block volumes, pinned by digest. A Sync hook creates the generated Secrets once: the PostgreSQL administrator, migrator and runtime passwords, the Valkey password, the web's session secret and the actors' internal token. The provision Job alone reads the administrator password and creates the two roles. The migration Job runs DDL as the migrator, and the Kubernetes root actor runs as the runtime role.

The provider tokens are the exception in ADR-0043. While Argo installs the services, make deploy waits for GitLab and Waldur to be Synced and Healthy. It then:

  • creates root's themelio-compat-root-actor token (api, sudo), revoking earlier ones, for the GitLab root actor only;
  • creates the password-less staff user themelio-compat and its single token, for the web only.

The values reach GitLab, Waldur and Kubernetes only on stdin. Each token expires after 30 days. A deploy rotates it when fewer than seven days remain and restarts only the workload that reads it.

Sign-in, Waldur and routes

Themelio signs in through the shared AAI's pharos-control-plane client, which gains its callback. aai-client.yaml makes make deploy render the client and the AAI CA into the themelio-oidc Secret. Every Themelio process trusts that CA, which also signs the edge. The web requests only the scopes the AAI defines: openid, voperson_id, email, profile, voperson_external_affiliation, schac_home_organization and entitlements.

On sign-in, the web creates or updates the user in Waldur through the Identity Bridge. Waldur's wrapper chart gains pharos.settings, Constance settings declared in the synced pharos-settings ConfigMap. Its PostSync bootstrap applies them with waldur override_constance_settings. Argo runs the hook only when a synced resource changes, so the settings cannot live in the hook alone. The command skips a setting it cannot save and still succeeds, so the hook fails on its report. The apps set FEDERATED_IDENTITY_SYNC_ENABLED, and Waldur keeps it set if the service is later removed.

The catalogue route themelio-compat.pharos reaches the web. Network policies deny ingress except from the namespace and the gateway's paired policy, and apply before the data servers start.

Qualification and remaining boundaries

On dev-ikons:

  • Sign-in: alice and bob sign in through the AAI in Chromium, which trusts only the AAI CA, and land on the dashboard (dx/common/scripts/service-login.sh themelio-compat).
  • Waldur: the bootstrap reports FEDERATED_IDENTITY_SYNC_ENABLED has been set to True, and the web syncs alice and bob into Waldur on sign-in. The check requires the setting on every dev box.
  • GitLab: alice and bob are GitLab users with the openid_connect identity.

Not exercised: a first sync of a user Waldur does not yet know, action execution (spaces, inference services, Slurm jobs), egress isolation, fresh-VM and reboot qualification, and other dev boxes.

Page source

Source snapshot · Revision f928834c8.