Sinks & projections
A signed Grid is the canonical model. Everything else — a profile page, a REST API response, a SQL table, or a knowledge graph — is a projection (a sink). Projections make Grids easy to query, render, and integrate. They are never authoritative: verification always goes back to the signed attestation on each cell.
Source of truth vs output
Signed Grid (gridz/1.0.0)
subject + theme + cells[] + root_attestation
└── each cell.attestation ◄── source of truth
│
│ publish / sync (projection only)
▼
┌──────┴──────┬──────────────┬─────────────┬──────────────┐
▼ ▼ ▼ ▼ ▼
gridz.bio GET /api/ Postgres / Neo4j S3 / Redis
(HTML UI) profile SQLite (graph) (object/KV)
(JSON) (relational)gridz.bio is one consumer of the spec — not the only output. The same verified Grid can simultaneously exist as:
- Rendered UI — HTML/React page (e.g.
kevin.gridz.bio) - HTTP JSON —
GET /api/profile/kevin.gridz.eth - On-chain index — EAS attestations +
GridzResolveron Base (see on-chain) - Relational database — Postgres, MySQL, SQLite for SQL analytics and joins
- Knowledge graph — Neo4j for traversals, agent discovery, linked data
- Object / document stores — S3, MongoDB, Redis for caching and bulk export
Any projection can be rebuilt from the signed Grid. If a database row disagrees with an attestation, the attestation wins.
Sink interface
@gridz/sinks (TypeScript) and gridz_sinks (Python) implement a common adapter pattern. Each sink exposes:
| Operation | Purpose |
|---|---|
write(cells, ctx) | Project signed cells into the sink. Returns a WriteResult per cell with a sink_native_uri (where the copy landed). |
read(query) | Fetch cells by subject DID (and optional key filter). Used to assemble a Grid for rendering or re-verification. |
delete(cellIds) | Remove projected cells from the sink (does not revoke on-chain attestations). |
project?(grid) | Optional whole-Grid projection into an alternate shape (e.g. a graph view). Sinks with capabilities.project: true may implement this. |
A sink write is never authoritative. It only records where a copy was stored. The signed attestation on each cell remains the proof; consumers call verifyGrid against the assembled Grid, not against the sink alone.
Database projections
Relational and document sinks store one row (or document) per cell, keyed by (subject.did, cell.key). The full cell JSON — including the attestation envelope — is persisted so the Grid can be reconstructed and verified offline.
Tabular pattern (SQLite, Postgres, MySQL)
CREATE TABLE gridz_cells ( subject TEXT NOT NULL, -- subject DID key TEXT NOT NULL, -- cell key, e.g. com.github id TEXT NOT NULL, -- stable cell id value_hash TEXT NOT NULL, -- attestation.value_hash (indexed) cell_json TEXT NOT NULL, -- full signed cell written_at TIMESTAMPTZ, PRIMARY KEY (subject, key) );
Typical uses:
- Analytics —
SELECT key, COUNT(*) FROM gridz_cells GROUP BY keyacross all subjects - Search — find every profile with a
com.githubcell or a specificagent-endpoint[mcp] - ETL — sync on-chain or API-fetched Grids into a warehouse for BI tools
- Local dev — SQLite (
:memory:or file) with no chain dependency
CLI: gridz publish --sink sqlite --grid grid.json. See CLI.
Document & object stores
| Sink | Layout | Use case |
|---|---|---|
| MongoDB | One document per cell, indexed by subject + key | Flexible schema, nested widget values, agent context blobs |
| S3 | s3://bucket/{subject}/{key}.json | Static export, CDN-backed profile archives, backup |
| Redis | Key-value per cell | Low-latency cache in front of chain or Postgres |
Knowledge graph projection
A Grid is already a small graph in structure: a subject node connected to many cells by key. The Neo4j sink in @gridz/sinks materializes that shape for traversal queries across many Grids.
Graph model
(:Subject { did: "did:pkh:eip155:8453:0x…" })
-[:HAS_CELL]->
(:Cell { key: "com.github", id: "…", value_hash: "0x…", cell: <full JSON> })On write, the sink runs:
MERGE (s:Subject {did: $subject})
MERGE (s)-[:HAS_CELL]->(c:Cell {key: $key})
SET c.id = $id, c.value_hash = $vh, c.cell = $cellWhy a knowledge graph?
- Agent discovery — traverse
(Subject)-[:HAS_CELL]->(Cell {key: "agent-endpoint[mcp]"})to find MCP endpoints across agents - Linked identities — connect subjects that share service keys, registry entries, or operator DIDs
- Org graphs — organizations with
gridz.tokenscells linked to token contract metadata in an external graph - RAG / semantic layers — attach embeddings to
Cellnodes while keepingvalue_hashfor cryptographic grounding
Graph nodes store the full signed cell JSON. Before trusting a value in a graph query, run verifyGrid on the reconstructed Grid (or verify the individual cell's attestation). The graph indexes and connects; signatures prove authenticity.
ENS as primary sink
For gridz.bio, the primary on-chain projection is ENS + EAS on Base. Each cell maps to resolver storage and an EAS gridz.cell.v1 attestation. The ENS sink in @gridz/sinks can also project to standalone *.eth names via text records (gridz.keys, gridz.layout, per-key values, and gridz.att[key] attestations).
ENS is a sink like any other — convenient for name resolution and wildcard reads, but verification still checks the attestation bytes, not "whatever ENS returned."
End-to-end flow
- Author — build a Grid (YAML, editor, or API). Cells may be draft / unattested during editing.
- Sign — wallet (or 1Claw HSM) signs each cell via EIP-712
GridzCell. See Attestations. - Publish — push to one or more sinks:
- gridz.bio → Base EAS + resolver (browser flow)
- CLI →
gridz publish --sink postgres|sqlite|neo4j|ens|… - MCP →
sink_publishtool for agent-driven sync
- Consume — read from any sink, assemble Grid JSON, render or query.
- Verify —
verifyGrid(grid)checks hashes and signatures independently of which sink supplied the data.
Choosing an output
| Goal | Output |
|---|---|
| Public profile page + ENS identity | gridz.bio (on-chain sink) |
| App integration, bots, agents | GET /api/profile/{subject} or @gridz/core directly |
| SQL reporting, dashboards, search | Postgres / MySQL / SQLite sink |
| Relationship traversal, agent registries, semantic search | Neo4j knowledge graph sink |
| Static backup, IPFS/CDN archive | S3 or file export |
| Offline verification only | Grid JSON file — no sink required |
Related
- Concepts — short intro to sinks
- Toolkit —
@gridz/sinkspackage - Attestations — what gets signed before projection
- Verification — trusting a Grid regardless of sink