# Legal Document Snapshot Integration

This guide defines the 2.0 groundwork for legal-document consent flows such as terms and conditions, privacy policies, and DPAs.

## Goal

The client should be able to record acceptance for the exact document release the user saw without needing to know c15t's internal `policyId`.

That means the preferred client contract is:

1. A terms server renders or resolves the active legal document release.
2. The terms server issues a signed `documentSnapshotToken` for that release.
3. The client sends that token back when the user accepts or rejects the document.
4. c15t verifies the token and stores append-only consent evidence against the matching legal-document release.

## System Responsibilities

### Terms Server

The terms server is the source of truth for the document release that was shown to the user.

It is responsible for:

* resolving the current legal document release
* knowing the release metadata:
  * `type`
  * `hash`
  * `version`
  * `effectiveDate`
* minting a signed `documentSnapshotToken`
* returning the rendered document and token to the client

The terms server should own signing. c15t should not expose a production-safe browser helper that can mint these tokens because doing that would require shipping the signing key to the client.

### Client SDK / UI

The client should:

* render the document content from the terms server
* hold the `documentSnapshotToken` returned for that rendered release
* call c15t accept or reject primitives with that token when the user acts

The client may know `policyHash`, but it should not need to know `policyId`.

### c15t Backend

The c15t backend is responsible for:

* verifying the signed `documentSnapshotToken`
* extracting authoritative release metadata from the token
* resolving the matching legal-document policy row
* storing append-only consent evidence for the subject and document release

## Preferred Request Contract

For legal-document consent writes, the preferred lookup order is:

1. `documentSnapshotToken`
2. `policyHash`
3. `policyId` as a compatibility fallback only

`documentSnapshotToken` is the auditable path because it proves which release the user saw without forcing the client to understand c15t internals.

`policyHash` remains useful as a lightweight fallback for integrations that can identify the rendered document release but do not yet have a signing service.

`policyId` should not be the long-term client contract.

## Snapshot Token Claims

The signed token should carry enough metadata for c15t to verify and resolve the document release:

* `iss`: token issuer
* `aud`: intended c15t audience
* `sub`: release hash
* `tenantId`: tenant that owns the release, when applicable
* `type`: legal document type
* `version`: release version string
* `hash`: stable release hash
* `effectiveDate`: ISO timestamp for the effective date
* `iat`: issued-at timestamp
* `exp`: expiration timestamp

The current demo helper uses that shape so the wire contract is established now, even though real issuance should move to a dedicated server flow.

## Auditability and Compliance

For a fully auditable flow:

* the rendered release must be versioned
* the release must have stable metadata, especially `hash`
* acceptance must be append-only
* the evidence should tie the subject, action, time, and exact release together
* signed snapshot tokens should be issued by a trusted server, not the browser

This gives c15t a defensible record of what document release was accepted and when.

## What Ships in 2.0

This PR is groundwork, not the full terms-platform rollout.

Included now:

* token-first legal-document consent inputs in c15t
* `policyHash` fallback support
* an example terms demo that identifies the user first and then records acceptance
* a demo-only unsafe browser signer in `examples/demo` for local testing when no real terms server exists yet

Deferred until the next phase:

* a production terms server that owns rendering and token issuance
* automatic release resolution from a real document service
* signed snapshot delivery from server to client as part of document rendering

## Demo-Only Unsafe Signer

`examples/demo/lib/unsafe-demo-legal-document-snapshot.ts` exists only to let the example app exercise the contract before the real terms server lands.

It is intentionally unsafe for production use because it requires exposing a signing key to the browser bundle.

Use it only for local development or temporary internal demos.

## If You Already Have a Privacy Policy Without a Hash

That is not a blocker for 2.0 groundwork, but it is not the end state either.

Short term:

* you can continue using existing legal-document records
* `policyId` compatibility can still exist server-side
* `policyHash` fallback can be added once release hashing exists

Long term:

* every rendered legal-document release should have a stable hash
* the terms server should issue snapshot tokens using that hash

Without a stable release hash, the audit trail is weaker because the acceptance cannot be tied as precisely to the rendered document version.
