Skip to content

Releases: modern-python/lite-bootstrap

1.3.2

Choose a tag to compare

@github-actions github-actions released this 19 Jul 15:18
56ba454

lite-bootstrap 1.3.2 — fix lite-bootstrap[litestar] import

1.3.2 is a patch release. Fully backward compatible with 1.3.1.

Bug fixes

  • import lite_bootstrap no longer crashes under lite-bootstrap[litestar]
    without prometheus-client.
    litestar_bootstrapper imported
    litestar.plugins.prometheus (which requires prometheus_client) under the
    is_litestar_installed guard, but the litestar extra does not install
    prometheus-client — only litestar-metrics does. So pip install lite-bootstrap[litestar] followed by import lite_bootstrap raised litestar's
    MissingDependencyException: prometheus_client. The import is now guarded by
    prometheus-client presence too (its only uses are inside the metrics
    instrument, already gated on that package). Found by a new per-extra isolation
    install-check in CI.

References

  • planning/changes/2026-07-19.04-extra-isolation-install-check.md

1.3.1

Choose a tag to compare

@github-actions github-actions released this 19 Jul 14:13
65845e0

lite-bootstrap 1.3.1 — fix bare-install import (typing-extensions)

1.3.1 is a patch release. Fully backward compatible with 1.3.0.

Bug fixes

  • Bare import lite_bootstrap no longer crashes on a missing
    typing_extensions.
    Core uses typing_extensions at runtime (a Self
    return annotation, and a TypedDict FastAPI response model that pydantic
    requires be a typing_extensions.TypedDict on Python < 3.12) but never
    declared it, so pip install lite-bootstrap with no extras followed by
    import lite_bootstrap raised ModuleNotFoundError: No module named 'typing_extensions'. typing-extensions is now declared as core's single
    dependency. It is pure Python, so free-threaded support is unchanged, and this
    is the leanest possible core.

    This corrects 1.3.0's note, which called core "zero-dependency": the code
    genuinely needs typing_extensions while Python 3.10/3.11 are supported. The
    bug was pre-existing (bare 1.2.3 failed the same way); every install with any
    extra masked it, because extras pull typing_extensions in transitively.

Backwards compatibility

Fully compatible with 1.3.0. No API or configuration changes; the only
difference is that a bare-core install now resolves typing-extensions and
imports cleanly.

References

  • planning/changes/2026-07-19.03-core-zero-dep-typing-extensions.md

1.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Jul 13:46
f84ffbe

lite-bootstrap 1.3.0 — free-threaded Python support, orjson becomes opt-in

1.3.0 is a minor release. Backward compatible with 1.2.3, with one dependency
change
(orjson moves from a mandatory core dependency to an opt-in extra).
It lands free-threaded CPython (3.13t/3.14t) support for core and most extras,
plus two import-safety fixes surfaced while verifying it.

