Skip to content
owenisasPublic

About

Origraph — AI content provenance platform. Invisible text watermarking SDK, provenance registry, browser extension. Champion at Hack The East 2026.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

Origraph

Invisible watermarks for AI-generated text. Verifiable provenance, on-chain.

Hack The East 2026 — Champion   Python JavaScript Solana License


Origraph is an AI content provenance platform. It lets model providers and platforms invisibly watermark AI-generated text so that — anywhere that text later appears — anyone can verify its origin, the model that produced it, and whether it has been tampered with.

The system is built around three components that work alone or together:

Component Role Stack
Watermark SDK Embeds invisible Unicode tags into LLM output (OpenAI, Anthropic, Gemini) Python · zero-dep core
Provenance Registry Issues, stores, and verifies provenance records; anchors batches to Solana Python · FastAPI · Solana
Browser Extension Detects and highlights watermarks on any web page in real time JavaScript · Manifest V3

Why it matters. As AI-generated text becomes indistinguishable from human writing, the provenance question — whose model wrote this, and when? — becomes unanswerable after the fact unless origin metadata is embedded at generation time. Origraph attaches that metadata invisibly, so it survives copy-paste, screenshots, and reformatting, and can be re-anchored to a public ledger for tamper-evidence.


Table of contents


How it works

Origraph encodes a compact origin payload into the text itself using Unicode zero-width characters — codepoints that render as nothing in every browser, terminal, and editor, but are preserved through copy-paste and most text pipelines.

The invisible tag

A payload is a 64-bit integer packed from structured metadata plus a CRC8 checksum:

┌──────────── 64-bit payload ────────────┐
│ schema (4b) │ issuer (12b) │ model (16b) │
│ model rev (16b) │ key id (8b) │ CRC8 (8b) │
└────────────────────────────────────────┘
   56 bits of provenance metadata  +  8 bits integrity

Each bit of the payload is mapped to one of two zero-width Unicode characters. The tag is wrapped with dedicated start/end sentinels (also zero-width) so a reader can locate and frame it even inside arbitrary text:

START  ZWJ ZWNJ ZWNJ ZWJ … (64 zero-width bits) …  END
Field Width Meaning
schema_version 4 bits Payload protocol version
issuer_id 12 bits Issuing organisation / deployment (0–4095)
model_id 16 bits Which model generated the text
model_version_id 16 bits Model revision
key_id 8 bits Key rotation identifier
crc8 8 bits Integrity check over the 56 data bits

Insertion that survives the real world

Tags are planted at the last safe boundary (whitespace or punctuation) inside each text chunk, and re-injected at a configurable token interval (default: every ~160 whitespace-delimited tokens). Redundant copies mean the watermark survives truncation, excerpting, and partial edits — a single surviving tag is enough to recover the full payload. Because insertion lands on word boundaries, the tag never splits a grapheme and is invisible to both humans and most downstream tokenizers.

Detection & stripping

Watermarker.detect() regex-extracts every <start>…<end> frame, re-bitpacks the zero-width chars, validates each tag's CRC8, and returns the decoded metadata plus a watermarked / valid / invalid summary. Watermarker.strip() removes every tag, returning the exact original text — useful for re-watermarking pipelines or for downstream consumers that want clean input.


Architecture

 ┌──────────────────────┐        ┌──────────────────────┐
 │  LLM provider API     │        │  Browser extension   │
 │  (OpenAI / Anthropic  │        │  (content script +   │
 │   / Gemini)           │        │   popup, MV3)         │
 └──────────┬───────────┘        └──────────┬───────────┘
            │ wraps response                 │ scans DOM text
            ▼                                ▼
 ┌──────────────────────┐        ┌──────────────────────┐
 │  Watermarker SDK     │        │  Detect + highlight   │
 │  - pack 64-bit tag   │        │  zero-width tags,     │
 │  - inject at safe     │        │  surface issuer/      │
 │    boundaries         │        │  model to the reader  │
 └──────────┬───────────┘        └──────────────────────┘
            │ issuer records batch
            ▼
 ┌──────────────────────────────────────────────────────┐
 │  Provenance Registry (FastAPI)                        │
 │  - issues & stores provenance records                 │
 │  - anchors a Merkle batch root to Solana              │
 │  - exposes verify API consumed by the extension       │
 └──────────────────────────────────────────────────────┘

The flow, end to end

  1. A model provider wraps its SDK with Watermarker — every generated response leaves the model already tagged, invisibly.
  2. Each issuance is registered with the provenance registry, which groups records into a Merkle batch and writes the batch root to Solana for timestamped, tamper-evident anchoring.
  3. When the text surfaces on any web page, the browser extension scans the DOM in real time, extracts detected tags, and queries the registry — surfacing issuer, model, generation time, and on-chain anchor to the reader.
  4. Anyone can later re-verify: the on-chain root pins the batch, and the CRC8 inside each surviving tag confirms the payload itself was not corrupted in transit.

Quick start

./scripts/bootstrap_demo.sh
DEMO_MODE=fixture ./scripts/run_demo.sh

Then open:

  • http://127.0.0.1:5050/ — landing page
  • http://127.0.0.1:5050/registry/demo/live — guided demo flow

DEMO_MODE=fixture runs entirely against deterministic fixtures — no external model or ledger calls. To exercise live providers:

DEMO_MODE=live ./scripts/run_demo.sh        # MINIMAX_API_KEY required for live chat

To expose the demo beyond localhost:

DEMO_MODE=fixture APP_HOST=0.0.0.0 APP_PORT=5050 ./scripts/run_demo.sh
BASE_URL=http://<machine-ip>:5050 ./scripts/check_demo.sh    # smoke check

