Decomposing hardcoded roles: rewriting access control in a Django app without breaking customers
How we replaced three hardcoded roles with 46 named permissions and customer-defined roles, and proved nothing changed before changing anything.
I’m Serhii Soldatov, a software engineer. I write long-form notes on architecture, access control and refactoring live systems: what we changed, and how we proved nothing broke.
How we replaced three hardcoded roles with 46 named permissions and customer-defined roles, and proved nothing changed before changing anything.
How a one-line urllib3 security bump turned into migrating a Django app from elasticsearch-py to opensearch-py, and what we vendored to keep the API responses unchanged.
A week of investigating Playwright on a fast-moving UI ended with a recommendation to stop. Four hidden costs that make end-to-end tests cheap to start and expensive to keep.
Django's bundled bash completion only knows command names and flags. django-completion adds app labels and migration names by reading a JSON cache that is rebuilt after each manage.py command, so Tab never loads Django.
How a multi-provider SSO requirement took me from rewriting a Django SSO library to an AWS Cognito setup where adding a new identity provider needs no server code changes.