Adds receipt evidence kind, 422 unprocessable, optional revision on research records, audit_stale on the privacy policy, per-route body caps (25 MiB artifact uploads), promotion checks the project exists, memory rules skip content-free statuses. Handoff ledger covers every Wave A card. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RNPhwu2bsaRNg3DETSAZoM
244 lines
6.0 KiB
JSON
244 lines
6.0 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://hermes.bstein.dev/contracts/hux/v1/privacy.schema.json",
|
|
"title": "HUX privacy policy, topic scoping and retention",
|
|
"description": "Sensitive-topic behaviour (HUX-10). The policy names each topic class, whether memory may be written from it, how long conversation-scoped context survives, and which just-in-time notice the surface must show. A retention audit record proves the rules ran.",
|
|
"$defs": {
|
|
"topic": {
|
|
"type": "string",
|
|
"enum": [
|
|
"health",
|
|
"finance",
|
|
"legal",
|
|
"relationships",
|
|
"credentials",
|
|
"minors",
|
|
"location",
|
|
"biometric"
|
|
]
|
|
},
|
|
"policy": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schema",
|
|
"version",
|
|
"topics",
|
|
"topic_scoping",
|
|
"retention_audit"
|
|
],
|
|
"properties": {
|
|
"schema": {
|
|
"const": "hux.privacy_policy.v1"
|
|
},
|
|
"version": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"topics": {
|
|
"type": "array",
|
|
"minItems": 8,
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"topic",
|
|
"sensitivity",
|
|
"memory_write",
|
|
"decay_days",
|
|
"notice"
|
|
],
|
|
"properties": {
|
|
"topic": {
|
|
"$ref": "#/$defs/topic"
|
|
},
|
|
"sensitivity": {
|
|
"$ref": "common.schema.json#/$defs/sensitivity"
|
|
},
|
|
"memory_write": {
|
|
"type": "string",
|
|
"enum": [
|
|
"ask",
|
|
"deny"
|
|
]
|
|
},
|
|
"decay_days": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 365
|
|
},
|
|
"notice": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 280
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"topic_scoping": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"scope_to_conversation",
|
|
"cross_surface_sharing"
|
|
],
|
|
"properties": {
|
|
"scope_to_conversation": {
|
|
"const": true
|
|
},
|
|
"cross_surface_sharing": {
|
|
"type": "string",
|
|
"enum": [
|
|
"never",
|
|
"same_owner_only"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"retention_audit": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"interval_days",
|
|
"actions"
|
|
],
|
|
"properties": {
|
|
"interval_days": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 30
|
|
},
|
|
"actions": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"uniqueItems": true,
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"expire_memory",
|
|
"decay_topic_context",
|
|
"purge_forgotten_content",
|
|
"report"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"audit_stale": {
|
|
"type": "boolean",
|
|
"description": "True when the last retention audit is older than 48 hours (SO-27)."
|
|
}
|
|
}
|
|
},
|
|
"notice": {
|
|
"type": "object",
|
|
"description": "Just-in-time notice a surface shows when a sensitive topic is detected. Emitted as event kind privacy.notice.",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schema",
|
|
"topic",
|
|
"conversation_id",
|
|
"text",
|
|
"controls",
|
|
"shown_at"
|
|
],
|
|
"properties": {
|
|
"schema": {
|
|
"const": "hux.privacy_notice.v1"
|
|
},
|
|
"topic": {
|
|
"$ref": "#/$defs/topic"
|
|
},
|
|
"conversation_id": {
|
|
"$ref": "common.schema.json#/$defs/id"
|
|
},
|
|
"text": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 280
|
|
},
|
|
"controls": {
|
|
"type": "array",
|
|
"minItems": 1,
|
|
"uniqueItems": true,
|
|
"items": {
|
|
"type": "string",
|
|
"enum": [
|
|
"forget_this_conversation",
|
|
"switch_to_private",
|
|
"disable_memory_here",
|
|
"dismiss"
|
|
]
|
|
}
|
|
},
|
|
"shown_at": {
|
|
"$ref": "common.schema.json#/$defs/timestamp"
|
|
}
|
|
}
|
|
},
|
|
"audit": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schema",
|
|
"id",
|
|
"ran_at",
|
|
"policy_version",
|
|
"results"
|
|
],
|
|
"properties": {
|
|
"schema": {
|
|
"const": "hux.retention_audit.v1"
|
|
},
|
|
"id": {
|
|
"$ref": "common.schema.json#/$defs/id"
|
|
},
|
|
"ran_at": {
|
|
"$ref": "common.schema.json#/$defs/timestamp"
|
|
},
|
|
"policy_version": {
|
|
"type": "integer",
|
|
"minimum": 1
|
|
},
|
|
"results": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"action",
|
|
"count"
|
|
],
|
|
"properties": {
|
|
"action": {
|
|
"type": "string",
|
|
"enum": [
|
|
"expire_memory",
|
|
"decay_topic_context",
|
|
"purge_forgotten_content",
|
|
"report"
|
|
]
|
|
},
|
|
"count": {
|
|
"type": "integer",
|
|
"minimum": 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"oneOf": [
|
|
{
|
|
"$ref": "#/$defs/policy"
|
|
},
|
|
{
|
|
"$ref": "#/$defs/notice"
|
|
},
|
|
{
|
|
"$ref": "#/$defs/audit"
|
|
}
|
|
]
|
|
}
|