Skip to content

Segregation of Duties

Applies to: All subscriptions

Purpose

Explain the maker-checker model, state precisely what changes when it is relaxed, and make clear whose decision that is. This setting is one of the first things an auditor asks about, and "it was easier during testing" is not an answer anyone wants to give.

Audience

The customer's finance control owner and internal audit, primarily. System administrators, who make the change. Implementation consultants, who must not make it unilaterally.

Prerequisites

Reference

The model

Segregation of duties separates preparation from commitment. The person who prepares a document is not the person who commits it.

Function Role Can
Maker Tax Executive Create, edit, correct, print, view
Checker Tax Controller Everything the maker can, plus generate, cancel, approve, issue, promote

The control exists because the acts on the checker's side are irreversible or externally visible: registering an invoice with the government, cancelling a registration, issuing a document, promoting a template that changes how every future document is interpreted.

Four further separations are built into the role set:

Separation Effect
Administration from transactions An org admin manages users and configuration but cannot commit a transaction
Logistics from tax Logistics roles hold the e-Way Bill family but cannot register invoices
Assurance from operations The auditor role can view and print, and nothing else
Sign-off from processing The Approver role holds invoice.approve and no transactional permission, so approval authority can be granted without processing authority

The two role axes

Approval in Complifly is governed by two independent fields on the user record, and both are required. Setting one without the other is the most common approval misconfiguration, and it is silent — no error, no log entry, no refused request.

System role Approval role
Stored in sys_user.role sys_user.approval_role_key
Governed by config/policies.js — the permission matrix dbo.mst_approval_role — the seniority ladder
Answers May this person call the approve endpoint? Which level of a multi-level approval are they?
Values that can approve Approver, Tax Controller, Super Admin Finance Executive, Finance Manager, Finance Controller, Business Head, Plant Head, Director, CFO
Missing → 403 on the approve call; no button in the UI The user is never named by any level, so nothing reaches them

The approval ladder

Seven levels, junior to senior. The rank matters: when several rules fire on one document, the levels they require are merged and ordered by rank.

Rank Approval role Typically
10 finance_executive AP/AR staff
20 finance_manager Team lead, routine value
30 finance_controller Owns the ledger; the usual second signature
40 business_head Commercial owner of the relationship
40 plant_head Same rank — a peer, not a further step
50 director Board-level sign-off
60 cfo Highest step

Assign both fields together, on Administration > Admin & Logs > Users & Roles. The ladder is also served by GET /api/admin/approval-roles for anyone provisioning users programmatically.

A level with no holder stalls silently

Nothing checks that somebody holds each approval role the matrix uses. If exactly one person holds finance_controller and they leave, every document routed through that level stops, with no alert. Assign each level used by your matrix to at least two people — any holder can clear it, and the history records which one did.

Controls the approval workflow enforces regardless of role

Control Behaviour
Self-approval Whoever submitted a document cannot decide it, whatever role they hold. Checked on identity, not role, and not waivable — not by an org admin, not by a Super Admin
Sequence Levels are decided in order. Level 2 cannot act before level 1 has
Administrative override An administrator with admin.api may force-approve or force-reject, but must give a written reason, and every remaining level is stamped OVERRIDDEN rather than APPROVED — a bypass is legible as a bypass

What relaxing it does

Setting SOD_ENFORCED to off collapses maker permissions into checker permissions. Specifically:

Role Gains, when relaxed
Tax Executive The full checker set — generate, cancel, approve, issue, promote
Org Admin The full checker set, adding transactional authority to configuration authority
Transport Manager, Logistics Operator The full checker set, including IRN generation
Approver Nothing. Deliberately excluded from the collapse

Note the breadth. Relaxation is not a narrow adjustment to one workflow: it grants transactional authority to roles that were deliberately built without it, including logistics and administration.

Approver is excluded on purpose. An approver who inherited the checker set would gain invoice.create and invoice.issue — the ability to raise a document and then sign it off, which is the single outcome the role was added to prevent. A tenant running in SME mode therefore keeps this one separation even though it has relaxed the others.

