# Persona Policy, Provenance & Rights

V3 ("Lilith") is an embodied, real-money, AI-generative metaverse where the same
body can teach a yoga class, headline a stadium concert, or wander a commons —
and where music, motion, costumes, and scenes are _generated_, not shipped. That
combination makes two questions cert-blocking rather than nice-to-have: **who is
allowed to act through this body, and in what tone** (persona policy at the
avatar), and **who owns, authored, and can revoke the thing this body just
made** (provenance and rights). V3 answers both by composing V1's safety, audit,
and provenance machinery through thin, server-authoritative V3 surfaces — the
same "don't reinvent trust" stance the platform takes everywhere. The avatar
runs a client-side _preview_; every binding decision is made on a server. Every
generated artifact is born with a provenance bundle and (on release) a signed
content credential, and a rights withdrawal cascades on a bounded clock. This
page is the architecture-side companion for the "Trust, Rights, Commerce, and
Operations" set; the section hub is
[../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md).

## What ships, honestly

The **policy engine and the provenance/rights data plane are real TypeScript**,
each backed by automation tests. `libs/v3/lilith-body-policy` (≈1,980 lines,
`src/index.ts`) is a fully-implemented, server-authoritative adapter over V1's
`@oshun/persona-policy-lilith` and `@oshun/avatar-pipeline`: rolling
voice-transcript tone scoring, a crisis-language classifier with a measured
recall/false-positive gate, costume-rule enforcement, avatar-swap impersonation
blocking, and a six-persona adversarial prompt suite are all computed, not
stubbed. On the provenance side, `libs/shared/content-security` implements C2PA
content-credential _plans_, Google SynthID watermark _plans_, forensic invisible
watermarks, a provenance-chain DAG with cycle detection and an integrity digest,
and a trust-scored authenticity verifier; `libs/v3/isis-music`'s
`track-provenance-bundle.ts` writes the V3 Saraswati track bundle; and
`libs/v3/saraswati-stage`'s `track-c2pa-manifests.ts` signs released tracks with
a **genuine Ed25519 signature** (Node `crypto`). Rights adjudication and the
24-hour enforcement bound are real code in `themis-rights-adjudication.ts`, and
consent ledgers (TTS-voice, class/concert recording) are real in `tara-studio`
and `lilith-identity-bridge`.

Three honest qualifications. **First**, `@oshun/content-security` is a
plan/verify layer: it emits the embedding _command_ and the verification
_policy_, defines per-modality detection thresholds, and verifies
externally-supplied signature/detection evidence — the actual watermark DSP and
the C2PA cryptographic signing run in external tooling, and its `stableHash` is
an FNV-1a content-address for stable IDs, **not** a cryptographic digest (the V3
track signer, by contrast, is real Ed25519). **Second**, "Lilith-Rights" is an
_operator-scope and role name_ (e.g. the operator id
`user:lilith-rights:tara-tts-consent`), not a single package — the machinery is
the composition of `content-security`, `isis-music`, `saraswati-stage`,
`tara-studio`, and the V1 `@oshun/audit-platform` described below. **Third**,
the full multi-surface takedown fan-out (archived performances flagged
historical, in-world replays paused, off-platform reshare notices) is a
documented cascade _contract_ driven over the V1 event bus; what is _coded and
gated_ is the Themis adjudication, the catalog-license pause, the
royalty-waterfall pause, and the 24-hour enforcement deadline. The sections
below say where each claim is backed.

## Persona policy at the body

The defining property is **server authority**. A UE client may run a
costume-rule preview before a wardrobe change commits, but
`@oshun/lilith-body-policy` makes every binding decision on the world server or
the relevant tenant service. The package's descriptor
(`v3LilithBodyPolicyDescriptor`) declares its upstreams exactly —
`['@oshun/persona-policy-lilith', '@oshun/avatar-pipeline']` — and six
capabilities, each with an operational metric the tests assert
(`v3LilithBodyPolicyReadinessScore` returns `matched/6`, so a single live
capability scores `0.167`). The five invocation points map to five evaluators:

