Case study
Access that expires by default: SharePoint governance under a no custom code rule
The client is a major Australian resources business, and their security posture rules out any application that holds their documents outside SharePoint. So we built the governance inside it: request buttons in the document library, approval routing that finds its own approver, permissions that expire on a clock, and an audit report that tells the business what it has actually granted.
Published anonymously at the client's protection. The client is a major Australian resources business, headquartered in Perth.
- Sector
- Mining and resources, Perth, operating nationally
- Shape of the work
- SharePoint-native governance tooling, SPFx and Power Automate
- Hard constraint
- No custom code, and no document, may leave the SharePoint tenant
- Delivered
- Four SPFx extensions plus the approval flows and audit reporting behind them
Why this one is anonymous
The client is a major resources business, and the material this system governs is exactly the material they would not want described. Project names, site names, document classifications and the shape of who is allowed to see what are all part of their commercial and security position. So this case study names no client, no site, no project stream and no individual. What is described is the design and the reasoning, which is the part that transfers.
It is worth saying what the system is not. It holds no operational technology, no process control and no safety systems. It governs documents in SharePoint and who may read them.
The rule that shaped everything: nothing leaves SharePoint
An organisation of this size does not evaluate a vendor's web application on its merits. It has a platform standard, and the standard says the documents live in the Microsoft 365 tenant and nothing custom sits outside it holding a copy or a credential. There is no server we could stand up, no database we could keep, and no integration that ships a document somewhere for processing.
That is a real constraint and we treated it as the brief rather than as an obstacle to negotiate. Everything we built runs as SharePoint Framework extensions inside the page the user is already looking at, or as Power Automate flows inside their own tenant. No component of it holds data, and there is nothing to decommission if the relationship ends: the lists, the flows and the extensions are all theirs, in their tenancy, from day one.
The problem: access that only ever accumulated
Sharing in SharePoint is easy, which is the problem. Anyone with edit rights can grant access to a folder in three clicks, and nothing in the product asks why, for how long, or whether the person on the other end is allowed to see it. Grants are permanent unless somebody remembers to remove them, and nobody remembers.
Compounding it, the answer to "who can see this document?" was genuinely hard to produce. Unique permissions were scattered through a deep folder tree at every level, held sometimes by a person and sometimes by a group, and reading them back meant walking the tree by hand. A business that cannot answer that question cannot review it, and a governance policy nobody can audit against is a document rather than a control.
There was a matching problem with classification. Documents were meant to carry a data classification and to live in the folder that matched it, but the two drifted. Restricted content sat in general folders and general content sat in restricted ones, and nothing surfaced the mismatch.
The constraints that shaped the design
- No custom code, and no document, leaves the tenantThe platform standard rules out a hosted application, an external database or any integration that moves a document out for processing. Everything runs as SharePoint Framework extensions and Power Automate flows inside the client's own tenancy, and the client owns all of it.
- The permission model has to stay SharePoint'sA parallel record of who can see what would drift from the real permissions and would have to be trusted over them. Every grant the system makes is an ordinary SharePoint grant, readable by every tool the client already has.
- Adoption decides whether governance worksA control people route around is not a control. The tooling sits in the document library toolbar beside the commands people already use, and the request dialog asks only for what the approval actually needs.
- Anything granted must be attributable, time limited and reviewableEvery grant traces back to a request with a named requester, a justification, an approver and an end date, and the whole permission surface can be exported and filtered on a schedule.
- Fail loudly, never silentlyIf the system cannot determine an owner, verify a signed agreement or confirm a classification, it refuses and says why. In a governance tool, a quiet fallback is the failure mode that costs the most later.
What we built
A request button in the document library, replacing the native share. The user selects files or a folder, and gets a dialog rather than a share panel: who the access is for, which permission level, how many weeks it should last, and why. Nothing is granted at that moment. The dialog writes a request row to a SharePoint list, and a Power Automate flow does the granting after the request has been approved. The separation matters more than it sounds: the person asking for access no longer has the ability to grant it, even though SharePoint would have let them.
Approval routing that finds its own approver. The most common reason a governance process gets abandoned is that the requester has to know who owns the content, and they do not. So the request works it out. It checks whether the folder has been pre-approved for sharing, in which case the request skips departmental approval by design. Failing that it checks whether the folder has a nominated owner of its own. Failing that it reads the folder's owning programme from the folder itself and looks up the group that owns approvals for that programme. If it cannot determine an owner it refuses the request and says so, rather than filing it somewhere nobody is watching.
A compliance gate before the request can be submitted at all. Every named person the requester picks is checked live against the register of signed agreements, and if anyone in the list has not signed, the submit button stays disabled and names the problem. This is the cheapest place in the whole system to catch it. Catching it at approval means an approver's time; catching it after the grant means an incident.
Expiry as the default, not an option. Every request carries a duration, capped at five years, and the expiry date is calculated when the request is made rather than left to a reviewer's calendar. Scheduled automation walks the open requests, warns before the date, and on the date removes the permission from every file in the request and marks the request closed. Access decays unless somebody renews it, which inverts the default that made the original problem.
Restricted folders that are restricted from the moment they exist. Creating one is its own button rather than the standard new folder command: it creates the folder, colours it so its status is visible in the library view, breaks permission inheritance, and strips the broad membership groups off it immediately. The alternative, which is what the business had, is a folder that inherits everything for the minutes or days between someone creating it and someone remembering to lock it down. Shareable folders are colour-stamped too, in a different colour, so the state of a folder is legible from the library rather than from a permissions dialog three clicks deep.
Publishing that will not proceed without the metadata. The publish button refuses a document that has no data classification, no revision and no owning programme, checks the file is not checked out or locked by someone else, allocates a controlled document number from a central sequence, renames the file to match, and writes a publish log entry. Document control stops depending on whether the author felt like filling in the columns.
And the report that made the rest defensible. Scheduled automation walks every item in the governed libraries, page by page, and builds a workbook with two things in it. The first is a permission matrix: every file and folder holding unique permissions, every user and group on it, and a tick against each permission level they hold, filterable. The second is a classification exception report, which puts each document's expected classification next to its actual one and colour-codes the disagreement, separating a document with no classification at all from one that is classified but sitting in the wrong place. The workbook is dated and lands back in a SharePoint library, so the business has a history of its own posture rather than a snapshot.
Why this shape rather than an application
Given a free hand, a system like this is a natural web application. We did not have a free hand, and on reflection the constraint improved the result in three ways worth naming.
The tooling appears where the work already happens. Nobody has to be told to go to the governance portal, because the buttons are in the document library toolbar next to the ones they already use. Adoption of a governance process is most of the battle, and a separate destination loses it.
The permissions model stays SharePoint's. We are not maintaining a parallel idea of who can see what, which would drift from the real one and would have to be trusted over it. The grants the flows make are ordinary SharePoint grants, so every existing tool the client has still reads them correctly.
And there is no custody. We are not holding their documents, their credentials or their audit trail, which means the security review is about what the code does rather than about who we are and what our hosting looks like. For a client of this size that is the difference between a project that starts and one that stays in assessment.
Where it landed
Sharing became a request with a reason, an approver, a compliance check and an end date attached, and it happens inside the same library the document lives in. The question of who can see a given document became a report the business runs rather than an exercise somebody does. Classification drift became a filterable list of exceptions instead of an assumption.
We have not published volumes, headcount or timelines here. They are the client's numbers and they would identify the business to anybody in the sector, which is the whole reason this page is anonymous.
What generalises
Most organisations do not have a sharing problem, they have an expiry problem. Grants are made for a reason that is true in March and false by August, and nothing in the tooling notices. Attaching a duration to the request, and automating the removal, fixes more than tightening who is allowed to grant.
The second thing that generalises is that a governance control you cannot report on is not a control. The permission matrix was not the glamorous part of this build, and it is the part that let the business see whether any of the rest was working.
And if your own environment has a rule like this one, that nothing custom may sit outside the tenant, it is worth knowing that it is a workable brief rather than a dead end. There is a great deal that can be built inside SharePoint and Power Platform, and the constraint tends to produce something the client can own outright.
That last point is the one Western Australian businesses ask about most, so it has its own page: custom software development for Perth businesses, including how a Queensland team runs an engagement two hours ahead of you.
Common questions
- Our security team will not approve custom code. Is that the end of the conversation?
- No, and this build is the reason we say so. SharePoint Framework extensions run inside the client's own tenant, in the page the user is already on, and Power Automate flows run in their Power Platform environment. Nothing is hosted by us, nothing holds a copy of a document, and the client owns every component from the first day. The security review is about the code, not about our infrastructure.
- Why not just use SharePoint's own sharing and access reviews?
- Native sharing does not ask for a justification, does not route to the person who owns the content, does not check the recipient against a compliance register, and does not expire. Where a native feature does the job we use it, and the permissions this system grants are ordinary SharePoint permissions. What we added is the process around the grant.
- What happens when a request cannot find an approver?
- It stops and tells the requester. An early version of that logic could have defaulted to a fallback approver, and we deliberately did not, because a request that silently lands with the wrong person is worse than one that fails visibly. It also surfaces gaps in the ownership data, which is useful in itself.
- Does the expiry ever remove access someone still needs?
- Yes, by design, and that is the point. The requester is warned before the date and can request an extension. Access that nobody was willing to re-request was access nobody needed, and the alternative is a permission set that only ever grows.
- Can this run against our own document libraries?
- The pattern transfers directly. The specifics that would change are the approval routing, which reflects how your organisation decides who owns content, the compliance checks that gate a request, and what your classification scheme expects. The request, approve, expire and report spine is the same.
