# 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 so plaintext is not permanently stored in `SKILL.md`, while keeping full version management and rollback.
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 uses `skill`)
- `target_key`: target identifier (usually the skill name)
Storage layout in user space:
```
viking://user/{user_space}/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 `values` as the candidate snapshot
- If `values` is identical to current `values`, no new version is created
- Otherwise a new version is created and activated
- New keys are allowed (no unknown-key rejection)
### activate
- Sets a historical version as active (writes back to `current.json`)
- Updates `active_version` in `.meta.json`
---
## 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.md
```
### Key Points
1. **Extraction source**: model returns JSON; `values` is used as privacy key-value pairs.
2. **Content replacement**: matched plaintext is replaced by placeholders:
- {{ov_privacy:skill:{skill_name}:{field_name}}}
3. **Block mapping captured**:
- `original_content_blocks`
- `replacement_content_blocks`
4. **Persisted content**: stored `SKILL.md` contains placeholders, not plaintext values.
---
## 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:
- `viking://agent/skills/{name}/SKILL.md`
- `viking://agent/{agent_id}/skills/{name}/SKILL.md`
### restore Rules
`restore_skill_content` behavior:
1. **Placeholder exists in content and value exists and is non-empty**
-> replace directly.
2. **Placeholder exists in content but value is missing/empty**
-> keep placeholder; add item to `unresolved_entries`.
3. **Config key is non-empty but not referenced by any placeholder in content**
-> add to extra-config notice (`Configured but not referenced in content`).
4. If `unresolved_entries` or extra-config entries exist, append notice block:
- `[OpenViking Privacy Notice]`
- `Related configured privacy values: ...`
- `Not replaced (missing config): ...` (if any)
- `Configured but not referenced in content: ...` (if any)
> Current implementation only runs restore when a `current` privacy config exists for that skill. If no current config exists, no notice is appended.
---
## Relationship with CLI/API
- Management plane: Privacy API/CLI for versions (query, write, rollback)
- Content plane: `read` automatically restores placeholders
- Separation of concerns: content files hold placeholders; privacy service holds sensitive values and versions
Common commands:
```bash
openviking privacy categories
openviking privacy list skill
openviking privacy skill
openviking privacy upsert skill --values-json '{"api_key":"..."}'
openviking privacy activate skill
openviking read viking://agent/default/skills//SKILL.md
```
---
## Benefits
- Reduces plaintext sensitive data exposure in skill content
- Versioning supports key rotation and fast rollback
- Transparent to callers: `read` returns restored executable skill text
- Notice block improves troubleshooting when config is incomplete or over-provisioned
---
## Related Documentation
- [Skills](../api/04-skills.md) - Skill write/read API
- [Privacy API](../api/10-privacy.md) - Privacy config endpoints
- [Context Extraction](./06-extraction.md) - Main extraction pipeline
- [Architecture Overview](./01-architecture.md) - Layering and module relationships