Task · TSO-0097

Decide precedence between env-supplied secrets and their _file siblings

Description

resolveSecretFiles records a conflict whenever a secret value and its “*file” sibling are both set, and Validate then hard-fails with “set only one, not both (value XOR file)” (internal/config/secretfile.go:108, internal/config/validate.go:979-980). applyTailnetEnvOverlays runs before that (internal/config/config.go:1911-1913), so a secret supplied through the documented TS2OTEL env convention collides with a client_secret_file that a chart or compose template wrote, and the process refuses to start.

This is a genuine design fork, not an obvious bug. The repo layering rule is defaults < YAML < environment, which argues env should win. The value-XOR-file rule is a deliberate guard against ambiguous credential sources, which argues the error is correct. TSO-0079 made it more reachable by expanding env injection to list-valued credentials.

Decide and document: either exclude env-overlaid entries from the conflict set so environment wins consistently with every other key, or keep the hard failure and make its message name the environment variable that caused it, so an operator can see which layer supplied the colliding value. Found by the post-Wave-3 sharded CodeRabbit pass.

Acceptance Criteria

Definition of Done

Implementation Plan

Implementation Notes

Final Summary

Kept security-preserving value-XOR-file refusal and made collisions name the exact environment variable and file source without exposing values. Added the missing Kubernetes-audit object-store file-secret resolution; focused tests, final review and the full gate passed.

View the source file on GitHub