Skip to content

v8.6.0 — Decision Mode PII governance: validator fixes + request/response NIK redaction + engine-fulfillable obligations

Choose a tag to compare

@saurabhjain1592 saurabhjain1592 released this 09 Jun 10:38
dfbbb5b

[8.6.0] - 2026-06-09 — Decision Mode PII governance: validator-assignment fixes, request + response NIK/NPWP redaction on every plane, and engine-fulfillable obligations

Community. Every change in this release lives in the platform/ and platform/shared/ binaries — the agent, the orchestrator, and the shared policy engine — so this release ships to the community mirror. The fixes and additions are reachable in both editions; where behavior differs by edition it is called out inline. In particular, the Enterprise build supplies checksum/province-validated Indonesian NIK/NPWP detection (the precision behind the redaction below), while Community uses pattern-based Indonesian PII detection — and as of this release both editions govern that PII on the request and the response path. No breaking changes; every API and policy-engine change is additive and backward-compatible.

Fixed (Community)

  • PII validators were misassigned for every database-loaded policy — email, phone, and IP detection were silently inert for all tenants. The policy loader selected a value validator with an exact ValidatorRegistry[policyID] lookup that never matched the sys_pii_* policy IDs, so every PII policy fell through to its category default — the credit-card validator for pii-global, which rejects every non-card string. The net effect: email / phone / ip detection never fired on the request or response path, on any deployment, and pan was validated against the Aadhaar validator. The loader and the evaluator now share a deterministic ValidatorForPolicyID (ordered segment-token match, replacing a non-deterministic map-iteration matcher in the evaluator). After the fix: email / phone / ip resolve to their correct validators (were inert); panValidatePAN (was Aadhaar); sys_pii_indonesia_phone / sys_pii_singapore_phoneValidatePhone (were accept-all). This has the broadest blast radius of anything in the release — it restored basic PII detection for every tenant. (#2565)
  • Indonesian NIK/NPWP leaked on the agent response path. The agent's response engine (POST /api/v1/mcp/check-output, used by the PEP/gateway response flow and the MCP tools/call path) derived its PII category whitelist from a hardcoded literal that omitted pii-indonesia, and ran no checksum-validated NIK/NPWP detector on responses. Response evaluation now derives the category whitelist from the enabled policies (UnifiedPolicyEngine.EnabledPIICategories plus a convention classifier for any pii--prefixed category), and runs the Indonesian detector on the response — blocking critical NIK/NPWP under PII_ACTION=block and masking under PII_ACTION=redact, while warn/log detect without mutating. Redaction is surfaced uniformly via OutputPolicyOutcome.WasRedacted() so an Indonesia-only redaction can neither leak the unmasked original nor be recorded as un-redacted in the audit trail. (#2565)
  • Indonesian NIK/NPWP leaked on the orchestrator / LLM-gateway response path. The orchestrator's ResponseProcessor.ProcessResponse (proxy / gateway / MAP LLM responses) carried no checksum-validated NIK/NPWP detector. The same Indonesian detector is now wired into the response path via a side-effect-free deep walk (maskIndonesiaPIIDeep) that masks string leaves in any decoded-JSON shape and folds detected type names into the audit RedactionInfo, with the same PII_ACTION semantics (detect-don't-modify on warn/log, mask/deny on redact/block). (#2568)
  • Indonesian NIK/NPWP was not redacted on the request path under PII_ACTION=redact. The request-phase entry points only hard-denied NIK under PII_ACTION=block; under redact they let it through. The validator-backed redact flag is now wired on all three request entry points — Gateway pre-check, POST /api/v1/decide, and POST /api/v1/mcp/check-input — so a checksum-valid NIK is redacted under redact (mirroring the existing RBI handling). Block mode still hard-denies. (#2573)
  • sys_pii_passport (block) and sys_pii_dob policies were validator-inert. Same misassignment class as the email/phone fix above: with no matching token they were stamped the credit-card default and never matched on any path. Added ValidatePassport and ValidateDOB, both proximity-gated — the passport/birth-date indicator must immediately precede the value — because the underlying patterns are broad and the shared engine's EvaluateAll has no confidence threshold (a valid match always fires). This prevents a generic order number from being blocked as a passport, or an invoice/due date from being redacted as a date of birth. (#2570)
  • Context-gated the broad Singapore PII detectors (postal code, UEN). They now redact only when a nearby label confirms the value; previously they fired on any matching number and — under engine-backed response redaction — could hard-block a benign tool response. No loss of real PII coverage; labelled values still redact. (#2575)

Added (Community)

  • Decision Mode obligations are now self-describing and engine-fulfillable. POST /api/v1/decide stays a pure Policy Decision Point and never mutates content. Each redact_pii obligation it returns now carries a fulfillment block — endpoint, method, phase, and the content_types the endpoint can redact — that tells a Policy Enforcement Point exactly which engine call discharges the obligation. Client-side redaction is impossible by construction: a conforming PEP POSTs the content to the named endpoint and forwards the engine-redacted result, rather than hand-rolling its own patterns. (ADR-056 / ADR-057.) (#2564)
  • POST /api/v1/mcp/check-input returns engine-redacted request content. check-input now returns redacted / redacted_statement (the engine-masked request statement) plus redaction_evaluated (whether the detector actually ran). This is the request-phase home that makes a /decide redact_pii obligation fulfillable, and is symmetric with check-output's response-phase redacted_data. Request redaction is policy-derived and connector-agnostic, and a PEP fails closed when redaction_evaluated is false (the detector did not run) so an un-evaluated request can never be forwarded as if it were clean. (#2564)
  • platform/shared/pep — the blessed PEP client. A shared client that runs the decide → fulfill-via-named-endpoint → forward flow with HTTP Basic auth. It holds no redaction logic of its own and fails closed if an obligation is not engine-fulfillable or the redactor did not run. The reference LLM and MCP adapters were corrected to fulfill (not silently drop) the redact_pii obligation. (#2564)
  • /health capability discovery advertises the new Decision Mode surface. The agent capability list (surfaced at GET /health) now includes decision_obligations and two_touch_redaction (since: 8.6.0), so SDKs, plugins, and PEPs can feature-detect the obligation contract and request + response redaction without version sniffing.

Tests (Community)

  • Per-plane deterministic CI tests for the request-phase Indonesian redaction (red on revert), validator-selection regressions (locale-phone narrowing, credit-card-default lock, passport/DOB proximity-gating both directions), and the response-path leak locks (WasRedacted gate, non-vacuous empty-set guard). Runtime end-to-end proofs against a live agent + orchestrator over real HTTP: 2563_response_pii_categories, 2566_orchestrator_indonesia_response, 2567_passport_dob_validators, 2563_obligation_pep, 2571_indonesia_nik_redaction, and a 2563_v860_release_smoke that boots the version-bumped tree and asserts /health reports 8.6.0 + the new capabilities, /decide emits a self-describing fulfillment obligation, and check-input returns redacted_statement.


See the v8.6.0 release notes for the full write-up. Source-available under BSL 1.1.