Features

  • Free-threaded CPython (3.13t/3.14t) support. lite-bootstrap is pure
    Python; the only thing that ever blocked it on a free-threaded interpreter
    was the mandatory orjson dependency (below). Core, logging, sentry,
    fastapi, and faststream (plus their -sentry/-logging/-metrics
    combos) now install and run on both 3.13t and 3.14t. litestar (+
    litestar-metrics) and fastmcp (+ fastmcp-metrics) land on 3.14t
    only
    msgspec (litestar) and cffi (fastmcp, via cryptography) both
    gate free-threaded support to Python 3.14+ and fail to build from source on
    3.13t. The gRPC otl exporter (grpcio has no ft wheels — use the new
    otl-http extra instead) and pyroscope (pyroscope-io is abi3-only and
    unmaintained) remain unavailable on free-threaded builds pending upstream
    fixes. See
    architecture/free-threading.md for
    the full support matrix and planning/deferred.md for the
    ecosystem blockers.

  • OTLP-http exporter: new opentelemetry_exporter_protocol config (grpc
    default | http) and an otl-http extra (no grpcio) so OTLP trace export
    works on free-threaded Python. otl now pulls
    opentelemetry-exporter-otlp-proto-grpc directly (was the opentelemetry-exporter-otlp
    meta); grpc behavior is unchanged.

  • orjson is now an opt-in extra (lite-bootstrap[orjson]) instead of a
    mandatory core dependency — it shipped no free-threaded wheels and its build
    refuses to compile under a free-threaded interpreter, which meant nothing,
    not even the pure extras, could install on ft before this change. The
    logging serializer falls back to the stdlib json accelerator when orjson
    is absent (byte-identical output for JSON-native values; ~2-5x slower;
    non-JSON-native types in log extra, e.g. datetime/UUID, render via repr
    instead of orjson's native encoding). Add [orjson] to keep the fast path
    on a standard (GIL) build. If your code relied on import lite_bootstrap
    pulling orjson in transitively, depend on orjson directly.

Bug fixes

  • import_checker's dotted find_spec checks no longer crash on an
    incomplete namespace.
    find_spec imports a dotted name's parent package
    first, so a present-but-incomplete opentelemetry install (e.g.
    opentelemetry-api without opentelemetry-instrumentation) previously
    raised ModuleNotFoundError instead of returning False, crashing import lite_bootstrap. Affected dotted checks now go through a
    ModuleNotFoundError-safe helper.
  • The gRPC OTLP exporter is no longer imported unconditionally.
    opentelemetry_instrument.py used to import
    opentelemetry.exporter.otlp.proto.grpc.trace_exporter whenever bare
    opentelemetry-api resolved, crashing import lite_bootstrap in any
    environment with opentelemetry-api present but the exporter package
    absent (e.g. lite-bootstrap[fastmcp], which pulls in bare
    opentelemetry-api transitively). The exporter import — and its use in
    bootstrap() — now sit behind their own is_otlp_grpc_exporter_installed
    guard. When opentelemetry_endpoint is set but the selected exporter package
    is absent, bootstrap() emits an InstrumentDependencyMissingWarning naming
    the extra to install ([otl] for gRPC, [otl-http] for HTTP); see
    architecture/instruments.md.
  • The OpenTelemetry instrument no longer assumes the SDK is present when only
    the API is.
    is_opentelemetry_installed (find_spec("opentelemetry")) is
    true with just opentelemetry-api, but the instrument imports
    opentelemetry.sdk.* — a separate distribution. An api-only environment
    (e.g. lite-bootstrap[fastmcp]) therefore still crashed at the sdk import
    even after the exporter guard above. A new is_opentelemetry_sdk_installed
    flag gates the sdk imports, and check_dependencies() requires both the api
    and the sdk. With all three fixes, lite-bootstrap[fastmcp] imports and runs
    on free-threaded 3.14t.

These bugs are not ft-specific — they affect any environment with a partial
opentelemetry stack — but ft verification work is what surfaced them.

Backwards compatibility

Fully backward compatible with 1.2.3 at the API level. The one dependency
change is the orjson move to opt-in described above; everything that imports
or configures lite-bootstrap continues to work unchanged on a standard (GIL)
build once orjson is installed (directly, or via the [orjson] extra).

References

  • Design bundle: planning/changes/2026-07-18.01-free-threaded-python-support.md,
    planning/changes/2026-07-19.01-fix-otel-api-sdk-conflation.md,
    planning/changes/2026-07-19.02-otlp-http-exporter.md.

1.2.3

Choose a tag to compare

@github-actions github-actions released this 01 Jul 20:44
7369e10

lite-bootstrap 1.2.3 — release pipeline on PyPI Trusted Publishing

No library changes. The package is identical to 1.2.2; this release exercises the new publish path end-to-end.

CI

  • Releases now authenticate to PyPI via Trusted Publishing (OIDC) instead of a long-lived PYPI_TOKEN secret. uv publish auto-detects the GitHub Actions id-token; the release job runs under a pypi environment that scopes the trusted publisher (#145).

Downstream

No action required. Nothing about the installed package changes.

1.2.2

Choose a tag to compare

@github-actions github-actions released this 01 Jul 18:30
8c5b1cd

lite-bootstrap 1.2.2 — bound Litestar Prometheus path cardinality by default

1.2.2 is a patch release framed as a bug fix, with one observable behavior change. It flips the Litestar Prometheus path-label default from raw URLs to the route template, closing an unbounded-cardinality footgun that grew process memory without limit on parameterized routes.

Bug fix

  • Litestar prometheus_group_path now defaults to True (PR #144). Litestar's own PrometheusConfig defaults group_path=False, so the path metric label recorded the raw request URL. Any route with path parameters then minted one time series per distinct value (/users/1, /users/2, …), growing the metric registry without bound — visible in production as steadily climbing memory. The new default binds the label to the route template (/users/{id}), so cardinality is bounded by the number of routes, not the number of distinct URLs.

    The new LitestarConfig.prometheus_group_path field is merged as {"group_path": <field>, **prometheus_additional_params}, so prometheus_additional_params["group_path"] still overrides it without a keyword collision — the previously-documented workaround keeps working unchanged. FastAPI is unaffected: prometheus-fastapi-instrumentator already labels by route template.

Behavior change

  • The Litestar path metric label now holds the route template instead of the raw URL. Dashboards, alerts, or recording rules keyed on raw parameterized paths (path="/users/1") will no longer match; they should key on the template (path="/users/{id}"). To restore the old raw-path behavior per application, set prometheus_group_path=False (or prometheus_additional_params={"group_path": False}).

Backwards compatibility

Fully backward compatible with 1.2.1 at the API level — the new field is additive and defaulted. The only observable difference is the metric-label value described above. Configs already passing group_path via prometheus_additional_params are unaffected (the dict still wins).

References

1.2.1

Choose a tag to compare

@lesnik512 lesnik512 released this 24 Jun 09:47
3bb26ad

lite-bootstrap 1.2.1 — lift the FastAPI 0.137 cap

1.2.1 is a patch release. No public-API or behavior changes. It removes the temporary fastapi<0.137 ceiling introduced in 1.1.1, now that the upstream prometheus-fastapi-instrumentator fix has shipped.

Dependency constraints

  • fastapi<0.137 cap removed from the fastapi extra (the single declaration every fastapi-* extra composes from). FastAPI 0.137 and 0.138 now resolve.
  • prometheus-fastapi-instrumentator floor raised on the fastapi-metrics extra: >=6.1>=8.0.1. The crash that motivated the cap required FastAPI ≥0.137 and instrumentator ≤8.0.0, so lifting the FastAPI ceiling is paired with a floor that guarantees the fixed instrumentator wherever metrics are installed.

The original cap was added in 1.1.1 because prometheus-fastapi-instrumentator read route.path unconditionally and crashed on FastAPI 0.137's internal _IncludedRouter route type. That is fixed upstream in instrumentator v8.0.1 (issue #370, closed 2026-06-22). lite-bootstrap's own offline-docs guard (the isinstance(route, Route) filter shipped in 1.1.1) remains in place.

Verified end-to-end against FastAPI 0.138.0 + prometheus-fastapi-instrumentator 8.0.2: full suite green at 100% coverage, including the offline-docs and metrics paths that previously crashed.

Backwards compatibility

Fully backward compatible with 1.2.0. No public API or behavior changed; this is purely a loosening of resolution constraints. Installs that were held at FastAPI ≤0.136 by the cap will now resolve forward to current FastAPI.

References

1.2.0

Choose a tag to compare

@lesnik512 lesnik512 released this 24 Jun 09:34
1b0860e

lite-bootstrap 1.2.0 — deeper seams: structured-log payload, unified teardown guard, OTel config tidy-up

1.2.0 is a minor release. Backward compatible with 1.1.1, with one observable behavior change (a new double-attach warning on Litestar and FastStream). It lands the shippable results of an architecture-deepening sweep: the structlog→Sentry contract gets a single owner, the teardown-on-shutdown guard is unified across all frameworks, and an OpenTelemetry config field moves to where it belongs.

Features

  • StructuredLogPayload owns the structlog→Sentry contract (PR #129). The rendered-log-line shape that the Sentry instrument used to sniff and re-parse inline now lives in one value object (lite_bootstrap.instruments.logging_factory.StructuredLogPayload), with its meta-key vocabulary exposed as the public STRUCTLOG_META_KEYS. This closes a silent-drift failure mode: previously, renaming or adding a structlog meta-key could quietly leak it into Sentry's contexts.structlog or drop the enrichment, with no test to catch it. Sentry output is unchanged for existing setups; the enrichment is now pinned by a round-trip test.

  • opentelemetry_excluded_urls now lives on OpenTelemetryConfig (PR #132). The field was OpenTelemetry's own setting but had been declared separately on each of the FastAPI, Litestar, and FastStream configs. It now lives on OpenTelemetryConfig, so it is available wherever OpenTelemetry is configured and is read with typed access internally. The automatic exclusion of the metrics path and (unless health-check spans are enabled) the health-check path from traces is unchanged and now covered by a regression test.

Behavior changes

  • The double-attach teardown guard now applies to Litestar and FastStream (PR #130). Teardown-on-shutdown wiring is unified behind a single BaseBootstrapper._attach_teardown_once seam. The safeguard that warns and skips when a second bootstrapper is constructed against the same application — previously present only on FastAPI and FastMCP — now covers Litestar and FastStream as well. If your code constructs two bootstrappers against one Litestar AppConfig or FastStream app, you will now see a UserWarning and the second teardown is skipped, where this was previously silent. This is non-breaking: the warning is informational, the second attach is skipped (not errored), and the first bootstrapper's teardown still runs on shutdown. Construct one bootstrapper per application.

Backwards compatibility

Fully backward compatible with 1.1.1. No public API was removed.

  • IGNORED_STRUCTLOG_ATTRIBUTES is retained in sentry_instrument as a silent alias of STRUCTLOG_META_KEYS, so existing imports keep working.
  • opentelemetry_excluded_urls is still set exactly as before (e.g. FastAPIConfig(opentelemetry_excluded_urls=[...])) — it is now inherited rather than locally declared. FreeConfig additionally accepts the field now (inert there, since Free has no HTTP surface).
  • The only observable difference is the new Litestar/FastStream double-attach warning described above.

Internal-only changes that do not affect the public API: FastMCP's double-attach detection moved from scanning the provider list to the shared attribute marker, and FastAPI's internal lifespan marker was renamed to the unified _lite_bootstrap_teardown_attached.

References

  • PRs: #129, #130, #132
  • Design bundles and the decisions behind the rejected/limited options: planning/changes/2026-06-23.01-structured-log-payload/, planning/changes/2026-06-24.01-unify-teardown-attach/, planning/changes/2026-06-24.02-otel-excluded-urls-home/, and planning/decisions/.

1.1.1

Choose a tag to compare

@lesnik512 lesnik512 released this 14 Jun 19:51
3d2bdc0

lite-bootstrap 1.1.1 — FastAPI 0.137 compatibility

1.1.1 is a patch release. No public-API or behavior changes. It restores compatibility with FastAPI 0.137 and pins a transitive incompatibility, nothing more.

Bug fixes

  • Offline docs no longer crash on FastAPI 0.137's _IncludedRouter (PR #122). FastAPI 0.137.0 added the internal _IncludedRouter route type (a BaseRoute subclass with no .path) to app.router.routes. enable_offline_docs filtered routes via an unchecked typing.cast(Route, route).path, which raised AttributeError: '_IncludedRouter' object has no attribute 'path' whenever a router was included (e.g. by the health-checks instrument). The filter now matches only real Route instances (isinstance(route, Route) and route.path in …), leaving _IncludedRouter and other route types untouched. Correct on both old and new FastAPI.

Dependency constraints

  • fastapi<0.137 cap on the fastapi extra (temporary). prometheus-fastapi-instrumentator (≤ 8.0.0) has the same unguarded route.path access and is not yet fixed upstream, so any lite-bootstrap install that pulls FastAPI 0.137 would break metrics. The cap lives on the base fastapi extra — the single declaration every other fastapi-* extra composes from — so the whole FastAPI surface resolves to a version tested end-to-end with no skew between extras. Lift the cap once a fixed instrumentator ships.

Backwards compatibility

Fully backward compatible with 1.1.0. No public API changed; the FastAPI fix is purely defensive. The only observable difference is the new fastapi<0.137 resolution ceiling, which holds installs at a known-good FastAPI until the upstream metrics fix lands.

References

1.1.0

Choose a tag to compare

@lesnik512 lesnik512 released this 05 Jun 19:00
558b1d5

lite-bootstrap 1.1.0 — Lifecycle hardening, config validation, CI gate

1.1.0 is a minor release. No intentional public-API breakage. The two behavior changes that could affect existing code are fixes to genuine bugs and are called out in Behavior changes below.

This release closes a 26-finding bug-audit cycle (audits + retro live under planning/specs/2026-06-05-bug-audit-v2*.md). The changes split across four shipped PRs:

  • #108 — Lifecycle & teardown correctness (10 findings)
  • #109 — Config UX & security validation (6 findings)
  • #110 — Hygiene + CI gate (4 findings)
  • #111 — Generalized TeardownError aggregation + cascade tests + README lifecycle docs (3 deferred follow-ups)

Test suite grew from 153 → 194 (+27%) at 100% line coverage throughout. pip-audit now runs on every PR and weekly via cron; a new filterwarnings config catches accidental InstrumentSkippedWarning emissions.

New features

  • Injectable prometheus_collector_registry on FastStreamConfig. Pass an existing prometheus_client.CollectorRegistry to expose counters registered elsewhere through FastStream's /metrics endpoint. Defaults to a fresh per-instance registry — fully backward compatible.
  • opentelemetry_excluded_urls field on FastStreamConfig. Was a getattr fallback before; now a discoverable, IDE-completable config field matching FastAPIConfig and LitestarConfig.
  • SentryInstrument.teardown(). Calls sentry_sdk.flush(timeout=2) then sentry_sdk.init() (no args) to reset the SDK to a no-op state. Previously the SDK stayed globally configured after bootstrapper teardown, leaking state across process-local tests.
  • FastStreamLoggingInstrument.teardown(). Restores broker.config.logger.params_storage to its pre-bootstrap value. The bootstrap mutated broker state; teardown didn't reverse it.

Bug fixes

Lifecycle & teardown (PR #108)

  • OpenTelemetry teardown now flushes spans and shuts down the tracer provider (LOG-1, LOG-2). bootstrap() stored the TracerProvider only as a local; teardown() couldn't reach it to call shutdown(). Buffered spans in BatchSpanProcessor were dropped on graceful shutdown. Teardown also restores the two OTel-namespace stdlib loggers (opentelemetry.instrumentation.instrumentor, opentelemetry.trace) to their pre-bootstrap disabled state.
  • LoggingInstrument.teardown() runs all cleanup steps even on partial failure (LOG-3). A raise from any handler.close() previously left remaining handlers attached, skipped the root-level reset, and never called close_handlers() on the memory factory. Now wrapped in try/finally with per-handler error capture; all collected errors raise together via TeardownError(errors).
  • LitestarOpenTelemetryInstrumentationMiddleware cache evicts dead refs (LOG-6). The old dict[int, ASGIApp] keyed by id() never evicted, holding wrapper OpenTelemetryMiddleware instances alive after Litestar dropped next_app. Replaced with weakref.WeakKeyDictionary; non-weakrefable apps fall through to the un-cached path.
  • Double-bootstrap on the same application is now detected and warned (LOG-7, LOG-8). Constructing two FastMcpBootstrappers around the same FastMCP (or two FastAPIBootstrappers around the same FastAPI) previously stacked teardown hooks. The second construction now emits a UserWarning, skips the re-attachment, and tells you the second bootstrapper's teardown() won't fire on ASGI shutdown.
  • Generalized TeardownError aggregation across all instruments (PR #111). OpenTelemetryInstrument, FastStreamLoggingInstrument, and SentryInstrument now run their full cleanup sequence even if an early step raises — aggregating errors into a single TeardownError or letting super().teardown() run via try/finally. Previously a misbehaving instrumentor / broker / Sentry flush silently skipped subsequent cleanup.
  • Pyroscope's precondition check survives python -O (LOG-5/SEC-4). Replaced two assert statements (in _narrow_app and PyroscopeInstrument.bootstrap) with explicit raise TypeError(...) and raise RuntimeError(...). python -O strips asserts; the invariants now hold under all optimization levels. Closes the two bandit B101 findings.

Config & security (PR #109)

  • FastAPIConfig no longer stomps user-supplied app's title/debug/version (UX-1). Previously the three assignments ran unconditionally; a user passing FastAPI(title="My API", version="3.0.0") would silently have those clobbered by lite-bootstrap defaults. Now the assignments only run in the UnsetType branch (when lite-bootstrap constructed the app). See Behavior changes below.
  • enable_offline_docs validates request.scope["root_path"] against the existing path allowlist (SEC-1). Invalid root paths (e.g., HTML-injection payloads via a malicious upstream proxy's X-Forwarded-Prefix) now fall back to empty and emit a warning instead of being reflected into Swagger/Redoc HTML script tags. Threat model: not an issue in default ASGI deployments; only matters if ProxyHeadersMiddleware trusts upstream prefix headers.
  • OpenTelemetry endpoint with insecure=True emits a warning for non-local hosts (SEC-2). New OpenTelemetryConfig.__post_init__ parses the endpoint (handles both host:port and scheme://host:port forms, including IPv6 brackets and unix://) and warns when traces would ship unencrypted to a non-localhost/127.0.0.1/::1/unix:// target.
  • CorsConfig rejects unsafe wildcard + credentials combos at construction (SEC-3). cors_allowed_credentials=True combined with cors_allowed_origins=["*"] (or a permissive regex like ".*"/".+") is the canonical CORS misconfiguration — browsers reject the response. Now raises ConfigurationError immediately instead of silently building a non-functional CORS layer. See Behavior changes below.

Hygiene & process (PR #110)

  • Missing-dependency events now log via stdlib logging in addition to warnings.warn (UX-4). Users running under python -W ignore or PYTHONWARNINGS=ignore previously saw nothing when a configured instrument's optional dep was missing. The new logger.warning line on lite_bootstrap.bootstrappers.base is unaffected by warning filters.

Behavior changes

Two changes could affect existing code in ways the previous release wouldn't have. Both fix real bugs; surfaced here so you can audit.

  1. User-supplied FastAPI instance retains its own title, debug, version. If you were relying on lite-bootstrap to overwrite these from service_name/service_debug/service_version after handing it a pre-built FastAPI(), you'll now see your original values. Migration: set these on your FastAPI() directly, or use FastAPIConfig(application_kwargs={...}) to have lite-bootstrap construct the app.

  2. CorsConfig(cors_allowed_origins=["*"], cors_allowed_credentials=True) now raises ConfigurationError. This combo was never functional — browsers reject responses with Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin: *. If your code constructed this combo and worked anyway (because the credentials header was silently dropped by FastAPI's CORSMiddleware), construction now fails with a clear message. Migration: enumerate allowed origins explicitly, or set cors_allowed_credentials=False.

New constraints documented

Three lifecycle constraints surfaced by the audit are now documented in README.md and CLAUDE.md:

  • One bootstrapper per application instance. Second construction emits a warning and skips re-attachment (see LOG-7/LOG-8 above).
  • One OpenTelemetryInstrument per process. The OTel SDK enforces set_tracer_provider as set-once via _TRACER_PROVIDER_SET_ONCE.do_once(...) (verified against opentelemetry/trace/__init__.py:548-556); teardown() cannot reset the global pointer.
  • __post_init__ cascade invariant. Every config-class __post_init__ must call super().__post_init__(). BaseConfig ships a no-op as the chain terminator. FastAPIConfig uses the explicit super(FastAPIConfig, self).__post_init__() form because @dataclass(slots=True) breaks bare super().

CI changes

  • security-audit.yml workflow added. pip-audit runs on every PR and weekly via cron against the lockfile (uv export --all-extras --no-hashes). The default-branch run is purely informational; PRs that introduce CVEs will block until resolved.
  • InstrumentSkippedWarning escalated to error in tests. Any unexpected emission outside a pytest.warns(...) block now fails the test (registered via pytest_configure() in tests/conftest.py; can't live in pyproject.toml because that import order breaks pytest-cov tracing).

Backwards compatibility

Aside from the two Behavior changes called out above, every public API behaves identically. New fields default to their old behavior (prometheus_collector_registry=None → fresh registry as before; opentelemetry_excluded_urls=[] → empty set as before). New warnings/validators trigger only on configurations that were already broken or risky.

The 26-fix list with full file:line references and rationale is in:

  • planning/specs/2026-06-05-bug-audit-v2.md — the audit
  • planning/specs/2026-06-05-bug-audit-v2-sequencing.md — the 3-PR breakdown
  • planning/specs/2026-06-05-bug-audit-v2-retro.md — what the cycle taught us

References

Read more

1.0.0

Choose a tag to compare

@lesnik512 lesnik512 released this 02 Jun 15:08
0d1b6ec

What's Changed

  • fix: honor root_path in offline-docs redoc handler by @lesnik512 in #89
  • fix: shut down TracerProvider in OpenTelemetryInstrument.teardown by @lesnik512 in #90
  • fix: make teardown idempotent and exception-safe by @lesnik512 in #91
  • fix: strip skip_sentry from Sentry context; drop dead is_X_installed conjuncts by @lesnik512 in #92
  • docs: document and pin BaseConfig.from_dict / from_object semantics by @lesnik512 in #93
  • refactor: extract OpenTelemetryServiceFieldsConfig mixin by @lesnik512 in #94
  • refactor: make BaseInstrument generic; delete pure-annotation subclasses by @lesnik512 in #95
  • fix: tighten Sentry idiom and typing micro-issues by @lesnik512 in #96
  • refactor: OTel instrument touch-ups (REF-1, LOW-3, LOW-5) by @lesnik512 in #97
  • test: add standalone instrument tests and is_valid_path negative tests by @lesnik512 in #98
  • refactor: split logging module + cleanup + lifecycle test by @lesnik512 in #99
  • refactor: drop unused abc.ABC from BaseInstrument; document config holders by @lesnik512 in #100
  • refactor: drop frozen=True from instruments; sentinel for FastAPIConfig.application by @lesnik512 in #101
  • feat: configurable broker ping timeout for FastStream health check by @lesnik512 in #102
  • refactor: rename OpentelemetryConfig → OpenTelemetryConfig; FreeBootstrapperConfig → FreeConfig by @lesnik512 in #103
  • chore: pin uv_build upper bound; assert pyroscope_endpoint precondition by @lesnik512 in #104
  • feat: add FastMcpBootstrapper by @lesnik512 in #105
  • fix: make BaseBootstrapper.bootstrap() idempotent by @lesnik512 in #106
  • refactor: replace InstrumentNotReadyWarning with is_configured classmethod + summary log by @lesnik512 in #107

Full Changelog: 0.28.1...1.0.0