feat: initial release — env decoder extracted from ai-fabric

Public API:
- Unmarshal(dst, opts...)
- UnmarshalPrefix(dst, prefix, opts...)
- AsMap() / AsMapPrefix(prefix)
- Options: WithTrim, WithWeaklyTyped, WithTagName, WithDecodeHook

Merges three divergent in-repo copies (ai-fabric/pkg/env,
markets-platform/TP-general-code/pkg/system, and the var/agents/issue-*
snapshots), adds error wrapping, prefix filter, and pluggable hooks.

15 pure-Go unit tests, no synthetic mocks, lint clean.

Extracted per inventar/docs/asr/ASR-0008-ai-fabric-audit.md.
This commit is contained in:
2026-04-24 13:41:13 +01:00
commit 288a5b600c
13 changed files with 714 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
// Package env reads process environment variables and decodes them into
// Go structs using underscore-delimited paths.
//
// A variable named "SERVICE_HTTP_PORT" becomes the path Service.HTTP.Port
// (case-insensitive, '_' is a path separator). Values are decoded via
// github.com/mitchellh/mapstructure, so numeric, boolean and slice
// conversions happen automatically.
//
// var cfg struct {
// Service struct {
// HTTP struct {
// Port int
// }
// Key string
// }
// }
// if err := env.Unmarshal(&cfg); err != nil { ... }
//
// UnmarshalPrefix ignores variables that don't start with the given
// prefix and strips it before building the path:
//
// _ = os.Setenv("APP_DB_HOST", "localhost")
// _ = env.UnmarshalPrefix(&cfg, "APP_")
// // cfg.Db.Host == "localhost"
//
// String values are TrimSpace-trimmed by default; pass WithTrim(false) to
// opt out.
package env