Watermark SDK

Zero-dependency core, optional SDK bindings for the three major providers.

pip install -e .                       # core only
pip install -e ".[openai]"             # + OpenAI wrapper
pip install -e ".[anthropic]"          # + Anthropic wrapper
pip install -e ".[google]"             # + Gemini wrapper
pip install -e ".[all]"                # everything
from invisible_text_watermark import Watermarker

wm = Watermarker(issuer_id=1, model_id=42, key_id=1)

tagged = wm.apply("The quick brown fox jumps over the lazy dog.")
result = wm.detect(tagged)

print(result.watermarked)            # True
print(result.payloads)               # [{'schema_version': 1, 'issuer_id': 1, ...}]
print(Watermarker.strip(tagged))     # original text, watermark removed

Provider integration

The wrappers transparently tag every model response without touching your call sites:

from openai import OpenAI
from invisible_text_watermark import Watermarker
from invisible_text_watermark.integrations.openai_wrapper import watermark_openai

client = watermark_openai(OpenAI(), Watermarker(issuer_id=1, model_id=100))
resp = client.chat.completions.create(model="gpt-4o", messages=[{"role": "user", "content": "hello"}])
# resp.choices[0].message.content now carries an invisible watermark

Equivalent wrappers exist for anthropic_wrapper and google_wrapper. All three inherit the same safe-boundary insertion and CRC8 validation logic, so detection is provider-agnostic.

Design notes

  • Zero runtime dependencies in the core — only the standard library, so it can be vendored into any inference path.
  • Schema-versioned payloads (schema_version field) allow future expansion without breaking older readers.
  • Key rotation (key_id) lets issuers rotate watermark keys without invalidating previously issued text.
  • Streaming-safe: TagInjector is stateful and re-arms across deltas, so it works identically against streaming and non-streaming completion endpoints.

Browser extension

A Manifest V3 extension that brings detection to where readers actually encounter the text — the open web.

Capability Mechanism
Auto-scan page text content script injected at document_idle on all URLs
Verify selected text popup + activeTab / scripting permissions
Real-time highlight content.css overlay on detected watermarks
Configurable behaviour chrome.storage-backed user preferences

Load it unpacked from extension/:

  1. Open chrome://extensions
  2. Enable Developer mode
  3. Load unpacked → select the extension/ directory

Provenance registry

The registry is what turns a per-document watermark into queryable, tamper-evident provenance.

  • Issues provenance records keyed by issuer_id + model_id + content hash.
  • Batches records into a Merkle tree and writes the root to Solana, giving every batch a public, timestamped anchor without per-record on-chain cost.
  • Exposes a verify API consumed by the browser extension and any third-party verifier.
  • Demo backend ships under origraph-registry-demo/ with both fixture and live modes — the fixture mode lets you experience the full flow end-to-end without any API keys.

A live demo is served from the same FastAPI app that powers the landing page — see Quick start.


Documentation

Document What it covers
docs/README.md In-repo platform overview & frontend stack
docs/DEMO_RUNBOOK.md Live demo flow + fallback procedures
docs/specs/ORIGRAPH_PROOF_BUNDLE_V1.md Decentralized proof bundle contract
docs/specs/origraph-proof-bundle-v1.schema.json Machine-readable proof schema
docs/strategy/ORIGRAPH_APPCHAIN_STRATEGY.md Longer-term appchain strategy
docs/strategy/PRODUCTION_INTEGRATION.md Production hardening path from the demo baseline
PROJECT_MAP.md Current-to-target repository map
DEMO_RUNBOOK.md Top-level demo runbook mirror

Project layout

.
├── invisible-text-watermark/      # Watermark SDK (Python, zero-dep core)
│   ├── src/invisible_text_watermark/
│   │   ├── zero_width.py           # Encode/decode + safe-boundary injection
│   │   ├── payload.py              # 64-bit packing + CRC8
│   │   ├── watermark.py            # Watermarker API + DetectResult
│   │   └── integrations/            # OpenAI, Anthropic, Gemini wrappers
│   └── tests/
├── extension/                      # Browser extension (MV3, JS)
├── origraph-registry-demo/         # Provenance registry demo (FastAPI + Solana)
├── origraph-landing-vercel/        # Landing page deployment
├── docs/                           # Specs, strategy, runbooks
├── scripts/                        # bootstrap_demo.sh, run_demo.sh, check_demo.sh
├── PROJECT_MAP.md
├── DEMO_RUNBOOK.md
└── LICENSE

Licensing

Origraph uses a split-license model to keep the SDK and extension permissively usable while protecting the reference registry demo against closed-source forks.

Path License
Root (/, docs/, scripts/) Apache-2.0 — LICENSE
invisible-text-watermark/ Apache-2.0 — invisible-text-watermark/LICENSE
extension/ Apache-2.0 — extension/LICENSE
origraph-landing-vercel/ Apache-2.0 — origraph-landing-vercel/LICENSE
origraph-registry-demo/ AGPL-3.0 — origraph-registry-demo/LICENSE

Hack The East 2026

🥇 Champion — Hack The East 2026

Hong Kong's AI hackathon · 2026

This project won top honours out of the field at Hack The East 2026 for its end-to-end take on AI content provenance: invisible watermarking that travels with the text, a verifiable registry anchored on Solana, and a browser extension that makes detection visible to any reader, anywhere.


Origraph is a research/demo project. The watermark is invisible — the provenance is not.

About

Origraph — AI content provenance platform. Invisible text watermarking SDK, provenance registry, browser extension. Champion at Hack The East 2026.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages