Feature Flags¶
Applies to: All subscriptions
Purpose¶
Document every per-GSTIN switch: what it does, its default, the reasoning behind that default, and the consequence of changing it. Three of these flags change what the system does without a person present, and those deserve a decision rather than a default.
Audience¶
System administrators and implementation consultants. The three off-by-default flags also concern the customer's finance control owner.
Prerequisites¶
- Modules and Licensing
- Administrator access to the permissions matrix
Reference¶
How flags resolve¶
Every GSTIN starts from a platform default so a newly provisioned registration works immediately. An explicit per-GSTIN setting, where present, always wins.
Flags are per GSTIN, never per company and never per user. A group can therefore enable a module on one registration while the rest continue unchanged — which is the right way to pilot anything with legal consequence.
Values are cached briefly for performance. A change takes effect within about a minute, or immediately on re-authentication. This is why "I changed it and nothing happened" is usually impatience rather than a fault.
The flags¶
| Flag | Default | What it controls |
|---|---|---|
EINVOICE_ENABLED |
On | e-Invoice module: IRN generation, cancellation, printing |
EWAYBILL_ENABLED |
On | e-Way Bill module: generation, Part-B, extension, consolidated bills |
RECONCILIATION_ENABLED |
On | Reconciliation and matching screens |
SOD_ENFORCED |
On | Segregation of duties. See below |
AUTO_IRN_ENABLED |
Off | Fires IRN generation automatically on ingest |
INVOICING_ENABLED |
Off | Invoice Generation Module |
ERP_WRITEBACK_ENABLED |
Off | Sends compliance outcomes back to the ERP |
IGM_CREDIT_RULE |
WARN |
Credit management. ALLOW switches it off — limits are recorded but never checked at post time; the interface labels this value OFF. WARN flags a breach and posts anyway; BLOCK refuses the post until a checker overrides it |
IGM_APPROVAL_VALUE_THRESHOLD |
0 (off) |
Invoice value above which approval is required |
IGM_APPROVAL_DISCOUNT_PCT |
0 (off) |
Discount percentage above which approval is required |
IGM_DISCOUNT_OVER_MAX_ACTION |
BLOCK |
When a line discount exceeds the item's maximum: BLOCK outright, or APPROVE (allowed, but requires approval) |
IGM_APPROVAL_ENGINE |
Off | Multi-level approval workflow, rather than the simpler threshold gate |
The three that default to off, and why¶
These share a property: enabling one changes what the system does without a person present, or sends data outward. Neither is a convenience, so neither is inherited.
AUTO_IRN_ENABLED. Fires IRN generation the moment a document is ingested. It is an automation, not a module unlock — and registering an invoice is a legal act that consumes a billed call and permanently consumes a document number. The default is off so that generation stays a decision until someone deliberately chooses otherwise. Enable it only when validation quality is proven; automating generation over a poor-quality feed produces rejections at volume.
INVOICING_ENABLED. Unlocks the Invoice Generation Module, which raises invoices inside Complifly. A module unlock with legal consequence.
ERP_WRITEBACK_ENABLED. Sends compliance outcomes to the ERP. Two properties matter operationally:
- It is enforced at emission, not at delivery. A tenant with this off stores not one outbound event — so there is nothing to purge, index, back up or explain.
- It does not backfill. Emission starts from the moment it is enabled. Seeding an ERP with existing compliance state is a separate, explicit exercise.
Segregation of duties, and what relaxing it means¶
SOD_ENFORCED defaults to on: the person who prepares a document is not the person who commits it. Preparation and commitment sit with different roles.
Turning it off collapses maker permissions into checker permissions. A user who could previously only prepare can then also approve, issue and cancel. This is a legitimate configuration for a small business where the same person genuinely performs both functions and no separation is possible — but it is a control decision belonging to the customer's finance control owner, not a convenience for an implementation team frustrated by an approval step.
Record the decision in writing. It is exactly the kind of setting an auditor asks about, and "it was easier during testing" is not an answer.
Invoice Generation Module rules¶
The IGM_* flags encode business rules the customer chooses, not statutory constraints:
| Setting | Decision it encodes |
|---|---|
| Credit rule | Whether exceeding a customer's credit limit warns or blocks |
| Approval value threshold | The value above which a second pair of eyes is required |
| Approval discount percentage | The discount above which approval is required |
| Discount over maximum | Whether an excessive line discount is refused or routed for approval |
| Approval engine | Whether a multi-level workflow replaces the simple threshold gate |
A threshold of 0 means the rule is off, not that everything requires approval.
All twelve are on one screen¶
Every flag on this page has a control on Admin & Logs > Operational Controls,
one column per flag and one row per registration. That is enforced by a test
(__tests__/admin/operationalMatrix.test.js) which reads the flag list from the
code and the columns from the component, so a flag cannot be added to the product
without a control appearing — or a control left behind for a flag that was removed.
Before 2026-08-30 the matrix was short one column, and it was the one that
mattered most: INVOICING_ENABLED, the master switch for Invoice Generation.
Every one of its sub-settings was present and the switch itself was not.
The table scrolls horizontally. With twelve controls it is wider than most screens; the registration column stays fixed while you scroll so a checkbox on the right is always attributable to a row.
Two modules have no flag¶
TDS and DPDP are licensed modules with no per-GSTIN switch, and their routes carry no feature gate — only authentication. There is therefore nothing to put on the matrix for them, and nothing that would enforce it if there were.
Verify: Adding
TDS_ENABLEDandDPDP_ENABLEDto the matrix would require the correspondingrequireFeaturegates on those routers first. A switch that writes a value nothing reads is worse than no switch: it reports success and changes nothing. H2
Validation¶
After changing a flag:
| Check | Method | Pass condition |
|---|---|---|
| Set against the right GSTIN | Open the permissions matrix | The flag shows against every intended registration — check all of them, not only the one you are signed in to |
| Change has propagated | Wait about a minute, or re-authenticate | Behaviour reflects the new value |
| Module screens appear | Navigate to the module | Entry present and it opens |
| Role can actually use it | Sign in as a real user of that module | Controls are enabled, not greyed out. Module visibility and permission are separate gates |
| Automation behaves as intended | With auto-generation on, ingest one document | It generates without intervention. With it off, it waits |
| Segregation change is understood | With enforcement off, sign in as a preparer | They can now approve and issue. Confirm this is intended and recorded |
| Write-back is emitting | With write-back on, process a new document | An outbound event appears. Older documents produce nothing — by design |
| Approval thresholds fire | Create a document above and below the threshold | Above requires approval; below does not |
| Decision recorded | Change log | Who decided, when, and why — especially for segregation of duties |
Troubleshooting¶
| Symptom | Cause | Action |
|---|---|---|
| Module enabled but no screen | Set against the wrong GSTIN, or cache not yet expired | Confirm the registration; wait a minute or re-authenticate |
| Screen present, everything greyed out | The user's role lacks the permissions | Fix the role, not the flag. See Roles and Permissions |
| Automation not firing after enabling the module | Automation is a separate flag from the module unlock | Enable the automation deliberately |
| Automation firing on poor-quality documents | Auto-generation enabled before validation quality was proven | Turn it off, fix the feed, then re-enable |
| Write-back on but the ERP has nothing for older documents | Emission is not retrospective | Expected. Plan a separate seeding exercise |
| Approvals unexpectedly required | A threshold set to a low value, or the approval engine enabled | Review the IGM_* settings |
| Approvals never required | Thresholds left at 0, which means off |
Set a real value |
| A preparer can suddenly approve | Segregation of duties was relaxed | Confirm this was a recorded decision. If not, re-enable it |
| One registration behaves differently from the rest | Per-GSTIN settings have diverged | Compare across all registrations. Usually intended, occasionally an oversight |
| An auditor asks who authorised relaxing segregation | No record kept | Record every control-relevant flag change at the time it is made |
Related Articles¶
- Modules and Licensing — what each module covers
- Roles and Permissions — the second gate
- Segregation of Duties — the control model in depth
- Module Configurations — configuring each module
- Write-back API — what enabling write-back starts