Skip to main content
Enterprise AI, decodedJune 2026

May 26, 2026Case Study

Authorisation by Impact Radius: A Field Note on Building Deterministic Governance for a Code Agent

Almost every code agent today is governed at the file level — can it touch this file? — and that is the wrong question. The blast radius of a change is not a property of the file; it is a property of the features that depend on it. Authorise an agent to edit a timezone utility and you may have silently authorised it to break invoicing, audit timestamps, and regulatory reporting, with a clean file-level check and a regulator letter three weeks later. This field note, from a working bug-fix agent on a Python and React codebase, shows the right floor: join the codebase's technical-structure graph (extracted automatically) to a business-meaning graph mapping modules to features (authored by hand), and let a deterministic enforcer walk the join to authorise across a change's full feature footprint before any code is written. The property that matters most is that the agent's own correctness is not load-bearing for authorisation correctness — the enforcer reads the real code graph, not the agent's claims. The costly part, authoring the meaning layer, becomes self-maintaining when feature tags are left inline as the agent works. And the pattern generalises to any consequential agent whose technical objects differ from the business objects authorisation must reason about.

8 minCore Agent ArchitectureKnowledge Graphs & OntologySemantic Layer & Enterprise SemanticsGovernance Risk & TrustTraceability & Explainability

§ 01

Frame


This is a field note, not a product pitch. A few months ago I built an experimental bug-fix agent against a Python + React codebase. The agent read user-reported issues, proposed fixes, and — if a deterministic authorisation layer let it — ran the fix through a test bed and promoted the result. If anything regressed, a human took over.

The interesting part is not the agent. Agents are getting cheap. The interesting part is the layer that decided whether the agent was allowed to act, and on what basis. I built that layer around an idea most code-agent governance is still missing: file-level authorisation is the wrong floor. The right floor is impact-radius authorisation in business terms — what features does this change impact, and is the agent authorised across all of them?

This piece is about the architectural shape, not the stack. Companion piece in this Knowledge Hub: Microsoft's Agent Governance Toolkit review, which explains where this layer fits in the broader agent governance market.

§ 02

The wrong question code agents are being asked


Most code agents in 2026 — Claude Code, Cursor agent mode, Copilot Workspace, the long tail of in-house bug-fix bots — are governed at the file level. CODEOWNERS rules, branch protection, lint policies, PR review requirements. The control story is "can the agent touch this file?"

That question is wrong.

A bug-fix agent that touches timezone_utils.py is not asking "may I modify this file?" It is asking "may I make a change whose downstream impact will ripple through every feature that depends on date and time parsing — invoicing, scheduling, audit logs, notifications, regulatory timestamping — given that I cannot verify in advance which features will or will not regress?"

File-level authorisation cannot answer that question. The blast radius of a change is not a property of the file. It is a property of the features that depend on the file. If you authorise an agent at the file level, you are authorising it on the wrong unit of analysis. You will eventually ship a change whose file-level authorisation was clean and whose feature-level impact was a regulator letter, a customer-experience incident, or both.

