CodeRigor

FREE LESSON

Capstone: an access-controlled note service policy

Compose validated requests, real tenant-scoped SQLite, object permission, session lifetime, CSRF, encoded views and allowlisted audit outputs.

A security control can work in isolation while the application around it still leaks data. A valid session can be combined with a query that omits tenant scope. A correct owner check can be bypassed by a list route. A safe error helper can be skipped by an exception handler. The capstone therefore composes a small, explicit request pipeline and tests both returned results and database state.

The toy service is an ordinary Python function. It receives an in-memory SQLite connection, a trusted session store, a request dictionary and an explicit clock. It opens no listening socket and runs no browser. Its status numbers and dictionaries model a service interface; they are not real HTTP responses. The build is graded with executed public and hidden fixtures, not a project-completion checkbox.

A request earns authority one boundary at a time
start / 3
Every failing gate returns a fixed response before a database write.
A request earns authority one boundary at a time
Every failing gate returns a fixed response before a database write.

A request may contain only method, session, note_id, csrf and text. Unknown fields are rejected. In particular, the request cannot mass-assign a new owner, tenant or role. The trusted principal comes from a live, unrevoked session. The note identifier uses the earlier canonical ASCII spelling. GET reads; POST updates text after an additional CSRF check and comment validation. No other method is supported.

The query binds both tenant and note ID. This tenant filter is part of the authorization composition: the supplied role helper assumes its row is already scoped. A tenant administrator or auditor can read any row in that tenant; a member can read only owned rows. Updates allow members on their own rows and administrators on any row in their tenant. Auditors remain read-only. Missing and unauthorized objects produce the same public 404 body in this fixture, reducing direct existence disclosure through that response contract. It does not equalize timing or all observable behavior.

Check both output and state
start / 2
A denied request leaves every row unchanged; a permitted update changes only the selected text.
Check both output and state
A denied request leaves every row unchanged; a permitted update changes only the selected text.

A successful response renders original note text with the fixed HTML text encoder. Updates bind the new text through SQLite, so punctuation remains data in storage and is encoded only in the view. Audit lines contain only action, authenticated actor ID and status; they never copy the session cookie, CSRF value, request text or arbitrary request dictionary.

Python
from html import escape
original = "Jo's <draft> & notes"
print(original)
print("<p>" + escape(original, quote=True) + "</p>")

The two lines represent one text value at different boundaries. The database should retain the first value, while the view uses the second representation. A hidden test reads stored text after an update to catch premature HTML encoding.

Failure must precede mutation. Expired sessions, tenant mismatches, read-only roles, wrong CSRF tokens and malformed text cannot change the note. Tests take snapshots before these requests, then compare all rows and change counts afterward. The caller owns transaction completion: the function does not commit or roll back, including after successful updates. Unexpected database failures propagate to a surrounding service layer, which would need transaction cleanup and a generic exception response; this lab does not implement that layer.

Before submission, trace a tenant-7 administrator requesting a tenant-9 note and an auditor submitting a valid CSRF token. Neither a strong role nor a correct token can remove an earlier scope or action restriction. Completing the capstone demonstrates a specific local policy composition and regression method. Real authentication issuance, browser behavior, filesystem uploads, deployment and broader threat modeling remain separate work.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Review 39:26–59:57 (SQL values), 1:07:51–1:12:44 (server-side validation) and 1:12:44–1:28:39 (CSRF). The capstone adds the explicit tenant/object policy and local regression evidence.