Changelog¶
Changelog¶
Unreleased¶
0.13.3 - 2026-05-26¶
Runtime: Close shared gateway :class:
httpx.AsyncClienton unified-stack lifespan shutdown (fixes leak on defaultfluxlit dev/run).URL session: :func:
~fluxlit.url_session.hydrate_url_session_typedmerges validatedmodel_dump()intosession_state, not raw store blobs.Gateway: Do not forward POST bodies to Streamlit after mid-request client disconnect (HTTP 499).
Pages: Register-time error for :class:
~fluxlit.url_session.SessionStore-annotated parameters even when a default is present; :class:~fluxlit.pages.di.Dependshonorsuse_cachewithin a single page run.Runtime: Emit
lifespan.startup.failedwhen inner FastAPI lifespan exits during unified startup without completing.Docs: Document
Depends(use_cache=...)in Streamlit pages: typing, Depends, and manifests; align Contributing and Testing with requiredty checkand coverage gates.CI: Matrix
testjob enforces--cov-fail-under=100on fast tests (same gate as thedocsjob).
Upgrading from 0.13.2: No intentional breaking changes. GET requests aborted by an early client disconnect now receive 499 instead of being proxied to Streamlit.
0.13.2 - 2026-05-26¶
Dependencies: cap
fastapibelow0.136.3(PyPI advisoryMAL-2026-4750on the0.136.3release) until upstream resolves thefastaroptional-dependency concern.Auth: Case-insensitive
Bearertoken extraction in :class:~fluxlit.auth.jwt.JWTBearer.Auth: :func:
~fluxlit.auth.streamlit.prepare_streamlit_api_clientcloses the bootstrap :class:~fluxlit.client.ApiClientwhen the BFF exchange raises.Auth: :class:
~fluxlit.auth.oidc.InMemoryOIDCBFFTokenStoreuses a lock for concurrent PKCE / exchange access.Gateway: Redact
auth_codeand match sensitive query keys case-insensitively in access logs; close the shared upstream :class:httpx.AsyncClienton ASGI lifespan shutdown.Streamlit: Reuse a cached :class:
~fluxlit.client.ApiClientinst.session_stateacross reruns in the managed entrypoint.URL session: Default query param from :attr:
~fluxlit.config.FluxlitSettings.url_session_query_param; :func:~fluxlit.url_session.hydrate_url_session_typedvalidates store payloads before merging intosession_state.Pages: Register-time error when a page requires :class:
~fluxlit.url_session.SessionStorebutFluxLit(session_store=None); injected :class:~fluxlit.pages.flags.FluxlitFeatureFlagsrespects settings and env; :func:~fluxlit.pages.di.Dependsaccepteduse_cache=Falsebut did not honor it until 0.13.3.Testing: :meth:
~fluxlit.testing.FluxLitTestClient.select_pageand :func:~fluxlit.testing.apptest_select_pageacceptpage_overrides.Docs: Correct :func:
~fluxlit.pages.query.parse_query_paramsmulti-value query documentation.
Upgrading from 0.13.1: No intentional breaking changes. Authorization: BEARER … headers now work; invalid URL-session blobs no longer partially hydrate session_state before typed validation fails.
0.13.1 - 2026-05-14¶
Gateway (WebSocket): After
websocket.accept, relay failures log, issue a single best-effortwebsocket.close(code 1011) on generic errors, and ignore duplicate close attempts; coverConnectionClosedfrom upstreamsendwithout treating it as a relayException.CI:
scripts/smoke_fluxlit_run.shprobesfluxlit runon the smoke app (/api/healthzthen/api/readyz); newfluxlit-run-smokeGitHub Actions job.Docs:
http_proxymodule docstring on a possible future streaming upstream hop and tradeoffs (memory vs complexity).Auth (OIDC BFF): :class:
~fluxlit.auth.oidc.OIDCBFFTokenStoreprotocol, :class:~fluxlit.auth.oidc.InMemoryOIDCBFFTokenStore, and :attr:~fluxlit.auth.oidc.OIDCBFFConfig.bff_token_storefor shared PKCE / exchange storage across API replicas;SECURITY.mdandexamples/oidc_bff_pluggable_store/README.mdupdated.
Upgrading from 0.13.0: No breaking changes for default apps. Optional: inject bff_token_store for multi-replica OIDC BFF; keep pins on fluxlit>=0.13,<1.0 or bump to fluxlit==0.13.1 in lockfiles.
0.13.0 - 2026-05-13¶
Phase 2 follow-through:
scripts/soak_metrics.shand soak methodology in Runbooks / Testing; weekly informational FluxLit soak job insoak-scheduled.yml;soak-fluxlit-dispatchruns metrics soak when metrics are enabled.Scale docs: multi-replica Redis / shared store failure modes in URL session continuity (no cookies); ingress engine pointer table in Deployment and cross-link in Production TLS and edge headers.
Stability charter in code: module notes on metrics/manifest/logs/settings;
MANIFEST_V1_*key sets; contract tests for Prometheus series names vsGATEWAY_PROMETHEUS_METRICSand manifest v1 keys.DX: expanded
fluxlit doctor --strictrows (OAuth subpath, proxy headers, upstream read timeout, rejected forward names, unlimited proxied body withtrust_proxy, CORS/security headers, conflicting public base URL envs); optionalFLUXLIT_STRICT_STARTUP/strict_startupon :class:~fluxlit.config.FluxlitSettingsto raise on the same class of misconfigurations at import time.Tracing: nested
fluxlit.gateway.upstream_httpspan (hook) around the gateway → Streamlit HTTP hop; observability docs updated for span names and W3C traceparent passthrough on the internal hop.Security / supply chain:
SECURITY.mdsupported-version policy aligned with the current 0.x line and support matrix; httpx private typing imports called out with a contract test (tests/test_httpx_import_contract.py) and a contributor bump note inCONTRIBUTING.md.Pages:
Cookieresolves fromset_page_cookie_contextandst.context.cookies(same precedence pattern asHeader);fluxlit doctorhints mention explicit header/cookie injection when HTTP forwarding is off.Ops:
GET /api/readyzStreamlit probe aggregates per-path HTTP statuses when every candidate URL is non-2xx (upstream_http_faileddetail withpath:codesegments).Gateway: access-log query redaction treats
query_stringdecode failures asUnicodeErroronly (customdecodeimplementations used in tests).Docs: support matrix intro targets 0.13.x; Streamlit pages typing documents
Cookieresolution and async-Dependstimeout / daemon-thread caveat.
Upgrading from 0.12.x: Bump pins to fluxlit>=0.13,<1.0. Optional: set FLUXLIT_STRICT_STARTUP=1 in containers where misconfiguration should fail the process early; expand fluxlit doctor --strict in CI if you rely on the new FAIL rows.
0.12.0 - 2026-05-13¶
Stability charter: documented gateway Prometheus metric names/labels/bucket policy, page manifest
manifest_version1 fields, structured log field contracts, and experimentalFluxlitSettingsflags in Support matrix and expanded Observability; draft 1.0 compatibility & deprecation subsection.Multi-replica: operations checklist in Deployment; new runbook Multi-replica: new Streamlit session after refresh; optional Kubernetes PDB and Service sessionAffinity examples under
examples/kubernetes/; cross-links from URL session continuity (no cookies).Evidence: new
scripts/soak_readyz.shfor/api/readyzsoak summaries; chaos/soak script headers aligned with expected signals; Runbooks scripted load table; manual GitHub Actions workflowsoak-fluxlit-dispatch.yml; Testing recipe.DX:
fluxlit doctor --stricttreats broadforwarded_allow_ips(withtrust_proxy) andpublic_base_urlpath vs public mount mismatch as FAIL (use with--warnings-onlyor fix config).
Upgrading from 0.11.x: Bump pins to fluxlit>=0.12,<1.0. CI or release gates may use fluxlit doctor --strict alongside fluxlit config --strict for proxy hardening. Re-read Support matrix stability tables when pinning dashboards or manifest consumers.
0.11.0 - 2026-05-12¶
Runtime: unified
FluxLitASGI lifespan fails fast when Uvicorn runs withworkers> 1 (detected viauvicorn.lifespan.on.LifespanOn); setFLUXLIT_ALLOW_UNIFIED_UVICORN_MULTIWORKER=1to override (unsupported). See Deployment and Configuration.Gateway: log at DEBUG on
fluxlit.gatewaywhen Prometheus histogram observation raises instead of swallowing silently (the request still completes; that hop’s metric may be missing).Roadmap: Phase 2 “suggested PR slices” subsection links scripts, docs, and follow-up DX work.
Proxy matrix: Traefik v3.2 strip-prefix smoke stack on port 8085 (
docker-compose.traefik.yml,traefik-dynamic.yml); wired intodocker/proxy-deployment/run-all-proxy-smokes.shand the reverse-proxy matrix in Deployment.Cookbook: gateway Prometheus metrics, Kubernetes-style
healthz/readyzprobes,fluxlit config --strictin CI, andFLUXLIT_GATEWAY_MAX_PROXY_REQUEST_BODY_BYTES/ 413 guidance in Cookbook.Diagnostics: :func:
fluxlit.gateway.forward_headers.rejected_gateway_forward_header_allowlistand settings capture of rejected allowlist names;fluxlit config/ :func:~fluxlit.config.config_print.collect_configuration_warningswarn on credential-style names users listed but the gateway never forwards, and whentrust_proxyis on with unlimited proxied upload body size;fluxlit doctoraddsgateway_forward_rejected_names; verbosegateway_proxyincludesmax_proxy_request_body_bytesandmax_concurrent_upstream_http.Packaging: Hatch sdist excludes stray virtualenv directories under
examples/souv build/ PyPI sdists do not fail on disallowed symlinks.Internal: Consolidate affirmative
FLUXLIT_*environment parsing viafluxlit.runtime.env_parse.truthy_env(used forFLUXLIT_DEBUG, URL-session test guards, and related call sites).
Upgrading from 0.10.x: Bump pins to fluxlit>=0.11,<1.0. Re-check FLUXLIT_GATEWAY_FORWARD_CLIENT_HEADERS_TO_STREAMLIT if you list credential header names (they are ignored); new warnings may appear in fluxlit doctor / fluxlit config --strict when trust_proxy is enabled without a body limit. If you run the unified FluxLit ASGI app under Uvicorn with --workers > 1, use one worker per replica and scale out (lifespan startup fails unless you set the unsupported FLUXLIT_ALLOW_UNIFIED_UVICORN_MULTIWORKER override).
0.10.0 - 2026-05-12¶
Gateway: optional
FLUXLIT_GATEWAY_FORWARD_CLIENT_HEADERS_TO_STREAMLIT/ :attr:~fluxlit.config.FluxlitSettings.gateway_forward_client_headers_to_streamlitcopies an allowlist of browser header names onto the gateway → Streamlit HTTP hop (st.context.headers/ :class:~fluxlit.pages.di.Header); credential and hop-by-hop names are rejected. See :mod:fluxlit.gateway.forward_headersand Configuration.Pages: async :class:
~fluxlit.pages.di.Dependscallables and awaitable returns resolve when an asyncio loop is already running by using a short-lived side thread (0.9 raisedTypeErrorin that case). :class:~fluxlit.pages.di.Headerfalls back tost.context.headersafterset_page_header_context.Doctor / verbose: new checks for readiness path hints, WebSocket proxy documentation pointers, upstream timeout sanity, async-depends warning, forwarded-header warning;
gateway_proxyblock influxlit doctor --verbose/--json.Proxy matrix: Caddy strip-prefix smoke on port 8084 (
docker-compose.caddy.yml);run-all-proxy-smokes.shruns it; Deployment compatibility table updated.Docs: new Cookbook (recipes); expanded Streamlit pages: typing, Depends, and manifests for async deps and header forwarding.
Upgrading from 0.9.x: Bump pins to fluxlit>=0.10,<1.0. If you use FLUXLIT_ASYNC_PAGE_DEPENDS=1 under asyncio-heavy hosts, re-test async Depends (resolution now uses a side thread when a loop is active). Optional header forwarding is off by default.
0.9.0 - 2026-05-12¶
Streamlit pages (0.9): :class:
~fluxlit.pages.records.PageRecordregistry with :attr:~fluxlit.app.FluxLit.page_records; :meth:~fluxlit.app.FluxLit.pageacceptsicon,tags, and staticpage_meta; handlers may return :class:~fluxlit.pages.meta.PageMetafor breadcrumbs and similar post-run UI. :class:~fluxlit.pages.di.Depends, :class:~fluxlit.pages.di.Header, and :class:~fluxlit.pages.di.Cookieresolve extra parameters beside(st, client)(see Streamlit pages: typing, Depends, and manifests). Optional :class:~fluxlit.url_session.SessionStoreon :class:~fluxlit.app.FluxLitenablesSessionStoreinjection.Navigation: :meth:
~fluxlit.app.FluxLit.navigationwith :class:~fluxlit.pages.navigation.NavigationModelorders multipage sidebar entries by path.Query / session: :func:
~fluxlit.pages.query.parse_query_params, :class:~fluxlit.pages.query.Query, :class:~fluxlit.pages.session_state.SessionModel, and :func:~fluxlit.url_session.hydrate_url_session_typedfor typed URL/session payloads.Registration & CI: duplicate
@app.pagepaths, or distinct paths that normalize to the same Streamliturl_pathslug (for example/aand/a/), raiseValueErrorat registration; :func:~fluxlit.pages.validate.validate_fluxlit_pagesreports the same for CI.Slug & lazy validate: :func:
~fluxlit.pages.slug.page_slugcentralizes slug rules;validate_fluxlit_pagesis available on :mod:fluxlit.pagesvia lazy__getattr__to avoid import cycles.Manifest & CLI: :meth:
~fluxlit.app.FluxLit.build_page_manifest(manifest_version1,manifest_stability**stable);fluxlit pages manifestandfluxlit pages validate(–strictfor signature checks independent of settings); optionalchildrenkeys frompage_meta`` in the manifest.PageMeta children & nav:
PageMeta.childrenmerges title/icon overrides and sibling ordering beforest.navigation(unknown paths warn); cycles inchildrenemitUserWarningduring ordering; :mod:fluxlit.streamlit.nav_builduses a heap-ordered frontier for the ready queue.Deep links: the Streamlit entrypoint passes the same ordered
page_recordslist to :func:~fluxlit.deep_links.match_nav_pageas tost.navigation, so?page=matches the visible sidebar (see Deep links and query parameters).Strict signatures: :class:
~fluxlit.config.FluxlitSettings.strict_page_signatures/FLUXLIT_STRICT_PAGE_SIGNATURES; clearer errors when annotations cannot be resolved.Async depends: optional async dependency callables when
FLUXLIT_ASYNC_PAGE_DEPENDS=1(resolved withanyio.runwhen no asyncio loop is running); :attr:~fluxlit.config.FluxlitSettings.async_page_dependsforfluxlit config/ doctor visibility.Experimental generator pages: :class:
~fluxlit.pages.flags.FluxlitFeatureFlagsand :attr:~fluxlit.config.FluxlitSettings.experimental_yield_pagesmirrorFLUXLIT_EXPERIMENTAL_YIELD_PAGES; when enabled, generator handlers run twonext()steps in one script run.fluxlit doctor --check-pages/--verboserun validate-style checks and warn when this flag is on.Docs: PageMeta vs
set_page_configtruth table; gatewayHeader/Cookiebridge; generator and Protocol typing guidance;page_overrides/FLUXLIT_TEST_PAGE_OVERRIDESin Testing; :mod:fluxlit.gateway.http_proxynotes on headers in the Streamlit process.Tooling:
tytest overrides ignoreinvalid-parameter-defaultandunresolved-reference(FastAPI-styleDependsdefaults and deliberate forward refs in tests).Testing: :meth:
~fluxlit.testing.FluxLitTestClient.streamlitacceptspage_overrides(JSON viaFLUXLIT_TEST_PAGE_OVERRIDES) for dependency injection in AppTest.Typing: :class:
~fluxlit.app.FluxLitis a :class:typing.Genericover settings type for static checkers; :class:~fluxlit.streamlit.page.PageFnallows optional :class:~fluxlit.pages.meta.PageMetareturns.CLI / packaging:
fluxlit pagessubgroup;fluxlit buildDockerfile pinfluxlit>=0.9,<1.0;fluxlit newminimal scaffold includestyping.Any, :class:~fluxlit.client.ApiClient, and aDependsexample.
Upgrading from 0.8.x: Bump pins to fluxlit>=0.9,<1.0. :attr:~fluxlit.app.FluxLit.pages remains (path, title, handler) tuples. Opt into strict_page_signatures, manifest, and DI markers as needed; see Streamlit pages: typing, Depends, and manifests.
0.8.1 - 2026-05-12¶
Gateway / settings:
normalize_api_mount_pathinfluxlit.api_mountaligns gateway dispatch withinternal_api_base_urlandFluxLitPublicUrlswhenapi_mount_path/FLUXLIT_API_MOUNT_PATHomits a leading slash (e.g.api→/api); :class:~fluxlit.config.FluxlitSettingsvalidatesapi_mount_path;create_gateway_appnormalizesFLUXLIT_API_PREFIXthe same way.Gateway: WebSocket upstream
websockets.connecttimeouts (TimeoutError) are caught and the client socket is closed with code 1011 instead of leaking an ASGI exception.Gateway: Prometheus and debug JSON ASGI responses set
more_body: falseon the terminal body message (stricter ASGI consumers).Client: :class:
~fluxlit.client.ApiClientrejects absolute and scheme-relativepathvalues so httpx cannot bypassbase_urlto another host (:class:ValueError).OIDC BFF: :class:
~fluxlit.auth.oidc.OIDCBFFConfigaddsallow_unverified_id_token_for_custom_oidc(defaultFalse). Non-:class:~fluxlit.auth.oidc.GenericOIDCClientproviders must set it toTrueto keep parse-onlyid_tokensubextraction (tests or providers that verify tokens themselves). Emptypublic_base_urlnow emits a runtime warning at route registration.Docs / observability: HTTP gateway proxy module and
gateway_max_proxy_request_body_bytesdocument full upstream response buffering; :class:~fluxlit.url_session.InMemorySessionStoredocumentsttl_seconds=0semantics and trims oversize stores by oldest insertion order.Docs: README coverage wording matches CI (100% line coverage; one test-helper
pragma: no cover); historical CHANGELOG CI note uses--cov-fail-under=100;docs/testing.mddocumentsty-checkas a required workflow job;docs/security.mdanddocs/migration-auth.mdcover the above auth/client changes.CI:
ty-checkno longer usescontinue-on-error.
Upgrading from 0.8.0: Bump pins (for example fluxlit==0.8.1 in Compose lockfiles). If you use custom :class:~fluxlit.auth.oidc.OIDCProvider with :func:~fluxlit.auth.oidc.register_oidc_bff_routes (not :class:~fluxlit.auth.oidc.GenericOIDCClient), set OIDCBFFConfig.allow_unverified_id_token_for_custom_oidc=True only when your provider already verified id_token or in controlled tests; otherwise switch to GenericOIDCClient for JWKS validation. If :class:~fluxlit.client.ApiClient calls used absolute URLs as paths, switch to relative paths (or construct a separate httpx client for off-host calls).
0.8.0 - 2026-05-12¶
CLI:
fluxlit configprints resolved binding, redacted effective settings, derived internal API base, and structured configuration warnings (with documentation links); supports--jsonand--strict.Public URLs:
FluxLit.urlsexposes :class:~fluxlit.application.public_urls.FluxLitPublicUrlswithapp_base,api_base,docs_url,redoc_url,openapi_url,health_url,ready_url, andfor_page(includingquery=) so links matchFLUXLIT_ROOT_PATH,FLUXLIT_API_MOUNT_PATH, andFLUXLIT_PUBLIC_BASE_URLunder the unified gateway.Debug mode:
FLUXLIT_DEBUG=1orfluxlit dev/run/workbenchwith--debugturns on gateway access logs, API request logging, bumps the default log level todebugwhen it was stillinfo, serves a redactedGET /__fluxlit/debugsnapshot (unlessapi_mount_pathwould shadow it), records recent dispatches in-process, prints a[fluxlit-debug]banner to stderr at unified startup, and makes :meth:fluxlit.app.FluxLit.get_clientpropagateX-Request-IDto the API. Seedocs/configuration.md,docs/cli.md,docs/troubleshooting.md, anddocs/observability.md.Doctor:
fluxlit doctor --verbose/-vprints a redacted effective-configuration snapshot (pages, derived internal API base, OpenAPI URLs, proxy/session extras);--json --verboseadds averboseobject to the payload.Workbench / Posit:
fluxlit workbenchand--workbenchondev/runenable Uvicorn proxy headers and print a loopback browser URL hint; see platforms and CLI docs for Posit Connect / Workbench-styleFLUXLIT_ROOT_PATHdeployments.Testing, deep links, and multipage Streamlit:
FluxLitTestClientsupportsroot_mount/with_root_path, per-callroot_pathonapi_get/api_post,streamlit(..., query_params=...), andassert_docs_available(); AppTest helpersapptest_assert_no_errors,apptest_select_page, andassert_no_streamlit_exception;query_params,match_nav_page, andFluxLitPublicUrls.page_urlfor query and page URLs. The Streamlit entrypoint appliesmatch_nav_pagebeforest.navigationwhen using multipagenav_pagesso?page=deep links resolve. Seedocs/testing.mdanddocs/deep-links.md. Closes #31.Streamlit → API client:
ApiClient.with_bearerfor bearer auth on top of the injected page client; new guidedocs/streamlit-api-client.md(when to use injectedclientvsfor_fluxlit, errors, shared internal base). Closes #28.Docs: New guide URL sessions, query tokens, and email links (security) on URL-session ids vs auth tokens, email/invite links, JWTs in URLs, Referrer-Policy, and how logging/debug redaction applies. Cross-links from url-session, deep-links, secrets, security, and index. Closes #30.
Docs / proxy smoke: Path-prefixed reverse-proxy guide for
/apps/my-appin Production TLS and edge headers; Docker Compose + nginx underdocker/proxy-deployment/(including CIrun-all-proxy-smokes.sh);smoke-test.shnow asserts/api/docs. Closes #33.Docs: Expanded support matrix with production pinning patterns (
uv,pip-tools), explicit core dependency lower bounds, Streamlit extra guidance, testing compatibility notes, and upgrade checklist cross-links.
Upgrading from 0.7.x: fluxlit build emits pip install "fluxlit>=0.8,<0.9" in generated Dockerfiles; refresh pinned Compose lockfiles (examples/docker_compose/requirements.in / requirements.txt) and Kubernetes image tags when you bump the FluxLit line. Run fluxlit config after changing proxy or public URL env vars.
0.7.0 - 2026-05-11¶
Testing API:
streamlit_main_path()is now a public helper for supportedAppTest.from_file(...)usage;FluxLitTestClient.streamlit()uses it and setsFLUXLIT_TESTS=1during AppTest runs.Testing docs:
docs/testing.mdnow includes an app-developer Pytest recipe, guidance forFluxLitTestClient, StreamlitAppTest,ApiClient,st.data_editor, dynamic widget keys, and multipage smoke tests. A newexamples/multipage_apptest/demo shows stable multipage patterns.URL session test mode: URL-session helpers no-op under
FLUXLIT_TESTS=1unlessFLUXLIT_FORCE_URL_SESSION_IN_TESTS=1is set.FLUXLIT_DISABLE_URL_SESSION=1remains an explicit disable switch in any environment.Doctor diagnostics:
fluxlit doctorreports additional import/config context, includingsys.pathhead entries, ambiguous top-level import candidates, loaded module file paths, effective API prefix, URL-session state, proxy/public-base-url fields, and missingauth/metricsextras.Configuration:
FLUXLIT_PUBLIC_BASE_URLis the preferred public OAuth base URL.PUBLIC_BASE_URLis accepted as a compatibility fallback only when the namespaced value is unset;fluxlit doctorwarns or fails on conflicting values depending onFLUXLIT_STRICT_PUBLIC_BASE_URL.Docs: README, CLI, configuration, troubleshooting, URL-session, quickstart, testing, and roadmap docs were refreshed for the 0.7 testing and diagnostics work.
Upgrading from 0.6.1: Prefer FLUXLIT_PUBLIC_BASE_URL over PUBLIC_BASE_URL in deployment configuration. If your AppTest suite intentionally exercises URL-session continuity, set FLUXLIT_FORCE_URL_SESSION_IN_TESTS=1; otherwise FLUXLIT_TESTS=1 now keeps URL-session helpers inert during headless tests.
0.6.1 - 2026-05-11¶
Runtime: File-backed import targets now prepend the target module’s directory to
sys.pathbefore execution, so top-level multi-file apps can use sibling imports withmain:appand explicit./path/main.py:apptargets without settingPYTHONPATH.
Upgrading from 0.6.0: Remove entrypoint workarounds that manually insert the app
directory into sys.path solely for sibling imports. Keep explicit package installs or
project-root test setup if your app intentionally imports packages outside the target
module’s directory.
0.6.0 - 2026-05-11¶
0.6 development: canonical smoke app shared by E2E/proxy/load paths; expanded
fluxlit doctordiagnostics including--json; stable gateway log and Prometheus metric contracts; optional no-dependency tracing hooks plus an OpenTelemetry example; runnable URL-session external-store examples and platform docs; scaffold profiles; richer local smoke/load/chaos scripts; broader Docker proxy smoke matrix.
0.5.0 - 2026-05-11¶
Tests / CI: coverage job enforces
--cov-fail-under=100;ty-checkjob (pinnedty); E2E uploads Playwright traces on failure; weeklysoak-scheduledworkflow exercisesscripts/soak_http.shagainsthttp.server; shared fixturesgateway_test_client_factory/requires_streamlit_apptest; gateway header-filter, Prometheus counter, readiness (302/readyz404), WebSocketslowreconnect stress, andDictSessionStorecontract tests.URL session (Phase 2 follow-on):
fluxlit.url_session(SessionStore,InMemorySessionStore,ensure_url_session,hydrate_url_session,persist_url_session) for refresh continuity without cookies; user guidedocs/url-session.md; AppTest + unit tests.Gateway logs: structured
queryfield on gateway access / debug logs with redacted session query values (fluxlit_sidandFLUXLIT_URL_SESSION_QUERY_PARAM); newFluxlitSettings.url_session_query_param.Kubernetes:
examples/kubernetes/ingress.example.yamlreference Ingress (not applied by default).Supply chain & containers: CI uploads a CycloneDX SBOM (
cyclonedx-sbomartifact) alongsidepip-auditon.[auth];fluxlit build,examples/docker_compose, anddocker/proxy-deploymentuse digest-pinned Python slim and non-rootappuser; Compose example addsrequirements.in/requirements.txtviapip-compile.Docs:
docs/production-tls.md(TLS, HSTS,forwarded_allow_ips, CSP notes),docs/secrets.md(logs, secret stores, JWT/OIDC rotation); cross-links from README, index, deployment, configuration, security, observability, auth-recipes, troubleshooting, architecture, quickstart, testing, CONTRIBUTING, example READMEs, andROADMAP.mdsecurity row status.0.5 roadmap / production hardening:
examples/kubernetes/reference manifests; deployment scaling + multi-worker docs;docs/runbooks.md;docs/support-matrix.md;scripts/soak_http.sh;upgrade-smokeworkflow; OpenAPI contract test; optional gateway Prometheus metrics (fluxlit[metrics]); observability updates (RED metrics, traceparent recipe, correlation limits).Configuration:
FluxlitSettings/FluxLitpassthroughs for Streamlit (streamlit_run_cli_args,streamlit_page_config→st.set_page_config) and StarletteCORSMiddleware(cors_middleware_kwargs);fastapi_kwargsdocumented as the fullFastAPI(...)hook.Gateway / operations: authoritative
X-Request-IDon proxied HTTP and WebSocket to Streamlit;FluxlitSettingsfor upstream connect/read timeouts, max proxied request body (413), concurrent upstream HTTP cap, sharedhttpx.AsyncClientconnection limits, WebSocket open/ping/close/max_sizetuning;uvicorn_graceful_shutdown_timeout_swired intofluxlit dev/fluxlit runUvicorn config when set.Logging:
fluxlit.logging.JsonLogFormatter(stdlib JSON, mergesextrafields).Docs:
docs/observability.md(correlation diagram, JSONdictConfig, SLO/alerting sketches),docs/deployment.md(Kubernetes graceful shutdown),docs/configuration.mdgateway env table; README, index, quickstart, architecture, testing cross-links.Tests: gateway correlation integration and proxy robustness modules; expanded
test_logging_json/test_config_settings;test_streamlit_page_config; FastAPIopenapi_url/ CORSexpose_headerscoverage; unified lifespan asserting Streamlit argv includesstreamlit_run_cli_args.Safety: Reject
streamlit_run_cli_argsthat override sidecar port/address/baseUrlPath; strip CORS middleware kwargs that duplicate FluxLit-controlled keys; always set FastAPItitle/root_pathfrom settings afterfastapi_kwargsmerge.ASGI / Uvicorn:
FluxLitis a first-class ASGI app (uvicorn app:app); unified stack viaasgi_from_fluxlit/create_unified_appwith lifespan bridged to the inner FastAPI app, Streamlit sidecar lifecycle, and spec-shaped HTTP/WebSocket error responses.Imports:
load_fluxlitprefers a local./<module>.pywhen resolving targets (avoidsapp.py/PYTHONPATHshadowing); optionalFluxLit(import_target=...)for explicitmodule:attr.CLI:
fluxlit newwritesfluxlit.tomlwithtargetandgateway_port; mentionsuvicorn app:app.Tests:
tests/test_asgi_unified.pyfor lifespan, concurrent HTTP, streaming request bodies, sidecar failure, and related edge cases.Docs / roadmap: Quickstart and deployment document the simple Uvicorn entrypoint; ROADMAP adds planned Version 0.5 production-hardening themes and ties Phase 4 delivery to that track.
0.4.1¶
Docs: Fix PyPI version badge image URL in
README.md(use Shieldspypi/vbadge).
0.4.0¶
Runtime (Windows):
fluxlit shutdown/shutdown_unified_processusetaskkill /Tinstead ofos.kill(SIGTERM);--forceusestaskkill /T /F. PID liveness usesOpenProcess(avoids locale-dependenttasklistparsing).Readiness:
GET /api/readyz/fluxlit.health.probe_streamlit_readyrequire a 2xx response from the Streamlit upstream root (stricter than treating any status below 500 as ready).Gateway: Return 502 when the Streamlit upstream URL resolves empty at request time (e.g. missing state file); WebSocket connections get a clear close when upstream is missing.
Dev: On
--reload-scope=full, if the new Streamlit process does not open its port in time, terminate it, print stderr guidance, and stop the gateway.CI: Docs job runs
sphinx-build -W(warnings as errors).Docs: Windows
shutdownbehavior (taskkill); deployment, observability, and troubleshooting updates for readiness behavior.Runtime: Map IPv6 unspecified bind
::to loopback forFLUXLIT_INTERNAL_API_BASE(same as0.0.0.0).OIDC BFF: Validate
id_tokenwith IdP JWKS when usingGenericOIDCClient; optionalOIDCBFFConfig.id_token_audience/id_token_leeway_seconds; parse-only fallback for otherOIDCProviderstubs.JWT: Run PyJWT/JWKS decode in a worker thread via
anyio.to_threadto avoid blocking the event loop.Gateway: Use Latin-1 for stripped
raw_path; log exceptions while streaming proxied response bodies.API:
FluxLit.attach_oidc_loginraises if called twice on the same instance.CI: Release workflow runs
pip-audit(same as main CI);slowpytest marker;slow-testsandcoveragejobs (uploadcoverage.xmlartifact); expanded gateway and auth tests; Playwright E2E includingFLUXLIT_ROOT_PATH.Docs: OIDC in-memory store and JWKS
id_tokenbehavior in security, auth-recipes, andSECURITY.md; fix OIDC docstring cross-reference (Streamlit exchange helpers); README,docs/testing.md, index, roadmap testing table, and cross-links for the test/CI layout.
0.3.0¶
Auth (optional
fluxlit[auth]): JWT bearer validation with HS256 (dev) or JWKS (RS256/ES256),RequireScopes/RequireRoles, first-party HS256 minting for BFF flows.OIDC:
GenericOIDCClient(OpenID discovery + Authorization Code with PKCE),register_oidc_bff_routeswith one-timeauth_codeexchange for Streamlit-safe token handoff.Forward auth:
TrustedProxyUser/TrustedProxyUserConfigwith optional HTTPS and client-host checks.Client:
ApiClientdefault_headers,auth_header_factory,propagate_request_id, andApiClient.for_fluxlit(bearer_token=...).Streamlit:
exchange_auth_code_from_query,bearer_headers_from_session,prepare_streamlit_api_client.Security: opt-in
FluxlitSettings.enable_security_headersand CORS (cors_allow_origins,cors_allow_credentials);public_base_urlfor OAuth redirects;SECURITY.mdand CIpip-auditon.[auth]; PyPISecurityproject URL; sdist includesSECURITY.md.CLI:
fluxlit doctorJWT clock-skew note, OAuth/CORS guidance.Config / UX:
FLUXLIT_JWT_*,FLUXLIT_OIDC_BFF_SECRET,jwt_leeway_seconds;JWTBearer.from_fluxlit_settings,FluxLit.make_jwt_bearer,FluxLit.attach_oidc_login.Docs: security architecture, auth recipes, migration guide, README quick links and secured-API section, quickstart/index updates; reference example
examples/reference_auth/; docs extra includesitsdangerousfor Sphinx.Tests: JWT/OIDC/BFF/error-path coverage, Streamlit auth helpers, security middleware,
ApiClientheader merging / request-id propagation, friendly security ergonomics tests.
0.2.0¶
Config:
fluxlit.tomlandpyproject.toml[tool.fluxlit]for defaulttarget, bind options, and log level (fluxlit.config.project). Precedence: CLI → environment → project file → defaults.CLI:
fluxlit buildwrites a starterDockerfileand.dockerignore;fluxlit doctorreports PASS/WARN/FAIL checks (import, port bind, deps,FLUXLIT_INTERNAL_API_BASE) with optional--warnings-only.CLI:
fluxlit dev/runaccept an omittedtargetwhen configured in a project file;--reload-scope=gatewaydocuments gateway-only reload; stderr warns that Streamlit does not reload.Pages:
FluxLit.discover_pages(directory, package=...)imports sibling modules and callsregister(app)for opt-in multipage packages.Client:
ApiClient.get_model/post_modelfor Pydantic-validated JSON.Observability: Gateway sets a request id from
X-Request-ID(or generates one) vialogging_context; optionalFluxlitSettings.enable_request_loggingadds FastAPI access logs at INFO.Dependencies:
tomlion Python 3.10 for TOML parsing (stdlibtomllibon 3.11+).Docs: Sphinx + MyST site under
docs/, optionalpip install -e ".[docs]", Read the Docs config (.readthedocs.yaml), CIdocsjob, PyPIDocumentationURL points to RTD; repository planning docs live atPLAN.mdandROADMAP.md.Testing: Broader unit and integration tests (gateway edge cases, CLI,
streamlit_mainimport paths,pytest-cov+ Coverage config for thesrc/layout).
0.1.0¶
Unified gateway + sidecar runtime (single public port; HTTP + WebSocket proxy to Streamlit).
CLI:
dev,run,new,doctor.Configurable API prefix (
api_mount_path/ gatewayapi_prefix) with/apidefault.Runtime hardening (gateway stops if Streamlit exits; improved shutdown behavior).
Testing support:
FluxLit-native
FluxLitTestClientFastAPI/Starlette TestClient tests for gateway routing
Streamlit AppTest coverage (version-dependent)
CLI + ApiClient contract tests
CI (GitHub Actions) and contributor docs.