Deepen PracticeOrdered learning track

Approval Policy and Entitlement Engine

Learn Enterprise CPQ OMS Camunda 7 - Part 036

Building an approval policy and entitlement engine for enterprise CPQ/OMS, covering authority, delegation, commercial limits, object-level permissions, policy evidence, Camunda integration, and auditability.

15 min read2972 words
PrevNext
Lesson 3664 lesson track3653 Deepen Practice
#java#microservices#cpq#oms+7 more

Part 036 — Approval Policy and Entitlement Engine

Enterprise CPQ dies when “approval” is treated as a button.

A real approval system is not:

if discount > 20%, manager approval required

That is only the beginning.

A production CPQ approval system must answer harder questions:

  • Who is allowed to create this quote?
  • Who is allowed to see this account?
  • Who may apply this product discount?
  • Who may override margin guardrails?
  • Who may approve a quote they also authored?
  • What if the approver is on leave?
  • What if the approval policy changed after the quote was submitted?
  • What if the customer belongs to a restricted segment?
  • What if the quote has multiple product families with different authority chains?
  • What evidence proves that the accepted quote was approved under the right policy?

That is why CPQ needs an approval policy and entitlement engine.

The mental model:

Entitlement decides what a user may attempt.
Policy decides what the business requires.
Approval records prove who accepted responsibility for an exception.

Do not collapse these three into one boolean.


1. Approval, Authorization, and Entitlement Are Not the Same

These terms are often mixed together. In CPQ/OMS, that causes security bugs and commercial leakage.

Authorization

Authorization asks:

Is this subject allowed to perform this operation on this object?

Example:

Can user U edit quote Q?

Entitlement

Entitlement asks:

What commercial actions, products, accounts, regions, or price boundaries is this subject entitled to operate within?

Example:

Can sales rep U sell product offering P to customer C in region R?
Can U apply discount up to 12% for product family F?

Approval Policy

Approval policy asks:

Given this quote and its risk/exception profile, what approvals are required before the quote may proceed?

Example:

This quote requires approval from:
- Sales Manager because discount is 18%
- Finance because margin is below threshold
- Legal because custom terms were added

Approval Decision

Approval decision asks:

Did an authorized approver approve/reject/request rework for a specific quote revision under a specific policy version?

Example:

Manager M approved quote Q revision 4 using policy version PV-2026-07.

These concepts must remain separate.

If you merge them, you cannot audit why a quote was allowed.


2. The Core Invariant

The most important invariant:

A quote may only advance past a protected lifecycle boundary if the required approvals for that exact quote revision have been satisfied by authorized approvers under an applicable policy version.

Break it down:

  • protected lifecycle boundary: submit, approve, accept, convert to order, cancel, amend.
  • required approvals: derived from policy evaluation.
  • exact quote revision: approval is not transferable to modified quote content.
  • authorized approvers: approver must have authority at decision time.
  • applicable policy version: the policy used must be known and recorded.

This invariant is not a UI rule. It must be enforced by quote service/workflow/policy boundaries.


3. Policy Engine Responsibilities

The policy engine should be able to answer:

  1. What actions is the user entitled to attempt?
  2. What quote/order actions are blocked and why?
  3. What approval requirements exist for this quote revision?
  4. What approver roles or authority levels are required?
  5. Which specific users are eligible approvers?
  6. Whether a specific approval decision is valid.
  7. Whether existing approvals are still fresh after quote change.
  8. Whether delegated approval is valid.
  9. Whether a four-eyes rule is violated.
  10. What evidence should be stored for audit.

The engine should not:

  1. Mutate quote lifecycle directly.
  2. Complete Camunda tasks directly without domain command semantics.
  3. Store raw UI state.
  4. Replace domain service validation.
  5. Become a generic rules dumping ground.

4. Policy Inputs: Decision Facts

Policy evaluation must be based on explicit facts, not ad-hoc service calls hidden inside rule code.

Example QuoteApprovalFacts:

