DEV Community

Cover image for Your API Shouldn't Expose Tables. It Should Expose Memory Acts
Eugene Popov
Eugene Popov

Posted on

Your API Shouldn't Expose Tables. It Should Expose Memory Acts

Your API Shouldn't Expose Tables. It Should Expose Memory Acts.

"When everyone lies, INDB remembers what you saw."

We didn't set out to build a faster PostgreSQL.

We set out to build something awkward to categorize: an Interpretational Database — memory where meaning is read, not filed. Not an archive that swells. A system that inhales chaos, exhales noise, and keeps a signed core.

Live at indb.tech. Docs at docs.indb.tech. This is what we actually shipped in v0.7.


The category mistake

Most data systems assume:

  1. You define meaning at write time (schema, types, migrations)
  2. You store rows
  3. You query with SQL-shaped verbs

Human memory doesn't work like that.

You observe first. Meaning arrives later — context-dependent, sometimes contradictory. Repetition compresses into habit. Some things you store but never consciously access.

INDB models that pipeline explicitly:

Phase Metaphor What happens
Inhale Ingest Accept raw events — tokens + location, no judgment
Exhale Fusion Compress repetition; reputation filters noise
Axiom Sign What survives can be Ed25519-signed, tamper-evident

That's not marketing poetry. It's how the API is organized.


Seven fields. No schema. On purpose.

INDB has no migrations. No column types in the SQL sense. Everything is an Event — a universal container:

Field Type Role
id string UUID v4 — auto-generated, immutable
timestamp float Unix epoch — time of observation
raw_data_anchor string[] Tokenized signal — abstract fingerprint
location string | OSM Spatial anchor — path or geo object
ttl int | null Decay in seconds (null = permanent)
fusion_count int How many observations merged
source_id string | null Trust chain / reputation
blind_payload string | null Zero-knowledge encrypted blob
binary_payload bytes | null Raw binary — images, streams, gRPC

If you need forty columns, you're probably modeling an archive — not memory.

Inhale an event:

curl -X POST https://api.indb.tech/api/v2/events \
  -H "Content-Type: application/json" \
  -d '{
    "raw_data_anchor": ["server", "heartbeat", "ok"],
    "location": "infra/edge/eu-west",
    "ttl": 86400
  }'
Enter fullscreen mode Exit fullscreen mode

You're not inserting a row. You're teaching the engine a new fragment of reality.


Semantic types, not SQL columns

Under those seven fields sits a semantic type system — types describe what kind of thought you're storing, not how many bytes it occupies:

Type Role
location The Anchor — spatial grounding via OSM
blind The Secret — client-encrypted, server-opaque
binary The Payload — raw media, sensor streams, files
struct The Graph — nested, recursively validated objects
bigint The Scale — nanosecond precision, crypto integers > 2⁵³
string The Narrative — text with optional regex/length constraints
number The Value — quantifiable floats and ints
null The Void — explicit absence

On ingest, INDB infers intent: a dict with lat/lon becomes location; raw bytes become binary; nested dicts become struct. You don't declare ALTER TABLE — you send data, the kernel classifies it.

The distinction that matters for privacy:

  • binary — server knows it's binary, validates size and MIME, but does not interpret content
  • blind — server does not know what's inside; ChaCha20-encrypted client-side, stored as Base64 opaque blob. Cognitive modules skip it entirely

Full spec: docs.indb.tech/TYPING/


Space is index

The location field is not a tag. It is a spatial anchor — the Cognitive Engine uses it for proximity, clustering, and relevance.

Format A — virtual namespace (logical paths, agents, books, services):

{ "location": "books/Dostoevsky/The_Idiot" }
Enter fullscreen mode Exit fullscreen mode

Format B — OSM geo object (real-world grounding):

{
  "location": {
    "lat": 55.7558,
    "lon": 37.6173,
    "osm_id": "node/1234567"
  }
}
Enter fullscreen mode Exit fullscreen mode

Coordinates are validated (lat −90…90, lon −180…180). osm_id accepts all three OpenStreetMap entity types — node/, way/, relation/. A café, a street, a district — all valid anchors.

Geo also lives in tokens. Prefix osm: in raw_data_anchor (e.g. osm:London, UK) ties the signal to a place without duplicating the location field.

What the engine does with it:

  • Echo harmonic analysis weights meta-location at 50% — events anchored to the same OSM object resonate stronger
  • Fusion penalises multiple osm: tokens in one event — prevents over-clustering on geographic coincidence alone
  • Haversine distance between coordinate pairs drives proximity scoring across the cluster

Same event, two ways to ground it — namespace for fiction and agents, OSM for sensors and field work:

curl -X POST https://api.indb.tech/api/v2/events \
  -H "Content-Type: application/json" \
  -d '{
    "raw_data_anchor": ["sensor", "temperature", "22.4", "osm:Jerusalem, Israel"],
    "location": {"lat": 31.7683, "lon": 35.2137, "osm_id": "node/26131744"}
  }'
Enter fullscreen mode Exit fullscreen mode

Cognitive verbs, not CRUD

Our public API reads like memory acts, not database operations:

Verb Endpoint Question it answers
Inhale POST /api/v2/events Remember this moment
Lens POST /api/v2/interpret How do you see it? (context, mood)
Echo search / resonate Who else feels like this?
Subwave POST /api/v2/subwave/broadcast Broadcast one frequency — horizontal resonance
Slice POST /api/v2/slice Shift the reading (what-if + observer profile)
Paradox POST /api/v2/paradox Hold superposition before content exists
Recovery GET /api/v2/recovery/key/{key_id} Restore by public identity — never private key

