v8.6.0 — Decision Mode PII governance: validator fixes + request/response NIK redaction + engine-fulfillable obligations
[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 thesys_pii_*policy IDs, so every PII policy fell through to its category default — the credit-card validator forpii-global, which rejects every non-card string. The net effect:email/phone/ipdetection never fired on the request or response path, on any deployment, andpanwas validated against the Aadhaar validator. The loader and the evaluator now share a deterministicValidatorForPolicyID(ordered segment-token match, replacing a non-deterministic map-iteration matcher in the evaluator). After the fix:email/phone/ipresolve to their correct validators (were inert);pan→ValidatePAN(was Aadhaar);sys_pii_indonesia_phone/sys_pii_singapore_phone→ValidatePhone(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 MCPtools/callpath) derived its PII category whitelist from a hardcoded literal that omittedpii-indonesia, and ran no checksum-validated NIK/NPWP detector on responses. Response evaluation now derives the category whitelist from the enabled policies (UnifiedPolicyEngine.EnabledPIICategoriesplus a convention classifier for anypii--prefixed category), and runs the Indonesian detector on the response — blocking critical NIK/NPWP underPII_ACTION=blockand masking underPII_ACTION=redact, whilewarn/logdetect without mutating. Redaction is surfaced uniformly viaOutputPolicyOutcome.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 auditRedactionInfo, with the samePII_ACTIONsemantics (detect-don't-modify onwarn/log, mask/deny onredact/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 underPII_ACTION=block; underredactthey let it through. The validator-backed redact flag is now wired on all three request entry points — Gateway pre-check,POST /api/v1/decide, andPOST /api/v1/mcp/check-input— so a checksum-valid NIK is redacted underredact(mirroring the existing RBI handling). Block mode still hard-denies. (#2573) sys_pii_passport(block) andsys_pii_dobpolicies 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. AddedValidatePassportandValidateDOB, both proximity-gated — the passport/birth-date indicator must immediately precede the value — because the underlying patterns are broad and the shared engine'sEvaluateAllhas 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/decidestays a pure Policy Decision Point and never mutates content. Eachredact_piiobligation it returns now carries afulfillmentblock —endpoint,method,phase, and thecontent_typesthe 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-inputreturns engine-redacted request content.check-inputnow returnsredacted/redacted_statement(the engine-masked request statement) plusredaction_evaluated(whether the detector actually ran). This is the request-phase home that makes a/decideredact_piiobligation fulfillable, and is symmetric withcheck-output's response-phaseredacted_data. Request redaction is policy-derived and connector-agnostic, and a PEP fails closed whenredaction_evaluatedis 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) theredact_piiobligation. (#2564)/healthcapability discovery advertises the new Decision Mode surface. The agent capability list (surfaced atGET /health) now includesdecision_obligationsandtwo_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 (
WasRedactedgate, 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 a2563_v860_release_smokethat boots the version-bumped tree and asserts/healthreports8.6.0+ the new capabilities,/decideemits a self-describingfulfillmentobligation, andcheck-inputreturnsredacted_statement.
See the v8.6.0 release notes for the full write-up. Source-available under BSL 1.1.