{
  "quoteId": "Q-2026-000231",
  "quoteRevision": 4,
  "tenantId": "tenant-a",
  "customer": {
    "customerId": "C-100",
    "segment": "ENTERPRISE",
    "riskTier": "MEDIUM",
    "country": "ID"
  },
  "seller": {
    "userId": "U-10",
    "roleCodes": ["SALES_REP"],
    "region": "APAC",
    "teamId": "TEAM-7"
  },
  "commercials": {
    "currency": "USD",
    "totalRecurring": "12000.00",
    "totalOneTime": "1500.00",
    "maxDiscountPercent": "18.00",
    "minMarginPercent": "11.50",
    "hasManualOverride": true,
    "hasCustomTerms": false
  },
  "products": [
    {
      "productFamily": "CONNECTIVITY",
      "offeringId": "PO-FIBER-1G",
      "discountPercent": "18.00",
      "marginPercent": "11.50"
    }
  ],
  "lifecycle": {
    "quoteStatus": "PRICED",
    "priceStatus": "FRESH",
    "configurationStatus": "VALID"
  }
}

This object is the policy engine's input contract.

A policy result must include evidence:

{
  "policyVersion": "PV-2026-07-01",
  "decisionId": "DEC-9912",
  "requiresApproval": true,
  "requirements": [
    {
      "requirementCode": "DISCOUNT_MANAGER_APPROVAL",
      "reason": "Max discount 18.00% exceeds seller authority 12.00%",
      "approverRole": "SALES_MANAGER",
      "minimumAuthorityLevel": "REGIONAL_MANAGER",
      "scope": {
        "productFamily": "CONNECTIVITY",
        "region": "APAC"
      }
    }
  ],
  "blockers": [],
  "evidence": {
    "matchedRules": ["RULE-DISC-APAC-003"],
    "inputHash": "sha256:..."
  }
}

Without evidence, policy is just an opinion.


5. Authority Model

Approval authority is usually based on several dimensions:

  • role
  • hierarchy level
  • region
  • product family
  • customer segment
  • discount threshold
  • margin threshold
  • deal size
  • contract term
  • risk category
  • delegated authority
  • temporary assignment

A simplistic authority table:

Authority LevelMax DiscountMin MarginScope
Sales Rep10%20%Own accounts
Sales Manager20%15%Team accounts
Regional Director30%10%Regional accounts
Finance ApproverAnyBelow 10% requires financeAssigned product families
Legal ApproverN/AN/ACustom terms

But authority is rarely one-dimensional.

Example:

A regional director may approve 28% discount for connectivity products in APAC,
but not for regulated government accounts,
and not if they authored the quote,
and not if margin is below finance threshold.

The policy engine must handle composed constraints.


6. Entitlement Model

Entitlement controls what a user may attempt before approval is even considered.

Examples:

  • User may quote only assigned accounts.
  • User may sell only certain product families.
  • User may see prices only for their sales channel.
  • User may apply manual discount only up to entitlement limit.
  • User may submit quote but not accept quote.
  • User may approve only quotes outside their authorship.
  • User may perform fallout recovery only for assigned region.

Entitlement is not only security. It is also commercial containment.

A user can be allowed to view a quote but not allowed to reprice it. A user can be allowed to edit quote lines but not override discount. A user can be allowed to submit for approval but not approve.

Do not represent entitlement as one role string.


7. Policy Service Boundary

A clean architecture has a dedicated policy/entitlement service or module.

The policy service provides:

  • capability evaluation for UI
  • entitlement evaluation for command attempts
  • approval requirement evaluation
  • approver candidate resolution
  • approval decision validation
  • policy version publication
  • simulation API
  • audit evidence storage

It should not be a service that every business rule is thrown into. Catalog rules remain in catalog/configuration. Pricing calculation remains in pricing. Quote lifecycle remains in quote. Policy service owns commercial authority and decision requirements.


8. Data Model

A simplified relational model:

