Repository navigation
Introduction
The mechanism metalayerlab's interceptors would otherwise each copy. mitm-proxy (an HTTP/TLS proxy) and sluice (a FUSE filesystem) were generated from the same template, and each got its own copy of the settings engine in a project-owned config.py. Template fixes never reached those copies, and they drifted: the same YAML value was coerced three different ways, two of them silently wrong. interpose holds one engine, and a fix reaches every consumer as a version bump.
It holds mechanism, not policy. A project keeps its own settings, its Config dataclass and its rules that span settings. interpose never touches transports (HTTP, TLS, FUSE): it renders the metrics text, and the project serves it.
| Version | What |
|---|---|
| v0.1 |
interpose.settings (the layered settings engine) and interpose.secret (Secret, read_secret_dir) |
| v0.1.1 |
interpose.metrics: Prometheus text exposition with declared label sets (design 0002) |
| v0.1.2 |
interpose.pipeline: the middleware loop and per-project, per-middleware failure policy (design 0003) |
A project declares its settings once, as Setting(key, default, help, ...) entries in a Settings object bound to its environment-variable prefix and default config path. Settings.resolve() reads the YAML file, then gives every setting the first value found in this order:
-
<PREFIX><KEY>_FILE: a file holding the value (Docker and Kubernetes secrets) -
<PREFIX><KEY>: an environment variable - the YAML file (
<PREFIX>CONFIG, else the default path) - the declared default
The default's type is the setting's type, and coercion is strict: a YAML 0.5 for an int setting is an error, not 0. A section setting (is_section=True) takes a whole YAML subtree instead, such as per-middleware options, frozen as a read-only Section for the project to validate. The result, Resolved, holds the typed values and where each came from. A secret=True setting comes back as a Secret, which prints as ******** until reveal() is called. The same declarations generate each project's wiki settings table. The rules are on Architecture Internals.
- Outside metalayerlab's own projects. It isn't on PyPI, and its API is shaped by its consumers' needs. For general use, pydantic-settings or dynaconf do more.
- Float or per-request settings. Values are str, int, bool, a list of strings or a section, read once at startup. A section is free-form: interpose checks only that it is a mapping with string keys, and the project validates what is in it. A list section may declare its items' fields, which interpose types as settings.
-
Rules between settings (two settings set together or not at all). Write those in the project's
load_config, afterresolve().
interpose | Shared mechanism for metalayerlab interceptors — a policy-configurable async middleware pipeline, the layered settings loader, Secret values, and Prometheus text exposition.
GitHub • Releases • Issues • Changelog • Contributing
This wiki is generated from docs/wiki/ on every push to main: edits made here are overwritten. Change it with a pull request.
- 🧅 One middleware loop; fail open or closed is policy, per project and per middleware
- 🥞 One lookup order:
_FILE> environment > YAML > default - 🧱 Strict types: no silent
0for a YAML0.5 - 🧭 Where each value came from, for every setting
- 🔒
Secret: masked in logs, reprs and errors - 📈 Prometheus text with labels from declared value sets