The service account this site's automated pipeline runs under, api_publisher, is a small role: a handful of permissions in a YAML file, tracked in sync/ like every other piece of this site's configuration. Reading that file today tells you what it can do. Reading its git history tells you something more useful — a dated record of exactly which capability got added on which day, and why, because each addition landed in its own commit with its own explanation.
Day one: the minimum that could possibly work
The role's first commit, August 15, granted exactly four permissions:
access contentcreate article contentedit own article contentuse text format restricted_html
That's the complete permission set needed to create an article through the JSON:API and have its body render as anything richer than stripped plain text. Nothing about scheduling, nothing about deletion — because at that point, none of that existed yet. The pipeline could publish content and edit its own content. That was the entire feature.
The commit message for that first version is just "wip." Not a detailed writeup of the design decision — a placeholder, because at that point it genuinely was one: an early cut of the role, refined by a config re-export a few minutes later the same evening that added a missing system module dependency the role's own permissions actually required. The minimalism wasn't the result of careful upfront planning captured in a thoughtful commit message; it was the natural output of only writing down permissions for the one feature that existed yet, however roughly that got committed.
Thirteen days later: scheduling arrives, and one permission arrives with it
On August 28, a commit titled "Add drupal/scheduler for timed article publishing" adds exactly one line to the role's permission list:
schedule publishing of nodes
alongside a new scheduler module dependency. The commit message explains why this specific permission, not a broader one: it's what lets publish_article set a publish_on value through the API at all. Before this commit, there was no way for the automated account to schedule anything — articles could only be created and immediately reviewed, not queued for a future time. The permission shows up in the same commit as the feature that needed it, not before, and not as part of some anticipatory "might need this later" grant.
Later the same day: a second, narrower addition
A few hours after that, a separate commit grants one more permission:
delete own article content
The message is specific about the reason: letting the pipeline remove a node it just published if a post-publish check finds the rendered content is wrong, rather than leaving something broken sitting live. This is the narrowest possible version of "can delete things" — scoped to the role's own content, added only once a real self-correction step in the publishing process needed exactly that capability, not granted defensively alongside the earlier permissions just in case cleanup was ever necessary.
What the shape of this timeline actually shows
Three commits, thirteen days apart in the first gap and hours apart in the second, each adding exactly one capability at the moment a specific new feature required it. No commit in this history grants a permission "for later" or "just in case" — the account went from four permissions to seven, and every addition traces to a named, dated reason sitting right there in the commit message next to it. That's a different thing than reviewing a role's final permission list and judging whether it looks appropriately minimal in isolation. A YAML file with seven permissions in it, read cold, tells you the account's current capabilities and nothing about how it got there. The commit history is the part that actually demonstrates the account was built by adding exactly what was needed exactly when it was needed, rather than provisioned generously up front and never revisited.
The practical habit worth taking from this isn't "keep permissions in version control," though that's necessary for any of this to be checkable at all. It's that a service account's permission grants are worth committing one capability at a time, with the reason stated in the commit that adds it, specifically so a permission list stops being a single static artifact you have to trust and becomes a sequence of individually justified decisions you can actually go back and check, one at a time, months later.