feat: let a deployment add its own sensitivity labels alongside the built in six - #489
Conversation
…uilt in six Part of agentrust-io#479. The sensitivity vocabulary was six hardcoded labels, public, pii, confidential, hipaa_phi, mnpi, trade_secret, in SENSITIVITY_ORDER, and the catalog schema validated sensitivity_level against exactly that literal enum. A deployment whose own regulation names a tier above trade_secret, an Open, Confidential, Secret, Top Secret ladder for example, had no way to catalogue it truthfully. sensitivity.vocabulary in config now lets a deployment add new labels at any rank. It is additive only rather than a full replacement. Response inspection's content pattern detectors emit the built in tags pii and hipaa_phi directly, so a vocabulary that dropped either name would rank those detections at 0, the same fail open hole agentrust-io#478 closed for the catalog schema. Two layers enforce the additive guarantee: config parsing rejects a vocabulary key that names a built in label outright, and effective_sensitivity_order merges the built in table in last regardless, so a built in name can never be shadowed even by a mistake elsewhere in the chain. SessionManager and PolicyEvaluator each derive the effective vocabulary once from the same Config, so a session's max_sensitivity string and the sensitivity_level integer Cedar evaluates can never disagree about what a custom label ranks as. The catalog schema's sensitivity_level enum moved out of the static JSON schema into a Python level check at load time against this same effective set, so the vocabulary stays closed, just not hardcoded. Per call classification, the second half of agentrust-io#479, is left for a follow up change. Signed-off-by: Dipika Ranabhat <qubeena7@gmail.com>
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
imran-siddique
left a comment
There was a problem hiding this comment.
Approving. Reviewed in a separate worktree and ran the three test files this touches: 93 passed.
Three things I checked rather than took on trust, all of which you got right.
effective_sensitivity_order merges the built ins last, so a colliding config key cannot shadow pii or hipaa_phi even if the parser somehow let one through. That matters more than it looks: response inspection emits those tags directly, and order.get(tag, 0) fails open to rank 0, so a shadowed built in would silently downgrade to public. Defending it in two places for a case that should already be impossible is the right instinct here.
There are only two SessionState construction sites. The manager passes the effective order; the other is the benchmark harness, which uses public. So no production path can silently fall back to the built in ranking.
Moving sensitivity_level out of the JSON schema does not open a hole, because the load time check is still closed, just against a config dependent set, and the schema says why the enum is gone.
One thing for the follow up rather than this PR: compliance_domain keeps its hardcoded enum, so a deployment can now name its own sensitivity tier but not its own compliance domain. Whoever hits that will hit it immediately after adopting this.
Summary
Part of #479, the configurable vocabulary piece. Per call classification, the second piece of that issue, is left for a follow up.
The sensitivity vocabulary was six hardcoded labels, public, pii, confidential, hipaa_phi, mnpi, trade_secret, in SENSITIVITY_ORDER, and the catalog schema validated sensitivity_level against exactly that literal enum. A deployment whose own regulation names a tier above trade_secret, an Open, Confidential, Secret, Top Secret ladder for example, had no way to catalogue it truthfully.
sensitivity.vocabulary in config now lets a deployment add new labels at any rank.
Design decision worth flagging
The vocabulary is additive only, not a full replacement. Response inspection's content pattern detectors emit the built in tags pii and hipaa_phi directly when they spot an SSN, an email, a diagnosis code and so on. If a deployment's configured vocabulary could drop either of those names, those detections would rank at 0 by the ordinary unknown tag default, the same fail open hole #478 closed for the catalog schema, just moved to a different door.
So a vocabulary key that names a built in label is rejected at config load, and effective_sensitivity_order merges the built in table in last regardless of what config parsing did, so a built in name can never be shadowed even by a mistake elsewhere in the chain.
SessionManager and PolicyEvaluator each derive the effective vocabulary once from the same Config, so a session's max_sensitivity string and the sensitivity_level integer Cedar evaluates can never disagree about what a custom label ranks as.
Changes
Test plan