Six protocols on the wire: HTTP, GraphQL, WebSocket, gRPC, UDP, MCP. Zero Redis, Postgres, or Mongo in the kernel — we meant that literally.


Layer 2: what encryption alone can't give you

AES-256-GCM and TLS are Layer 1. Every vendor has them.

INDB's Layer 2 is structural:

Signed memory

Clients sign events locally. The server stores public_key + signatureprivate keys never traverse the API. Recovery uses key_id = SHA-256(public_key), a public fingerprint. API responses are also sealed with Ed25519.

blind_payload — the engine is a witness without eyes

You encrypt client-side. INDB stores an opaque blob. Replicates it across Raft nodes. Returns it on request.

It never reads it. No decryption key on server. Prism, Echo, Instinct work only on raw_data_anchor tokens — analytics without access to secrets.

The Black Box Contract is enforced at protocol level:

You may hide what is inside.

You may not hide that you were here.

When blind_payload is set, timestamp and location are mandatory — not a form validation quirk, a condition of existence. If authorities ask, the system has one answer:

"Something was here. This location. This time."

What it was — architecturally unknown.

We call this impossible to exfiltrate — not because we promise nicely, but because there's nothing to hand over.

(Client-side caveat: architecture breaks if your SDK logs keys into analytics. We document that boundary explicitly.)


Two kinds of paradox (same word, different phase)

This confused us internally until we named it:

Paradox (type)before observation.

POST /api/v2/paradox with empty raw_data_anchor. Context only. Content collapses when someone observes — sample_once births a signed Event; sample_on_read stays ephemeral.

Prism paradoxafter observation.

Fixed event, competing readings. Prism returns meaning, alternative_readings, perception_gap, is_paradoxical. The engine surfaces contradiction instead of picking a winner.

Same word. Different layer of memory. Both are signals, not errors.

Try Prism with observer context — meaning is relational, not baked in:

curl -X POST https://api.indb.tech/api/v2/prism/synthesize \
  -H "Content-Type: application/json" \
  -d '{
    "query": "felt almost impossible",
    "observer_context": {
      "token_weights": {"silence": 2.0},
      "vocabulary": {"Subjective": ["felt", "almost"]},
      "harmonic_weights": {"emotion": 0.8}
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Same tokens. Different observer. Different reading. System doesn't decide who's "right."


Grain: when barcode logic meets human memory

Strict Ed25519 is barcode-tier verification: ~0% noise tolerance. Correct for axioms. Wrong for memory — partial quotes, export damage, surface change.

So we shipped Grain — one kernel module, four tiers on the noise-tolerance axis:

Tier Real-world analog INDB mechanism
exact EAN-13 barcode Ed25519 / key_id
redundant QR Reed–Solomon N-of-M signed cluster (~30% damage)
resonant Handwriting biometrics Echo × source reputation, FAR/FRR knob
statistical SynthID-style watermark Token n-gram p-value

One endpoint. tier: auto picks from evidence. Responses expose uncertainty — false_accept_risk, insufficient_signal when the text is too short for statistical detection (honest floor, not fake confidence).

curl https://api.indb.tech/api/v2/grain/tiers
Enter fullscreen mode Exit fullscreen mode

Full spec: docs.indb.tech/GRAIN/

External world: four silos (barcode SDK, QR lib, biometric FAR/FRR, generative watermark). INDB: one spectrum inside the same pipeline that ingests, fuses, and signs.


Memory compresses (35:1 verified)

Repetition isn't data — it's pattern.

Three "home arrived" events fuse into one with fusion_count: 3. Routine compresses. An "alarm at 3am" stays distinct. Fusion ratio in testing: 35:1.

Reputation is gravity:

Mass = Count × Reputation²
Enter fullscreen mode Exit fullscreen mode

A thousand bot messages (rep 0.01) weigh less than one sensor heartbeat (rep 0.99). The system exhales crowd noise as waste heat.


Pluggable, not monolithic

Hermes connector: LLM agent memory via MCP (ingest_event, query_events).

Moltbook connector: AI agent social feed → events at moltbook://{submolt}/{author}.

Disable a connector — core still breathes. Modularity, not singleton.

Ops: browser WUI at api.indb.tech/wui/ or terminal TUI (./start_tui.sh).


Numbers we publish (v0.7 production)

  • <1ms ingestion (standalone)
  • 99.7% success under load (997/1000 events)
  • ~20ms Prism · <30ms Echo · ~25ms Instinct
  • 0 external databases in the stack
  • 6 wire protocols including MCP for agents

Raft 3-node cluster for self-hosters who want consensus — Docker Compose in docs.


Who is this for?

Not everyone. INDB is for systems where:

  • You need signed, tamper-evident history
  • You must prove presence without exposing content
  • Contradictions should be surfaced, not silently resolved
  • Identity verification must tolerate noise without abandoning axioms
  • AI agents need persistent interpretational memory, not another vector table bolted on

Legal evidence. Healthcare audit trails. Journalism source protection. IoT with UDP ingest and fusion. Agent memory (Hermes/MCP).


Try it in five minutes

# Health
curl https://api.indb.tech/health

# Inhale
curl -X POST https://api.indb.tech/api/v2/events \
  -H "Content-Type: application/json" \
  -d '{"raw_data_anchor":["devto","reader","hello"],"location":"blog/intro"}'

# Grain spectrum
curl https://api.indb.tech/api/v2/grain/tiers

# Swagger
open https://api.indb.tech/docs
Enter fullscreen mode Exit fullscreen mode

Links


We're building for truth in the age of manipulation. If your stack treats data as memory — not filing cabinets — we'd love to hear what you'd stress-test first.

Inhale the chaos. Exhale the noise. Remember the Axiom.

Top comments (0)