Skip to content

Commit 2bbd45b

Browse files
SashaMITcursoragent
andcommitted
docs(av): reconcile Phase 5 status — 3/4/5 core landed, wiring + cert open
Mark the pure core of chunks 3/4/5 as landed (selector, variant-set AAD weld encoder, manifest builder, per-asset secret KDF — all in ddrm-envelope::av/ lib.rs, fail-closed + unit-tested) and spell out precisely what remains: the pipeline WIRING (ddrm-media-authority serve selection, decrypt-provider AAD rebuild, mint emit) plus the real perceptual DSP (bounded-placeholder seam now; certified embed swaps in post media-survival cert). Adds a "remaining wiring" section with exact files and the one thing needed to validate end-to-end (a gateway bring-up with a synthetic asset; real media only for the perceptual cert). Notes the interleave-application follow-up as tracked, not dropped. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 65f0975 commit 2bbd45b

1 file changed

Lines changed: 72 additions & 10 deletions

File tree

docs/AV_WATERMARKING.md

Lines changed: 72 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,19 @@ media** at the FP-controlled threshold (real content / screen-record / CMAF leng
232232
single-leaker tracing or c=2 only — and the FP-controlled threshold pushes these minimums
233233
**up**, not down.
234234

235-
### Phase 5 — landed so far (chunks 1, 2, 6)
235+
### Phase 5 — landed so far (chunks 1, 2, 6 + the 3/4/5 *core*)
236236

237237
> Canonical chunk numbering follows [`PHASE5_BUILD_SPEC`](AV_WATERMARKING.md) (1 schema · 2 codeword
238238
> · 3 mint · 4 AAD-weld · 5 serve · 6 extractor · 7 overlay). The numbered list below predates that
239-
> spec; the ✅ markers map the two. **Landed = chunks 1, 2, 6** (the tractable, pipeline-free pieces
240-
> built on the proven research). **Mine, deferred to the live CENC/DASH/quorum pipeline = chunks 3
241-
> (mint transcode DSP), 4 (full-variant-set AAD weld), 5 (serve-time selector).**
239+
> spec; the ✅ markers map the two. **Landed = chunks 1, 2, 6**, plus the **pure, pipeline-free CORE
240+
> of 3/4/5** (`ddrm-envelope::av`): the serve-time **selector** (`select_symbols`), the
241+
> full-variant-set **AAD weld** encoder (`variant_set_commitment` +
242+
> `DecryptTranscriptV1::to_aad_with_all_bindings`), and the mint-side **manifest builder + per-asset
243+
> secret KDF** (`build_manifest`, `asset_secret_from_master`) — all fail-closed and unit-tested.
244+
> **Still mine / needs the live pipeline = the WIRING** (mint emit + serve selection + decrypt-boundary
245+
> rebuild), the **real perceptual DSP embed** (the bounded placeholder seam is specified but the
246+
> certified embed is deferred until media-survival cert), and **media-survival certification on real
247+
> content**. See "remaining wiring" below.
242248
243249
- **Chunk 1 — variant manifest schema.** `elastos.ddrm.av-variants/v1` lives in
244250
`capsules/ddrm-envelope/src/av.rs` (`VariantManifestV1`, behind the `av-variants` feature):
@@ -272,6 +278,27 @@ single-leaker tracing or c=2 only — and the FP-controlled threshold pushes the
272278
`bitERR 0`, true leaker ranked top with registration; all-erasures / no attribution without). The
273279
Rust `--extract-av-fingerprint` CLI is **deferred until the scheme is frozen/certified** (avoid a
274280
blind FFT port of an uncertified scheme — see the chunk-6 decision in `tools/av-forensics/README.md`).
281+
- **Chunks 3/4/5 — pure core (landed in `ddrm-envelope::av` + `lib.rs`).** The cryptography and
282+
selection logic the pipeline will call, built and tested ahead of the wiring so the boundary stays
283+
byte-aligned:
284+
- **Serve selector (chunk 5 core):** `select_symbols(manifest, bias_q, grant_digest)` returns the
285+
per-marked-segment symbol, fail-closed — wrong per-asset secret (bias-commitment mismatch),
286+
unsupported arity, or malformed manifest all `Err`; a single-encode manifest selects nothing.
287+
Arity-2 (A/B) direct mapping (codeword bit ↔ segment), matching the proven extractor.
288+
- **AAD weld (chunk 4 core):** `variant_set_commitment(manifest)` (domain-separated, length-prefixed
289+
hash of the full published set) bound via `DecryptTranscriptV1::to_aad_with_all_bindings`
290+
**strictly additive**: a non-fingerprinted open is byte-identical to the prior encoder (all goldens
291+
replay), a fingerprinted open binds the exact set (manifest swap / out-of-set variant fails the CEK
292+
unwrap closed at the decrypt boundary).
293+
- **Mint core (chunk 3 core):** `build_manifest(...)` assembles + validates a fingerprinted manifest
294+
from produced variants; `asset_secret_from_master(master, content_hash)` derives the per-asset
295+
watermark secret so mint and serve agree on the bias/codebook **without publishing or per-asset
296+
storing it** (manifest carries only the commitment; rotating `master` re-keys every asset). A
297+
round-trip test closes the mint→serve loop.
298+
- **Known follow-up (welded honesty):** the manifest's `interleave` is carried + committed but
299+
**not yet applied** across embed/select/recover (the proven extractor maps bit `i`→segment `i`
300+
directly); applying it is a single change that must land on the Rust selector AND the Python
301+
extractor together, then re-run the extractor. Tracked, not silently dropped.
275302

