Changelog¶
0.2.5¶
Fixes
- Admin edit/create forms were completely broken for any model using
TimestampMixin(includingUser, and anythingshakti generatescaffolds by default) — datetime fields had no form-value conversion and were incorrectly required. Columns with aserver_default(likecreated_at/updated_at) are now automatically read-only, and datetime input is now parsed correctly. See Admin Panel. - The monitoring dashboard rendered health-check messages, endpoint paths, and recent-request paths without HTML-escaping — the same class of issue fixed in the admin panel in 0.2.4. Fixed;
/monitor/has no auth in front of it by default, so this is worth upgrading for even if you don't use the admin panel. - Fixed a regression from 0.2.4's endpoint-metrics grouping fix: "recent requests" was showing the route template (
/posts/{id:int}) instead of the literal path that was actually hit (/posts/42).
0.2.4¶
Fixes — all security-relevant, upgrade recommended
import shakticrashed withModuleNotFoundErroron a barepip install shakti-framework—Admin/Authwere imported eagerly, pulling insqlalchemy/bcrypt/PyJWTeven if you never touch those features.Admin,Auth,APIKey, andUserare now loaded lazily; the base install only needspyyaml.- Admin panel:
Admin(db)withoutauth=silently signed session cookies with a hardcoded, publicly-known default secret key — anyone could forge an admin session. Now raisesValueErrorat startup instead; there is no default. See Admin Panel: Signing key. - Admin panel: the entire UI (list/edit views, search, flash messages, activity log) rendered database and request values into HTML with no escaping — a stored/reflected XSS hole reachable by any regular app user, not just an admin. Every interpolation point is now HTML-escaped.
- Admin panel: CSV export didn't sanitize cell values, so a field containing
=HYPERLINK(...)(set by any app user) would execute as a formula when an admin opened the export in Excel/Sheets. Cells are now neutralized per the standard CWE-1236 mitigation. WorkflowEngine: retry-backoff timers were untrackedasynciotasks, soqueue.stop()never cancelled them, and a job waiting to retry couldn't be cancelled (onlyPENDINGjobs could). Both fixed.Cache: in-memory eviction wasn't actually LRU — it evicted whichever entry had the soonest TTL, so a permanent (ttl=0) entry was evicted first instead of protected. Now a realOrderedDict-backed LRU.Monitor: per-endpoint metrics were keyed by the raw request path, so every unique id on a parameterized route (/posts/1,/posts/2, ...) created its own permanent, never-evicted dict entry — an unbounded memory leak, and an unauthenticated way to grow memory by hitting garbage 404 paths. Now grouped by the matched route's template.hatchling<1.32andtwine>=7.0pinned in the publish pipeline for PyPI compatibility.
0.2.3 / 0.2.2¶
Added
app.static(path, directory)— static file serving viaStaticFiles/FileResponse. Missing assets always return a real404(never an SPA-fallback200); content-hashed filenames getCache-Control: public, immutable, max-age=31536000. See Routing: static files.SecurityHeadersMiddleware—Strict-Transport-Security,X-Frame-Options,X-Content-Type-Options,Referrer-Policyon by default; opt-inContent-Security-Policy/Permissions-Policy. See Middleware.
Docs
- Filled in real content for 22 previously-stubbed pages across Core, Auth, ORM, AI, Workflows, Document AI, CLI, and Deployment.