HydraIssues

hydraorganization holds full-power admin tokens for services it only ever reads
open improvement Project: hydracluster Reporter: cederik 1 Sep 2026 09:58

Description

PROBLEM

The org dashboard (#597) is a backend-for-frontend: it reads four services server side and never exposes a credential to the browser. Two of those credentials are full admin tokens because neither service offers a read scope.

  • hydracluster admin token. hydraorganization calls only GET /api/v1/heads and GET /api/v1/nodes. hydracluster does define a read-only token (pkg/api/readonly.go, requireAdminOrReadOnly) but it covers /api/v1/nodes only, not /api/v1/heads, so the admin token is required for the pair. That same token also authorises the exec transport, which runs commands on every node in the fleet.
  • hydraexperiencelibrary admin token. hydraorganization calls only GET /api/v1/experiences. The same token can promote, retire and DELETE experiences.

hydraorganization issues nothing but GETs today, so this is latent rather than active. It stops being latent the moment that config leaks or a bug turns a read path into a write. Storing a fleet-exec-capable credential in a public-facing web service to render two numbers is more authority than the job needs.

ASK

  1. hydracluster: extend the existing read-only token to cover GET /api/v1/heads, so a dashboard-shaped consumer needs no admin token.
  2. hydraexperiencelibrary: add a read scope, or a second token that can only GET.
  3. Then reissue hydraorganization with the narrow credentials and remove the admin tokens from /srv/scales/hydraorganization/config.yaml.

ACCEPTANCE

  • hydraorganization's config holds no credential that can write to, delete from, or exec on any other service.
  • The dashboard still renders venue fleet counts and experiences with the narrow tokens.
  • The runbook records which scope each token needs, so the next consumer does not reach for admin again.