276303
1.**LANDED (chunk 1).** **Spec + manifest schema.** Define the variant manifest
277304
(`elastos.ddrm.av-variants/v1`: which segments carry `{A,B}`, the per-variant bit, the codeword
@@ -288,9 +315,12 @@ single-leaker tracing or c=2 only — and the FP-controlled threshold pushes the
288315
strategies** (random / majority / minority / all-ones / all-zeros / interleave): FP ≤ ε,
289316
100% detection. The published per-asset duration bound at this FP-controlled threshold
290317
still needs **real-media** re-validation (not code-level).
291-
3. **Serve-time selector (behind a flag, single-encode fallback).** `ddrm-media-authority`
292-
picks `variant[i]` from the codeword when a manifest exists; else serves the single
293-
encode and sets `fingerprinted:false`.
318+
3. **Serve-time selector (behind a flag, single-encode fallback).** ☑️ **Core landed**
319+
(`av::select_symbols`, fail-closed, unit-tested). **Remaining = wiring:** `ddrm-media-authority`
320+
(`compute_open_payload`) loads the manifest from the DASH dir, derives the per-asset bias from the
321+
node master, calls `select_symbols`, and reads the selected variant ciphertext per marked segment;
322+
else serves the single encode and sets `fingerprinted:false`. Needs the `av-variants` feature on
323+
`ddrm-media-authority` + a live serve path to validate.
294324
*Check:* with a two-variant fixture dir, two different grants produce two different
295325
served segment-byte sequences; with no manifest, both get the identical single encode.
296326
4.**LANDED as Python (chunk 6).** **Offline extractor.** Recovers the codeword → buyer,
@@ -299,9 +329,14 @@ single-leaker tracing or c=2 only — and the FP-controlled threshold pushes the
299329
*Check:* a file assembled from a known A/B sequence extracts back to that codeword
300330
(clean), and still extracts after a lossy re-encode + crop pass (validated: `bitERR 0`, leaker
301331
ranked top with FM registration).
302-
5. **Mint transcode pipeline (the heavy lift).** Produce `{A,B}` per segment with the
303-
per-variant DSP (video: spatial/temporal mark; audio: spread-spectrum/echo-hiding),
304-
CENC-encrypt, publish manifest.
332+
5. **Mint transcode pipeline (the heavy lift).** ☑️ **Core landed** (`av::build_manifest`,
333+
`av::asset_secret_from_master`). **Remaining = wiring + the real DSP:** produce `{A,B}` per marked
334+
segment, CENC-encrypt each, publish the manifest beside `stream.mpd`. The **embed has a bounded
335+
placeholder seam** (a valid, ignorable, byte-distinct marker — exercises mint→serve→select→weld
336+
end-to-end **without** a perceptual claim); the **real per-variant DSP** (video: spatial/temporal
337+
mark; audio: spread-spectrum/echo-hiding) **swaps in behind the same interface only after
338+
media-survival certification** (avoid shipping an uncertified perceptual embed in the trusted mint
339+
path).
305340
**Gating DSP research sub-item (the one genuine unknown):** blind **geometric
306341
registration** of the recovered mark — Phase 0 proved a search loop is insufficient (a
307342
fine scale grid made detection *worse*); it needs a **deterministic estimator** (an
@@ -328,6 +363,33 @@ single-leaker tracing or c=2 only — and the FP-controlled threshold pushes the
328363
Phases 1–4 are tractable and self-contained. **Phase 5 is the real cost** (a transcode
329364
pipeline) and gates the rest going live.
330365

366+
### Remaining wiring (precise — picks up where the landed core stops)
367+
368+
The pure core (selector, AAD weld, manifest builder, secret KDF) is in `ddrm-envelope::av` +
369+
`lib.rs`, fully unit-tested. What is **not** yet wired (each touches the trusted serve/decrypt path, so
370+
it needs a live serve path — synthetic media is enough; **real** content is only for the perceptual
371+
cert):
372+
373+
1. **`ddrm-media-authority` (serve, chunk 5):** add the `av-variants` feature; in `compute_open_payload`
374+
load `av-variants.json` from the DASH dir, derive `bias = asset_bias_vector(asset_secret_from_master(
375+
node_master, content_hash), m)`, call `select_symbols`, and read the **selected** variant ciphertext
376+
per marked segment (fall back to the flat `segment_paths` when no/invalid manifest). Set
377+
`fingerprinted` on the serve descriptor (`serve_media`).
378+
2. **AAD weld (chunk 4):** compute `variant_set_commitment(manifest)` on the serve side and pass it into
379+
`recover_quorum`'s transcript via `to_aad_with_all_bindings`; mirror it in
380+
`decrypt-provider::prepare_bound_open` so the seal and rebuild stay byte-identical (extend the
381+
`stream_segment` unit test).
382+
3. **Mint (chunk 3/5):** in `run_prepare_mint_media``media-provider` produce the per-marked-segment
383+
variants (placeholder embed seam), `encrypt-provider` CENC each, write the manifest via
384+
`build_manifest`, and persist the bias `master`→asset mapping for the serving node.
385+
4. **Smoke:** extend `quorum-helper-verify.sh` for the two-grant divergence check (different served
386+
bytes, byte-identical with no manifest).
387+
388+
**To validate this end-to-end I need you to:** bring up the gateway with a **synthetic** test asset
389+
(no real content required) so I can iterate the serve+mint wiring against a live path — same bring-up
390+
you ran before (`ELASTOS_DDRM_RIGHTS=chain`, `ELASTOS_DKMS_CARRIER=1`). **Real media + a screen-record
391+
are only needed later**, for media-survival certification + swapping the placeholder for the real DSP.
392+
331393
---
332394

333395
## 6. Principles conformance (pre-commit self-review hooks)

0 commit comments

Comments
 (0)