This document consolidates the fixes and improvements needed to bring this repository closer to a state-of-the-art, production-grade open source Python library.
- This list is based on a repository scan focusing on:
- packaging/metadata (
pyproject.toml,setup.py,requirements.txt) - CI workflows (
.github/workflows/*) - a set of core runtime modules (
apilinker/core/*) and README/doc entry points
- packaging/metadata (
- It is not a formal security audit and does not replace SAST/DAST, dependency scanning, or pentesting.
- Treat each section as an issue/PR checklist.
- The recommended approach is to do this in small PRs in the order in the “PR plan” section.
- Dependency conflict:
pydanticrequirement differs betweenpyproject.toml(v2) andrequirements.txt(v1). This can cause runtime breaks depending on install method. - Packaging duplication: project metadata and dependencies are duplicated across
pyproject.tomlandsetup.py, increasing drift risk. - Docs split-brain: repo contains both MkDocs and Sphinx configurations; deployment uses MkDocs, while
requirements.txtincludes Sphinx. This creates confusion, heavier installs, and likely stale docs.
- HTTP calls without explicit timeouts in core modules (risk of hangs).
- Broad exception handling in many modules; some failures are swallowed or lose context.
- Problem:
setup.pyduplicates project metadata and dependencies. - Fix:
- Preferred: remove
setup.pyentirely and rely onpyproject.toml/setuptools build backend. - If you must keep it: convert
setup.pyinto a minimal shim that reads metadata frompyproject.toml(do not duplicate deps).
- Preferred: remove
pip install .andpython -m buildproduce the same metadata regardless of install method.- Only one file defines dependencies and versioning for distribution.
- Problem:
requirements.txtconflicts withpyproject.toml(pydantic>=1.10.2vspydantic>=2.0.0). - Fix:
- Decide on one:
- If the codebase uses Pydantic v2 (you already use
ConfigDict), align everything topydantic>=2. - Otherwise, downgrade code usage to v1 and pin
pydantic<2.
- If the codebase uses Pydantic v2 (you already use
- Update
requirements.txtaccordingly or remove it entirely.
- Decide on one:
- Prefer Pydantic v2 and remove
requirements.txt(or make it a thin developer convenience that delegates to extras).
- Problem: optional feature groups exist (
mq,webhooks,docs) butrequirements.txtincludes optional stacks (Sphinx + OpenTelemetry + cloud SDKs + MQ libs), which is heavy and confusing. - Fix:
- Ensure all optional dependencies live under
project.optional-dependencies. - Avoid a root-level requirements file that installs everything.
- Ensure all optional dependencies live under
- Observation: version is managed across multiple files via
.bumpversion.toml. - Fix:
- Keep
.bumpversion.tomlas authoritative for “where version exists”, but ensure:- docs don’t hardcode old versions in narrative text
- URL casing and canonical name are consistent
- Keep
- Problem: MkDocs is deployed (
mkdocs gh-deploy) while a full Sphinx setup also exists. - Fix options:
- Option A (recommended): Keep MkDocs only.
- Remove Sphinx from default requirements.
- Either delete
docs/sphinx_setup/or clearly mark it deprecated.
- Option B: Keep Sphinx only.
- Remove MkDocs workflow and
mkdocs.yml.
- Remove MkDocs workflow and
- Option A (recommended): Keep MkDocs only.
- There is exactly one official docs build pipeline.
pyproject.toml“Documentation” URL points to the actual deployed docs.
- Problem: documentation URL differs between
pyproject.toml(ReadTheDocs) and README (GitHub Pages). - Fix:
- Choose the canonical docs URL and use it everywhere:
pyproject.toml- README
- CITATION.cff (if needed)
- Choose the canonical docs URL and use it everywhere:
- Problem: built docs directories (
site/,_build/) should not be tracked. - Fix:
- Ensure these directories are not committed.
- Keep
.gitignoreentries for them.
- Problem: current README shows a minimal worker loop but lacks production guidance.
- Fix:
- Add a “Production notes” section:
- graceful shutdown (SIGTERM handling)
- configuring log level/format
- DLQ location and retention
- recommended broker-native DLQ features (RabbitMQ DLX, SQS redrive, Kafka DLT)
- Add a “Production notes” section:
apilinker/core/auth.py: useshttpx.post(...)without explicittimeout=.apilinker/core/monitoring.py: useshttpx.Client()without configured timeouts.
- Introduce a shared, configurable default timeout (e.g., via config or constants).
- Ensure every call uses one of:
httpx.Client(timeout=...)httpx.post(..., timeout=...)
- No
httpx.*call occurs without explicit timeout.
- Problem: modules create new
httpx.Client()inside methods (monitoring) and direct module-level calls (httpx.post). - Fix:
- Use reusable clients where appropriate.
- Allow injecting a client/session in integrations (PagerDuty/Slack) to facilitate testing and resource reuse.
- Broad catches (
except Exception) appear in many core modules. - Some code paths explicitly
passon errors (e.g., best-effort provenance writes, router predicate failures, JSON parsing fallback).
- Replace broad catches with narrower ones where possible.
- Where broad catches are needed:
- log with
exc_info=True - include structured context (operation type, endpoint, message_id)
- define the policy: retry / DLQ / fail-fast
- log with
- Protocol method stubs should use
...instead ofpass. JsonMessageSerializer.loadsshould not silently coerce invalid JSON to string without at least debug logging.MessageRouter.routeshould log when predicates raise exceptions (currently it silently continues).MessageWorker.runusestime.sleep(...)which cannot be interrupted until sleep ends.
- Change Protocol stubs to
.... - Add debug logs for JSON decode failures and predicate exceptions.
- Consider implementing an interruptible sleep helper (sleep in small increments and check
stop_event).
- Observation:
JWTVerifier.verifyusesjwt.decode(..., options={"verify_signature": True}). - Risk: issuer/audience handling is defined but not clearly enforced via standard PyJWT parameters (this may be correct or may be incomplete depending on PyJWT version).
- Fix:
- Ensure verification includes:
- issuer (
issuer=) when configured - audience (
audience=) when configured - algorithm allowlist is enforced
- expiration/nbf validation behavior is explicit (defaults may vary)
- issuer (
- Ensure verification includes:
- Observation: secret management module is extensive.
- Fixes / checks:
- Ensure no secrets are ever logged.
- Consider adding redaction utilities for logs.
- Ensure environment-variable fallback does not inadvertently encourage storing secrets in plaintext files.
- Add CI steps/tools (choose based on your preferences):
pip-audit(dependency vulnerabilities)bandit(basic static checks)- GitHub Dependabot configuration
- Current: black, flake8, mypy, pytest with coverage threshold.
- Add:
- dependency vulnerability scan (
pip-audit) ruff(optional) as a faster linter (if you want to modernize)- build/test of sdist/wheel install to ensure packaging works
- dependency vulnerability scan (
- Observation: coverage omits many modules (security, scheduler, async connector, secrets, observability, webhooks).
- Risk: you may ship untested core behavior.
- Fix:
- Reduce omit list over time.
- If modules are truly optional, split them behind extras and conditionally test them.
- Ensure README snippets and key examples execute.
- Suggested approach:
- doctest-style tests for README code blocks (or curated snippets)
- minimal integration tests for message queue pipeline with dummy connectors (already present)
- Problem:
.gitignorelists multiple root markdown files suggesting internal/review artifacts. - Fix:
- Either:
- move them into
docs/developer-guide/and track them, or - delete them and stop generating them.
- move them into
- Either:
- Ensure
build/,dist/,site/, and Sphinx build outputs are not tracked.
- Fix
pydanticmismatch. - Decide the fate of
requirements.txt. - Ensure
pyproject.tomlis authoritative.
- Choose MkDocs vs Sphinx.
- Align documentation URLs.
- Remove stale configs/artifacts.
- Add explicit timeouts everywhere.
- Add reusable clients / injection points for monitoring integrations.
- Replace broad exception catches where possible.
- Add structured logging in critical swallow points.
- Protocol stubs
.... - Logging for router predicate exceptions and serializer decode errors.
- Interruptible sleeps for graceful shutdown.
- Add
pip-auditand optionallybandit. - Add Dependabot config.
- Docs: do you want to officially support MkDocs or Sphinx?
- Pydantic: commit to v2 everywhere, or downgrade to v1?
- Public API stability: which modules/classes are considered stable and supported (e.g. message queue connectors)?
- Resolve
pydanticversion conflict across installation methods - Remove duplicated packaging metadata (
setup.pyvspyproject.toml) - Consolidate docs pipeline (MkDocs vs Sphinx) and remove the other
- Add explicit
httpxtimeouts everywhere - Introduce consistent error handling policy (retry/DLQ/fail-fast) and logging
- Improve
message_queue.pyobservability (router/serializer) - Improve graceful shutdown responsiveness in
MessageWorker
- Changelog ordering and conventions
- Align project naming/URLs across docs and metadata
- Add security scanning in CI