DATA MODEL

The database is the API.

On The Grid, you don't write CRUD APIs and you don't maintain user databases. You define data schemas, capability rules, and event triggers. The user owns their rows. Apps hold revocable capability tokens.

Every “piece of user data” has up to four layers

The naive model — “user data goes in user's vault, app data goes in app's vault” — breaks the moment a user wants to take their post with them. A post is more than its bytes; it has captions, timestamps, ownership claims. The four-layer model captures the asymmetry.

L1

Bytes

File content — video, image, document, audio.

Stored in
def:dsf/content · content-addressed by hash
Owner
User (DID-rooted)
Schema
Format only (JPEG, MP4, PDF)
Portable
✓ universally
Survives if app shuts down
hash:abc123… · 4.2 MB · MP4
L2

Universal metadata

Title, caption, owner, content_ref, public/private, timestamps — fields every app of this type has.

Stored in
def:dsf/state · user namespace
Owner
User
Schema
grid:<type>/v<n> · Grid-standard
Portable
✓ to any app speaking the schema
Survives if app shuts down
did:alice/short-video/clip-007
· title, caption, content_ref → hash:abc123…
L3

App-specific metadata

Proprietary fields: effects, ranking signals, app-internal IDs, audit trails.

Stored in
def:dsf/state · app namespace
Owner
App
Schema
<app>:<type>/v<n> · app-defined
Portable
✗ proprietary
Survives if app shuts down
tiktok:post/12345 · effects, hashtags, ranking_signals…
· post_ref → did:alice/short-video/clip-007
L4

Aggregate signals

Derived data: cohort recommendations, trending lists, scoring models.

Stored in
def:dsf/state · app namespace
Owner
App
Schema
<app>:agg:<purpose>/v<n>
Portable
✗ derived
Survives if app shuts down
tiktok:agg:trending/2026-04 · top 100 clips this week,
· cohort_id, score, source_post → tiktok:post/12345

How revocation works

Each app you connect holds a capability token — a DID-signed grant scoped to a path pattern in your data (e.g., prefix · did:alice/short-video/*). When you revoke, the protocol invalidates the token. The app can't read your bytes. It can't read your universal metadata. What's left in its proprietary L3 namespace becomes a dangling reference — the app might keep that row for audit but its post_ref is unresolvable.

Why apps don't have backends

A traditional app is a backend + a frontend. The backend owns the user database. On The Grid, the backend disappears — there's no separate HTTP API layer. Apps are frontend code that:

  1. Authenticates the user via their DID (sign a challenge).
  2. Reads/writes data scoped by capability tokens, directly against def:dsf/state.
  3. Triggers side effects (email, payments, validations) as WASM functions in def:xsr bound to data events.

The protocol is the backend. The user owns the database. The app is a UI.

Your data, your DID, your rules.