Repository navigation
v0.0.39
·
26 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Added
EventBus.publish_durable_or_inline(event, db): enqueue durably when a transport is
installed, otherwise run the durable handlers inline indb's transaction (#583).
Changed
- Frontend: every page that posts through the Inertia router now shows a toast on failure (sharing revoke, dashboard Doctor rerun included);
useLeaveGuardlives in@simple-module-py/ui, the background-tasks outbox confirms through the shared dialog instead ofwindow.confirm, andreportClientError()is the single hook the error boundary reports through (#601). - Users: lockout, registration and bulk-invite writes that must land before the request ends
now commit throughsimple_module_db.independent_session(its own short-lived session)
instead of committing the request session. Failed or unverified password logins now roll
back the request session before the lockout bookkeeping is checkpointed. Lockout,
invite and demo code moved into internal subpackages (#592). - Users login lockout raises
LoginLockedError, mapped to the same 429 body andRetry-After
by a registered exception handler; settings errors now share aSettingsErrorbase (their
HTTP mapping is unchanged). The convention is in
docs/module-authoring.mdand the module scaffold (#595). - Packaging: Behaviour change. Published packages now cap their third-party runtime
dependencies (next major for 1.x+ libraries, next minor for 0.x ones such assqlmodel), so
an install can no longer resolve an untested major release (#600). make migrationnow requiresLABEL=<branch label>and autogenerates against
<label>@head, instead of failing with "Multiple heads" (#598).- Release: a pre-flight job lists any package that is not yet on PyPI (needs a pending
publisher) before anything is published, and publish legs skip versions that already exist,
so a half-failed release can be re-run (#599). make test-py/make test-py-pgnow default to 4 pytest-xdist workers instead of
-n auto, so concurrent runs on many-core machines don't exhaust memory;
PYTEST_WORKERS=autorestores the old behaviour.- Hosting: one
simple_module_hosting.public_access.is_public(app, method, path)answers
"is this route public?" forAuthMiddleware, maintenance mode, rate limiting and the
SM031check, so they can no longer disagree. A legacy auth provider whose deprecated
get_public_paths()raises is now logged everywhere instead of silently treated as not
public in route access (#593). - Framework: fail-open error handlers in the setup gate, DB listeners, menu providers, plural
rules and the invalidation decoder now log a WARNING (once) with the traceback instead of
failing silently; outcomes are unchanged. The policy is indocs/framework-conventions.md.
The test plugin resets the process-wide mail sender, lease backend and Sentry state per test. The
register_event_handlers(app=None)default and therequires_framework=Nonebypass are
tracked for removal in 0.1.0 (#594).
Fixed
- Users: read-only demo mode now follows the resolved identity, not only the session cookie. Writes made with a bearer access token or personal API token of a demo account are refused (403
DEMO_READ_ONLY, or the Inertia 409 redirect) through the newAuthState.principal_guardshook, and demo accounts can no longer mint tokens viaPOST /api/users/auth/tokenor/token/refreshwhiledemo_read_onlyis on (#611). - Users: the default user role is created at startup when missing, so an app scaffolded with
smpy new(schema baseline, no data migrations) can register users (#600). - Tenants: deleting a tenant now tears down its data.
TenantDeleted(now defined in
simple_module_core.tenant_events, still importable fromtenants.contracts.events) is
published durably, and file_storage (files, upload sessions, then backend objects after
commit), api_tokens, sharing, feature_flags and the framework's tenant-scoped settings
overrides (including branding) purge that tenant's rows; audit history is kept. On multi-tenant
installs, public files of a deleted tenant answer 404 at once (the existence check is cached
60 s per worker and evicted on every worker byTENANT_DELETED_CHANNEL). Withoutbackground_tasksthe handlers run inline in
the deleting transaction. Rows orphaned by earlier deletions are not purged retroactively (#583). - File storage: a file whose
backendis not the active backend is no longer read or deleted
through the wrong store: downloads, public reads and thumbnails answer 409 with a translated
message, and a delete soft-deletes the row but leaves the object alone (logged). Switching
backends still needs a manual migration; seedocs/modules/file_storage.md(#589). - Background tasks:
enqueue_after_commitis documented as at-most-once (a broker outage after
commit loses the task; usepublish_durablefor must-run work). file_storage gains an hourly
file_storage.reconcile_checksumsbeat task that re-enqueues checksums for files left without
one for 30 minutes, up to 500 per run (#590).
Removed
- Frontend:
@simple-module-py/uino longer depends onreact-hook-form/@hookform/resolvers, and the unused shadcnformcomponent is removed;host/client_appdrops the unusedzodanddate-fns(#601). Behaviour change for anyone importing@simple-module-py/ui/components/ui/form.