Skip to main content
DoneThat

AI Adoption GuideProcurementApprove

DoA compliance enforcement

AI cross-checks each approver against the delegation-of-authority matrix and flags unauthorized approvals before they post.

Procurement processRequestApproveSourceEvaluateSelectOrderReceiveReview

By Don, DoneThat’s AI coach · updated

Hold the click if the named person is not on the live matrix

DoA enforcement is a hard gate on the person who clicked, not a warning in the queue. Join that identity to the live delegation-of-authority matrix on amount, legal entity, and category. If they are over their limit, in the wrong entity, or missing from the row that covers this request, hold the approval and route it to the person the matrix actually names.

The matrix is the source of truth. Workflow defaults, manager chains, and "who usually signs this" are not. An unauthorized click that posts is a control failure even when the spend is real and the supplier is allowed.

This check runs at approve, after intake. Policy pre-check at intake can confirm supplier, catalog, and category rules. That pass does not prove the person about to click is authorized.

SAP, Coupa, Workday, and ServiceNow all host approval chains. The control is the same wherever the click happens: the named identity must match a live matrix row before the approval posts.

Match amount, entity, and category, not the org chart

Read three fields from the request and one identity from the click, then look up one matrix row.

  • Amount. Use the value DoA is written against, usually the PO or requisition total with the tax treatment your policy names. Approving a line without the header total will miss a limit.
  • Legal entity. Company code, not cost center, not plant nickname. A controller authorized in DE01 is not authorized in DE02 because they still sit in the same building.
  • Category. Capex versus opex, inventory versus services, or whichever axis your matrix actually uses. A $200,000 inventory limit does not authorize $200,000 of professional services.
  • Named identity. The person who clicked, as a stable HR or identity ID, not a display name and not a shared inbox.

If the row exists and the person is inside all three limits, the approval may post. If any axis fails, hold. Show the limit that failed and the named delegate on that row. If the row has no person, hold and send it to the DoA owner. Do not pick a manager from the org chart to keep the queue moving.

Self-approval is a separate hold: the requester cannot satisfy DoA by approving their own request, even when their limit would cover the amount.

Risk-based approval routing may add reviewers or skip courtesy layers. It cannot skip a matrix row or substitute a cheaper path when the amount requires a higher delegate.

A plant controller still in the default chain after a split

The walkthrough is illustrative, not a measured result.

A European manufacturing group splits one German company code into two: the original plant (DE01) and a new legal entity for a recently acquired warehouse (DE02). The plant controller, Anna, used to cover both sites on paper. Finance published a new matrix: Anna remains the DE01 maintenance-capex delegate up to €50,000. Above that, and for all DE02 spend in that category, the row names the regional finance director.

A €180,000 roof-repair PO is raised against DE02. The buying tool still defaults Anna as approver because her HR record still lists her as plant controller for Germany and the approval chain was copied from DE01. She clicks.

Join her identity to the live matrix: amount €180,000, entity DE02, category maintenance capex. She is over the DE01 cap even if the entity were right, and she has no DE02 row. Hold. Do not post. Route to the regional finance director named on the DE02 row. Put the failed axes on the hold reason: entity and amount, and show the €50,000 DE01 cap.

If the DE02 row is blank because finance has not named anyone yet, still hold. Queue it to the matrix owner. Filling the gap with Anna's skip-level, or with the next manager in the HR file, invents a delegate the board never authorized.

Stale HR data is the usual failure

Most false holds, and most unauthorized posts you catch in audit, come from a matrix that does not match the organization that exists this week.

Job changes, legal-entity splits, and acting cover during leave move faster than the spreadsheet or the workflow table. HR still shows last quarter's title. The buying tool still has last year's default chain. Enforcement will block legitimate work, or it will let the old controller keep signing, until those files agree.

Reconcile before you enforce:

  • Every matrix row has a person ID that still exists, a limit, an entity, a category, and an effective date.
  • Acting delegations have a start and an end. Cover during leave is a dated row, not a forwarded inbox.
  • When HR records a manager change, the matrix owner gets a work item. Do not wait for the annual policy refresh.
  • Run detection against recent approvals before you switch to blocking. The mismatches tell you whether the matrix or the org file is wrong.

If the same cost center or entity keeps failing, the threshold or the entity mapping is probably wrong. Fix the row. Do not widen the check to any director in the function.

Approval anomaly flagging will still catch unusual amounts and odd suppliers in a queue that is otherwise authorized. It is not a substitute for a missing matrix join. A familiar amount on a familiar supplier can still be an unauthorized click.

Backups and invented delegates are unauthorized clicks

When the named person is over their limit, route to the real delegate on the row. When that person is absent, route only to someone who also has a live row for the same amount, entity, and category.

A backup who is not on the matrix is an unauthorized approver with a courtesy title. Out-of-office forwarding, a team inbox, and a chat note that says "please approve while I am out" all produce the same failure. If cover is needed, the matrix owner adds a dated row. Until that row exists, the approval stays held.

Do not walk the org chart until someone with a higher title appears. Do not treat the requester's skip-level as implied authority. Do not copy the last person who approved a similar PO. Do not auto-approve because the only named delegate is on leave. Absence does not create authority. Low-risk auto-approval is a published threshold with an audit trail, not a way to clear a stuck DoA hold.

Split-PO detection belongs next to this control because people who cannot get a high enough approver will split the buy. Sequence detection is not DoA. Still reject each piece that is over the named person's limit, and hold the combined case for the delegate a single order would have required.

A policy pre-check pass is not DoA

Intake can be clean and the click can still be unauthorized.

Policy pre-check answers whether this supplier, channel, and category are allowed. DoA answers whether this person is allowed to bind the company for this amount in this entity. A request that passed intake still needs the matrix join at approve.

Keep the two reasons separate in the hold message. Mixing them trains requesters to argue policy when the problem is identity, and trains approvers to treat a green intake banner as permission to click.

The same separation applies to risk-based routing. Risk can add a category lead or skip a rubber-stamp layer. It cannot drop the matrix delegate or treat a low score as a license to post without a named, in-limit person.

If you auto-approve a low-risk band, that posting identity still needs a DoA row. A rule that says "under $5,000, no human" without one is an unauthorized posting with a nicer name.

Enforcement is finished when a held click shows the failed axis, names the live delegate or the matrix owner, and does not invent a person to keep the PO moving.

Is this worth automating for you?

Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other.

DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.

Measure the baseline first