Shared mechanism for metalayerlab interceptors — a policy-configurable async middleware pipeline, the layered settings loader, Secret values, and Prometheus text exposition.
Every metalayerlab interceptor (mitm-proxy, sluice) needs the same mechanism, and copies of it drifted, so it lives here:
- Pipeline (v0.1.2): the middleware pipeline core, with per-project and per-middleware failure policy.
- Settings and secrets (v0.1): each setting declared once, read from a
_FILEvariable, the environment, a YAML file or its default, and typed strictly, with theSecrettype that keeps secrets out of logs. - Metrics (v0.1.1): Prometheus text exposition with declared label sets.
Pin a release tag (interpose isn't on PyPI):
uv add "interpose @ git+https://github.com/metalayerlab/interpose@v0.1.0"from pathlib import Path
from interpose.settings import Setting, Settings, one_of, port
SETTINGS = Settings(
"MYAPP_",
(
Setting("log_level", "INFO", "Log level.", check=one_of("DEBUG", "INFO", "ERROR")),
Setting("listen.port", 8080, "Port to listen on.", check=port),
Setting("upstream.token", "", "API token.", secret=True),
Setting("allow.hosts", "", "Hosts to allow.", is_list=True),
),
default_path=Path("/etc/myapp/config.yaml"),
)
r = (
SETTINGS.resolve()
) # MYAPP_<KEY>_FILE > MYAPP_<KEY> > $MYAPP_CONFIG or the default path > default
r.values["listen.port"] # 8080, an int; a YAML 0.5 or true is a ConfigError
r.sources["listen.port"] # "default", "file", "MYAPP_LISTEN_PORT" or "MYAPP_LISTEN_PORT_FILE"
r.values["upstream.token"] # Secret('********'); .reveal() gives the value
r.values["allow.hosts"] # ("example.org", ...) from a YAML list or "a, b"The full walk-through is in the wiki's Quick Start.
Everything is in the wiki. Its source is docs/wiki/, in this
repository, reviewed with the code.
- Introduction: what it is and how it works
- API Reference: the public API
- Troubleshooting and FAQ
- Contributing and Release Process
Built with AI assistants; every change gets human review. AGENTS.md and .agents/stack.md are the only instruction files (stack, commands, rules, definition of done, docs map). Read them instead of this README.
| Assistant | Entry point |
|---|---|
| Claude Code | CLAUDE.md (imports both) + .claude/settings.json |
| Codex, Cursor, Copilot coding agent | AGENTS.md, natively (Copilot, Cursor pointers) |
| Gemini CLI | GEMINI.md (imports both) |
| Chat without repo access | docs/ai/prompts.md, "Context for a chat assistant" |
Humans: kick-off prompts are in docs/ai/prompts.md, and the review checklist in docs/ai/review-checklist.md.
uv sync # Python >= 3.13, dev tools included
uv run pytest # tests (80% coverage floor)
uv run ruff check && uv run mypy # lint and type checkNew project? Fill in .github/repository.toml (the description, homepage = the wiki, topics), then run
python3 scripts/repo-metadata.py to set GitHub's About box from it; CI warns when the two drift.
The workflow is: a branch, Conventional Commit PR titles, squash merge. Releases are automated by release-please. See Contributing.
This project was generated from template-base and template-python. Template fixes arrive as a weekly Template update PR per template.
Released into the public domain under the Unlicense.