| Trigger                        | Evaluator                                                                       | Action on violation                                                                                               |
| ------------------------------ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Voice transcript (rolling 5 s) | `evaluateV3VoiceTranscriptTonePolicy`                                           | First miss prompts the speaker; the second routes `voice-quality-violation` to the V1 `voice-quality-qa-queue`.   |
| Crisis language (rolling 5 s)  | `evaluateV3VoiceTranscriptCrisisClassifier` → `evaluateV3EmbodiedCrisisRouting` | In-world soft prompt + V1 `crisis-response-queue` handoff + on-call operator page.                                |
| Costume change                 | `evaluateV3CostumeRulePolicy`                                                   | Costume blocked; `v3.persona_policy.costume.checked` audit event.                                                 |
| Avatar swap                    | `evaluateV3AvatarSwapImpersonationPolicy`                                       | Protected-persona swap outside a sanctioned cosplay zone routes to `persona-registration-policy-mismatch` review. |
| AI-persona interaction         | `evaluateV3AIPersonaEnforcement`                                                | Out-of-scope asks graceful-no-op; medical/legal/financial/voice-copy/political hand off to a Lilith operator.     |

### The rolling window — context that decays

Voice policy is windowed, not per-utterance, which matters for both tone and
crisis. `buildV3VoiceTranscriptSlidingWindow` assembles a 5,000 ms window
(`V3_VOICE_TRANSCRIPT_WINDOW_MS`), keeping only segments that match the session
**and** speaker and overlap `[now − 5 s, now)`; another speaker's chatter and an
utterance that aged out are excluded by construction (a property the tests
assert: an "outside the active window" line never reaches the verdict). Tone
scoring delegates to V1's `evaluateLilithContemplativeToneQuality`; a failure
short of the repeat threshold (`V3_TONE_OPERATOR_ROUTE_REPEAT_THRESHOLD = 2`)
yields `prompt-speaker`, and the second failure escalates via
`routeLilithModerationEvent` to the operator queue with the failing tone axes in
the payload.

### Crisis routing — measured, then embodied

The same window feeds a crisis classifier built on V1's `detectLilithCrises`.
When a signal fires, `buildLilithCrisisResponsePlan` produces the resource set
and `evaluateV3EmbodiedCrisisRouting` assembles three things: a
**non-dismissible in-world soft prompt** (`safety-overlay`,
`blocksPracticeResume: true`, an assertive ARIA live region and a soft haptic
pulse), a handoff to the `v1-lilith-crisis-routing` pipeline, and an operator
notification that pages on-call and auto-suspends the session. This is not
best-effort: the classifier is validated against a labelled set of 22 positive
cases (one per `LilithCrisisType` — suicide-ideation, self-harm, acute-panic,
dissociation, trauma-resurfacing, substance, interpersonal/other-directed
violence, abuse, eating-disorder, child-safety, psychosis-adjacent, acute-grief)
and ~60 benign negatives, and `evaluateV3CrisisClassifierValidationSet` only
reports `releaseGateGreen` when **recall ≥ 0.95 and false-positive-rate ≤ 0.02**
(`V3_CRISIS_CLASSIFIER_MIN_RECALL` / `..._MAX_FALSE_POSITIVE_RATE`). A separate
13-case `evaluateV3EmbodiedCrisisRoutingDrill` requires **recall = 1.0** — every
drill prompt must produce the soft prompt, the handoff, and the page.

### AI-persona enforcement — stay-in-persona is a state machine

