Making an Application's Hidden Policy Visible
The database can enforce a rule correctly and still leave a team unsure what the application is allowed to ask for. This chapter focuses on that application-side boundary: access checks and query filters scattered through web code, and Ote's attempt to turn the resulting behavior into a reviewable policy. The practical value is to distinguish an explicit account of observed data access from a guarantee that every path, query, or downstream side channel has been covered.
The policy is often present only as behavior
Consider a course-management application that displays a student's grade sheet. The handler may first look up the current user's role for a requested course, reject the request if no role exists, check whether the role is that of an instructor, and only then query the grades for that course. The intended rule sounds simple: an instructor may see the grades for a course. The implemented rule is not located in one sentence. It is distributed across the role lookup, the branch conditions, the relationship between the role and course, and the query that retrieves grades.
That distribution is normal in a web application. A controller decides which operation to run. A model or library supplies data. A helper may add a condition. A later query may use a value returned by an earlier query. The access policy is therefore implicit in the set of queries the program can issue and the conditions under which it issues them. A missing check can reveal too much. An extra check can block legitimate behavior. A check can also appear to exist while a framework or library interaction silently prevents it from taking effect.
The problem worsens over time. A developer who wrote a handler may remember its purpose but not every condition that controls its database queries. A new endpoint may reuse a helper under a different assumption. A change to a model can alter which fields are loaded or when a query runs. Documentation may describe intended privacy while the program implements something broader or narrower. The application can continue to function in ordinary tests even though its actual data boundary is difficult for anyone to state precisely.
Ote approaches this problem by representing the policy as SQL view definitions. A view is a query over database tables, parameterized by trusted session information such as the current user's identity. Under this model, an application query is allowed if the information it requests can be answered using the views. The view is not a copy of one handler. It is a compact description of what data may be revealed under the conditions represented by the policy.
The distinction between trusted and untrusted inputs is central. A session identity established by authentication can legitimately appear in a policy, because it identifies the principal whose access is being described. A course ID supplied in an HTTP request is untrusted input. It may select which course the handler operates on, but it should not become a policy parameter that quietly grants access to whichever record the caller names. A view-based policy can express that a user may access their own role in any course, for example, without treating the requested course ID itself as proof of authorization.
This view formulation gives policy review three useful goals. Completeness means allowing every query the application can issue. Tightness means revealing as little information as possible while remaining complete. Conciseness means expressing the result in a form a person can read and reason about. These goals can conflict. A policy that retains every observed business condition may become verbose.