| additionalProperties | {“type”: “object”, “additionalProperties”: false, “required”: [“source”], “properties”: {“source”: {“enum”: [“vault”, “env”, “file”], “description”: “Where the secret lives · never an inline value (spec/01-envelope.md §secrets).”}, “key”: {“type”: “string”, “description”: “Store key (vault) or OS env var name (env).”}, “path”: {“type”: “string”, “description”: “File path · file source only · contents read at resolve time · masked.”}, “egress”: {“type”: “array”, “description”: “Sanctioned destinations for this secret · declassification (spec/01-envelope.md §egress) · absent/empty = default-deny (every exec:/invoke: reach is a leak).”, “items”: {“type”: “object”, “additionalProperties”: false, “required”: [“to”], “properties”: {“to”: {“type”: “string”, “description”: “The sanctioned sink · a tool id (nika:fetch · nika:notify · mcp:<server>/<tool>), exec, a provider-egress sink infer / agent (a secret in an infer/agent prompt), or outputs (the workflow boundary — a return value derived from the secret’s response) · SPECIFIC (no cross-tool laundering).”}, “host”: {“type”: “string”, “description”: “Static-literal destination host · sanctions only when the sink’s destination arg is exactly this host (a templated host stays the runtime check). Mutually exclusive with host_from_self.”}, “host_from_self”: {“type”: “boolean”, “description”: “The secret value IS the destination URL (host unknown statically) · sanctions only the direct-secret-URL shape with the non-occlusion guard. Mutually exclusive with host.”}}, “not”: {“required”: [“host”, “host_from_self”]}}}}, “allOf”: [{“if”: {“properties”: {“source”: {“const”: “file”}}}, “then”: {“required”: [“path”], “not”: {“required”: [“key”]}}, “else”: {“required”: [“key”], “not”: {“required”: [“path”]}}}], “description”: “A secret is a reference to a store · discriminated by source · vault/env require key · file requires path · optional egress: sanctioned-destination list (spec/01-envelope.md).”} |