# H/M Content Credentials Browser SDK

Version: `0.3.0`  
Status: `developer-preview`  
Runtime: modern browsers only  
Processing: browser-local  
Authentication: none  
Price for this preview: free

The H/M SDK exposes the same bounded Content Credentials evidence workflow used by the public workspace:

- Inspect one file.
- Read a declared-order provenance timeline with timestamp trust separated from manifest-declared action times.
- Read sanitized signer, timestamp-authority and credential-path diagnostics.
- Compare two evidence states.
- Create a structured Manifest Diff.
- Review up to 2,000 files sequentially.
- Create or verify a checksum-bound evidence envelope.
- Export a BagIt 1.0 Evidence Package.
- Create and verify a hash-chained enterprise audit report or ZIP bundle.
- Reproduce an exported report against a local source file.

The source bytes stay in the calling browser. The SDK sends no metrics, uses no browser storage and does not load a remote trust list.

## Important identity boundary

This is an H/M browser wrapper around the pinned `@contentauth/c2pa-web 0.13.1` verifier. It is not an official C2PA SDK, conformance certificate or legal compliance service.

## Import a pinned release

Use the versioned entrypoint in production:

```js
import {
  createContentCredentialsClient,
} from "https://hogarmas.net/content-credentials/sdk/v0.3.0/index.js";

const client = createContentCredentialsClient();
```

The unversioned alias is available for evaluation:

```js
import {
  createContentCredentialsClient,
} from "https://hogarmas.net/content-credentials/sdk/index.js";
```

Do not pin production behavior to the unversioned alias. The SDK is not published to npm yet.

The immutable `0.2.0` release remains available at `https://hogarmas.net/content-credentials/sdk/v0.2.0/index.js` for existing integrations.

## Inspect a file

```html
<input id="asset" type="file">
<pre id="result"></pre>

<script type="module">
  import {
    createContentCredentialsClient,
  } from "https://hogarmas.net/content-credentials/sdk/v0.3.0/index.js";

  const client = createContentCredentialsClient({
    onProgress(progress) {
      console.log(progress.stage, progress.percent);
    },
  });

  document.querySelector("#asset").addEventListener("change", async (event) => {
    const file = event.target.files?.[0];
    if (!file) return;

    const inspection = await client.inspect(file);
    document.querySelector("#result").textContent = JSON.stringify({
      manifest: inspection.report.provenance.state,
      integrity: inspection.report.integrity.state,
      signerTrust: inspection.report.signer.state,
      aiOrigin: inspection.report.aiOrigin.state,
      timelineEvents: inspection.timeline.eventCount,
      timestampTrust: inspection.trustDiagnostics.timestamp.state,
      sha256: inspection.report.asset.sha256,
    }, null, 2);
  });

  window.addEventListener("pagehide", () => client.dispose(), { once: true });
</script>
```

## Read timeline and trust diagnostics

```js
const inspection = await client.inspect(file);

for (const event of inspection.timeline.events) {
  console.log(event.order, event.kind, event.time?.trust);
}

console.log(inspection.trustDiagnostics.signer);
console.log(inspection.trustDiagnostics.timestamp);
console.log(inspection.trustDiagnostics.credentialPath.nodes);
```

Manifest actions retain their declared presentation order. A C2PA action `when` value is labeled `manifest-declared-untrusted`; it is not treated as proven chronology. A validated TSA timestamp is represented separately.

The credential path is sanitized. It can expose signer/TSA leaf subject, issuer and validity summaries plus observed role names, but it excludes certificate serial numbers, raw certificate bytes, intermediate certificate objects and root certificate objects.

## Compare two files

```js
const result = await client.compare(beforeFile, afterFile, {
  labels: {
    before: "before.jpg",
    after: "after.jpg",
  },
});

console.log(result.comparison);
console.log(result.manifestDiff);
```

The comparison reports bounded evidence differences. It does not identify who caused a change or whether visible content is factually true.

## Review a batch

```js
const controller = new AbortController();

const result = await client.batch(fileInput.files, {
  signal: controller.signal,
  onProgress(progress) {
    console.log(`${progress.fileNumber}/${progress.fileCount}`, progress.fileName);
  },
});

downloadText("content-credentials-batch.csv", result.csv(), "text/csv");

function downloadText(name, text, type) {
  const link = document.createElement("a");
  link.href = URL.createObjectURL(new Blob([text], { type }));
  link.download = name;
  link.click();
  URL.revokeObjectURL(link.href);
}
```

Batch guarantees:

- Maximum 2,000 selected files.
- Maximum 50 MB per file.
- One file is processed at a time.
- Full reports are compacted to one bounded row immediately.
- Calling `controller.abort()` stops after the current local file or local packaging step.
- File names and SHA-256 values are present in the batch output.

## Create an evidence envelope

```js
const { envelope } = await client.createEnvelope(file);
const verification = await client.verifyEnvelope(envelope);

console.log(verification.state);
```

The envelope checksum detects changed report bytes. It is not a digital signature and does not authenticate an exporter.

## Create an Evidence Package

```js
const result = await client.createPackage(file, {
  includeSource: false,
});

const link = document.createElement("a");
link.href = URL.createObjectURL(result.package.blob);
link.download = result.package.fileName;
link.click();
URL.revokeObjectURL(link.href);
```

