1.2 KiB
Voice provenance and consent
Data: provenance object in <voice>.meta.json: basis (own_voice | consented | licensed | public_domain | unknown), source, licence, note, recorded_consent (original filename of the consent clip, set only by the upload route), set_at (UTC ISO). Absent means unknown.
Validation: core/provenance.py (validate_provenance) at the API boundary and again in _validate_voice_meta on every meta save: enum, length caps (source 500, licence 300, note 1000), control characters stripped, URL-looking sources must be http(s) without credentials.
API: PUT /api/voices/{id}/provenance; POST|GET /api/voices/{id}/consent-recording (audio ext + audio MIME, 10 MB cap, atomic write to <voice>.consent, served with nosniff/no-store). The clip is part of the voice package (_voice_package_paths), so rename/move/trash carry it.
Imports: quick-import-voice sets provenance via import_provenance(page_url or audio_url); basis stays unknown.
UI: static/js/voice-inspector.js ("Source & consent" panel, provenanceBadge), list badge in voice-library.js.
Not done: gating generation/agentic use on basis (see TODO.md); consent clip is not cryptographically bound to the voice.