Consent Scope and Expiry Governance - Prevent Schema Drift in BUILD_RECEIPT Rows 2026
Your ffprobe duration matrix was GREEN. Mux challenge M5 matched pre and post durations. Legal still blocked the July highlight reel because consent_scope in the WAV read highlight_reel while consent_log.csv still said fest_public_vo from last month’s playtest terms—and BUILD_RECEIPT.json promoted wav_consent_metadata_ok: true on a receipt schema your CI never validated.
June–July 2026 micro-studios automated VO consent metadata and waveform-level proof faster than they governed vocabulary. The new failure mode is not missing fields—it is schema drift: enums, expiry formats, and boolean columns that disagree across consent_log.csv, embedded WAV tags, cousin receipts, and Thursday BUILD_RECEIPT row review.
This Industry News & Analysis note defines consent scope and expiry governance—registry files, migration windows, and audit gates—so technical proof and legal audit read the same words. It does not replace the VO evening tutorial (export steps) or the top 20 receipts hub (index)—it owns cross-artifact schema discipline.
Non-repetition note: Zero Steam Next Fest metadata surface checklists. Distinct from iXML recovery case study (strip points) and ffprobe matrix (clocks). Primary keyword: consent scope expiry governance BUILD_RECEIPT schema drift.
Who this note is for
| Audience | Outcome |
|---|---|
| Producer / release owner | Own form_version bumps and migration tickets |
| Legal / compliance liaison | Approve enum changes before WAV re-export |
| Audio lead | Embed only registry-approved consent_scope values |
| Automation engineer | CI assert against consent_schema_registry_v1.json |
| Beginner PM | Understand why “playback fine” ≠ audit pass |
Time: 45 minutes read; half-day to publish first registry + migrate one build_label.
Prerequisites: Active playtest with facilitator VO; at least one of consent_log.csv, VO_CONSENT_METADATA_RECEIPT.json, or BUILD_RECEIPT.json.
Why this matters now (June–July 2026)
- Automation outran vocabulary — Teams added
wav_consent_metadata_okandmetadata_survives_mux_okbeside legacyplaytest_clip_consent_okwithout a single enum source. - Form version churn — Playtest terms updated for July reels; spreadsheets still reference April scope strings.
- Expiry as string soup —
2027-12-31,2027-12-31T23:59:59Z, andexpires_after_festcoexist in different tools. - Publisher diligence — Q3 evidence packets join receipts; auditors compare column names, not waveforms.
- AI VO pipelines — Model-generated WAVs copy field names from prompts; wrong enums pass ffprobe (matrix) and still fail legal.
Direct answer: Publish consent_schema_registry_v1.json, pin form_version on every consent row, run governance gates G1–G8, file consent_scope_governance_receipt_v1.json, and block BUILD_RECEIPT promotion when scope/expiry disagree across artifacts—even when mux and duration proofs are GREEN.
Industry pattern — schema drift without playback failure
consent_log.csv uses fest_public_vo (April)
+
WAV embed uses highlight_reel (July playbook)
+
BUILD_RECEIPT boolean true (stale receipt file)
=
Audit FAIL, playback OK
H2 2026 observation: Micro-studios fixed technical gates (ffprobe, mux survival, design safe-zones) before fixing semantic gates. Legal reviews moved from “do we have a form?” to “do all systems use the same enum table on this build_label?”
Canonical field contract (four artifacts)
| Field | consent_log.csv | WAV LIST/iXML | vo_consent_metadata_receipt | BUILD_RECEIPT row |
|---|---|---|---|---|
consent_record_id |
UUID v4 | must match | must match | join key |
consent_scope |
registry enum | must match | must match | implied by receipt path |
consent_expires |
ISO date or registry rule | must match | must match | not duplicated—derived from receipt |
opt_out |
boolean | must match | must match | blocks public promotion |
form_version |
required | optional embed | required in receipt | consent_log_version column |
Beginner rule: If two cells disagree, playback truth loses to audit truth—re-export or fix CSV before public reel.
Developer rule: Never add ad-hoc scope strings in Audacity macros without registry bump—treat like API breaking changes.
consent_schema_registry_v1.json (source of truth)
Pin under release-evidence/governance/consent_schema_registry_v1.json:
{
"schema": "consent_schema_registry_v1",
"registry_version": "2026-05-playtest-july-v2",
"effective_build_labels": ["playtest-july-2027-rc1"],
"consent_scope_enum": [
"highlight_reel",
"internal_only",
"press_review",
"facilitator_raw_archive"
],
"deprecated_scopes": {
"fest_public_vo": {
"replaced_by": "highlight_reel",
"sunset_form_version": "playtest-april-2026-v1"
}
},
"consent_expires_format": "YYYY-MM-DD",
"expiry_policy": {
"must_exceed_reel_publish_date": true,
"grace_days_after_expiry": 0
},
"metadata_key_policy": "snake_case_v1",
"wav_embed_keys": [
"consent_record_id",
"consent_scope",
"consent_expires",
"opt_out"
],
"build_receipt_booleans": [
"playtest_clip_consent_ok",
"wav_consent_metadata_ok",
"metadata_survives_mux_ok",
"ffprobe_duration_matrix_ok"
],
"form_version_enum": [
"playtest-april-2026-v1",
"playtest-july-2026-v2"
]
}
Working dev note: Version the registry file, not individual WAVs—WAVs reference form_version inside metadata when legal requires traceability.
Governance gates G1–G8
| Gate | Owner | Pass when |
|---|---|---|
| G1 Registry published | Producer | consent_schema_registry_v1.json committed for build_label window |
| G2 consent_log aligned | Legal + PM | Every row uses current form_version and registry enums |
| G3 WAV embed spot-check | Audio lead | Sample ≥1 line per character_id matches log |
| G4 Receipt schema match | Audio lead | vo_consent_metadata_receipt_v1 fields ⊆ registry |
| G5 Expiry calendar | Legal | consent_expires ≥ planned reel publish date |
| G6 BUILD_RECEIPT row | Release owner | Booleans reference receipts that passed G3–G5 |
| G7 Thursday diff | Release owner | Row review includes consent columns |
| G8 Governance receipt filed | Producer | consent_scope_governance_receipt_v1.json GREEN |
G2 — consent_log.csv governance (beginner path)
Required columns after July 2026 discipline:
| column | type | example |
|---|---|---|
consent_record_id |
UUID | a1b2c3d4-0001-4000-8000-000000000001 |
consent_scope |
enum | highlight_reel |
consent_expires |
date | 2027-12-31 |
opt_out |
bool | false |
form_version |
enum | playtest-july-2026-v2 |
build_label |
string | playtest-july-2027-rc1 |
character_id |
string | facilitator_vo_07 |
Common mistakes:
| Mistake | Symptom | Fix |
|---|---|---|
| Copy-paste April rows | fest_public_vo in log |
Migrate scope per registry deprecated_scopes |
Missing form_version |
Audit cannot tell which terms apply | Add column; backfill |
| Expiry before fest date | Legal block despite GREEN mux | Extend date or narrow surface |
opt_out false in log, true in WAV |
Trust break | Re-export WAV from corrected row |
G3 — WAV embed verification (developer path)
After VO tutorial V2–V3, add governance assert:
import json, csv
from pathlib import Path
REG = json.loads(Path("release-evidence/governance/consent_schema_registry_v1.json").read_text(encoding="utf-8"))
allowed = set(REG["consent_scope_enum"])
log = {r["consent_record_id"]: r for r in csv.DictReader(
open("release-evidence/playtest/consent_log.csv", encoding="utf-8")
)}
# wav_fields: dict from your RIFF/iXML inspector keyed by consent_record_id
def assert_scope(wav_fields: dict) -> None:
row = log[wav_fields["consent_record_id"]]
if wav_fields["consent_scope"] not in allowed:
raise ValueError(f"scope not in registry: {wav_fields['consent_scope']}")
if wav_fields["consent_scope"] != row["consent_scope"]:
raise ValueError("WAV scope != consent_log scope")
if row["form_version"] not in REG["form_version_enum"]:
raise ValueError(f"unknown form_version: {row['form_version']}")
Wire into pre-mux CI after technical gates—semantic failure should exit 2 with readable message.
Expiry governance (scope vs time)
| Policy | Rule |
|---|---|
| Scope | What surfaces may use the line (highlight_reel vs internal_only) |
| Expiry | Last calendar day consent is valid for that scope |
| opt_out | Immediate revocation regardless of expiry |
Industry note: Teams confuse scope narrowing with opt_out. Narrowing scope requires re-export and registry-approved enum—not a silent spreadsheet edit.
Expiry vs fest calendar
| Event date | consent_expires must be |
|---|---|
| Reel publish 2027-07-15 | ≥ 2027-07-15 (or team policy +7d buffer) |
| Playtest-only archive | internal_only scope; expiry may be shorter |
Document buffer in registry expiry_policy—legal signs once, engineering enforces in CI.
Schema migration playbook (form_version bump)
When playtest terms change:
| Step | Action |
|---|---|
| 1 | Legal drafts new terms → assign playtest-july-2026-v2 |
| 2 | Update registry form_version_enum + deprecated_scopes |
| 3 | Migrate consent_log.csv rows (scripted, not hand-edited) |
| 4 | Re-export all public-scope WAVs |
| 5 | Re-run mux challenge if mux chain touched |
| 6 | Re-run ffprobe matrix |
| 7 | Reset BUILD_RECEIPT booleans to false until new receipts filed |
| 8 | File governance receipt with migration_ticket id |
Do not flip wav_consent_metadata_ok true on old receipt paths after migration—auditors compare file mtimes.
Migration script sketch
DEPRECATED = {"fest_public_vo": "highlight_reel"}
def migrate_row(row: dict) -> dict:
if row["consent_scope"] in DEPRECATED:
row["consent_scope"] = DEPRECATED[row["consent_scope"]]
row["form_version"] = "playtest-july-2026-v2"
return row
Log every changed consent_record_id in MIGRATION_LOG.md for standup.
BUILD_RECEIPT column drift (G6)
Typical 2026 consent-related booleans:
| Column | Proves | Cousin receipt |
|---|---|---|
playtest_clip_consent_ok |
Video MKV manifest | Lesson 243 |
wav_consent_metadata_ok |
Embedded WAV fields | Lesson 250 |
metadata_survives_mux_ok |
Post-mux survival | Mux challenge |
ffprobe_duration_matrix_ok |
Clock truth | Matrix #19 |
Drift class A: Boolean true, receipt file missing.
Drift class B: Boolean true, receipt fields use deprecated scope.
Drift class C: Boolean false, marketing already uploaded reel.
Thursday row review gates R4–R7 on scope rows—add consent booleans to your row catalog template.
"consent_governance": {
"consent_log_version": "playtest-july-2026-v2",
"registry_version": "2026-05-playtest-july-v2",
"governance_receipt": "release-evidence/governance/consent_scope_governance_receipt_v1.json"
}
consent_scope_governance_receipt_v1.json
{
"schema": "consent_scope_governance_receipt_v1",
"build_label": "playtest-july-2027-rc1",
"registry_path": "release-evidence/governance/consent_schema_registry_v1.json",
"registry_version": "2026-05-playtest-july-v2",
"form_version_active": "playtest-july-2026-v2",
"rows_in_consent_log": 12,
"rows_scope_mismatch": 0,
"rows_expiry_violation": 0,
"wav_spot_check_count": 4,
"wav_spot_check_pass": 4,
"gates": {
"G1_registry": "pass",
"G2_consent_log": "pass",
"G3_wav_embed": "pass",
"G4_receipt_schema": "pass",
"G5_expiry": "pass",
"G6_build_receipt": "pass",
"G7_thursday_diff": "pass",
"G8_filed": "pass"
},
"consent_scope_governance_ok": true,
"cousin_receipts": {
"vo_consent_metadata": "release-evidence/audio/VO_CONSENT_METADATA_RECEIPT.json",
"metadata_survives_mux": "release-evidence/audio/mux-challenge/latest/metadata_survives_mux_receipt_v1.json",
"ffprobe_duration_matrix": "release-evidence/audio/ffprobe-matrix/ffprobe_duration_matrix_receipt_v1.json"
},
"public_reel_allowed": true
}
public_reel_allowed may be true only when consent_scope_governance_ok and cousin technical receipts agree.
Cross-link to reel design and disclaimers
Reel design R4 displays disclaimer text tied to build_label. If scope says internal_only but design template says public fest copy, governance fails even when typography passes.
Producer checklist: Design, legal, and registry must list the same surface name (fest_public, highlight_reel, etc.)—pick one vocabulary in registry appendix.
Facilitator and multi-channel contracts
Multi-channel facilitator contract should reference form_version in daily notes—facilitators must not invent scope strings in Discord.
| Channel | Scope note |
|---|---|
| Steam playtest | Often internal_only for raw VOD |
| Public July reel | highlight_reel only with GREEN governance |
| Press screener | press_review requires separate log rows |
AI-generated VO and backlog forward
Model pipelines should read registry JSON at generation time—not copy enums from last month’s prompt. #22 AI voice QA reason-codes triages wrong tags (G1–G8); this note handles approved vocabulary.
Comparison — governance vs cousin articles
| Question | This URL | Cousin |
|---|---|---|
| How to export WAV? | link only | VO tutorial |
| Does metadata survive mux? | requires aligned enums first | Mux challenge |
| Why July urgency? | vocabulary + expiry | July trend |
| Duration drift? | orthogonal | ffprobe matrix |
| Missing iXML? | orthogonal | Recovery case study |
Stakeholder RACI (July 2026 spine)
| Role | G1 registry | G2 log | G3 WAV | G5 expiry | G6 BUILD_RECEIPT | G8 sign-off |
|---|---|---|---|---|---|---|
| Legal | A | A | C | A | C | A |
| Producer | R | R | C | C | R | R |
| Audio lead | C | C | R | I | R | C |
| Release owner | I | C | C | I | R | C |
| Automation | C | C | R | R | R | I |
A = accountable, R = responsible, C = consulted, I = informed.
Beginner translation: Legal owns words; audio owns bytes; producer owns the registry file living in git.
Three drift scenarios (walkthrough)
Scenario A — Deprecated scope in log only
| Artifact | value |
|---|---|
| consent_log | fest_public_vo |
| WAV embed | highlight_reel |
| BUILD_RECEIPT | wav_consent_metadata_ok: true |
Triage: G2 FAIL—run migration script; re-export WAV; set boolean false until new receipt.
Not a mux bug—do not open ffmpeg tickets.
Scenario B — Expiry before reel date
| Artifact | value |
|---|---|
| consent_expires | 2027-06-01 |
| reel publish | 2027-07-15 |
Triage: G5 FAIL—legal extends expiry or narrows surface to internal_only and removes line from public manifest.
ffprobe matrix may still PASS—do not confuse clocks with consent dates.
Scenario C — Stale boolean after toolchain GREEN
| Artifact | state |
|---|---|
| Mux challenge | PASS last week |
| form_version | bumped yesterday |
| BUILD_RECEIPT | booleans still true |
Triage: G6 FAIL—reset booleans; re-run cousin receipts under new form_version.
Thursday row review catches this if consent columns are in the catalog.
jq CI asserts (registry-aware)
REG=release-evidence/governance/consent_schema_registry_v1.json
SCOPE=$(jq -r '.consent_scope' release-evidence/audio/VO_CONSENT_METADATA_RECEIPT.json)
jq -e --arg s "$SCOPE" '.consent_scope_enum | index($s)' "$REG"
FV=$(jq -r '.form_version_active' release-evidence/governance/consent_scope_governance_receipt_v1.json)
jq -e --arg f "$FV" '.form_version_enum | index($f)' "$REG"
Exit non-zero on failure—message should print registry_version for support.
Quarterly registry review calendar
| Cadence | Activity |
|---|---|
| Weekly | Thursday diff includes consent booleans |
| Per playtest wave | form_version bump + migration log |
| Monthly | Audit deprecated_scopes for sunset |
| Pre-fest | Legal signs expiry buffer policy |
| Post-incident | Add drift class to MIGRATION_LOG.md |
Pair monthly review with Friday Block 5 evidence hygiene—archive superseded registry files under release-evidence/governance/archive/.
Publisher and platform diligence questions (2026)
Questions micro-studios should answer without opening Audacity:
- Where is the enum source of truth for
consent_scope? - What
form_versionapplies to thisbuild_label? - How do you detect deprecated scopes in old CSV rows?
- What resets BUILD_RECEIPT booleans after a terms change?
- Show governance receipt beside VO and mux cousin receipts.
PQ3 diligence packets that omit (5) get follow-up emails—even when demo smoke is GREEN.
OBS video consent vs WAV scope (do not merge)
| Lane | Receipt | Scope field location |
|---|---|---|
| Video clips | Lesson 243 | MKV manifest |
| VO WAV | Lesson 250 | embedded LIST/iXML |
Governance rule: highlight_reel on video does not imply highlight_reel on VO—both rows must exist in consent_log.csv with matching IDs.
OBS highlight preflight stays video-only.
Workshop — half-day registry install
| Block | Minutes | Output |
|---|---|---|
| Legal + PM | 60 | Approved enum list + expiry buffer |
| Engineering | 90 | consent_schema_registry_v1.json + jq asserts |
| Audio | 60 | Spot-check script on 4 WAVs |
| Release | 30 | BUILD_RECEIPT column template update |
| Producer | 30 | consent_scope_governance_receipt_v1.json filed |
Exit criterion: Team can recite difference between Drift class A/B/C without opening slides.
Surface vocabulary appendix (reduce design/legal drift)
Publish a one-page surface_vocabulary_v1.md beside the registry:
| Term | Meaning | Used in |
|---|---|---|
fest_public |
Store-visible fest demo or capsule | BUILD_RECEIPT surface |
highlight_reel |
Short facilitator VO cut for marketing | consent_scope enum |
playtest_invite |
Steam playtest branch only | Playtest isolation |
internal_only |
Team archive; no public mux | consent_log |
Beginner mistake: Using fest_public as a consent_scope value—registry should reject it at G2 CI.
Dual-audience quick start
Beginners (30 minutes):
- Open
consent_log.csvand confirmform_versioncolumn exists. - Compare one row’s
consent_scopeto VO tutorial field list. - If strings differ, stop public reel—ask legal which enum is correct.
- File a ticket; do not edit WAV by hand without audio lead.
Developers (same day):
- Commit registry JSON.
- Add jq asserts to CI.
- Wire governance receipt generation into mux night script.
- Extend Thursday row review catalog with four consent booleans.
Incident response — scope mismatch discovered post-upload
| Hour | Action |
|---|---|
| 0 | Pull public reel if opt_out or wrong scope risk |
| 1 | Export drift table: log vs WAV vs BUILD_RECEIPT |
| 4 | Legal confirms correct scope per participant |
| 24 | Re-export affected WAVs; re-run mux + matrix if needed |
| 48 | File new governance receipt; update BUILD_RECEIPT |
Document in MIGRATION_LOG.md—partners may ask weeks later.
Contract with ten-minute ritual (#23)
| Ritual step | Governance dependency |
|---|---|
| Open consent log | G2 must pass |
| Spot-check WAV | G3 uses registry enums |
| Promote boolean | G6 requires governance receipt path |
Ritual is fast; registry is correct—the ritual runs after registry enums are decided, so you flip wav_consent_metadata_ok only on scope/expiry-aligned WAV bytes.
Evidence folder layout
release-evidence/governance/
consent_schema_registry_v1.json
archive/
consent_schema_registry_v1-2026-04.json
consent_scope_governance_receipt_v1.json
MIGRATION_LOG.md
release-evidence/playtest/
consent_log.csv
Industry signals (June–July 2026, qualitative)
Teams report three recurring phrases in compliance threads:
- “Playback is fine” — usually means technical receipts GREEN, governance not run.
- “We copied metadata” — often means spreadsheet copy, not re-export (metadata-as-artifact opinion #21).
- “Same UUID” — necessary but not sufficient; scope must match.
No invented metrics—pattern synthesis from public facilitator forums and partner intake checklists.
opt_out and scope interaction matrix
| opt_out | consent_scope | Public reel |
|---|---|---|
| true | any | BLOCK |
| false | internal_only | BLOCK |
| false | highlight_reel | allowed if expiry OK |
| false | press_review | allowed only on press surface |
Automate this table in CI as public_surface_allowed(scope, opt_out)—do not rely on producer memory during upload night.
Auditor readout (what legal receives)
Zip without game repo:
consent_schema_registry_v1.json- Redacted
consent_log.csv consent_scope_governance_receipt_v1.json- Spot-check proof for one WAV
- BUILD_RECEIPT excerpt (consent booleans only)
Auditors validate enums and dates—not DAW brand.
Key takeaways
- Schema drift breaks audits while playback still works—govern vocabulary before adding more booleans.
consent_schema_registry_v1.jsonis the enum source of truth for scope, expiry format, and form versions.form_versionbumps trigger re-export and receipt reset—not spreadsheet-only edits.- Scope ≠ expiry ≠ opt_out—three different gates; do not merge in standup language.
- BUILD_RECEIPT booleans must point at receipts validated under the active registry.
- Pair G1–G8 with Thursday row review and the top 20 hub.
- Deprecated scopes need explicit
replaced_byin registry—no silent find-replace in CSV. - CI should assert registry membership before mux night.
- Lesson 250 owns BUILD_RECEIPT milestone; this note owns cross-file enum discipline.
- Pair with #21 metadata-as-artifact opinion for standup language; use #23 ten-minute ritual as the pre-mux promotion gate.
- Archive superseded registry JSON under
governance/archive/—never delete without migration log entry. - Treat registry bumps like API semver for consent fields.
FAQ
Is this legal advice
No—it's an engineering governance pattern; legal approves enums and expiry rules you encode in the registry.
Can we use camelCase in WAV tags
Only if registry metadata_key_policy changes—default July spine is snake_case_v1 per VO tutorial.
What if one line is press_review and others highlight_reel
Allowed—each row carries its own scope; reel manifest must not mux internal_only lines into public cuts.
Do we version the registry per game or per studio
Studio-wide registry with effective_build_labels array is typical; fork only when titles diverge on legal terms.
How often to bump form_version
When playtest terms change—not on every build_id.
Can governance pass if ffprobe matrix fails
No—governance is necessary, not sufficient; technical cousin receipts must also be GREEN.
Where does consent_log live
Default release-evidence/playtest/consent_log.csv—same spine as release evidence taxonomy.
Should publishers see deprecated scopes
Yes in migration logs—proves you did not silently rename without participant notice.
Relationship to BUILD_RECEIPT beginner tutorial
Adopt first BUILD_RECEIPT evening week one; add registry by week three when VO consent cluster goes live.
What blocks public_reel_allowed
consent_scope_governance_ok: false OR any cousin receipt blocking OR opt_out on any manifest line.
Can we store registry in Notion instead of git
No—CI and auditors need versioned JSON in release-evidence/; Notion may link to git hash only.
How does this relate to Lesson 243 and 250
243 governs video clip consent receipts; 250 governs VO BUILD_RECEIPT milestone—registry covers both field vocabularies where they share consent_record_id.
What if Steam playtest terms differ from fest reel terms
Use separate form_version values in registry; never mix rows in one CSV without form_version column.
Should facilitators sign form_version
Yes—add to facilitator contract acknowledgment line.
Can we auto-promote scope from internal to highlight_reel
Only with new participant consent row—governance migration is not a substitute for legal approval.
What is the minimum team size to maintain a registry
One producer plus legal consult quarterly—solo devs can run G1–G8 with a half-day install and Thursday diffs.
Does governance replace legal review of playtest terms
No—it ensures engineering artifacts use the same words legal already approved in those terms.
Govern consent scope and expiry like an API—registry enums, migration discipline, and BUILD_RECEIPT rows that agree with WAV bytes before the next July reel upload. Re-run G1–G8 whenever form_version changes, not only when ffmpeg changes.