The trust layer the internet was always missing. The open, post-quantum, federated standard for verified human identity and AI content provenance. Free in every jurisdiction, in perpetuity.
Trust Identity Protocol (TIP) was invented by Dinesh Mendhe (ORCID 0000-0003-1158-3259) and is published by The AI Lab Intelligence Unobscured, Inc. (theailab.org). The protocol is stewarded by the AI Trust Council, an independent multi-stakeholder body convened on 3 May 2026.
Cite this work: Mendhe, D. (2026). Trust Identity Protocol (TIP): An Open Standard for Verified Human Identity and Content Provenance on the Internet (1.0). The AI Lab Intelligence Unobscured, Inc. https://doi.org/10.5281/zenodo.20722378
Keywords for search: trust identity protocol · TIP protocol · TIP-ID · CTID · content TIP ID · AI trust ID · AI trust council · AI trust registry · global seal of trust · TIPCL-1.0 · CNA-2.2 · canonical normalization algorithm · post-quantum cryptography · ML-DSA-65 · ML-KEM-768 · SLH-DSA · FIPS 203 · FIPS 204 · FIPS 205 · NIST post-quantum · federated DAG · verified human identity · content provenance · deepfake defense · human or AI · #HumanOrAI · EU AI Act · EU AI Act Article 50 · Digital Services Act · GDPR · eIDAS 2.0 · WebAuthn · C2PA alternative · verifiable internet · open standard · Dinesh Mendhe · The AI Lab Intelligence Unobscured · Wikidata Q139715497 · Wikidata Q139715509 · DOI 10.5281/zenodo.20722378
Trust Identity Protocol (TIP) Whitepaper, Version 1.0 is published. The canonical public specification of the protocol (140 pages, eleven Parts, twelve Appendices, licensed CC BY 4.0) is available in PDF, HTML, EPUB, and DOCX at theailab.org/whitepaper and permanently archived on Zenodo (CERN) under DOI 10.5281/zenodo.20722378. The Concept DOI 10.5281/zenodo.20722377 always resolves to the latest printing.
Cite as: Mendhe, D. (2026). Trust Identity Protocol (TIP): An Open Standard for Verified Human Identity and Content Provenance on the Internet (1.0). The AI Lab Intelligence Unobscured, Inc. https://doi.org/10.5281/zenodo.20722378
TIP Protocol (Trust Identity Protocol) is an open, federated, post-quantum cryptographic protocol that provides three things the internet has never had:
- Verified human identity: provably one person, one account, backed by government ID and 3D biometric verification
- Signed content provenance: every piece of content permanently bound to a declared origin (human-written, AI-assisted, AI-generated, or mixed)
- Deterministic public trust scores: a 0-1000 reputation score computed from an immutable public ledger, reproducible by any node
TIP Protocol is to internet trust what HTTPS is to internet encryption. Before HTTPS, any data on the internet could be intercepted and tampered with. The solution was not a product: it was an open protocol that every browser, server, and platform adopted. TIP Protocol takes the same approach for trust in human identity and content origin.
tip://id/US-a3f8c91b2d4e7021 ← Verified human identity (TIP-ID)
tip://c/OH-7f2a91bc3d5e-a3f8 ← Content provenance record (TIP-CONTENT)
892 / 1000 [HIGHLY TRUSTED] ← Public trust score (TIP-TRUST)
AI can now generate indistinguishable text, images, video, and audio at near-zero cost. Within a few years, no human will reliably distinguish AI-generated content from human-created content by inspection alone. Deepfakes have influenced elections. AI-cloned voices have enabled wire fraud. AI-written articles saturate search results.
Existing solutions all fail the same way:
- Centralized verification services: single points of failure
- Content credentials (C2PA): no identity binding, no trust scores
- Decentralized identifiers (DIDs): no content provenance, no scoring
- AI detection: arms race that no one wins
TIP Protocol reframes the problem: instead of asking the impossible question "is this content fake?", it asks the tractable question "does this content match what its creator declared?"
┌─────────────────────────────────────────────────────────────────┐
│ Layer 1: TIP-ID (Identity) │
│ Verified human bound to post-quantum keypair via 4-layer │
│ biometric stack. One human, one TIP-ID. Federated, portable. │
│ URI: tip://id/[REGION]-[ML_DSA_PUBKEY_HASH_16] │
├─────────────────────────────────────────────────────────────────┤
│ Layer 2: TIP-CONTENT (Provenance) │
│ Content hash + mandatory origin declaration (OH/AA/AG/MX) │
│ signed by creator's TIP-ID and recorded on the federated DAG. │
│ URI: tip://c/[ORIGIN]-[HASH14]-[ID_SHORT] │
├─────────────────────────────────────────────────────────────────┤
│ Layer 3: TIP-TRUST (Reputation) │
│ Deterministic 0-1000 score computed from complete DAG history. │
│ Any node, anywhere, computes the same score from the same data. │
│ No central database. No hidden manipulation. │
└─────────────────────────────────────────────────────────────────┘
│
Federated DAG Network
(anyone can run a node, anyone can verify)
Add these to any web server: no SDK, no account, no code required:
# Nginx
add_header X-TIP-Author "tip://id/US-a3f8c91b2d4e7021";
add_header X-TIP-CTID "tip://c/OH-7f2a91bc3d5e4a-a3f8";
add_header X-TIP-Origin "OH";
add_header X-TIP-Signature "[ML-DSA-65 signature base64]";
add_header X-TIP-Content-Bind "[domain-bind-hash]";# Apache (.htaccess)
Header set X-TIP-Author "tip://id/US-a3f8c91b2d4e7021"
Header set X-TIP-CTID "tip://c/OH-7f2a91bc3d5e4a-a3f8"
Header set X-TIP-Origin "OH"
Header set X-TIP-Signature "[ML-DSA-65 signature base64]"
Header set X-TIP-Content-Bind "[domain-bind-hash]"<!-- HTML meta tags -->
<meta property="tip:author" content="tip://id/US-a3f8c91b2d4e7021" />
<meta property="tip:ctid" content="tip://c/OH-7f2a91bc3d5e4a-a3f8" />
<meta property="tip:origin" content="OH" />A TIP node runs ML-DSA-65 signatures on every transaction and Groth16 ZK proofs on every identity registration. Both are CPU-bound, so single-core hosts are not sufficient even for a pilot.
| Tier | vCPU | RAM | Storage | Throughput target |
|---|---|---|---|---|
| Minimum | 2 | 2 GB | 20 GB SSD | < 1K registrations / day |
| Recommended | 4 | 4 GB | 100 GB NVMe SSD | < 100K registrations / day |
| High-traffic | 8 | 8 GB | 500 GB+ NVMe SSD | > 100K registrations / day |
Notes:
- Storage grows ~14 KB per DAG transaction (signature + canonical JSON). Transient consensus data (certificates, equivocation votes, mempool, expired rotation participation) is pruned automatically by the cert-GC and rotation-boundary handlers; canonical state (transactions, identities, content, scores, commits, committee history) is retained as the authoritative ledger.
- Node.js 18+ and 64-bit OS are required (
better-sqlite3and the post-quantum crypto bindings ship as native modules).
Two paths depending on whether you're running the canonical federation or spinning up a local multi-node setup for development.
- Production — start the founding node that bootstraps the federation
from
genesis.js. This is the path The AI Lab runs in production. It is also the path needed by any operator running a registered node whose identity bundle was delivered out-of-band. - Development — generate any number of additional nodes locally
using
scripts/register-node.js, each with isolated data, logs, and ports. Use this for local 2/3/4-node federations or for issuing registration bundles that get delivered to external operators.
The genesis founding-node identities (a 3-node committee) are minted at seed time and never change for the life of the federation. Each operator receives two files out-of-band (Bitwarden Send / Signal / hardware token):
.env: the node's config; no inline secrets, only a pointer to the key filetip-node-<id>.tip.json: the ML-DSA-65 keypair (THE secret; see step 2 for ownership , the container reads it as uid 1001, not your login user)
Step 1. Clone and install:
git clone https://github.com/theailab/tip-protocol.git
cd tip-protocol
npm installStep 2. Place the delivered files:
cp /path/to/delivered/node.env .env && chmod 600 .env
mkdir -p genesis-data/backups
cp /path/to/delivered/tip-node-<id>.tip.json genesis-data/backups/
# The container runs as tipnode (uid 1001) and the backups dir is mounted
# read-only: a key file chmod 600 under YOUR user makes the node crash-loop
# with EACCES. Hand the file to the container's uid:
sudo chown 1001 genesis-data/backups/tip-node-<id>.tip.json
sudo chmod 400 genesis-data/backups/tip-node-<id>.tip.json
# keep a second copy OFF the live server (offline/cold storage)Security group / firewall for a node instance: inbound TCP 4000 (public
API; also what Prometheus scrapes) and TCP 4001 from the other nodes'
security group (libp2p). Nothing else inbound.
Fronting nodes with Cloudflare: proxied DNS record, an Origin Rule rewriting
the destination port to 4000, SSL mode Flexible (until origin TLS), and a
cache-bypass rule for the node hostnames. A 521 on BOTH http and https while
http://<ip>:4000/health answers means the Origin Rule is not applying ,
check it is deployed and matches on the Hostname field.
The node reads its keypair from that file via TIP_NODE_CREDENTIALS_FILE
(already set in the delivered .env); docker compose mounts
genesis-data/backups/ read-only into the container. Orchestrated
deployments (K8s/Swarm/ECS) can instead mount the file as a platform
secret and point TIP_NODE_CREDENTIALS_FILE at the mount path, no code
changes needed.
Step 3. Adjust the deployment-specific values in .env. Identity
(TIP_NODE_ID, TIP_NODE_CREDENTIALS_FILE) and ports come pre-filled,
leave them as delivered. Update only:
# ── Network — adjust per host ─────────────────────────────────────────────
TIP_PUBLIC_IP=<this-server's-public-ip> # required for libp2p reachability
TIP_PUBLIC_URL=https://tip.example.org # optional, surfaced in API responses
TIP_CORS_ORIGINS=* # comma-separated origins, or "*"
# ── Database — pick one driver (see "Database Configuration" below) ──────
DB_DRIVER=postgres # sqlite | postgres | mariadb | mssql | oracle
DB_HOST=localhost # Docker service name when in compose
DB_PORT=5432
DB_NAME=tip_protocol
DB_USER=tip
DB_PASSWORD=<db-password>The delivered .env already sets TIP_DATA_DIR, TIP_DB_PATH, and
TIP_LOG_DIR to per-node paths. Leave those as delivered.
Step 4. Open the firewall:
PORT(REST API)TIP_P2P_PORT(libp2p TCP)
Step 5. Start.
Native:
npm startDocker Compose:
docker compose up -d
docker compose logs -f tip-nodeStep 6. Verify:
curl -s http://localhost:$PORT/health | jq '{joinState: .data.consensus.narwhal.joinState, halted: .data.consensus.halt.halted, peers: .data.peers.connected}'
# → { "joinState": "ready", "halted": false, "peers": 0 } ← founding node alone
curl -s http://localhost:$PORT/health | jq -r '.data.p2p.bootstrap_addr'
# → "/ip4/<your-ip>/tcp/4001/p2p/12D3Koo..."The bootstrap_addr is what every other node will use as
TIP_BOOTSTRAP_PEERS when it joins.
The full multi-node bring-up (0 to a live, converged federation: git deploy,
per-node keys, S3 media, observability, validation gates, and the reset order
for an existing chain) is the runbook in
docs/DEPLOYMENT.md.
scripts/register-node.js issues a NODE_REGISTERED tx on the running
federation (signed by the founding VP) and writes a complete
self-contained bundle for the new node — including isolated data/
and logs/ directories so multiple nodes on the same host don't
clobber each other. Use this both for local multi-node testing and for
producing the bundles that get delivered to external operators.
Step 1. Clone and install (skip if already done):
git clone https://github.com/theailab/tip-protocol.git
cd tip-protocol
npm installStep 2. Generate a fresh genesis (3 founding nodes + founding VP + founding identities):
cp .env.example .env && chmod 600 .env # once, before first seed
npm run seed:localOn a fresh clone this mints everything; on a machine that already has
genesis-data/backups/, it reuses those keys and leaves the genesis
unchanged. Only run npm run seed:fresh:local when you deliberately want
a brand-new federation: it wipes the backups and mints all-new keys,
which changes genesis_hash and requires a cluster reset.
What this does (scripts/seed.js --local-cluster):
- Mints ML-DSA-65 keypairs for the founding VP, 4 founding identities and
3 founding nodes, and writes each as a
.tip.jsoningenesis-data/backups/: the single on-disk key store (genesis.json carries only the public side) - Registers each founding identity with a REAL Groth16 dedup proof
(proof bytes persist in the identity's backup so re-seeds stay
byte-identical and
genesis_hashis stable) - Patches
.envwith node1'sTIP_NODE_CREDENTIALS_FILEpointer and generatesnode2-env/node-2.env+node3-env/node-3.envwired for the local docker cluster (fixed IPs, per-node DBs, bootstrap multiaddr computed from node1's deterministic peer id)
The private keys live only in
genesis-data/backups/on the machine that ranseed(.gitignored). Anyone cloning the repo gets the public genesis but must re-seed their own isolated dev federation.
npm run seed (without :fresh) reuses every entity whose backup
.tip.json exists and mints fresh keys only for missing ones; with all
backups present the genesis hash does not change. seed:local /
seed:fresh:local additionally (re)generate the node2/node3 env files.
Step 3. Start the local 3-node cluster:
docker compose -f docker-compose.local.yml up -d --build
curl -s localhost:4000/health | jq '.data.consensus.halt.halted' # false once quorum formsThis brings up postgres + node1/node2/node3 (the genesis committee:
3 nodes, quorum 2). Each node loads its keypair from the mounted
genesis-data/backups/*.tip.json. Native single-node alternative:
npm start (uses .env as-is).
Once a node reports joinState=ready you can register additional
nodes against it.
Step 4. Generate one or more additional nodes:
node --experimental-vm-modules scripts/register-node.js \
--name "Partner Node" \
--node-url http://localhost:4000 \
--port 4100 \
--p2p-port 4101 \
--public-ip 127.0.0.1| Flag | Default | Description |
|---|---|---|
--name |
TIP Node <id> |
Human-readable node name |
--node-url |
http://localhost:4000 |
Any healthy node's REST URL |
--port |
4100 |
REST API port for the new node |
--p2p-port |
<port>+1 |
libp2p TCP port for the new node |
--public-ip |
127.0.0.1 |
Publicly-reachable IP of the new node |
The script writes:
generated_nodes/<slug>-<short-id>/
├── <slug>.env ← drop-in env file (no inline keys; mirrors .env.example)
├── <id>.tip.json ← the ML-DSA-65 keypair, chmod 600; the env points at it
└── data/ ← per-node DB + keystore directory
The generated .env mirrors .env.example exactly (same sections, same
defaults) with the node's values overlaid: identity, ports, bootstrap
multiaddr, TIP_NODE_CREDENTIALS_FILE, per-node TIP_DATA_DIR /
TIP_LOG_DIR, and the DB settings carried from the machine that ran the
script (postgres by default).
Start a generated node:
node --env-file=./generated_nodes/<slug>-<short-id>/<slug>.env node/src/index.jsIssuing bundles to external operators: deliver the generated
<slug>.env and <id>.tip.json out-of-band (Bitwarden Send, Signal,
hardware token). The recipient follows the Production steps above:
.env at the repo root, the .tip.json in genesis-data/backups/,
adjust TIP_PUBLIC_IP + DB credentials, run. Identity and
TIP_BOOTSTRAP_PEERS must NOT be regenerated, they're tied to the DAG
registration.
Two helper scripts make iterating on dispute flows tractable on a local cluster:
scripts/seed-temp-users.js— register N synthetic identities at varied scores so jury selection has a realistic pool to draw from (default: 50 users, 70% jury-eligible).scripts/drive-jury.js— auto-submit commit + reveal across all summoned jurors for a live dispute, optionally biased so the verdict lands UPHELD or DISMISSED.
CLI flags, the post-seed restart gotcha, and an end-to-end runbook
("file a dispute, drive it to a verdict in one developer session")
live in scripts/README.md.
| Symptom | Likely cause |
|---|---|
Node tip://node/... not in registry at handshake |
TIP_NODE_ID / credentials file edited or regenerated. Restore the delivered .tip.json + .env exactly, OR re-run register-node.js for that node. |
TIP_NODE_CREDENTIALS_FILE ... unreadable at boot |
The .tip.json is missing from genesis-data/backups/ (or not mounted into the container). Copy it back / check the compose volume. |
Genesis hash mismatch at handshake |
Wrong network / forked federation. The peer's genesis.js differs from yours. |
No bootstrap peers configured — discovery via mDNS only |
TIP_BOOTSTRAP_PEERS is empty. Founding nodes leave this empty intentionally; everyone else needs the founding node's bootstrap_addr here. |
joinState stuck at syncing or catching_up |
Bootstrap peer unreachable, or it is itself behind — check firewall, DNS, and the upstream peer's /health. |
DB connection error (Postgres / MariaDB / Oracle) |
For Docker, set DB_HOST to the service name (postgres, mariadb, oracle) not localhost. For native runs on the host, localhost is correct. |
Multiple generated nodes sharing one node/logs/ |
TIP_LOG_DIR not set in the node's .env. Re-generate with the latest register-node.js (logs default to ./logs/<slug>-<short-id>). |
In a founding .env (production) |
In a generated .env (development / external operator) |
|---|---|
TIP_NODE_ID (founding identity) |
TIP_NODE_ID (registered identity, written by script) |
TIP_NODE_CREDENTIALS_FILE=genesis-data/backups/<id>.tip.json |
TIP_NODE_CREDENTIALS_FILE=generated_nodes/<slug>/<id>.tip.json |
TIP_BOOTSTRAP_PEERS empty (node1) or node1's multiaddr |
TIP_BOOTSTRAP_PEERS=<a healthy node's bootstrap_addr> |
PORT=4000, TIP_P2P_PORT=4001 |
PORT=<assigned>, TIP_P2P_PORT=<assigned> |
TIP_DATA_DIR=./data, TIP_LOG_DIR per node |
per-node ./generated_nodes/<slug>/data + ./logs/<slug> |
Operator-set: TIP_PUBLIC_IP, TIP_PUBLIC_URL, TIP_CORS_ORIGINS, DB_DRIVER + DB credentials |
Same |
TIP Protocol supports five database engines. Switch by changing DB_DRIVER in .env — no code changes required.
DB_DRIVER |
Engine | npm package | Notes |
|---|---|---|---|
sqlite |
SQLite (file) | better-sqlite3 |
Installed — local dev only, no DB server needed |
postgres |
PostgreSQL | pg |
Installed — production default |
mariadb |
MariaDB / MySQL | mysql2 |
Installed |
mysql |
MySQL | mysql2 |
Alias for mariadb |
oracle |
Oracle Database 23ai | oracledb |
Installed (thin-mode, no Instant Client needed) |
mssql |
SQL Server | mssql |
Installed |
SQLite — local dev (no DB server):
DB_DRIVER=sqlite
TIP_DB_PATH=./data/tip.dbPostgreSQL — production default:
DB_DRIVER=postgres
DB_HOST=localhost # Docker service name: postgres
DB_PORT=5432
DB_NAME=tip_protocol
DB_USER=tip
DB_PASSWORD=secretDocker: docker compose -f docker-compose.local.yml up -d (postgres starts by default, no profile flag)
MariaDB / MySQL:
DB_DRIVER=mariadb
DB_HOST=localhost # Docker service name: mariadb
DB_PORT=3306
DB_NAME=tip_protocol
DB_USER=tip
DB_PASSWORD=secretDocker: docker compose -f docker-compose.local.yml --profile mariadb up -d
Oracle Database 23ai:
DB_DRIVER=oracle
DB_HOST=localhost # Docker service name: oracle
DB_PORT=1521
DB_NAME=FREEPDB1 # service name, not SID
DB_USER=tip
DB_PASSWORD=secretDocker: docker compose -f docker-compose.local.yml --profile oracle up -d
SQL Server 2022:
DB_DRIVER=mssql
DB_HOST=localhost # Docker service name: mssql
DB_PORT=1433
DB_NAME=tip_protocol
DB_USER=sa
DB_PASSWORD=StrongPass123! # must meet SQL Server complexity rules
DB_SSL=true
DB_SSL_REJECT_UNAUTHORIZED=false # dev only — self-signed certDocker: docker compose -f docker-compose.local.yml --profile mssql up -d
For remote or cloud databases, also set
DB_SSL=true(and optionallyDB_SSL_REJECT_UNAUTHORIZED=true). Connection pool defaults areDB_POOL_MIN=2/DB_POOL_MAX=10and apply to all server-side drivers. The Knex adapter uses an in-memory mirror for reads + fire-and-forget for writes (seenode/src/db/knex-adapter.js).
All schema (DDL) lives in versioned migrations under node/src/db/migrations/, not
in store code. Run them from the node/ directory. The default environment reads
DB_DRIVER, so the npm scripts apply to whatever DB your .env points at:
cd node
npm run db:migrate # apply all pending migrations
npm run db:status # show completed + pending migrations
npm run db:rollback # undo the last batch
npm run db:fresh # roll everything back, then re-apply from emptydb:migrate on a brand-new DB applies 000_baseline.js and builds the full
schema from zero. Knex has no migrate:fresh (that is a Laravel command);
db:fresh is the knex-native equivalent (rollback --all + migrate:latest).
To target one engine explicitly (ignoring DB_DRIVER), pass --env —
sqlite | pg | mariadb | mssql | oracle:
# Postgres (production)
npx knex --knexfile knexfile.js --env pg migrate:latest
# Fresh re-run: roll everything back, then re-apply from empty
npx knex --knexfile knexfile.js --env pg migrate:rollback --all
npx knex --knexfile knexfile.js --env pg migrate:latestA fresh node applies 000_baseline.js (the full schema) on first migrate. Add
schema changes as new NNN_description.js files; see
node/src/db/migrations/README.md for the numbering, tagging
(consensus-affecting vs node-local), and authoring rules.
Registered content can carry media attachments (images, audio). Media
bytes are content-addressed (media_id = SHAKE-256(bytes), deduplicated
by construction) and are NOT stored on chain; only the hash references
are. Access is restricted to the five roles with standing on the content
(author, assigned reviewer, disputer, juror, expert reviewer), and a
three-stage retention sweep deletes bytes after their dispute-relevance
window (21d base, 7d post-adjudication, 7d post-appeal); the on-chain
hashes remain verifiable forever.
Two interchangeable storage backends:
| Backend | Use | Env |
|---|---|---|
fs (default) |
development, single machine | TIP_MEDIA_BACKEND=fs, TIP_MEDIA_FS_PATH=./data/media |
s3 |
production | TIP_MEDIA_BACKEND=s3 + bucket/region/KMS vars |
Storage is per-node: each operator provisions, pays for, and serves their own bucket; peers fetch media through the origin node's API, never from each other's buckets.
Setting up the S3 backend is one command (creates the bucket, encryption key, and node credentials in ~10 minutes, for any host: EC2, EKS, Hetzner, dev laptop):
cd infra/s3-media
cp terraform.tfvars.example terraform.tfvars # fill 3 values
./setup.sh # prints the env block for the nodeFull start-to-end guide (including how to get AWS credentials):
infra/s3-media/README.md. Operator
runbook with console paths and smoke tests:
docs/PROD_S3_SETUP.md.
The Node.js process serves plain HTTP on PORT and plain TCP libp2p on
TIP_P2P_PORT — TLS is terminated at the reverse proxy or load
balancer in front of it. Nginx, Caddy, Cloudflare, or any L7 LB is
sufficient; no TLS configuration inside the node is required.
For libp2p connections to remote peers, secure transport (Noise / TLS 1.3) is handled inside the libp2p stack itself — independent of any reverse proxy in front of the REST API.
Each node exposes Prometheus-format metrics on GET /metrics over its
REST port. A ready-to-run local stack (Prometheus + Grafana with the
TIP Federation dashboard pre-loaded) lives in infra/observability/:
cd infra/observability
cp .env.example .env # edit if you want non-default creds or node list
docker compose up -d- Grafana → http://localhost:3030 (defaults
admin/admin) - Prometheus → http://localhost:9090
Add or remove scrape targets by editing TIP_NODE_TARGETS in .env,
no edit of prometheus.yml needed. Full local setup and configuration are in
infra/observability/README.md. The
production runbook (one monitoring host + per-node promtail log shipping, TLS,
auth, and the DNS/permissions gotchas) is
infra/observability/prod/README.md.
<!-- Load once -->
<script src="https://badge.theailab.org/tip-badge.min.js" defer></script>
<!-- Use anywhere -->
<tip-badge tip-id="tip://id/US-a3f8c91b" size="120" variant="gold-dark"></tip-badge>
<tip-badge type="mark" size="80" variant="light"></tip-badge>
<tip-badge auto size="80"></tip-badge>Every piece of content registered through TIP Protocol carries a mandatory origin declaration. There are four categories:
| Code | Label | Meaning | Visual |
|---|---|---|---|
OH |
Original Human | Created entirely by the uploader without AI generation tools | Blue shield |
AA |
AI-Assisted | Human primary author; AI tools used for enhancement | Purple shield |
AG |
AI-Generated | AI primary creator; human role was prompting or curation | Amber shield |
MX |
Mixed/Composite | Multiple sources, some human and some AI | Gray shield |
Conservative labelling is never penalised. If you declare content as AI-Generated when it was actually human-created, there is zero penalty. The system incentivises over-disclosure.
| Score | Tier | Shield | Meaning |
|---|---|---|---|
| 850-1000 | HIGHLY TRUSTED | ✓ Green | Exceptional long-term record of consistent, honest origin declarations |
| 650-849 | TRUSTED | ✓ Blue | Established credibility, accurate origin labelling over time |
| 400-649 | VERIFIED | ✓ Gold | Identity confirmed by accredited VP, no violations. Default starting tier |
| 200-399 | CAUTION | ⚠ Amber | Mislabelling incidents or unresolved disputes on record |
| 0-199 | NOT TRUSTED | ✗ Red | Severe or repeated violations, identity may be suspended |
Scores are computed deterministically from the DAG. Any protocol-compliant node produces the same score for any TIP-ID from the same DAG history. There is no central score database and no hidden manipulation.
TIP Protocol mandates post-quantum cryptography at the protocol level. Every conforming implementation MUST use these algorithms:
| Function | Algorithm | Standard | Key/Sig Size |
|---|---|---|---|
| Primary signatures | ML-DSA-65 (Dilithium) | FIPS 204 | PK: 1.9KB, Sig: 3.3KB |
| Root signatures | SLH-DSA-128s (SPHINCS+) | FIPS 205 | PK: 32B, Sig: 7.8KB |
| Key encapsulation | ML-KEM-768 (Kyber) | FIPS 203 | PK: 1.1KB |
| Hashing | SHAKE-256 / SHA-3 | FIPS 202 | 256-bit output |
Hybrid signatures (Ed25519 + ML-DSA-65) are used during the transition period (Years 1-3) for backward compatibility.
TIP Protocol uses a Directed Acyclic Graph (DAG), not a blockchain:
- No proof-of-work: no energy-intensive mining
- Parallel processing: each transaction references two prior transactions
- Throughput: exceeds 5,000 transactions per second
- Anyone can run a node: no permission required
- Full decentralization roadmap: Phase 1 (coordinator), Phase 2 (21 validators), Phase 3 (self-validating at 100 TPS)
| Type | Role | Who Runs It |
|---|---|---|
| Full Node | Complete DAG history, independent verification | Enterprises, universities, NGOs |
| Light Node | Recent transactions + Merkle proofs | Browser extensions, mobile apps |
| VP Node | Full node + biometric hardware, mints TIP-IDs | Accredited Verification Providers |
| Archive Node | Complete DAG + historical snapshots | Academic institutions |
Any organisation can become a Verification Provider and issue TIP-IDs by:
- Implementing the four-layer biometric verification stack
- Passing an independent security audit
- Signing the TIP-VP Code of Conduct
- Receiving accreditation from The AI Lab Intelligence Unobscured, Inc.
Category A: Identity-native organisations (banks, telecom, biometric companies like iProov, Jumio, Yoti)
Category B: Content platforms and journalism organisations (news publishers, CPJ, RSF, SPJ)
Category C: Government digital identity programmes (EU eIDAS, UK DSIT, Estonia e-Residency)
Category D: Educational institutions (universities, colleges, research institutes)
To apply for VP accreditation: accreditation@theailab.org
# Resolve a TIP-ID
GET /v1/identity/:tipId
# Get trust score only
GET /v1/identity/:tipId/score
# Resolve content provenance
GET /v1/content/:ctid
# Look up content by hash (Creator Mode)
GET /v1/content/by-hash/:canonicalHash
# Register new content
POST /v1/content/register
# File a dispute
POST /v1/content/:ctid/dispute
# Revocation list
GET /v1/revocations
# Node health
GET /v1/health
# DAG statistics
GET /v1/statsFull API documentation: docs/API.md
TIP Protocol is designed from the ground up for GDPR compliance:
- Zero raw biometrics stored: facial scans produce a SHAKE-256 hash only; raw data is destroyed in the device secure enclave
- Peppered deduplication hash: device-held pepper prevents nation-state reidentification attacks
- ZK proof on DAG: deduplication is proven without revealing the hash
- Score visibility modes: FULL_PUBLIC / TIER_ONLY (default) / VERIFIED_ONLY
- Article 17 erasure: score history can be erased while preserving content provenance
- DPIA published before any European deployment
- DPO appointed as required by Article 37
tip-protocol/
├── README.md ← You are here
├── LICENSE.txt ← TIP Community License v1.0 (TIPCL-1.0)
├── NOTICE.txt ← Required attribution notice
├── PATENTS.md ← Patent disclosure
├── CONTRIBUTING.md ← How to contribute
├── CODE_OF_CONDUCT.md ← Community standards
├── SECURITY.md ← Security policy and disclosure
├── CHANGELOG.md ← Version history
├── .env.example ← Environment variable template
├── .gitignore ← Git ignore rules
│
├── spec/ ← Protocol specification (CC-BY 4.0)
│ └── TIP_Protocol_Specification_v4.0.md
│
├── docs/ ← Extended documentation
│ ├── API.md ← Full REST API reference
│ ├── GETTING_STARTED.md ← Step-by-step integration guide
│ ├── DEPLOYMENT.md ← Node + federation deploy (0 to live)
│ ├── PROD_S3_SETUP.md ← Production S3 media backend setup
│ ├── TESTING_RUNBOOK.md ← Test suites + live-cluster validation
│ ├── VP_ACCREDITATION.md ← How to become a Verification Provider
│ ├── GDPR_COMPLIANCE.md ← GDPR and privacy architecture
│ ├── CRYPTOGRAPHY.md ← Post-quantum cryptography details
│ └── BADGE_DESIGN.md ← Visual badge specifications
│
├── node/ ← Node.js reference implementation
│ ├── package.json
│ ├── src/
│ │ ├── index.js ← Entry point
│ │ ├── dag.js ← DAG engine + SQLite store + MemoryStore
│ │ ├── genesis.js ← Genesis bootstrap
│ │ ├── api.js, routes/ ← REST API
│ │ ├── services/ ← Identity, content, dispute, governance, ...
│ │ ├── consensus/ ← Narwhal/Bullshark, commit-handler, rotation-coord
│ │ ├── network/ ← libp2p, handshake, peer-discovery
│ │ ├── sync/ ← Snapshot install, anti-entropy, peer-sync
│ │ ├── validators/ ← Tx validator, business rules
│ │ ├── db/ ← Multi-DB adapter (Knex: pg/mariadb/mssql/oracle)
│ │ └── middleware/ ← Express error handler, request id, validation
│ └── tests/
│
├── python/ ← Python reference implementation
│ ├── requirements.txt
│ ├── setup.py
│ ├── tip_node/
│ │ ├── __init__.py
│ │ ├── dag.py
│ │ ├── identity.py
│ │ ├── content.py
│ │ ├── trust.py
│ │ ├── crypto.py
│ │ └── api/
│ └── tests/
│
├── sdk/ ← JavaScript SDK for platform integration
├── cli/ ← Command-line tools
├── browser-extension/ ← [Moved to github.com/theailaborg/tip-extension]
├── badge/ ← <tip-badge> web component
└── scripts/ ← Utilities
├── seed.js ← Genesis block generation (founding-node bootstrap)
├── register-node.js ← Issue NODE_REGISTERED tx + emit per-node bundle
└── zk-setup.js ← Groth16 trusted-setup helper
TIP Protocol uses a layered licensing model:
| Asset | License | Details |
|---|---|---|
| Protocol Specification | CC-BY 4.0 | Free for everyone, forever. Attribution required. |
| Reference Implementation | TIPCL-1.0 | Free under $100K revenue. Paid above. Converts to Apache 2.0 on January 1, 2031. |
| TIP™ Trademarks | Trademark Law | Reserved by The AI Lab. Separate license required. |
| Patent Claims (16 inventions, A-P) | Patent Law | Included in TIPCL commercial license. Valid to ~2047. |
Free for: Individuals · Nonprofits · Journalism organisations · Governments · Education · Businesses under $100K annual revenue
Requires a Commercial License: Any entity with Annual Revenue exceeding USD $100,000 using TIP Protocol in a revenue-generating product or service.
Mandatory attribution for all users:
Built on TIP Protocol by The AI Lab Intelligence Unobscured, Inc.
theailab.org | Licensed under TIPCL-1.0
See LICENSE.txt for full terms.
Commercial licensing: licensing@theailab.org
We welcome contributions from the community. Please read CONTRIBUTING.md before opening a pull request.
Good first issues: documentation improvements, additional language SDKs, test coverage
Core protocol changes: require RFC process (see docs/RFC_PROCESS.md)
Security vulnerabilities: see SECURITY.md: do not open a public issue
TIP™, AI Trust ID™, AI Trust Registry™, and The Global Seal of Trust™ are trademarks of The AI Lab Intelligence Unobscured, Inc. This repository and its license do not grant any rights to use these marks. See TRADEMARKS.md for permitted uses.
This software implements inventions that are the subject of pending U.S. patent applications filed by Dinesh Mendhe and assigned to The AI Lab Intelligence Unobscured, Inc. See PATENTS.md for details.
Copyright 2026 The AI Lab Intelligence Unobscured, Inc.
Authored by Dinesh Mendhe · theailab.org
TIP™ · AI Trust ID™ · AI Trust Registry™ · The Global Seal of Trust™
Trademarks of The AI Lab Intelligence Unobscured, Inc.