Conversation
Files that embed age ciphertext as base64 values, plain or zstd-compressed, are now recognized as encrypted, in any text format. This is how mise stores age-encrypted environment variables. As with sops, the path rules don't apply to such a file, the ciphertext values are skipped, and the rest of the file is still scanned. Detection decodes each value, so no tool is named. The secrets guide now covers syncing secrets encrypted with the tool you already use (mise, sops or age), consuming them as environment variables, using one key per person, and rotating secrets if the key leaks. The mise guide no longer says a missing key fails silently: mise errors unless age.strict is false. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
dotsync should work alongside whatever tools people already use (mise, GNU Stow, sops and others), so it recognizes encrypted formats and never names a tool.
cipherFormats: age values embedded in a readable file. A run of base64 counts as ciphertext when it decodes to an age file, either directly or inside a zstd frame. This covers both of the forms mise writes for age-encrypted env vars ({ age = "…" }and{ age = { value = "…", format = "zstd" } }), and it works the same in YAML, JSON and dotenv. Such a file is treated like a sops file: the path rules don't apply, the encrypted values are skipped, and every other line, plus the rest of each value's line, is still scanned. As a result, a file likeconf.d/secrets.toml, ortoken: '<age base64>', now syncs instead of being blocked.cipherFormat.valuesis now a func rather than a regexp, because age values have to be decoded to be recognized.mise set -g --age-encrypt). It also corrects a claim that a missing key fails silently: mise reports an error unlessage.strict=false.dotsync still doesn't encrypt anything itself, and it has no hooks, so "dotsync never runs commands" still holds.
How was this tested?
internal/dotsync/dotsync_test.go): table cases for plain and zstd mise values, dotenv and YAML embeddings, plaintext on the same or other lines, and base64 that isn't age (plain, zstd, fake header).TestEncryptedSecretsSyncInManagedDirectorynow also syncs aconf.d/secrets.tomlholding age values. A mutation check (detector forced to false) makes 10 cases fail.mise set --age-encryptoutput (mise 2026.9.12), both forms. Confirmed that mise decrypts it, and that it errors without a key.go vet,go test -race,gofmtandgolangci-lintare clean, and the docs site builds.website/src/content/docs/updated if behavior changed🤖 Generated with Claude Code