Skip to content

Releases: fsecada01/component-framework

v0.5.1b0 — Epic A: state security (signing, locked fields, CSRF audit)

Choose a tag to compare

@fsecada01 fsecada01 released this 01 Jul 21:36

Interim beta release shipping Epic A — State Security & Integrity (#21) complete. v0.6.0b0 remains reserved for the full Hardening Foundation milestone once Epic B (DOM morphing) lands.

Added

  • HMAC-signed client state (A1, #35) — stdlib-only core/signing.py: StateSigner (HMAC-SHA256, versioned cfs1.<payload>.<mac> tokens) + CorruptStateError. Enable via StateSigner.configure(secret) or STATE_SIGNING_KEY; comma-separated keys enable rotation (first signs, all verify). Enabled: all outbound state signed, tampered/unsigned/raw-dict inbound rejected with 400. Disabled: legacy behavior + one-time warning. See docs/STATE_SIGNING.md.
  • Locked server-trusted state fields (A3, #37)locked_fields: ClassVar[frozenset[str]] for state keys the client must never influence. Excluded from dehydrate(), stripped on hydrate() with a warning; enforced in the core lifecycle so all adapters are covered. See docs/LOCKED_FIELDS.md.

Security

  • Closed the dict bypass: all adapters route inbound state through StateSerializer.load_untrusted() — state can no longer be submitted as a raw JSON object to skip verification.
  • Replay/rollback gap closed: stale-but-validly-signed state can no longer roll back server-owned fields.
  • Django ComponentView.handle_error() maps client input errors (ValueError, incl. corrupt state) to 400 instead of 500.

Documentation

  • docs/SECURITY_CSRF.md (A4, #36) — per-adapter CSRF coverage table (Django-only today), the form-encoded no-preflight CSRF vector, and CSWSH guidance for all WebSocket adapters.
  • docs/STATE_SIGNING.md (A2) — per-adapter key setup + rotation procedure.

Full test suite: 477 passed across Python 3.11–3.14 (36 new signing tests, 21 new locked-fields tests, zero regressions).

🤖 Generated with Claude Code

v0.5.0b0 — Flask adapter, optimistic UI

Choose a tag to compare

@fsecada01 fsecada01 released this 24 Jun 20:48
6bfdb22

Minor beta release bundling three features merged since v0.4.1b0.

Highlights

  • Flask adapter ([flask] extra) — FlaskRenderer (Jinja2-backed, shares the app's jinja_env) plus a synchronous component endpoint exposed as a Flask blueprint (POST /components/<name> via register_component_routes(app)). Parses JSON and HTMX form-encoded bodies; JSON 404/400/500 errors. The [flask] extra pulls only flask>=3.0. See examples/flask_example.py. (#5)
  • Optimistic UI patchingcomponent-client.js applies an optimistic patch synchronously before the request resolves (reading data-optimistic / data-optimistic-toggle), rolling back on the server response. Ships component-framework.css with [data-loading]/[data-optimistic] hooks and updated .d.ts typings. (#16)
  • Sharing an existing JinjaX catalog — guidance + docs for constructing JinjaxRenderer with the host app's existing Catalog so component templates inherit globals and filters. (#13)

Changed

  • [all] and [dev] extras groups now include the flask extra.

Install

pip install "component-framework[flask]==0.5.0b0"

API docs: https://fsecada01.github.io/component-framework/

Full Changelog: v0.4.1b0...v0.5.0b0

v0.4.1-beta

v0.4.1-beta Pre-release
Pre-release

Choose a tag to compare

@fsecada01 fsecada01 released this 25 Mar 20:18

What's Fixed in 0.4.1-beta

HTMX Form-Encoded Request Support (#15)

FastAPI and Litestar adapters now accept both application/json and application/x-www-form-urlencoded requests. Previously, HTMX's default form-encoded POSTs caused 400 Bad Request errors.

  • Both adapters detect content-type and parse accordingly
  • JSON string values in form fields (payload, params, state) are auto-parsed
  • Matches the existing Django adapter behavior
  • Added python-multipart to [fastapi] extras (required by Starlette for form parsing)

CI Fix

  • Suppressed ty invalid-method-override warnings for intentional Django CBV/Channels Liskov violations
  • Applied ruff format to SSE test files

Docs

  • Added Litestar setup guide (docs/site-pages/litestar-guide.html)
  • Replaced JS EventSource snippet with HTMX SSE extension markup
  • Updated all site page navigation to include Litestar Guide
  • Updated version badges and framework references across docs

Install: pip install "component-framework[fastapi,litestar,django]==0.4.1b0"

Full Changelog: v0.4.0b0...v0.4.1b0

v0.4.0-beta

v0.4.0-beta Pre-release
Pre-release

Choose a tag to compare

@fsecada01 fsecada01 released this 25 Mar 02:31

What's New in 0.4.0-beta

Litestar Adapter (#6)

First-class Litestar adapter with the same ergonomics as FastAPI and Django:

  • component_endpoint + create_component_routes() for HTTP
  • LitestarWebSocketConnection + WebSocket endpoint
  • [litestar] optional extras group: pip install "component-framework[litestar]"
  • Example app in examples/litestar_example.py

Async Event Handlers (#10)

async def on_* handlers are now properly awaited:

  • Component.async_dispatch() — async entry point for async adapters
  • Component.async_handle_event() — awaits coroutine handlers, works with sync too
  • FastAPI, Litestar, and WebSocket adapters updated to use async_dispatch
  • Sync handle_event() now raises ComponentError if the handler is async (fail-fast instead of silently dropping the coroutine)

SSE Streaming (#12)

StreamingComponent subclass for long-running operations that emit intermediate renders via Server-Sent Events:

class RagQueryComponent(StreamingComponent):
    async def on_analyze(self, query: str):
        async for step in rag_service.stream(query):
            self.state["step"] = step
            yield  # emit intermediate SSE frame
        self.state["done"] = True
  • POST /components/{name}/stream endpoint for FastAPI and Litestar
  • Each yield triggers a render and emits data: {"html": ..., "state": ...}
  • Non-generator handlers gracefully produce a single frame

State Size Guard (#14)

StateSerializer.serialize() now checks serialised state size:

  • Warning at 64 KB (configurable via StateSerializer.warn_bytes)
  • Hard error at 512 KB (configurable via StateSerializer.max_bytes)
  • Both thresholds can be disabled by setting to 0

Bug Fix: JS Double-Serialisation (#11)

Fixed component-client.js double-stringifying the payload field. Added server-side guards in FastAPI and Litestar adapters for backward compatibility with cached older JS.


Install: pip install "component-framework[fastapi,litestar,django]==0.4.0b0"

Full Changelog: v0.3.1b0...v0.4.0b0

v0.3.1b0 — Registry idempotency, static file namespacing

Choose a tag to compare

@fsecada01 fsecada01 released this 24 Feb 02:50

What's new in 0.3.1

Patch release fixing two bugs surfaced by real-world Django integration (closes #8, #9).

Fix: registry idempotency (#8)

registry.register() previously raised ValueError any time the same component name was seen a second time — including during Django test discovery, where the test runner adds multiple paths to sys.path and the same module file ends up imported under two different dotted names (e.g. core.components.counter and backend.core.components.counter).

registry.register() now accepts re-registration of the same class under the same name as a silent no-op. Genuine conflicts — a different class trying to claim an already-registered name — still raise ValueError with a clearer message.

Before (workaround required):

# Had to abandon the decorator API entirely
class Counter(Component):
    ...

if registry.get("counter") is None:
    registry.register("counter")(Counter)

After (clean decorator API works again):

@registry.register("counter")
class Counter(Component):
    ...

Fix: static file namespacing (#9)

component-client.js was shipped at static/js/component-client.js inside the package. Django's AppDirectoriesFinder strips the static/ prefix, so collectstatic placed the file at js/component-client.js in STATIC_ROOT — a bare path that collides with any other app shipping files into js/ and does not match the documented {% static 'component_framework/js/component-client.js' %} tag.

The file is now at static/component_framework/js/component-client.js, following the Django app static file namespacing convention. collectstatic now produces component_framework/js/component-client.js.

Update your base template if you used the workaround path:

<!-- Before (workaround) -->
<script src="{% static 'js/component-client.js' %}"></script>

<!-- After (correct, documented path) -->
<script src="{% static 'component_framework/js/component-client.js' %}"></script>

Upgrading

pip install "component-framework==0.3.1b0"
# or via uv:
uv add "component-framework==0.3.1b0"

Full changelog: v0.3.0b0...v0.3.1b0

v0.3.0b0 — Optional extras, docs overhaul

Choose a tag to compare

@fsecada01 fsecada01 released this 24 Feb 02:50

What's new in 0.3.0

Breaking change — optional extras

FastAPI, Uvicorn, and JinjaX are no longer installed by default. Django-only projects no longer pull in the FastAPI stack as a dependency.

Before (0.2.x):

pip install component-framework

After (0.3.0+):

# Django only (default)
pip install component-framework

# FastAPI + JinjaX
pip install "component-framework[fastapi]"

# Everything
pip install "component-framework[all]"

Docs site

A full API reference site is now published via GitHub Pages, built with pdoc and a custom dark-themed template. Includes worked examples for e-commerce, admin panels, customer support, LMS, and financial dashboards.

Changes since 0.2.0-beta

Features

  • feat(deps): Make FastAPI/Uvicorn/JinjaX optional extras — Django projects install a significantly smaller dependency footprint (#7)

Fixes

  • fix(ci): Use full install for test job so conftest.py Django imports resolve correctly
  • fix(tests): Restore original adapter modules after _reload_adapter in test teardown to prevent state leakage between tests
  • fix(docs): Correct JS URL detection, root index links, and lint errors in docs pipeline
  • fix(docs): Bridge nav-dropdown hover gap with ::after pseudo-element to prevent menu flicker

Docs

  • Ratify project constitution v1.0.0 and propagate to speckit templates
  • Overhaul pdoc template: full dark theme, fixed version bar, highlight.js colour palette
  • Add Terminal Modern UI, home page, e-commerce example, and site-pages pipeline
  • Add admin panel, customer support, LMS, and financial dashboard examples
  • Update version references and install commands throughout

Full changelog: 0.2.0-beta...v0.3.0b0