NOTICE: All information contained herein is, and remains
the property of TechnoCore Automate.
Updated : 2026-03-19
ConfigIni is the central configuration manager for
Axion. It loads hierarchical YAML configuration from
config.yaml with package-specific overrides, variable
substitution, and optional secret backends (Infisical,
AWS Secrets Manager).
No longer inherits from ConfigParser — it is a
standalone class that reads YAML directly.
Get(section, option, default) resolves values in
this order:
config.yaml → <package>.<section>.<option>config.yaml → base.<section>.<option>Steps 2-5 are skipped when yaml_only=True.
package: homechoice
base:
smtp:
server: smtp.example.com
port: 587
ai:
default: mcp:ollama:mistral
terraform:
mariadb:
username: tf_user
password: tf_password
homechoice:
database:
active: primary
connections:
primary:
host: db.example.com
user: app
password: secret
db: mydb
smtp:
server: smtp.homechoice.com
| Variable | Resolves to |
|---|---|
$package$ |
Active package name |
$dns$ |
<package>.domain.dns value |
$terraform$ |
terraform.<section>.<option> |
$environment_KEY$ |
AXION_KEY env variable |
Set AXION_YAML_ONLY=true to bypass all secret
backends and run purely from config.yaml:
export AXION_YAML_ONLY=true
python ServeReport.py
All Infisical/AWS calls are skipped. Useful for
local development, testing, and debugging.
All Get() results are cached in _get_cache dict.
Call clear_cache() to invalidate.
Secrets fetched from Infisical are cached in
infisical_cache with a 3600-second TTL. Expired
entries trigger a live API call.
When both Infisical and AWS are down, the disk cache
(data.config/secrets_cache.yaml) serves values.
The cache is encrypted with the reference package
key and loaded once into memory.
Seed the cache:
ini.seeddisk_cache() # Infisical → disk
ini.seed_awsdisk_cache() # AWS → disk
Enabled when base.infisical.enabled: true and
valid credentials are configured. Uses Universal Auth
(Machine Identity).
base:
infisical:
enabled: true
host: https://app.infisical.com
client_id: xxx
client_secret: xxx
Auto-migration: In UAT deployment, config.yaml values
are automatically created in Infisical on first read.
Fallback when Infisical is unavailable. Stores one
JSON blob per project slug.
Retrieve a config value. Handles:
$terraform$ / $package$ / $dns$ substitutionReturns database connection config dict with
host, user, password, db, type, collation.
Tries new nested connections format first, falls
back to flat <name>ip, <name>user format.
Retrieve a named secret from Infisical or AWS.
Invalidate the Get() result cache.
Print to console with ⚙️ config | prefix, only
when DO_DEBUG=True.
_NOT_LOADED for$ check before_apply_substitutions_deep_merge — not recreatedloaded flagshortuuid — imported only when terraform| Test File | Tests | Coverage |
|---|---|---|
test_ConfigIni_configtest.py |
81 | Package resolution, base fallback, overrides, substitutions, terraform, value types, caching, missing package, edge cases |
test_ConfigIni_cache_infisical.py |
26 | In-memory cache, disk cache fallback, save/load roundtrip, fallback chain, Infisical integration |
test_ConfigIni_yaml_only.py |
23 | Live config.yaml with yaml_only mode |
test_config_migration.py |
10 | Keycloak/Encryption use get_ini_value |
# Run all ConfigIni tests
pytest resource.test/pytests/factory.core/test_ConfigIni*.py -v
# Run with configtest.yaml only
pytest resource.test/pytests/factory.core/test_ConfigIni_configtest.py -v
The annotate CLI command rewrites config.yaml with
human-readable descriptions, unique package GUIDs, and
public encryption keys embedded.
# Annotate config.yaml in place
python factory.core/ConfigIni.py annotate
# Write to a different file
python factory.core/ConfigIni.py annotate --output /tmp/preview.yaml
What it adds:
guid (UUID4) per package section for integration verificationpublic_key from data.config/<package>_public.pem (public key only, safe to share)All existing values are preserved exactly.
Descriptions are loaded from:
resource.config/config_descriptions.yaml
This file maps config paths to one-line descriptions:
base.mqtt: MQTT — real-time message broker for event streaming, logging, and IoT
base.mqtt.host: MQTT broker hostname
base.mqtt.port: MQTT broker port (8886=TLS, 1883=plain)
IMPORTANT: Update config_descriptions.yaml every time a new
integration, service, or config section is added to config.yaml.
Then run python factory.core/ConfigIni.py annotate to regenerate
the annotated output.
Axion deployment names are mapped to Infisical environment
slugs. Infisical has three environments: live, uat, sim.
| Axion Deployment | Infisical Environment |
|---|---|
dev |
uat |
development |
uat |
staging |
uat |
uat |
uat |
sim |
sim |
prod |
live |
production |
live |
live |
live |
Unknown deployment values default to uat.
The infisical command runs a full write/read/delete cycle
using the package GUID from config.yaml as the test value:
# Test active package
python factory.core/ConfigIni.py infisical
# Test specific package
python factory.core/ConfigIni.py infisical --package-name gekko
The test performs 5 steps:
AXION_INTEGRATION_TEST_<PACKAGE>guid:<package_guid>Requires annotate to have been run first (to generate
package GUIDs).
encrypt(), decrypt(), and has_public_key() create an
ObjEncryption(DB=-1) instance. The DB=-1 parameter is
critical — using DB=0 causes an infinite connection loop
because ObjEncryption.__init__ calls connect_db() which
calls ConfigIni.decrypt() again.
Objects.py — get_ini_value() wrapperObjData.py — self.get_ini_value() on all objectsObjConstants.py — ConfigIniConstantsresource.config/config_descriptions.yaml — config annotation descriptionsresource.notes/encryption.md — key managementUpdated : 2026-03-31