Revision history for Config::Abstraction - Merge and manage configuration data from different sources
0.40 Sun Aug 2 04:37:58 PM EDT 2026
[ Security ]
- Fix YAML code injection: YAML::XS v0.91 ignores $YAML::XS::DisableCode and
materialises callable CODE refs from !!perl/code tags. New private helper
_sanitize_yaml_values() recursively replaces CODE and GLOB refs with undef
after every LoadFile/Load call. Do not rely on DisableCode for security.
- Fix XML external entity (XXE) injection at all four XMLin() call sites: file
content is now pre-read and checked for <!ENTITY ... SYSTEM|PUBLIC declarations
before parsing; XMLin receives a string reference rather than a filename so no
entity is resolved. Files containing external entity declarations are skipped
with a carp warning.
- Fix XXE bypass via Config::Auto fallback: after the XML XXE guard blocked a
file and set $data to undef, YAML::XS returned a non-HASH scalar (truthy),
causing the if(!$data) fallback chain to run; Config::Auto then re-read and
expanded the entity. Fixed by saving raw file content before the parsers run
and conditioning the entire fallback chain on the absence of entity declarations.
- Fix encryption_key_file silent failure: when encryption_key_file was specified
explicitly in the constructor but the named file did not exist, the module
silently fell back to unencrypted operation. The constructor now croaks
immediately. Files sourced from environment variables still fail silently.
[ Performance ]
- _flatten_keys: eliminate O(N^2) hash copying by delegating to new private
_flatten_into helper that writes each leaf key into a caller-supplied
accumulator hashref exactly once; benchmarks show 2x speedup on a 60-leaf
config (20 000 iter/s -> 40 000+ iter/s).
- get()/exists(): cache the compiled sep_char regex as $self->{'_sep_re'} at
construction time instead of recompiling qr/\Q$sep_char\E/ on every key
lookup; benchmarks show ~50% speedup on repeated get() calls.
- _is_local_host(): cache Sys::Hostname::hostname() result on the object
($self->{'_cached_hostname'}) so the syscall is made at most once per
Config::Abstraction instance, not on every directory entry evaluation.
[ Bug Fixes ]
- Fix AUTOLOAD method dispatch using stale $self->{data} (raw constructor
defaults) instead of the fully merged $self->{config}; file and environment
overrides were silently invisible through AUTOLOAD accessor calls.
- Fix AUTOLOAD in flatten mode: Hash::Flatten uses '.' as separator regardless
of sep_char, so the sep_char-separated method name is now translated to dotted
form before lookup in the flat config hash.
- Fix _load_remote_dir using a hardcoded file list that omitted TOML files and
the new environment-specific tiers (base.{env}.* / local.{env}.*); the
dynamic @_file_list is now passed from _load_config to _load_remote_dir.
[ Enhancements ]
- Add Readonly constants for AES-256-GCM sizes ($_AES_NONCE_SIZE,
$_AES_TAG_SIZE, $_AES_KEY_SIZE, $_ENC_PAYLOAD_MIN, $_HEX_KEY_LEN,
$_B64_KEY_MIN, $_B64_KEY_MAX) replacing inline magic numbers.
- Add =head1 LIMITATIONS documenting: separator escaping, Data::Reuse status,
Windows env-var case sensitivity, AUTOLOAD sep_char requirement, and TOML
in remote directories.
- Add full POD (EXAMPLE / API SPECIFICATION / MESSAGES / FORMAL SPECIFICATION /
PSEUDOCODE) to get(), exists(), all(), encrypt_value(), and prefer_*().
- New t/locales.t: geographic (ISO-3166 country-code environment tiers) and
POSIX locale subtests; uses local $! = ENOENT; my $msg = "$!"; idiom to
obtain locale-specific strings without POSIX::strerror.
- Declare CryptX as an optional_features entry in META so installers can prompt
users who want AES-256-GCM encryption support.
- New C<environment> constructor option: activates two additional file tiers --
base.{env}.* (loaded immediately after base.*) and local.{env}.* (loaded
immediately after local.*). When not supplied, auto-detected from
{env_prefix}ENV (e.g. APP_ENV), then PLACK_ENV, then NODE_ENV. Missing
env-specific files are silently skipped; invalid names (anything other than
/^[A-Za-z0-9_\-]+$/) cause a croak.
- New C<validators> constructor option: a hashref mapping dotted config keys to
per-key validation rules. Each rule may be a type-name string (integer, number,
float, boolean, string, array, hash), a compiled regex, a coderef, or a hashref
combining type/pattern/min/max/required constraints. Violations croak immediately
after the merge (or on first access when lazy => 1).
- New C<checker> constructor option: a YAML string or hashref prototype passed to
Config::Checker for template-based structural validation. Config::Checker is
optional; if absent a carp warning is emitted and validation is skipped.
- TOML file support: base.toml and local.toml are now discovered
automatically in config_dirs alongside YAML/JSON/XML/INI equivalents;
TOML is also tried as a fallback parser in the all-parsers chain used
for extensionless config_file entries. Requires TOML::Tiny (TOML 1.0).
If TOML::Tiny is absent the module gracefully skips .toml files.
- New C<lazy> constructor option: when true, all source discovery and file
I/O are deferred until the first accessor call (get/exists/all/explain_sources/
prefer_*/merge_defaults/AUTOLOAD), reducing startup overhead for applications
that may not always consume the configuration. With lazy loading the
constructor always returns a blessed object; schema validation likewise
runs on first access rather than at construction time.
- Remote configuration via the Newcastle Connection convention: entries in
config_dirs beginning with /../hostname/path are fetched from the named
host over SSH using File::Slurp::Remote, processed through the same
format-detection and Hash::Merge pipeline as local files, and merged in
the same position as their equivalent local directory would be
- Local-host short-circuit: /../localhost/, /../127.0.0.1/, /../::1/, and
/../$hostname/ (FQDN and short form, case-insensitive) are unwrapped to
their plain directory path and read from disk directly -- no SSH connection
is made, so a shared config entry degrades gracefully on the host itself
- New dependency: File::Temp (used to parse INI content fetched as a string,
since Config::IniFiles requires a real filesystem path)
- Document the Newcastle Connection convention and the rationale for choosing
the /../ prefix over hostname:/path, file://, ssh://, and plain hostname/path
- Honour $CONFIG_DIRS in the environment
- New public method explain_sources(): returns a hashref keyed by dotted
config key; each value carries the final merged value and an ordered list of
{type, label, value} source records showing every source that contributed to
that key, from lowest to highest precedence
- New public methods prefer_env(), prefer_file(), prefer_data(), prefer_argv():
return the value that a specific source layer contributed to a key, bypassing
higher-precedence sources; fall back to get() when that layer did not set the key
- _load_config() and merge_defaults() now save and restore
Hash::Merge::get_clone_behavior() around their set_clone_behavior(0) calls,
preventing the no-clone global state from leaking into unrelated merge() calls
and fixing a "Can't store CODE items" crash when data contains coderefs
[ Bug Fixes ]
- merge_defaults() was permanently mutating $self->{'config'} via
'delete $config->{global}'; fixed by working on a shallow copy
- Windows: skip Newcastle Connection localhost subtest when tempdir() returns
a drive-letter path (C:\...) that cannot be embedded in /../localhost$dir
- Windows: skip unreadable-file subtests in extended_tests.t where
chmod(0000, $file) is a no-op and files remain readable
0.39 Sun May 24 16:16:50 EDT 2026
[ Bug Fixes ]
- Don't use fixate for now, what works on Linux doesn't work on MACOS
and vice versa. I don't know why.
0.38 Wed May 20 21:46:58 EDT 2026
[ Enhancements ]
- Document the "defaults" argument to new()
[ Bug Fixes ]
- Fix fatal croak on malformed or degenerate YAML/JSON files in config_dirs;
parse failures now warn and skip the file rather than aborting construction,
consistent with existing XML and INI error handling
- Fix corruption of coderefs and blessed objects passed via the 'data' argument;
added _is_plain_scalar() guard to skip non-string scalars in the YAML colon-file
value-munging loop, and fixed Data::Reuse::fixate() being called with a
dereferenced hash instead of a hashref in get()
- Fix Data::Reuse::fixate() crash in get() by passing hashref scalar directly
rather than dereferencing, and guard against double-fixation with !tied check
- Fix exists() to return explicit 0 rather than empty string in flat mode
- Fix circular initialisation crash when logger option is provided:
Log::Abstraction is now bootstrapped directly in new() rather than
via _load_driver(), which would attempt to use the logger before
it was fully set up
0.37 Mon Dec 1 07:43:07 EST 2025
Only use Data::Reuse if it's installed - its installation often fails
Added the --version option to config-dump
0.36 Wed Oct 15 08:12:49 EDT 2025
Ignore files that don't parse
Added the exists() method
0.35 Mon Oct 13 18:38:37 EDT 2025
Bump some minimum versions - GitHub#6
Fix remote possibility where STDERR could close if Config::Abstract dies
0.34 Fri Sep 5 08:37:21 EDT 2025
Added bin/config-dump
If schema is passed in, validate the config file against it
0.33 Thu Jul 17 08:19:41 EDT 2025
The config_path value wasn't being stashed properly
0.32 Wed Jun 18 14:47:07 EDT 2025
Bash doesn't allow colons in variable names, so use _ everywhere
0.31 Tue Jun 17 14:52:57 EDT 2025
Fix GitHub#4
0.30 Thu Jun 5 15:30:25 EDT 2025
Try harder to ensure the running script isn't loaded as its own configuration
Test argv and note that argv now need to start with --
0.29 Mon May 26 20:55:38 EDT 2025
Also look in ${script_name}.cfg, ${script_name}.conf and ${script_name}.config
Allow new() to accept just one parameter - the name of a file
0.28 Sat May 24 09:00:10 EDT 2025
Look in the current directory, unless given an absolute path
0.27 Fri May 23 17:04:52 EDT 2025
Look in generic DOCUMENT_ROOT/../conf before site specific DOCUMENT_ROOT/conf
Added the level argument to new()
Look in the current directory
0.26 Fri May 16 21:10:49 EDT 2025
Change location of bug reports to RT
Bumped minimum version of XML::PP (GitHub#1 - ANDK)
Turn off clone behavior
0.25 Thu May 15 07:57:07 EDT 2025
Added the 'merge' option
Improved the documentation of the merge_defaults routine
0.24 Mon May 12 16:15:09 EDT 2025
Added the 'no_fixate' option
0.23 Mon May 12 12:01:49 EDT 2025
Fix tests on machines that have configuration files installed elsewhere
Look in more places for the config files, when config_dirs is not given
Consider $script_name for configuration data as well
'file' means 'config_file'
0.22 Fri May 9 14:31:28 EDT 2025
Fix CI tests
0.21 Fri May 9 13:55:23 EDT 2025
Handle YAML crashes on reading an INI file
0.20 Tue May 6 20:07:40 EDT 2025
Added merge_defaults()
0.19 Tue May 6 13:48:46 EDT 2025
Make the data passed to the contructor be the default values
0.18 Tue May 6 08:17:31 EDT 2025
Use the file config_dirs/default as the base
Honour CONFIG_DIR
0.17 Mon May 5 07:45:21 EDT 2025
Try harder to find the files
0.16 Thu May 1 07:25:25 EDT 2025
Handle mixed case environments a bit better
0.15 Tue Apr 29 20:24:10 EDT 2025
Makefile.PL: Prefer XML::PP, since XML::Simple can have loading problems on Windows
Improved the fallback to Config::Auto when XML::Simple isn't working
new() now fails, silently, if there's no config file
Use Config::Abstract to load .pl files, but note RT#164587
0.14 Mon Apr 28 11:17:20 EDT 2025
Allow logger to be an array ref
Fail more gracefully
Fall back to XML::PP if XML::Simple can't be loaded
Config_path is now a list
0.13 Tue Apr 22 15:08:00 EDT 2025
Added the data option to new()
sep_char option to new() wasn't being remembered
Added AUTOLOAD support
Fix typo - 'durs' should read 'dirs'
0.12 Mon Apr 21 10:29:54 EDT 2025
Allow environment variables to use '::' to separate fields
0.11 Mon Apr 21 08:56:35 EDT 2025
Make the environment variable override simpler for simple cases
0.10 Sun Apr 13 21:45:12 EDT 2025
Check with JSON::Parse first
Use Data::Reuse, but note RT#100461
Note the filetype
0.09 Sat Apr 12 15:48:48 EDT 2025
Better fix for old Perls
0.08 Sat Apr 12 10:59:22 EDT 2025
Fix code on older Perls
0.07 Thu Apr 10 19:40:41 EDT 2025
Change the default for config_dirs to $HOME/.conf, $DOCUMENT_ROOT/conf, ./conf
In YAML files, split comma separated entries
Honour path as well as config_dirs
0.06 Wed Apr 9 08:30:55 EDT 2025
Put the paths used to load the configuration file into config_path
Only load the modules that are needed
Improved logging of errors
Added _load_driver
0.05 Tue Apr 8 09:50:15 EDT 2025
Added tests for all()
Added the logger option to new()
Added the config_files option
0.04 Mon Apr 7 21:06:26 EDT 2025
Better handling of config_file mode when an XML file is missing its header
Handle more drivers
Added the sep_char option
0.03 Mon Apr 7 16:22:16 EDT 2025
Use Params::Get
Needs Test::Most
Improved handling of XML files
0.02 Mon Apr 7 12:50:34 EDT 2025
Added config_file option
0.01 Mon Apr 7 11:45:31 EDT 2025
First draft