Each of the six GA Saraswati AI artists gets a policy profile from
`createV3SaraswatiGAPersonaPolicyProfiles()` (one per genre cell: electronic,
indie-folk, hip-hop, classical-crossover, ambient, devotional).
`evaluateV3AIPersonaEnforcement` resolves one of three actions:
`stay-in-persona` for in-scope asks; `graceful-noop` for role-swap and
system-prompt-disclosure attempts (matched against literal phrase sets like
`'ignore previous instructions'`, `'reveal your system prompt'`,
`'act as my private assistant'`); and `operator-handoff` for the unsafe classes
— medical/legal/financial advice (via V1 `classifyLilithUnsafeClaimClasses`),
living-public-figure voice-copy (via `detectLilithVoiceAbuseSignals` against a
restricted-identity list), and political persuasion. The release gate is
`evaluateV3SaraswatiAIPersonaAdversarialPromptSuite`: **6 personas × 6
adversarial prompts = 36 cases**, and `passed` is true only when
`policyBreachCount === 0` — a single persona that breaks character, leaks a
prompt, or gives medical advice fails the suite. Critically, `policyBreached`
treats a `stay-in-persona` outcome on a prompt that _should_ have been refused
as a breach, so the gate cannot be satisfied by a permissive classifier.

## Provenance — every artifact is born documented

V3 attaches provenance at two layers: a **domain bundle** that travels with the
artifact in-platform, and a **C2PA content credential** that makes an export
verifiable off-platform.

### The V3 track provenance bundle

`writeSaraswatiTrackProvenanceBundle` (`isis-music/track-provenance-bundle.ts`)
emits a `saraswati.music.track-provenance-bundle.v1` record carrying the seven
required sections the inspector validates: the **model card** (provider, model,
version, training disclosure, license — e.g. "no living-artist voice clone"),
the **prompt seed** (deterministic seed + fingerprint, so a generation is
reproducible), the **reference set** (each a `sha256`-hashed source: a Sophia
citation, a rights clearance, a persona-policy tag), the **generating user**,
the **persona** (with its `voiceConsentLedgerId`), the **lineage-credit
distribution** (which `inspectSaraswatiTrackProvenanceBundle` rejects unless it
sums to exactly 100%), and the **artifact refs** (master, review preview,
inspector URI). The store-level `evaluateSaraswatiTrackProvenanceBundleWrite`
enforces `everyGeneratedTrackHasBundle` — no track ships without one. The same
bundle pattern is what `avatar-pipeline` uses for avatars
(`createImportedAvatarProvenanceBundle()`, both variants of a premium persona
sharing one bundle id), described in
[Avatar, Animation & Spatial Audio](./avatar-animation-and-audio.md).

### C2PA on export — a real signature for tracks, a plan for the rest

Two C2PA paths exist, and the honesty line runs between them.
`saraswati-stage/track-c2pa-manifests.ts` is the **real-signature path**: a
released track is signed with an Ed25519 key via Node `crypto`
(`createDefaultSaraswatiTrackC2paSigner()` uses a deterministic dev seed; the
production key is KMS-bound, with the Adobe-CAI trust root tracked as `[~]`),
and `verifySaraswatiReleasedTrackC2paManifest` performs genuine tamper detection
against the required assertions (`c2pa.actions.v2`,
`org.oshun.v3.track-release`, `...generated-artifact-provenance`,
`...rights-waterfall`, `...pro-registration`, `...adobe-cai-verification`). The
shared `content-security/provenance.ts` is the **plan/verify path**:
`createC2PAContentCredentialPlan` builds the assertion store, signer binding
(`ecdsa-p256-sha256`), embedding command, and `verificationPolicy`
(`requireSignature`, `requireManifestStore`); `createSynthIDWatermarkPlan` emits
a Google-SynthID plan per modality with calibrated detection thresholds (text
0.78, image 0.82, audio 0.80, video 0.84); and `verifyContentAuthenticity`
computes a **trust score** (C2PA 0.40 + chain 0.25 + AI declaration 0.20 +
SynthID 0.15) and a verdict (`verified-human` … `verified-ai-generated` /
`mixed-provenance` / `insufficient-evidence` / `tampered`), surfacing typed
findings for each missing or mismatched signal. The `createProvenanceChain` DAG
proves lineage integrity: it topologically orders nodes, rejects cycles, and
records an integrity digest that `validateProvenanceChainIntegrity` recomputes
to catch tampering. This layer plans and verifies; the cryptographic embedding
runs downstream.

### Forensic watermarking — invisible, per-recipient, robustness-tested