The right unit of analysis for code-agent authorisation is the feature footprint of the proposed change. To compute that, you need two things most engineering organisations do not have in a queryable form:

  • A graph of the code's technical structure — what functions exist, what calls what, what depends on what.
  • A graph of the code's business meaning — which modules implement which features that real users and real teams actually care about.
  • And you need them joined.

    § 03

    What I built


    Two graph layers, joined at the module level.

    The technical-structure graph was extracted automatically from the codebase. Standard tooling can do this for any modern language — functions, classes, imports, call edges, all derived deterministically from the source. No human authoring needed.

    The business-meaning graph I authored by hand. Each node was a user-facing feature — bug reporting, issue triage, notification dispatch, audit log timestamping. Each feature had an implements relationship pointing to the modules that physically realise it. Many-to-many: a single module could implement multiple features, and a single feature was typically implemented across multiple modules.

    The agent's workflow was simple: before any code was written, the agent submitted its proposed change to an enforcer service. The enforcer walked the join — from the proposed code change, to the modules affected, to the features impacted, to the authorisation envelope. If the agent was authorised across the full feature footprint, the fix proceeded to a test bed. If not, it escalated to a human-in-the-loop, with the impact closure attached as the reason.

    Concretely: a user reports a timezone bug in notifications. The agent proposes a fix to a utility function. The enforcer walks the graph and finds the utility is implementing four features — notification dispatch, audit log timestamping, PR composition timestamping, test bed report timestamping. The agent's authorisation envelope covers only two of them. Decision: deny, escalate to HITL. The reviewer sees the impact closure in one screen and decides whether to widen the envelope or take the fix over.

    Compare what file-level authorisation would have done: "Can the agent edit timezone_utils.py? Yes." Ship. Audit log timestamps regress silently. Compliance discovers it during a review three weeks later.

    The difference is not better tooling. It is asking the right question.

    § 04

    What worked, and the property that mattered most


    Decisions were deterministic. Same proposed change, same graph state, same decision. The agent's reasoning could be probabilistic; the gate it had to pass through was not.

    Decisions were audit-replayable. Every Check could be re-run later against the graph state at the time and produce the same answer. Most authorisation systems do not give you that.

    And most importantly: the agent's own correctness was no longer load-bearing for authorisation correctness. The agent supplied only the change it wanted to make. The enforcer resolved the impact closure independently. If the agent omitted, hallucinated, or misstated a fact about its own change, the enforcer caught it because the enforcer was reading the actual code graph, not relying on what the agent claimed.

    This is the architectural property worth paying attention to. Most agent-governance designs implicitly trust the agent to assemble the facts the policy operates on. That trust is misplaced. Authorisation should walk the graph itself.

    § 05

    The hardest part — and how to make it self-maintaining


    The technical-structure graph is essentially free. Modern tooling builds it in minutes.

    The business-meaning graph is not free. Someone has to author it. For a small codebase, a day. For a serious one, a few weeks of focused work by someone who knows what the business actually cares about. This is the cost that stops most teams from adopting this pattern.

    The way through it is to stop thinking of the feature graph as a separate artefact someone maintains, and start thinking of it as a side effect of normal coding work.

    The mechanism, in one sentence: instruct the coding agent to leave structured feature tags inline in the code as it writes, then auto-generate the mapping artefact at the end of every session by reading those tags from the AST.

    This sounds redundant. It is not. The two channels serve different purposes:

  • The mapping artefact is what the enforcer reads. Fast, structured, query-optimised. Operational.
  • The inline tags are the durable source of truth. If the mapping artefact is lost or corrupted, you can regenerate it by re-extracting the tags. If you lose the inline tags, you cannot mechanically reconstruct them from the mapping artefact — you would be reverse-engineering meaning from a downstream view.
  • The architectural principle: meaning has to be embedded where the meaning is created. Code is where features are implemented. The feature tag belongs in the code. The mapping artefact is a regeneratable view of those tags joined with the technical structure. View can be rebuilt from source. Source cannot be rebuilt from view.

    This also gives you three softer benefits. The tag is right there in the PR diff at review time, so reviewers naturally validate it. The tag travels with the function across refactors. And the inline tags are tool-agnostic — they survive any change in the rest of the stack.

    The cost equation changes meaningfully. The feature graph stops being a two-to-three-week upfront authoring project and starts being ongoing, incremental work that flows through the normal PR cycle. The architectural shape becomes economically viable for teams that previously could not justify the upfront cost.

    § 06

    Why this generalises beyond code agents


    The pattern — technical-structure graph joined to business-meaning graph, with authorisation expressed in the join — is not specific to code agents. It is the shape of relational authorisation for any consequential autonomous agent.

    A claims agent reasons about claim records, but the business cares about policies, coverages, and regulatory jurisdictions. A finance agent reasons about transactions, but the business cares about approval authorities and counterparty relationships. A supply-chain agent reasons about SKUs, but the business cares about supplier contracts and delivery obligations.

    In every case, the agent reasons about technical objects. The business cares about business objects. Authorisation has to be expressed in the join.

    The technical graph is generic enough to extract automatically. The business graph is yours to author. There is no shortcut to that part — but once you have authored it for authorisation, it serves many other purposes. Dependency analysis. Compliance scoping. Regression risk modelling. Regulatory mapping. The feature graph is not just an authz asset. It is a meaning-layer asset.

    This is the deeper reason this matters more than the agent-governance market has yet acknowledged. The authorisation question is the easiest useful question to ask of a technical-and-business join graph. Once the join exists, dozens of questions become tractable. The build cost is real. The option value is large.

    § 07

    The takeaway for CTOs and heads of engineering


    If you have a code agent in your roadmap — even experimental — file-level authorisation is the wrong floor. Move to feature-level. That means building a join between the technical structure of your codebase (free) and a business-meaning layer over it (yours to author, but self-maintaining if you do it right).

    The shape works. The market has not yet caught up. If you are building autonomous agents that act on systems with real business consequences — and most CTOs are — the question is not whether you will eventually need this. It is whether you build it consciously now or retrofit it under pressure later.

    For where this layer fits in the broader agent governance stack — content guardrails, action-layer policy engines, hardware-attested confidential computing — read the companion piece: Microsoft's Agent Governance Toolkit: An Honest Review for Enterprise Leaders.

    Built with off-the-shelf open-source components — AST extraction, an embedded triple store, SPARQL for the enforcer queries, and Celery for the test bed pipeline. Happy to talk through the specifics with anyone interested; reach out.