The model separates:

  • policy definition
  • authority assignment
  • delegation
  • evaluation result
  • requirement
  • decision

That separation is what makes audit possible.


9. Policy Versioning

Approval policy changes over time.

Common mistake:

Quote submitted under old policy.
Approver approves after policy changed.
System evaluates using latest policy.

This creates audit ambiguity.

Better:

  1. Quote revision is submitted.
  2. Policy engine evaluates using active policy version.
  3. Evaluation result stores policyVersion, inputHash, and requirements.
  4. Approval tasks are created from the stored requirements.
  5. If quote changes, previous evaluation is invalidated.
  6. If policy changes, decide whether in-flight quotes keep old policy or require re-evaluation by explicit rule.

Policy application modes:

ModeMeaningUse Case
LOCK_ON_SUBMISSIONQuote uses policy active at submission timeStrong audit stability
REVALIDATE_ON_APPROVALApproval must satisfy latest policy tooHigh-risk regulated flows
REVALIDATE_ON_ACCEPTANCEQuote can be approved, but acceptance checks latest blockersCommercial risk control
MANUAL_REVIEW_ON_POLICY_CHANGEIn-flight quotes are flaggedMajor policy migration

Pick one deliberately. Do not leave it accidental.


10. Approval Requirement Lifecycle

Approval is not a boolean.

Requirement lifecycle:

Quote lifecycle references approval summary, but requirement lifecycle is its own audit trail.

Important fields:

  • requirement id
  • requirement code
  • quote id
  • quote revision
  • policy version
  • required authority
  • current status
  • approver candidates
  • decision id
  • invalidation reason

A quote is approval-satisfied only if all active requirements are satisfied or waived by valid authority.


11. Approval Chain Computation

A quote may require multiple approvals.

Examples:

Discount exception -> Sales Manager
Margin exception -> Finance
Custom terms -> Legal
Strategic account -> VP Sales
Restricted segment -> Compliance

Approval chain can be:

Parallel

All required approvers can decide independently.

Sequential

Approval happens in order.

Conditional

Later approvals depend on earlier decisions or updated facts.

Manager approves discount.
If manager requests deeper discount change, reprice and re-evaluate policy.

The policy engine should produce a requirement graph, not just a flat list.


12. Four-Eyes and Conflict of Interest

A common enterprise control:

The person who created or materially modified the quote must not be the only approver of the same quote.

This is often called four-eyes control.

Conflict rules:

  • author cannot approve own quote
  • last modifier cannot approve after material change
  • delegate cannot approve if delegator is also conflicted, depending on policy
  • direct subordinate approval may be disallowed for specific risk tiers
  • same user cannot satisfy two independent requirements if segregation is required

Model conflict explicitly:

{
  "approverUserId": "U-99",
  "eligible": false,
  "ineligibilityReasons": [
    {
      "code": "QUOTE_AUTHOR_CONFLICT",
      "message": "Quote author cannot approve this requirement."
    }
  ]
}

Do not hide this as “no approvers found.”


13. Delegation

Approvers go on leave. People change roles. Escalations happen.

Delegation must be controlled.

Delegation dimensions:

  • delegator
  • delegate
  • effective period
  • scope
  • reason
  • created by
  • approval by admin/manager if required
  • maximum authority allowed
  • exclusions

Example:

{
  "delegatorUserId": "MGR-1",
  "delegateUserId": "MGR-2",
  "effectiveFrom": "2026-07-01T00:00:00+07:00",
  "effectiveTo": "2026-07-15T23:59:59+07:00",
  "scope": {
    "region": "APAC",
    "productFamilies": ["CONNECTIVITY"],
    "maxDiscountPercent": "20.00"
  },
  "exclusions": {
    "customerSegments": ["GOVERNMENT"]
  }
}

Delegation is not just adding someone to a group. It is temporary authority with evidence.


14. Approval Policy Evaluation Flow

The important part:

  • Policy service evaluates.
  • Quote service persists approval evaluation reference.
  • Workflow service orchestrates tasks.
  • Audit records evidence.