`content-security/watermarking.ts` plans the invisible marks that make leaks
traceable: per-session **video** (luma-DCT midband, frame-cadenced tiles, robust
to transcode/compression/screen-capture), transcode-robust **audio**
(psychoacoustic spread-spectrum, 1.2–4.2 kHz band, time-scale invariant),
resilient **image** (DCT-wavelet hybrid), and per-recipient **document**
watermarks (recipient code + canary phrases + layout perturbation).
`identifyWatermarkSource` matches an extracted observation back to a registered
`WatermarkRecord` above a confidence floor, and
`createWatermarkRobustnessTestSuite`

- `evaluateWatermarkRobustness` define and score the transformation gauntlet
  each mark must survive. The provenance bundle records the watermark hash; this
  is how an off-platform reshare ties back to a session and a recipient.

```mermaid
flowchart TB
  GEN["Generation (Isis / Saraswati / Tara)"] --> BUNDLE["Provenance bundle<br/>writeSaraswatiTrackProvenanceBundle<br/><sub>model card · seed · refs · lineage 100%</sub>"]
  GEN --> WM["Forensic watermark<br/>content-security/watermarking"]
  BUNDLE --> REL{Release}
  WM --> REL
  REL -->|export| C2PA["C2PA manifest (Ed25519)<br/>track-c2pa-manifests"]
  REL --> AUDIT["@oshun/audit-platform<br/>hash-chain ledger"]
  TD["Provenance withdrawal /<br/>rights claim"] --> THEMIS["Themis adjudication<br/>themis-rights-adjudication"]
  THEMIS -->|≤ 24 h| ENF["Enforce: catalog-license-paused<br/>+ royalty-waterfall-paused"]
  ENF --> BUS["V1 event bus fan-out<br/>replays paused · editions historical · reshare notices"]
  ENF --> AUDIT
```

## Rights and takedown

### Themis adjudication on a 24-hour clock

Ownership and unlicensed-use disputes route through
`saraswati-stage/themis-rights-adjudication.ts`, a three-step state machine:
`fileSaraswatiThemisRightsDispute` → `issueSaraswatiThemisRightsDecision` →
`enforceSaraswatiThemisRightsDecision`. Dispute kinds include
`remix-priority-claim`, `ownership-challenge`, `sample-use-claim`, and
`independent-rights-holder-takedown`; evidence kinds include
`released-track-c2pa-manifest` and `consent-ledger` (so the C2PA manifest and
the consent ledger are first-class adjudication evidence). A decision resolves
to `credit-claimant`, `uphold-original-rights`, or `pause-release`, and
enforcement emits the corresponding actions: `rights-record-updated`,
`royalty-waterfall-updated`, `catalog-license-paused`, `claim-denial-audited`.
The **24-hour SLA is a coded invariant**, not a doc promise:
`SARASWATI_THEMIS_RIGHTS_MAX_ENFORCEMENT_MS = 86_400_000`, and
`enforceSaraswatiThemisRightsDecision` _throws_ if enforcement lands more than
that after the decision (or before it).
`evaluateSaraswatiIndependentRightsHolderTakedownFlow` ties the knot for the
takedown case: it passes only when the outcome is `pause-release`, the
`catalog-license-paused` action fires with a real `catalogHoldRef`, and
`enforcementLatencyMs ≤ 24 h`. Upstream, `fingerprint-pre-release-check.ts`
(Audible Magic / Pex) catches collisions _before_ release, returning
`editorial-review-required` when a master matches a major-label or independent
reference — so most rights conflicts are stopped at the gate, not litigated
after.

### Consent and rights records

