Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

What this solves

Regulated-finance, public-sector, and healthcare pilots need to prove that the decisioning system does not discriminate against protected groups. The platform reports four fairness metrics today (disparate impact, equal opportunity, demographic parity, counterfactual), but reporting alone doesn’t stop a flow from going live when those metrics breach. The hard-gate is the enforcement layer.

How it works

Two enforcement points:
  1. Pre-publish gatePOST /api/v1/decision-flows/publish evaluates the policy against the last 7 days of decision traces. If any threshold is breached, the call returns 422 Unprocessable Entity with the violation list, and the flow stays in its previous status. The publish is blocked, not deferred.
  2. Continuous re-check cronGET /api/v1/cron/fairness-recheck runs daily; for every tenant that has opted into continuousRecheck, it re-evaluates the gate and flips active flows back to paused when thresholds drift. Audit-logged with the violation reasons.
Override is via the existing four-eyes governance — set fairnessPolicy.override.{approvedBy, expiresAt} and the gate skips with an audit-logged warning until the override expires.

Step 1 — Configure the policy

curl -X PUT https://playground.kaireonai.com/api/v1/tenant-settings \
  -H "Content-Type: application/json" -H "X-Requested-With: XMLHttpRequest" \
  -d '{
    "fairnessPolicy": {
      "enabled": true,
      "sensitiveAttribute": "ageBand",
      "thresholds": {
        "disparateImpactRatio": 0.8,
        "demographicParityGap": 0.2,
        "equalOpportunityGap": 0.2
      },
      "minSampleSize": 100,
      "continuousRecheck": true
    }
  }'
  • disparateImpactRatio: 0.8 is the EEOC four-fifths rule (29 CFR § 1607.4D) — the lowest selection rate across protected groups must be at least 80% of the highest.
  • demographicParityGap: 0.2 blocks publishes where any pair of groups differs in selection rate by more than 20 percentage points.
  • equalOpportunityGap requires labeled outcomes (the customer would have converted); skipped automatically when labels aren’t available.
  • minSampleSize: 100 — the gate skips with a logged “insufficient samples” reason when fewer than 100 usable decision traces exist in the 7-day window.
  • continuousRecheck: true enables the post-publish drift cron.

Step 2 — Make sure the trace carries the sensitive attribute

The hard-gate reads decision_traces.requestAttributes[sensitiveAttribute] (added in manual-sql migration 22). Any recommend that passes the attribute in body.attributes is automatically eligible:
curl -X POST https://playground.kaireonai.com/api/v1/recommend \
  -H "Content-Type: application/json" -H "X-Requested-With: XMLHttpRequest" \
  -d '{
    "customerId": "cust-12345",
    "decisionFlowKey": "your-flow",
    "attributes": { "ageBand": "65+", "tier": "platinum" }
  }'
Without the attribute on the request, that trace becomes unusable for fairness sampling — the gate will skip with a “no usable samples” message until enough traces with the attribute exist.

Step 3 — Try to publish

curl -X POST https://playground.kaireonai.com/api/v1/decision-flows/publish \
  -H "Content-Type: application/json" -H "X-Requested-With: XMLHttpRequest" \
  -d '{ "id": "<flow-id>" }'
When the gate fires:
{
  "title": "Fairness gate blocked publish",
  "detail": "One or more fairness thresholds configured on this tenant were breached over the last 7 days of decision traces.",
  "violations": [
    "disparate impact ratio 0.612 < threshold 0.8",
    "demographic parity gap 0.314 > threshold 0.2"
  ],
  "metrics": {
    "sampleSize": 1247,
    "disparateImpactRatio": 0.612,
    "demographicParityGap": 0.314,
    "equalOpportunityGap": 0.187
  },
  "override": "To bypass, an admin can set tenant.settings.fairnessPolicy.override = { approvedBy, expiresAt } via four-eyes governance."
}
The flow remains in its previous published state. Nothing rolls out.

Step 4 — Four-eyes override (when justified)

Documented exceptions are bypassed via the override block — both fields required:
curl -X PUT https://playground.kaireonai.com/api/v1/tenant-settings \
  -H "Content-Type: application/json" -H "X-Requested-With: XMLHttpRequest" \
  -d '{
    "fairnessPolicy": {
      "enabled": true,
      "sensitiveAttribute": "ageBand",
      "thresholds": { "disparateImpactRatio": 0.8, "demographicParityGap": 0.2, "equalOpportunityGap": 0.2 },
      "minSampleSize": 100,
      "continuousRecheck": true,
      "override": {
        "approvedBy": "compliance-team@company.com",
        "expiresAt": "2026-07-01T00:00:00Z"
      }
    }
  }'
While the override is active, every gate evaluation logs "Fairness gate bypassed via active override" with the approvedBy value — audit trail for the compliance team.

What gets auto-paused

When the continuous re-check cron detects drift on a tenant with continuousRecheck: true:
  • Every flow with status: "active" is updated to status: "paused".
  • A decision_flow audit-log row is written with action: "auto_pause", reason: "fairness_recheck_drift", and the violation list.
  • Operators see paused flows in Studio with the audit reason visible in the change history.
To re-enable, fix the upstream cause (model retrain, feature change, segment adjustment), let the next decision-trace window accumulate, and re-publish.

Gotchas

  • Sample sourcing requires manual-sql/22. Run psql ... -f prisma/manual-sql/22_decision_trace_request_attributes.sql once; this adds the requestAttributes JSONB column and a GIN index. Without it, the gate skips with "no usable samples".
  • The 7-day window is fixed. If your traffic is low, set minSampleSize accordingly or increase trace sampling rate (decisionTraceSampleRate).
  • continuousRecheck only auto-pauses currently-active flows. Re-publish brings them back; the gate evaluates again at that point.

Proof reference

T35 of the proof bundle (this section is forthcoming) will capture the full breach → block → override cycle with verbatim payloads.