Repository navigation
Security hardening (CSRF, rate-limiting, secure cookies) + dev tooling - #1
Merged
Merged
Conversation
Add a dev toolchain and wire it into the Tests workflow so every PR is linted, type-checked, and measured for coverage before images publish. - ruff: pycodestyle/pyflakes/isort/bugbear/comprehensions/pyupgrade, with the codebase's deliberate style (compact `if cond: return` guards, FastHTML's repeated get/post handlers, FT component calls) configured out. - mypy: scoped to the FT-free logic/data layer (FastHTML's dynamically generated tags can't be resolved from `import *`); union-attr disabled for sqlite-utils' Table|View access pattern. - coverage via pytest-cov. - .gitignore the coverage artifacts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Security hardening - CSRF protection (app/csrf.py): a per-session token, exposed in a <meta> tag, is auto-attached by client JS to POST forms (hidden field) and HTMX requests (X-CSRFToken header). A Beforeware ahead of the auth gate rejects any unsafe request whose token doesn't match the session — covering /login and /setup too. No per-form changes required. - Auth rate limiting (app/ratelimit.py): 10 attempts / 5 min per client on /login and /setup throttles online password guessing. - Secure cookies: SUBTRACKER_SECURE_COOKIES=1 marks the session cookie Secure and sets SameSite=strict (off by default for plain-HTTP dev). Permission constants - Extract the permission catalog into a dependency-free app/permissions.py with a Perm class (single source of truth for names). Migrate all 53 call sites from string literals to constants so a typo is an AttributeError at import time, not a silent allow/deny. Type/lint cleanup - Fix implicit-Optional annotations across the logic/data layer and a few missing var annotations so mypy is clean; apply ruff's import sorting. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Expand the suite from 43 to 66 tests: - CSRF: tokenless/wrong-token POSTs are 403; valid form token and the HTMX header path both pass; pages expose the <meta> token. - Rate limiter: unit behaviour + /login throttling after too many tries. - RBAC at the HTTP layer: a viewer is denied the new/create routes and the admin/users pages; a team admin is allowed — guarding the per-route permission checks, not just the resolver. - Subscription lifecycle: create -> edit -> soft-delete -> restore, and permanent-delete (row gone, audit retained). - Import/export round-trips (CSV + JSON) and bad-row reporting. - Permission-catalog drift guard: Perm constants match the catalog. conftest gains CSRF-aware post()/login()/setup_first_admin() helpers and an autouse fixture that resets the process-global rate limiter between tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The security notes claimed CSRF/rate-limiting/Secure cookies were "not yet implemented" — update to reflect what now ships, add the SUBTRACKER_SECURE_COOKIES env var, and document the ruff/mypy/coverage commands and the new modules in the project layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens the app for untrusted networks and adds a lint/type/coverage toolchain.
<meta>+ client JS (POST forms & HTMXX-CSRFTokenheader); a Beforeware rejects mismatches, including on/loginand/setup. No per-form changes required.SUBTRACKER_SECURE_COOKIES=1→Secure+SameSite=strict(off by default for plain-HTTP dev).app/permissions.pywith aPermclass; all 53 call sites migrated off string literals so a typo is an import-time error, not a silent allow/deny.Verification
ruff check✅ ·mypy✅ ·pytest66 passed (72% coverage) ✅🤖 Generated with Claude Code