Consent is stored as withdrawable ledgers, not one-time checkboxes.
`tara-studio/tts-voice-consent.ts` models the instructor voice-signature grant
(`tara-tts-voice-signature-consent:v1`, purposes `aja-cues` / `localized-dubs`,
status `active`/`withdrawn`, a **30-day** withdrawal window, every change
written as a rights-log entry under the `user:lilith-rights:...` operator
scope), with sibling contract, scope-lock, and royalty-distribution modules.
`lilith-identity-bridge/recording-consent.ts` governs class and concert capture:
a participant chooses `full` / `observer` / `decline-and-leave`, which resolves
to a concrete `avatarRecordingTreatment` (`visible` / `generic-silhouette` /
`not-recorded`), `voiceRecordingTreatment` (`master-mix` /
`excluded-from-master-mix`), and `chatRecordingTreatment`, with minor-attendee
guardian confirmation required and a mid-session opt-out path. Every consent
decision and rights enforcement publishes a canonical event through V1's
`@oshun/audit-platform` — a hash-chained, tamper-evident ledger
(`hash-chain.ts`) with investigation export, compliance attestation,
content-license review, and source-asset lineage. V3 produces the evidence;
Oshun retains and exports the investigation-ready trail, and a DSAR over a V3
user joins these records to the UE/Pixel-Streaming session data the identity
bridge holds.

## Edge cases and failure modes

- **Context decays, deterministically.** The 5 s window excludes other speakers
  and aged-out utterances structurally, so a crisis line that scrolled past the
  window can't re-fire and a neighbour's words can't be scored against you.
- **The crisis gate is two-sided.** A permissive classifier can't pass — recall
  ≥ 0.95 catches misses and FPR ≤ 0.02 catches over-triggering; the drill
  demands recall = 1.0 for the full embodied response (prompt + handoff + page).
- **Lineage must total 100%.** A provenance bundle whose credit shares don't sum
  to exactly 100 is marked incomplete, and the store refuses to pass — royalty
  routing can't be ambiguous.
- **Takedown is bounded, not eventual.** Enforcement outside the 24-hour window
  throws; the takedown flow asserts the catalog hold and the latency bound
  together, so "paused, eventually" is not a valid state.
- **Real signature vs. content-address.** The track C2PA path detects tampering
  with a genuine Ed25519 signature; the shared `stableHash` is an FNV-1a
  identifier, and authenticity verification consumes externally-supplied
  signature evidence rather than minting it — read it as a verifier, not a
  signer.
- **"Lilith-Rights" is a role, not a service.** Looking for a `lilith-rights`
  package will mislead; the capability is the composition named above, gated by
  the operator scope that appears in the consent ledgers.

## How it connects

Persona policy reaches up into the embodiment stack and down into identity and
commerce. The costume and avatar-swap checks operate on the realms, costume
slots, and `lilithSafetyCostumeRuleCheck` defined in
[Avatar, Animation & Spatial Audio](./avatar-animation-and-audio.md), and the
account ↔ avatar binding every decision is made against is owned by the bridge
described in
[V1 Integration & the Identity Bridge](./v1-integration-and-identity-bridge.md).
The rights side is the trust spine of the economy: the lineage-credit
distribution in the provenance bundle is exactly the royalty waterfall that
[Commerce & Royalties](./commerce-and-royalties.md) settles on-chain via Aje,
and a Themis `pause-release` is what stops a payout mid-flight. The `@oshun/*`
packages this page composes — `persona-policy-lilith`, `avatar-pipeline`,
`content-security`, `audit-platform` — sit in the platform domain map at
[../../platform/oshun-domain-libraries.html](../../platform/oshun-domain-libraries.html).

## Related

- [Avatar, Animation & Spatial Audio](./avatar-animation-and-audio.md) — the
  realms, costume slots, and avatar provenance bundles persona policy enforces
  on
- [V1 Integration & the Identity Bridge](./v1-integration-and-identity-bridge.md)
  — the account ↔ avatar binding every server-authoritative decision references
- [Commerce & Royalties](./commerce-and-royalties.md) — the royalty waterfall
  the provenance bundle encodes and a takedown pauses
- [Oshun Domain Libraries](../../platform/oshun-domain-libraries.html) — where
  `persona-policy-lilith`, `content-security`, and `audit-platform` sit
- The section hub: [../V3_ARCHITECTURE.md](../V3_ARCHITECTURE.md)