Camunda is not the policy engine. It is the task/process engine.


15. Camunda 7 Integration

Camunda 7 should receive stable business references:

{
  "quoteId": "Q-2026-000231",
  "quoteRevision": 4,
  "approvalEvaluationId": "AE-9912",
  "approvalRequirementIds": ["AR-1", "AR-2"],
  "tenantId": "tenant-a"
}

Avoid passing full price traces, full quote lines, or full customer data as process variables.

The BPMN process should call services by semantic command:

Create approval task for requirement AR-1
Complete approval requirement AR-1 as APPROVED by user U-99
Notify quote service when all requirements satisfied

Not:

Set variable discountApproved = true

A boolean variable does not prove authority.


16. Semantic Task Completion

Task completion must validate the decision.

Bad flow:

POST /engine-rest/task/{id}/complete
variables: { approved: true }

Correct flow:

POST /approval-requirements/{requirementId}/decisions

Request:

{
  "decision": "APPROVE",
  "comment": "Approved based on strategic account commitment.",
  "idempotencyKey": "01J..."
}

Policy/approval service validates:

  • task exists
  • requirement exists
  • quote revision matches
  • approver is eligible
  • approver has authority
  • four-eyes rule not violated
  • requirement still active
  • idempotency key not reused incompatibly

Then it records decision and tells workflow service to complete the corresponding task.

Task completion is a consequence of a valid business decision. It is not the business decision itself.


17. Policy Result as Evidence

Every approval requirement should be traceable back to facts.

Evidence record:

{
  "evaluationId": "AE-9912",
  "policyVersion": "PV-2026-07-01",
  "evaluatedAt": "2026-07-02T10:15:00+07:00",
  "quoteId": "Q-2026-000231",
  "quoteRevision": 4,
  "inputHash": "sha256:abc...",
  "factsSnapshotLocation": "s3://audit/policy/AE-9912/input.json",
  "resultSnapshotLocation": "s3://audit/policy/AE-9912/result.json",
  "matchedRules": ["RULE-DISC-APAC-003", "RULE-MARGIN-FIN-002"],
  "engineVersion": "policy-engine-1.12.0"
}

This lets you answer months later:

  • What did the system know?
  • Which policy version was active?
  • Which rules matched?
  • Who approved?
  • Was the approver eligible?
  • Did the quote change afterward?

Without this, audit becomes archaeology.


18. Policy Implementation Options

There are several implementation choices.

Option A: Code-Based Policy

Rules are Java code.

Good:

  • type-safe
  • testable
  • easy to refactor
  • works for complex logic

Bad:

  • business changes require deployment
  • harder for business users to inspect
  • risk of hidden behavior

Option B: DMN Decision Tables

Rules are modeled as decision tables.

Good:

  • explainable
  • business-readable if well-designed
  • versionable
  • good for tabular policy

Bad:

  • complex procedural logic is awkward
  • overuse creates unreadable tables
  • data preparation still needs code

Option C: Hybrid

Use code for fact preparation and orchestration, DMN/table rules for business policy.

This is usually best for CPQ.

Java prepares clean QuoteApprovalFacts.
DMN/table evaluates approval requirements.
Java validates authority and stores evidence.

Do not let rules call random services. Do not let code hide all commercial thresholds.


19. API Design

Policy service API should be explicit.

Evaluate Capabilities

POST /policy/capabilities/quote

Request:

{
  "userId": "U-10",
  "tenantId": "tenant-a",
  "quoteId": "Q-1",
  "quoteRevision": 4,
  "requestedActions": ["EDIT", "REPRICE", "SUBMIT_FOR_APPROVAL", "ACCEPT"]
}

Response:

{
  "capabilities": [
    {
      "action": "EDIT",
      "allowed": true
    },
    {
      "action": "ACCEPT",
      "allowed": false,
      "reasonCode": "APPROVAL_REQUIRED"
    }
  ]
}

Evaluate Approval Requirements