Two approval controls also survive relaxation entirely: the approval level must still match, and nobody can approve a document they submitted. Relaxation widens who can be asked to approve; it never lets a level be skipped.

When relaxation is legitimate

There is a real case for it. A small business where one person genuinely performs preparation and commitment — because there is no second person — gains nothing from a control that only produces a blocked screen. The setting exists for that situation.

It is not legitimate as:

  • A way past an approval step that is slowing down user acceptance testing
  • A default applied because nobody decided
  • A temporary measure at go-live that is never reviewed

The distinction is whether a control owner decided, with the consequence understood.

Whose decision it is

The customer's finance control owner, not the implementation team and not the system administrator who makes the change.

Record:

Record Why
Who decided An auditor will ask
When To establish the period affected
The business reason "No second person available" is a reason; "faster" is not
Compensating controls, if any Review of issued documents, for example
Review date Circumstances change as an organisation grows

If relaxation is not acceptable but staffing is thin

Options short of relaxing the setting:

Option Trade-off
One checker covering several areas Concentrates authority in one person, but keeps preparation separate
A checker outside the immediate team Slower, but preserves the control
Relax for one GSTIN only The setting is per registration, so a small subsidiary can differ from the group
Relax with a compensating review Documented review of committed documents

The third option is under-used. Because the setting is per GSTIN, a group does not have to choose one posture for every registration.

Validation

Check Method Pass condition
Current state known Check the setting per GSTIN Known for every registration, not assumed
Enforcement works With it on, sign in as a tax executive and attempt to generate an IRN Refused
Relaxation works as documented With it off in a test environment, repeat Permitted
Breadth understood With it off, check what a logistics operator can now do Confirm the customer intended to grant transactional authority to logistics
Decision recorded Change record Names the decision-maker, date and reason
Consistent across registrations Compare the setting across all GSTINs Deliberate, whether uniform or not
Compensating controls in place Where relaxed, confirm the agreed review is happening Evidenced, not merely planned
Review scheduled Operations calendar A date to revisit the decision

Troubleshooting

Symptom Cause Action
A maker cannot generate an IRN Segregation enforced. Working as designed Explain the model. Do not relax the setting to resolve a single ticket
A maker can suddenly generate an IRN Segregation relaxed Confirm this was a recorded decision. If not, re-enable and investigate who changed it
A logistics user can register invoices Relaxation collapsed their permissions into the checker set Expected effect. If unintended, this is the strongest argument for re-enabling
Auditor asks who authorised relaxation No record kept Record every control-relevant change at the time. Reconstructing it later is unconvincing
Approvals block a go-live Approval thresholds, not segregation Check the Invoice Generation thresholds first; they are a separate control
One registration behaves differently Setting differs per GSTIN Confirm it is deliberate
Relaxed during testing and never reviewed The classic failure Add a review date at the moment of relaxation, not afterwards
Customer wants partial relaxation for one action Not supported — relaxation is all or nothing per GSTIN Consider per-GSTIN relaxation, or a role change with the consequence accepted
An approver sees the workflow panel but no Approve button Their system role does not hold invoice.approve Assign the Approver system role (or Tax Controller). The approval role alone is not enough
An approver can approve, but no document ever reaches them No approval_role_key on their user record, or a different one Check both fields on the user. The panel names the role the document is waiting on
A document sits PENDING with nobody able to act The level names an approval role no active user holds Assign that approval role to someone. This is why levels want two holders
A senior approval appears in the history as OVERRIDDEN It was taken through Force Approve rather than by the named approver Expected if an administrator bypassed. If it is happening routinely, the approvers are not set up — fix the roles rather than normalising the override
A user cannot approve their own document even as Super Admin Self-approval is blocked on identity and is not waivable Correct behaviour. Use Force Approve with a reason, or have another holder of the level decide