Privacy Configs and Skill Privacy Extraction/Restore
This page explains OpenViking privacy configs and how they work with skill write-time extraction and read-time restore.
Goal
Privacy configs separate sensitive values (such as api_key, token, base_url) from skill body content to reduce plaintext storage of recognized values in SKILL.md, with version lookup and switching. Extraction relies on a model and replaces only recognized, matched spans; it does not guarantee discovery of every sensitive value.
Core goals:
- Auto-extract sensitive values at write time and replace with placeholders
- Auto-restore values from the active config at read time
- Provide version query, switching, and auditability
Core Objects and Storage Layout
Privacy configs are keyed by category + target_key.
category: config category (currently skill usesskill)target_key: target identifier (usually the skill name)
Storage layout in user space:
viking://user/{user_id}/privacy/{category}/{target_key}/
├── .meta.json # metadata (active_version/latest_version/labels, etc.)
├── current.json # active version snapshot
└── history/
├── version_1.json
├── version_2.json
└── ...current.json and history/version_x.json are full values snapshots.
Version Semantics
upsert
- Each upsert treats incoming
valuesas the candidate snapshot - If
valuesis identical to currentvalues, no new version is created - Otherwise a new version is created and activated
- New keys are allowed (no unknown-key rejection)
valuesis a full snapshot, not a patch; omitted old keys are absent from the new version
activate
- Sets a historical version as active (writes back to
current.json) - Updates
active_versionin.meta.json - Does not rotate or revoke credentials at an external service; it only selects the values OpenViking uses
Skill Privacy Extraction (Write Path)
When adding a skill via add_skill, OpenViking runs extraction + placeholderization.
add_skill
-> SkillProcessor._sanitize_skill_privacy
-> extract_skill_privacy_values (LLM extracts values)
-> placeholderize_skill_content_with_blocks (replace plaintext with placeholders)
-> privacy.upsert(category="skill", target_key=skill_name, values=...)
-> write placeholderized SKILL.mdKey Points
- Extraction source: model returns JSON;
valuesis used as privacy key-value pairs. - Content replacement: matched plaintext is replaced by placeholders:
{{ov_privacy:skill:{skill_name}:{field_name}}}
- Block mapping captured:
original_content_blocksreplacement_content_blocks
- Persisted content: matched spans become placeholders; unmatched content remains unchanged. This processes the skill body, not every attached file.
Skill Restore on Read (Load Path)
When reading SKILL.md, FSService.read attempts placeholder restoration automatically.
fs.read(uri)
-> get_skill_name_from_uri(uri)
-> privacy.get_current(category="skill", target_key=skill_name)
-> restore_skill_content(content, skill_name, current.values)URI Matching
Current matching is suffix-based: /skills/{name}/SKILL.md, so it supports user-scoped skill paths such as:
viking://~/skills/{name}/SKILL.mdviking://user/{user_id}/skills/{name}/SKILL.md
restore Rules
restore_skill_content behavior:
Placeholder exists in content and value exists and is non-empty
-> replace directly.Placeholder exists in content but value is missing/empty
-> keep placeholder; add item tounresolved_entries.Config key is non-empty but not referenced by any placeholder in content
-> add to extra-config notice (Configured but not referenced in content).If
unresolved_entriesor extra-config entries exist, append notice block:[Privacy Config Notice]Missing config: ...(if any)Configured but not referenced in content: ...(if any)
Current implementation only runs restore when a
currentprivacy config exists for that skill. If no current config exists, no notice is appended.
read returns restored values, and extra-config notices also include values. Privacy APIs and historical snapshots can return full values as well. This feature does not redact responses or encrypt storage; see Storage Encryption for encryption.
Relationship with CLI/API
- Management plane: Privacy API/CLI for versions (query, write, rollback)
- Content plane:
readautomatically restores placeholders - Separation of concerns: content files hold placeholders; privacy service holds sensitive values and versions
Common commands:
ov privacy categories
ov privacy list skill
ov privacy skill search-web
ov privacy upsert skill search-web --values-json '{"api_key":"..."}'
ov privacy activate skill search-web 1
ov read viking://~/skills/search-web/SKILL.mdBenefits
- Reduces plaintext sensitive data exposure in skill content
- Version history supports configuration changes after external credential rotation
- Transparent to callers:
readreturns restored executable skill text - Notice block improves troubleshooting when config is incomplete or over-provisioned
Related Documentation
- Skills - Skill write/read API
- Privacy API - Privacy config endpoints
- Context Extraction - Main extraction pipeline
- Architecture Overview - Layering and module relationships