POST /policy/approval-evaluations/quote

Response:

{
  "approvalEvaluationId": "AE-9912",
  "policyVersion": "PV-2026-07-01",
  "requiresApproval": true,
  "requirements": []
}

Resolve Approver Candidates

GET /policy/approval-requirements/{requirementId}/candidates

Record Decision

POST /approval-requirements/{requirementId}/decisions

Simulate Policy

POST /policy/simulations/quote-approval

Simulation is important for admins before publishing policy changes.


20. Policy Simulation

A serious policy engine needs simulation.

Before publishing a new policy, business/admin users should be able to ask:

  • How many open quotes would require new approval?
  • Which quotes would become blocked?
  • Which product families are affected?
  • Which regions are affected?
  • Which approver groups would receive more workload?
  • Which previous approvals would be invalidated?

Simulation output:

{
  "simulationId": "SIM-2026-07-02-01",
  "candidatePolicyVersion": "PV-DRAFT-9",
  "sampleSize": 10000,
  "impact": {
    "newApprovalRequiredCount": 231,
    "approvalNoLongerRequiredCount": 58,
    "blockedQuoteCount": 12,
    "estimatedAdditionalApproverTasks": 311
  },
  "topReasons": [
    {
      "reasonCode": "MARGIN_BELOW_NEW_THRESHOLD",
      "count": 144
    }
  ]
}

Policy changes are production changes. Treat them like releases.


21. Authorization Enforcement Points

Authorization must be enforced in multiple places.

BoundaryCheck
BFFUI capability, coarse access, object visibility
Quote Servicecommand authorization, lifecycle invariant
Pricing Serviceprice override entitlement
Policy Serviceauthority and approval eligibility
Workflow Servicetask claim/complete permission
Document Serviceartifact access permission
Order Serviceorder action permission
Search/Read Modelrow/object filtering and redaction

Do not rely on only the BFF. Do not rely on only the identity provider. Do not rely on only Camunda task assignment.

Each service must protect its own state-changing operations.


22. Stale Approval Handling

A quote approval becomes stale when material facts change.

Material changes:

  • quote line added/removed
  • quantity changed
  • price changed
  • discount changed
  • customer changed
  • product offering changed
  • term changed
  • manual override changed
  • legal/commercial term changed
  • policy-critical characteristic changed

Non-material changes might not invalidate approval:

  • internal note added
  • UI display name corrected
  • document regenerated from same snapshot
  • comment added

Define this explicitly.

Example invalidation rule:

If quote revision changes due to commercial material change,
all approvals tied to previous revision become invalid.

Approval freshness should be visible:

{
  "approvalStatus": "STALE",
  "staleReason": "QUOTE_COMMERCIALS_CHANGED_AFTER_APPROVAL",
  "previousApprovedRevision": 4,
  "currentRevision": 5
}

Do not silently reuse approval from old quote content.


23. Waivers

Some requirements can be waived. But waiver is itself an approval decision.

Waiver fields:

  • requirement id
  • waived by
  • waiver authority
  • reason
  • expiry if any
  • policy version
  • audit evidence

Waiver example:

{
  "requirementId": "AR-99",
  "decision": "WAIVE",
  "reasonCode": "PRE_APPROVED_STRATEGIC_DEAL",
  "comment": "Approved by executive deal desk under strategic account program.",
  "evidenceReference": "DOC-EXEC-APPROVAL-123"
}

A waiver without authority is a bypass. A waiver without evidence is an audit risk.


24. Approval Metrics

Policy and approval engine should expose business and operational metrics.

Metrics:

  • approval required rate by product family
  • average approval cycle time
  • rejection rate
  • rework rate
  • stale approval rate
  • escalation rate
  • policy blocker count
  • approver workload
  • overdue task count
  • delegated approval count
  • waiver count
  • approval invalidation count
  • quote conversion rate after approval

These metrics reveal whether policy is protecting the business or slowing it down unnecessarily.

