# wdy-manifest v0.1 Specification

- Status: **v0.1 draft (2026-09)**. From v0.1: fields are only added, never renamed; historical records stay verifiable forever.
- Scope: a **verifiable provenance manifest** for micro-drama / micro-film verticals. WDY issues no copyright registrations — the manifest records *how and by whom a file was produced at a point in time*; ownership is decided by registrations, contracts, and courts.
- Chinese version: https://wdy.org.cn/certified/rules/wdy-manifest/v0.1/wdy-manifest.spec.zh.md

## 1. Field table

| Field | Required | Notes |
|---|---|---|
| `manifest_version` | ✅ | fixed `"0.1"` |
| `record_id` | ✅ | `WDY-YYYY-NNNN-XXXXXX`: 4-digit year + 4-digit sequence + 6-char random suffix (ambiguous letters 0/O/1/I/L excluded, ~10⁹ space) — sequence keeps the ledger auditable, the random suffix makes verify links non-enumerable; verify page at `wdy.org/certified/verify/<record_id>/` (Chinese at `…/zh/`) |
| `title` | ✅ | work title |
| `content_type` | ✅ | `video` / `script` / `storyboard` / `poster` / `report` / `document` / `dataset` / `webpage` |
| `file.filename` / `file.size_bytes` / `file.sha256` | ✅ | master-file SHA-256 (lowercase hex); recomputed at verification |
| `provenance.production_mode` | ✅ | `ai` / `live` / `hybrid` / `authored`（人类写作，AI 占比固定 0，无 AI 标识义务） |
| `provenance.ai_tools[]` | advised | `{name, role}` e.g. `{"name":"Kling v2","role":"video-gen"}` |
| `provenance.ai_generated_ratio` | ✅ | 0–1; must sum to 1.0 with `live_action_ratio` |
| `provenance.live_action_ratio` | ✅ | see above |
| `ai_disclosure.visible_label` | ✅ | AI/hybrid works must be `true` (visible on-screen AI label) — **issuance refused otherwise** |
| `ai_disclosure.metadata_marking` | ✅ | implicit metadata marking (China's AI-content labelling measures, eff. 2025-09-01; micro-drama: NRTA Order No. 16 Art. 34) |
| `ai_disclosure.eu_ai_act_article_50` | optional | `{applicable, machine_readable_marking:{metadata, pixel_watermark}, disclosure_log_url}`; if `applicable=true`, both markings must not be false (EU AI Act Art. 50, applicable 2026-08-02; machine-readable marking transition for pre-existing systems ends 2026-12-02) |
| `rights_claims[]` | advised | `{role, party, basis, scope}` — **records each party's self-declared claim; states no ownership conclusion** |
| `rights_evidence[]` | optional | fingerprints of supporting documents (contracts, credit pages): `{filename, size_bytes?, sha256}` — **originals stay with the submitter, never uploaded**; enables later "this is that exact document" checks |
| `contact` | advised | `{name, email, org?}` submitter contact for verify-link delivery; **not shown on the public verify page** |
| `anchors.tsa` | optional | RFC 3161 trusted-timestamp anchor: `{provider, serial, timestamp, gen_time, policy, digest_algorithm, message_imprint, tsr_file, tsr_sha256, endpoint, ca_hint, stamped_at}` — the first three fields are the original v0.1 names; the rest are additive. The token file (`.tsr`) is served next to the verify page and is verifiable offline with `openssl ts -verify` |
| `anchors.opentimestamps` | optional | OpenTimestamps (Bitcoin) anchor: `{type, protocol, chain, digest_algorithm, message_digest, calendars[], proof_file, proof_sha256, status, block_height, submitted_at, confirmed_at}` — the proof file (`.ots`) is served next to the verify page; independently verifiable against Bitcoin via public block explorers (`tools/ots_anchor.py --verify`) or the official `ots` client |
| `anchors.zhixin` | optional | ZhiXinChain (Tencent consortium chain) anchor: `{type, chain, api_endpoint, anchor_target, hash_sm3, ev_id, tx_id, block_height, tx_time, extend_info, cert_url, anchored_at}` — chain-issued certificate verifiable at the chain operator's certificate page |
| `anchors.storage[]` | optional | `[{type: "arweave"\|"s3"\|"ipfs", ref}]` public replicas |
| `c2pa_mapping` | optional | bridge to C2PA 2.1 (see §3) |
| `request.evidence_tier` | optional | submitter's requested evidence tier: `standard` (hash + co-signature + public verify page) / `tsa` (adds trusted-timestamp anchoring) / `judicial` (adds judicial-chain anchor or notarization, dispute-grade) — tier plan & fees are confirmed in WDY's review email |
| `request.referral` | optional | reseller/referral code (2–16 uppercase alphanumerics), auto-captured by the submit page for partner attribution |
| `signer.name` / `signer.key_id` | ✅ | issuing party + key id (e.g. `2026-rot1`) |
| `created_at` | ✅ | ISO-8601 UTC |
| `signature` | ✅ | `{alg:"Ed25519", key_id, created_at, value(base64)}` |

## 2. Signing scheme

1. Take the manifest object **without** the `signature` field;
2. Canonicalize: `JSON.stringify(sorted keys, compact separators, UTF-8)`;
3. Sign the canonical bytes with **Ed25519**; store base64 in `signature.value`;
4. Public keys published at `https://wdy.org/.well-known/wdy-key.pub` (one `key_id=base64` per line);
5. Private keys stay offline in `keys/` (never in the repo, never on the server); rotated, with the rotation in the `key_id`.

Two signing roles:
- **Submitter** fingerprints locally (browser tool or CLI) — file never uploaded;
- **WDY** reviews the manifest and co-signs → the signature attests *"WDY reviewed and published this record at time T"*, not *"WDY has seen the file"*.

## 3. C2PA 2.1 bridge

| C2PA concept | wdy-manifest counterpart |
|---|---|
| Claim Generator | `provenance.ai_tools[]` |
| Assertions (trainedAlgorithmicMedia / metadata marking) | `provenance.production_mode` + `ai_disclosure.metadata_marking` |
| Hard Bindings (SHA-256) | `file.sha256` |
| Signature (COSE/Ed25519) | `signature` (independent JWS-style object) |
| Ingredient (asset list) | planned v0.2: `episode_tree[]` referencing upstream manifests |

Principle: **keep native C2PA manifests embedded in source files; use the wdy layer as the re-anchoring point when platforms strip metadata** — after transcoding, provenance is still recoverable from the wdy record via the SHA-256 binding.

## 4. Verification

- Local: `python wdy_verify.py <manifest.json> <original file> --pub wdy-key.pub` → recompute hash + verify signature + check ratios;
- Browser: `wdy.org/submit.html` computes fingerprints locally; verify pages at `wdy.org/certified/verify/<record_id>/`;
- Any third party **needs no trust in WDY**: original file + manifest JSON + public key is enough to re-verify everything offline.
- **Independent anchors** (per record, where present): RFC 3161 timestamp tokens (`.tsr`) and OpenTimestamps proofs (`.ots`) are served next to the verify page; verification recipes are printed in the corresponding block on that page. Tools: `tools/tsa_anchor.py`, `tools/ots_anchor.py`.
