fix: cap request bodies, link login error, add book-form retry, guard double add

Limit request bodies to 1 MiB (413 JSON), wire aria-describedby on the
login form, add Retry and cancellation to the book form load, disable
Add entry while a note POST is in flight, and poll pg_isready in README.

Claude-Session: https://claude.ai/code/session_01M9MLit5Ko3X4s7rzC5Kv7X
This commit is contained in:
2026-10-02 14:36:14 -05:00
parent 35ad0b13e2
commit 2512c67893
9 changed files with 72 additions and 13 deletions
+3
View File
@@ -18,6 +18,9 @@ MUTATING_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
def create_app() -> Flask:
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
app = Flask(__name__)
# Werkzeug buffers and parses the whole body before our validation runs, so unauthenticated
# callers could exhaust memory; 1 MiB is far above the largest legitimate payload (10,000-char note).
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024
db.init_app(app)
auth.init_app(app)
app.register_blueprint(books.bp)
+5
View File
@@ -30,3 +30,8 @@ class AppTests(ApiTestCase):
response.get_json(),
{"error": "Request body must be JSON with Content-Type: application/json"},
)
def test_oversized_body_is_rejected_before_parsing(self):
response = self.call("POST", "/api/auth/login", {"username": "a", "password": "x" * (2 * 1024 * 1024)})
self.assertEqual(response.status_code, 413)
self.assertIn("error", response.get_json())