A policy engine is not just control. It is feedback about commercial process design.


25. Testing Strategy

Test policy with scenario catalogs.

Example scenarios:

ScenarioExpected Result
Sales rep discount 5%, margin 30%No approval
Sales rep discount 18%, margin 25%Sales manager approval
Discount 18%, margin 8%Sales manager + finance approval
Custom legal termsLegal approval
Author attempts own approvalRejected by four-eyes rule
Delegate approves within scopeAccepted
Delegate approves outside scopeRejected
Quote changed after approvalApproval stale
Policy changed after submissionBased on configured policy application mode
Government customer with restricted productCompliance approval or blocker

Policy tests should verify:

  • result correctness
  • matched rule evidence
  • policy version
  • input hash stability
  • approver eligibility
  • invalidation behavior
  • audit record creation

Do not test only happy-path approvals. The value of the engine is in exceptions.


26. Failure Modeling

FailureCorrect Behavior
Policy service unavailable during quote submitFail closed or queue for review, depending on risk mode
Approver directory unavailableRequirement remains pending; candidate resolution degraded
Delegation data staleDo not approve if authority cannot be verified
Policy version missingBlock protected lifecycle transition
Approval decision duplicateReturn same idempotent result
Quote revision mismatchReject decision as stale
Camunda task completion failed after decision storedReconcile task completion by requirement id
Camunda task completed but decision not storedTreat as invalid; rebuild/repair from audit if possible
Policy evaluation timeoutUnknown/no decision; do not advance lifecycle

The safest rule:

If authority cannot be proven, do not approve.

This may create operational friction, but it preserves defensibility.


27. Anti-Patterns

Anti-Pattern 1: Approval as Status Field

quote.approved = true

This loses who, why, when, under what authority, and for which revision.

Fix:

Store approval requirements and decisions as separate records.

Anti-Pattern 2: Role Equals Authority

ROLE_MANAGER can approve all discounts

This ignores product, region, customer, margin, delegation, and conflict.

Fix:

Model authority scope.

Anti-Pattern 3: UI-Only Approval Check

The UI hides the approve button, but backend accepts the command.

Fix:

Validate approval authority server-side.

Anti-Pattern 4: Camunda Variable as Approval Truth

approved = true

A process variable is not enough evidence.

Fix:

Persist approval decision in approval/domain service and use Camunda for orchestration.

Anti-Pattern 5: Policy Without Versioning

Rules change, but old decisions cannot be explained.

Fix:

Version policy and store evaluation evidence.

Anti-Pattern 6: No Simulation

Business publishes policy changes blindly.

Fix:

Add policy simulation and impact analysis.


28. Production Checklist

Before the policy/entitlement engine is production-ready:

  • Authorization, entitlement, approval requirement, and approval decision are separate concepts.
  • Approval is tied to quote revision.
  • Policy version is stored with every evaluation.
  • Input facts and result evidence are hashable and auditable.
  • Approver eligibility is validated at decision time.
  • Four-eyes/conflict rules are explicit.
  • Delegation has scope, time window, and audit trail.
  • Approval invalidation rules are explicit.
  • Waivers require authority and evidence.
  • BFF receives capabilities but does not decide final approval.
  • Quote service revalidates protected lifecycle transitions.
  • Camunda tasks are semantic, not raw variable writes.
  • Policy simulation exists before publication.
  • Metrics expose approval cycle health.
  • Failure behavior is fail-closed for protected transitions.

29. The Core Lesson

Approval is not a button. Approval is a chain of evidence.

The system must prove:

this quote revision
under this policy version
with these commercial facts
required these approvals
which were decided by these eligible people
at these times
before this lifecycle transition happened

That is the difference between a demo CPQ and an enterprise CPQ.

The approval policy and entitlement engine is where commercial control becomes executable, testable, and defensible.

In the next part, we move from commercial authority to the external enterprise systems that often decide whether an order can be fulfilled: inventory and availability integration.

Lesson Recap

You just completed lesson 36 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.