The package uses BagIt 1.0 directory conventions, SHA-256 payload and tag manifests, W3C PROV-O JSON-LD, a provenance timeline and trust diagnostics. The H/M package profile is not an official C2PA Evidence Package standard.

Set `includeSource: true` only when the recipient must receive the original asset. That option places the complete source bytes in the ZIP.

## Create an enterprise audit record

```js
const { audit } = await client.createAudit(file, {
  caseId: "CASE-2042",
  organization: "Example newsroom",
  reviewer: "Local reviewer",
  purpose: "Publication provenance review",
  includeFileName: false,
});

const verification = await client.verifyAudit(audit);
console.log(verification.state);

const result = await client.createAuditBundle(file, {
  caseId: "CASE-2042",
  locale: "en",
});
```

The audit ZIP contains canonical JSON, a separate verification result, provenance timeline, trust diagnostics, print-ready HTML, Markdown and a SHA-256 file manifest. Its event ledger is hash chained. It does not include the source asset, digitally sign the report or authenticate the declared operator.

## Reproduce an exported report

```js
const envelope = JSON.parse(await envelopeFile.text());
const result = await client.reproduce(envelope, sourceFile, {
  labels: {
    exported: "exported-report",
    current: "current-reanalysis",
  },
});

console.log(result.reproduction.state);
```

Reproduction checks three separate facts:

1. Whether the envelope checksum still matches its exported report.
2. Whether the current source SHA-256 matches the exported report.
3. Whether bounded evidence observations match after local reanalysis.

## Error handling

```js
import {
  ContentCredentialsSdkError,
} from "https://hogarmas.net/content-credentials/sdk/v0.3.0/index.js";

try {
  await client.inspect(file);
} catch (error) {
  if (error instanceof ContentCredentialsSdkError) {
    console.error(error.code, error.message);
  }
}
```

Stable error codes:

- `aborted`
- `disposed`
- `empty`
- `invalid-file`
- `invalid-options`
- `read-error`
- `too-large`
- `unsupported`

## Content Security Policy

A cross-origin integration must allow the versioned ESM, verifier fetch, WebAssembly compilation and the verifier's Blob worker. A minimal starting point is:

```http
Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://hogarmas.net 'wasm-unsafe-eval';
  connect-src 'self' https://hogarmas.net;
  worker-src 'self' blob:;
```

Merge these directives into the host application's existing policy. Do not replace a stricter production policy without review.

## Browser and runtime requirements

- ESM modules
- `Blob` and `File`
- WebAssembly
- Web Workers and `blob:` worker URLs
- `crypto.subtle`
- `AbortSignal` for optional stop control

Node.js, Deno, service-worker-only execution and server-side verification are not supported by `0.3.0`.

The first inspection downloads the pinned verifier and WebAssembly payload. Later calls in the same client reuse the local verifier and process files sequentially.

## Contracts

- [SDK manifest](https://hogarmas.net/content-credentials/sdk/sdk-manifest.json)
- [TypeScript declarations](https://hogarmas.net/content-credentials/sdk/v0.3.0/index.d.ts)
- [Report Schema](https://hogarmas.net/content-credentials/report-schema.json)
- [Comparison Schema](https://hogarmas.net/content-credentials/comparison-schema.json)
- [Manifest Diff Schema](https://hogarmas.net/content-credentials/manifest-diff-schema.json)
- [Provenance Timeline Schema](https://hogarmas.net/content-credentials/provenance-timeline-schema.json)
- [Trust Diagnostics Schema](https://hogarmas.net/content-credentials/trust-diagnostics-schema.json)
- [Batch Schema](https://hogarmas.net/content-credentials/batch-schema.json)
- [Evidence Envelope Schema](https://hogarmas.net/content-credentials/evidence-envelope-schema.json)
- [Reproduction Schema](https://hogarmas.net/content-credentials/reproduction-schema.json)
- [Evidence Package profile](https://hogarmas.net/content-credentials/evidence-package-profile.json)
- [Audit Report Envelope Schema](https://hogarmas.net/content-credentials/audit-report-envelope-schema.json)
- [Pinned verifier files and hashes](https://hogarmas.net/content-credentials/vendor/v0.13.1/vendor.json)

## Evidence boundaries

The SDK does not:

- upload a source file;
- retain source bytes in browser storage;
- call an AI model;
- generate a truth or fake score;
- prove that AI was absent;
- load a remote signer trust list;
- expose a complete certificate chain, intermediate/root certificate objects or raw certificate bytes;
- expose raw certificate serial numbers;
- turn manifest-declared action times into trusted chronology;
- authenticate an H/M evidence-envelope exporter;
- authenticate an audit-report operator, organization or exporter;
- certify legal or regulatory compliance.

A valid Content Credential can support cryptographic integrity observations. It cannot by itself prove that the visible content or a signed statement is factually true.

## Enterprise integration

The public developer preview is free and keyless. Commercial embedding, private pinned builds, integration support, audit-report templates and service-level agreements are available only by written agreement.

Contact: [jpyesihui@gmail.com](mailto:jpyesihui@gmail.com)
