Authorization in Django: From Permissions to Policies — Part 11 — A Full Workflow, End to End
Tracing a Single Request Through Authority, Validity, and State

By now, the system is no longer abstract.
We are past definitions and isolated boundaries. Three layers are in place—permissions, policies, and invariants—each with a narrow responsibility and a distinct failure mode.
What remains is to see them operate together.
Not as a framework feature or a checklist, but as a single request moving through a real system—without blurred responsibilities, duplicated logic, or hidden assumptions.
This part follows that path end to end.
— From request handling to state mutation.
— From permission to policy to invariant enforcement.
The Scenario
Consider a familiar operation.
A user attempts to publish an article.
At a glance, this appears simple. In practice, it crosses every boundary discussed so far.
Publishing is:
An action not everyone may attempt
A transition valid only under certain conditions
A state change that must never partially occur
It is an ideal example not because it is exceptional, but because it is ordinary.
Step 1: Permission — May This Actor Attempt This Action?
The request enters the system.
The first question is intentionally narrow:
Is this user allowed to attempt publishing at all?
This is a permission check.
Not this article.
Not now.
Not under these conditions.
Only capability.
The system consults stable, declarative data:
Does the user possess the publish_article permission?
No article state is examined.
No ownership is inferred.
No workflow is consulted.
If this check fails, the request ends immediately.
The system has not rejected the action. It has rejected the actor.
That distinction is foundational.
Step 2: Policy — Is This Action Valid Right Now?
Once capability is established, context becomes relevant. This is where policy applies.
Policies answer a different question: Given the current state of the system, is publishing valid at this moment?
Here, the system may evaluate:
Is the article still a draft?
Has it already been published?
Is the user the owner or an assigned editor?
Are all required fields complete?
Is publishing allowed at this time?
— These checks are conditional.
— They are domain-specific.
— They evolve as the system evolves.
Crucially, they are evaluated before any irreversible change occurs.
When a policy fails, the meaning is precise:
The user is allowed to attempt this action
But this specific attempt conflicts with current state or rules
This is not a lack of authority.
It is a lack of validity now.
The request is denied, and the system remains unchanged.
Step 3: Approaching Mutation
At this point, two things are true:
The actor is permitted to attempt the action
The action is valid under current policy
Yet this is still not enough.
The most serious failures do not come from missing permission checks or incorrect policies. They arise during mutation:
Concurrent requests
Retries after partial failure
Background jobs bypassing request paths
Bugs that skip checks entirely
This is where the final layer becomes decisive.
Step 4: Invariants — What Must Never Be False?
Publishing is not just an action. It is a commitment.
Once published:
The article cannot revert to draft
Publication metadata must exist and agree
Related records must reflect the same state
The transition must be atomic
These are not decisions. They are guarantees.
Invariants are enforced at the point of state mutation:
Inside database transactions
Through constraints and guarded updates
Via explicit, irreversible transition logic
When an invariant fails, the system does not deny a request. It rejects a state.
That distinction matters.
An invariant violation means the system was about to become invalid—regardless of who initiated the change or why.
The correct response is rollback, logging, and alerting. The system protects itself.
Failure Modes, Clearly Separated
Seen together, the layers fail in fundamentally different ways:
Permission failure — The actor should never have been allowed to attempt this.
Policy failure — The request is understandable, but invalid under current conditions.
Invariant failure — The system was about to enter an impossible state.
Each failure tells a different story.
Each demands a different response.
None is interchangeable.
Why This Holds Under Pressure
Now consider real-world stress:
Two publish requests arrive simultaneously
A background worker retries after a timeout
An internal script bypasses HTTP entirely
A partial refactor omits a policy check
The system remains correct—not because every path is perfect, but because guarantees are enforced where mistakes cannot bypass them.
Permissions limit surface area.
Policies govern intent.
Invariants enforce reality.
This is not defensive programming. It is structural integrity.
The Architecture, Fully Assembled
At the end of the request, the system has done exactly three things:
Verified capability
Evaluated contextual validity
Enforced irreversible truth
Nothing leaked.
Nothing duplicated.
Nothing was silently trusted.
This is what it means for authorization to be architectural rather than procedural.
Where We Go Next (Part 12 Preview)
We have now followed a request all the way through:
Entry → Authorization → Policy → Mutation → Enforced Reality
What remains is to examine what happens when these boundaries collapse—when permissions attempt to encode state, when policies try to guarantee truth, or when invariants are treated as optional.
That is where systems fail.
The next part examines those failure modes directly.
Not as hypotheticals, but as architectural patterns observed in real systems, under real load.
Bibliography / References
Eric Evans (2003). Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley.
https://www.domainlanguage.com/ddd/Martin Fowler (2003). Patterns of Enterprise Application Architecture. Addison-Wesley.
https://martinfowler.com/books/eaa.htmlMartin Kleppmann (2017). Designing Data-Intensive Applications. O’Reilly Media.
https://dataintensive.net/Vaughn Vernon (2013). Implementing Domain-Driven Design. Addison-Wesley.
https://vaughnvernon.co/?page_id=168Django Software Foundation. Django Authorization Overview (Permissions and Authentication).
https://docs.djangoproject.com/en/stable/topics/auth/Pat Helland (2015). Immutability Changes Everything. Communications of the ACM.
https://queue.acm.org/detail.cfm?id=2884038



