feat: add date-anchored default editions @osterman (#2762)
## what- Add date-anchored
edition:defaults, the--editionoverride, andatmos describe/list editioncommands. - Journal default changes and add config, CLI, docs, snapshot, and cast coverage for edition-aware behavior.
- Make describe component/dependents honor graceful YAML error handling without requiring implicit identity authentication.
why
- Let projects upgrade Atmos without silently adopting later default changes, while giving operators visibility into effective defaults.
- Avoid duplicate post-auth error output and let component inspection continue when recoverable YAML values cannot resolve.
references
- N/A
Summary by CodeRabbit
-
New Features
- Added experimental date-pinned configuration editions via
--edition,ATMOS_EDITION, oratmos.yaml. - Added
describe editionandlist editionscommands for inspecting default changes. - Added component mock support with
--use-mocks. - Added configurable component filtering, provenance display, error handling, and help filtering.
- Added experimental date-pinned configuration editions via
-
Bug Fixes
- Improved table sizing, terminal wrapping, whitespace, tree output, authentication handling, and validation exclusions.
- Preserved clearer error details and prevented unintended authentication attempts.
-
Documentation
- Added documentation and examples for editions and updated command and configuration references.
refactor(store): move backends into pkg/store/providers subpackage @osterman (#2575)
## what- Move the concrete store backend implementations (AWS SSM, Azure Key Vault, Google Secret Manager, Redis, Artifactory) out of
pkg/storeinto a newpkg/store/providerssubpackage, keepingpkg/storeas a pure interface/type boundary (theStoreinterfaces,StoreConfig/StoresConfig/StoreRegistrytypes, auth-config types, error sentinels, and generated mocks). - Introduce a self-registering registry:
pkg/storeownsStoreRegistry,NewStoreRegistry, and aRegister(type, factory)API; each backend registers its factory from aninit(), so the typeswitchis replaced by a map lookup.pkg/configblank-importspkg/store/providersso the built-in backends register at startup (database/sql driver pattern). - Update call sites and add a
pkg/store/providersexclusion to theprovider-agnostic-authdepguard rule so its cloud-SDK imports are permitted (matchingpkg/auth/providers).
why
- Isolates the cloud-SDK-heavy backend code from the store contract, mirroring the established
pkg/auth/providers/pkg/secrets/providerslayout and makingpkg/storea clean type/interface package. - The registry pattern removes the awkward split where the factory lived under
providersbut was named after theStoreRegistrytype it returned;pkg/storenow owns both the registry type and its construction, and adding a backend is one self-contained file that registers itself. - No user-visible change: identical store types resolve, unknown types still return
ErrStoreTypeNotFound, identity warnings are preserved. Builds clean, all affected tests pass, andgolangci-lint --new-from-rev=origin/mainreports zero issues.
references
- N/A
Summary by CodeRabbit
- New Features
- Storage backends now use a consistent registration model, improving support for configured providers and aliases.
- Bug Fixes
- Improved handling of missing configuration, invalid values, authentication failures, access errors, and unavailable data.
- Tests
- Expanded coverage for provider validation, key behavior, error scenarios, and concurrent registry operations.
- Documentation
- Clarified storage registry configuration in the schema.
- Chores
- Improved CI reproducibility and license-report generation.
feat(toolchain): add --format=plain/json to atmos toolchain get @osterman (#2845)
## what- Adds a
--formatflag toatmos toolchain getwith three modes:table(default, unchanged),plain(bare version string only), andjson(structured output with tool/version/installed fields, or a full version list under--all). - Routes the new
plain/jsonoutput through the data channel (stdout, pipeable) instead of the styled UI channel (stderr), via newprintVersionsPlain/printVersionsJSONhelpers inpkg/toolchain/get.go. - Rejects
--format=plaincombined with--allwith a newErrToolchainPlainFormatWithAllFlagsentinel, since there's no single version to print in that case. - Adds a changelog post and links it into the toolchain roadmap milestone.
why
- Extracting a tool's version in scripts/CI previously required regex-scraping the human-styled table output (checkmark indicator, ANSI colors,
2>&1since it's written to stderr), e.g.atmos toolchain get vale-cli/vale 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1. --format=plaincollapses that toversion=$(atmos toolchain get vale-cli/vale --format=plain), and--format=jsongives scripts structured access to installed status without adding a new dependency.
references
Summary by CodeRabbit
- New Features
- Added table, plain, and JSON output formats to
atmos toolchain get. - Added
--format/-f, environment-variable support, and shell completion. - Plain output provides version strings; JSON provides structured tool and installation details.
- Added table, plain, and JSON output formats to
- Bug Fixes
- Added validation for unsupported formats and incompatible
--alland plain output options.
- Added validation for unsupported formats and incompatible
- Documentation
- Updated command documentation, scripting examples, and roadmap information.
🚀 Enhancements
fix(scaffold): resolve relative write-target directories consistently @osterman (#2855)
## what- Fixes
atmos scaffold generateso a relative target directory (e.g. the CLI's own default./my-project) works, instead of rejecting every file withpath traversal not allowed. validateWriteTargetinpkg/generator/engine/templating.gonow resolves the write directory (realDir) through the sameResolveAndCleanBasePathhelper already used for the target base (realBase), instead of a barefilepath.EvalSymlinksthat stays relative for relative inputs.- Adds a regression test,
TestProcessFile_RelativeTargetPath, covering a relativetargetPathend-to-end (previous tests only exercised absolutet.TempDir()targets, so this case was never caught).
why
realBasewas always absolutized before comparison, butrealDirwas resolved with a barefilepath.EvalSymlinks, which returns a relative path unchanged when given a relative input. Comparing an absolute path against a relative one never matched the containment check, so it fired as a false-positive path traversal on every write whenever the target directory was relative — including the command's own default target.- Absolute targets happened to work only because
filepath.Dir(fullPath)was already absolute in that case, masking the bug.
references
- Closes #2851
Summary by CodeRabbit
-
Bug Fixes
- Fixed file generation for relative target paths, such as
./my-project. - Improved path resolution while preserving containment and symlink safety checks.
- Fixed file generation for relative target paths, such as
-
Tests
- Added coverage confirming generated files are written to the expected destination with the correct content.