В любой записи в базу зашито допущение: у факта одно значение. Два несовпадающих наблюдения об одном объекте — конфликт, который положено разрешить до коммита, и разрешается он UPDATE. Пока данные генерирует ваш же код, допущение верное.

Ломается оно на наблюдениях. Сенсоры расходятся в показаниях, и оба показания настоящие. Агент пишет о состоянии файла, который человек уже поправил руками. Два источника сообщают разное, и разрешить противоречие в момент записи нечем — контекст, в котором одно из них весит больше, появляется только в момент вопроса.

INDB стоит на этом: смысл производится при чтении, а не фиксируется при записи. Вместо CRUD три фазы — вдох (Inhale, принять сырое наблюдение), выдох (Exhale, сжать повторы и отфильтровать шум репутацией), аксиома (Axiom, подписать то, что выжило).

Событие вместо строки

Миграций нет, есть универсальный Event. Заполнить в нём обязательно два поля: токены-сигналы raw_data_anchor и место location. id и timestamp система ставит сама, остальное опционально — ttl, temporal_metadata для временных фильтров, source_id со ссылкой на реестр источников, blind_payload, binary_payload, счётчик слияний fusion_count с флагом is_fused и signature, если событие подписано клиентом.

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}'

Это «что, где, когда, от кого, насколько часто». Нужно сорок колонок — вы проектируете архив, а не память, и это другой инструмент.

Восемь типов вместо шестидесяти

Система типов классической СУБД в основном описывает раскладку на диске и в памяти, а не смысл: int2 против int4 — калибр, varchar(n) против text — исторический артефакт. Планировщику нужно, интерпретации нет, а платится миграциями.

Восемь типов INDB отвечают не на «как это лежит», а на «что с этим делать движку»:

Тип INDB

Зачем он в системе типов

Покрывает типы PG

number

По нему модули считают арифметику и дистанцию; диапазон в min/max, а не в имени типа

smallint, integer, real, double precision, numeric, money, serial

blind

Непрозрачность проверяема протоколом только когда она свойство типа, а не соглашение прикладного слоя

bytea + pgcrypto с самописной обвязкой

bigint

Наносекунды и криптозначения не влезают в float64, а округление здесь портит доказательство

bigint, numeric для целых, bit varying

string

Из него Echo набирает токены и гармоники; ограничение длины — в схеме поля, не в типе

char, varchar, text, xml, tsvector, tsquery

null

Prism различает «не наблюдали» и «наблюдали пусто», иначе perception_gap считается по выдумке

NULL с трёхзначной логикой

struct

Внешние payload приходят вложенными как есть; валидация рекурсивная, без миграции

json, jsonb, hstore, композитные, домены

binary

Форма нужна для квот, TTL и транспорта; содержимое интерпретировать незачем

bytea, large objects

location

Половина веса в Echo: пространство участвует в выводе, а не доживает в WHERE

point, line, box, polygon, circle, PostGIS geometry/geography

Тип выводится сам: словарь с lat/lonlocation, сырые байты — binary, вложенный словарь — struct. DDL нет.

Платите контролем над раскладкой байтов, индексами под конкретный числовой тип и точной десятичной арифметикой. Банковский леджер на этом не строят.

Модули, которые читают смысл

Раз смысл не записан, его кто-то должен произвести на чтении. Этим занимаются модули интерпретации, и все они read-only: в хранилище не пишет никто из них, писать умеют только Inhale и Fusion.

Prism — контекстный синтез вокруг seed-события. Собирает облако смысла из токенов и локации, считает significance_score (редкие токены весят больше, плюс коэффициент кластеризации по локации и fusion_count) и вешает context_labelObjective Data, Pattern, Anomaly или Background. Возвращает не только вывод, но и уверенность в нём с конкурирующими прочтениями.

Echo — резонанс. Строит гармонический отпечаток якоря из множества токенов, эмоциональной классификации и метаданных локации, затем оценивает каждое событие в памяти по формуле 0.20 × токены + 0.30 × эмоции + 0.50 × мета и отдаёт то, что прошло порог 0.3.

Instinct — тот же вопрос с ручкой адреналина 0.0–1.0. На нуле аналитический режим с глубоким разбором токенов и уверенностью около 10%, на 0.5 alert (~46%), на единице чистый рефлекс по метаданным (~82%). Поверх работают триггеры: совпадение локации даёт +0.7 к уверенности, подпись владельца +0.5, критические токены +0.3.

Deduction — вывод цепочками. По набору seed-событий и запросу в заданном радиусе достраивает связи и выдаёт заключение вместе с самой цепочкой, а не только итог.

Subwave — горизонтальный бродкаст. Echo пускает волну по плоскости токенов, локации и времени, Subwave настраивает достижимые узлы на одну частоту — подпись якоря плюс опциональный модификатор, — и те, что залочились (lock = W_res × resonance + W_tok × token_alignment + W_fac × factor_alignment), образуют связный кадр в resonance_edges.bin. Пересчитывать всю память не нужно, отвечают только узлы с реальной массой.

Slice и What-if — сдвиг облака модификатором: смысл движется, якоря стоят, исходные события не меняются. What-if это базовый запрос плюс slice, и в режиме core он работает без LLM — арифметика по графу, модель нужна максимум для пересказа.

Lens — Triple-Half: два контекста смешиваются в заданной пропорции, 90/10 в пользу свежего для алертинга, 10/90 для долгих закономерностей. Один корпус, разные ответы.

Место как индекс

location принимает логический путь (books/Dostoevsky/The_Idiot) или OSM-объект с координатами и валидируемым osm_id для node/way/relation. Один тип вместо геометрического зоопарка и PostGIS сверху.

Те самые 50% веса в Echo — это оно: на наших данных место оказалось сильнейшим предиктором связи между наблюдениями, сильнее и токенов, и эмоциональной окраски. Расстояние считается по гаверсинусу; несколько osm:-токенов в одном событии Fusion штрафует, иначе всё склеивается по географическому совпадению.

API, который спрашивает, а не выбирает

Эндпоинты названы глаголами памяти, потому что отвечают не на те вопросы, что SELECT. POST /events — это Inhale, поток append-only: ни UPDATE, ни DELETE по событию не существует в принципе, изменить прошлое нечем. POST /interpret не забирает данные, а запрашивает перспективу: контекст и цель решают, какие воспоминания всплывут первыми. GET /search считает гармоническую близость вместо LIKE '%текст%'.

Отдельно про парадокс, потому что слово в контексте БД звучит туманно. Парадокс в INDB — не баг и не исключение валидации, а явно зафиксированное состояние двух видов: либо есть факт наблюдения объекта, но нет данных о содержимом, либо два подписанных источника выдают взаимоисключающие сигналы и оба имеют право. POST /paradox заводит такой контекст с пустым raw_data_anchor, пока никто не наблюдал, в отдельном хранилище, а не флагом на событии; на чтении та же ситуация видна как is_paradoxical от Prism.

Чем то же самое приходится делать в обычном стеке:

Глагол INDB

Собирается сейчас из

POST /events

INSERT плюс апсерт-логика дедупликации и запрет на UPDATE дисциплиной команды

POST /interpret

SELECT + прикладной ранжировщик + реранкинг результатов RAG

POST /lens/query

два запроса с разными временными окнами и смешивание весов в коде

GET /search

LIKE/tsvector либо внешний вектор-стор с cosine

POST /subwave/broadcast

рекурсивный CTE или отдельная графовая БД рядом

POST /slice

копия данных, UPDATE в транзакции, ROLLBACK

POST /what-if

промпт к LLM поверх выборки, без воспроизводимости

POST /paradox

строка с NULL и флагом «ещё не наблюдали» в прикладном коде

POST /grain/verify

подпись, N-of-M кворум и статистика — три библиотеки и клей между ними

Транспорт — HTTP, GraphQL, WebSocket, gRPC, UDP, MCP. Внешних баз в ядре нет: ни Redis, ни Postgres, ни Mongo.

TUI: всё то же самое без curl

Наблюдать это из curl неудобно, поэтому в поставке есть полноэкранная консоль на Textual — подключается к живому API, по умолчанию к продовому, INDB_API_URL переключает на локальный узел или балансировщик:

cd db && ./start_tui.sh
python3 -m cli.indb_cli tui --api http://localhost:8888
docker compose --profile tools run --rm tui
┌──────────────────────────────────────────────────────────────────────────┐
│  INDB                          https://api.indb.tech · clock             │
│  [████████░░░░] Loading Events…                                          │
├──────────────────────────────────────────────────────────────────────────┤
│ Control │ Events │ Modules │ Cluster │ Query │ Analytics │ Scripts       │
├──────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│                     [ active tab content ]                               │
│                                                                          │
├──────────────────────────────────────────────────────────────────────────┤
│  q Quit   r Refresh   e Events   m Modules   p Query   a Analytics  …    │
└──────────────────────────────────────────────────────────────────────────┘

Семь табов, переключение цифрами и буквами (e события, p запросы, a аналитика, s скрипты, r обновить всё). Control держит total events, процент fusion-сжатия, статус сервера и CPU/RAM, плюс кнопки Run Tests, Run Audit и Restart — локально; в контейнере они скрыты. Events — живой поток с клиентским фильтром и серверным /api/v2/search, где помечает слитые события. Cluster опрашивает /health и /raft/status по каждому узлу и показывает, кто лидер и на каком term.

Главное там — Query Lab: все когнитивные вызовы из предыдущего раздела с полями вместо JSON-тела. Interpret ходит как Neutral | books/Bible/KJV | peace, Echo Resonate принимает UUID, скопированный из таба Events, рядом Prism Synthesize и Instinct с адреналином 0.0–1.0, Lens, Deduction, What-If, Context Slice, Paradox Create/Read и Recovery Identity по key_id. Отдельный таб Scripts гоняет против живого API integrity check, explore_db, audit_protocols, analyze_books и проверку интеграции с Hermes, стримя stdout в лог.

Тот же набор есть в браузере как WUI, если терминал не ваш способ смотреть на систему.

Ответ, который признаёт, что не уверен

Prism возвращает основное прочтение и рядом alternative_readings — конкурирующие версии сохраняются. perception_gap от 0 до 1 мерит неоднозначность, от 0.25 поднимается is_paradoxical. Противоречие — сигнал, а не ошибка валидации.

has_unread_essence включается при наличии blind_payload: вывод построен по токенам, но у события есть закрытая часть.

У Grain четыре вердикта вместо true/false: verified, likely_same_origin, insufficient_signal, rejected. Ради insufficient_signal всё и делалось — двадцать токенов не дают статистического доказательства, и честнее сказать «сигнала недостаточно», чем натянуть уверенность.

Каждый ответ опечатан Ed25519 серверным ключом: проверяет кто угодно, включая недоверяющую сторону. В транзите не подменить, задним числом не переписать.

Подпись с двух сторон

Ответы сервера подписаны всегда — приватный ключ в env, публичный отдаётся открыто. События подписывает клиент локально и по желанию: ключ не уезжает с устройства, его нет ни в теле запроса, ни в логах, ни в recovery API. UDP-телеметрию подписывать дорого и незачем, юридически значимое наблюдение — обязательно.

signed и valid в ответе разделены: «не подписано» и «подпись не проходит» — разные факты.

Идентичность — key_id = SHA-256(public_key). На нём держится восстановление: приватного ключа, seed и общего секрета в протоколе нет.

«Мы не читаем ваши данные» — политика, а политика меняется вместе с владельцем компании. Подпись не меняется.

Blind: аналитика без доступа к содержимому

Шифруете на клиенте, INDB получает непрозрачный блоб, репликует по Raft и возвращает по запросу, ни разу не прочитав: ключа на сервере нет.

Содержимое не попадает в поиск, логи, WUI и TUI, и движок не знает, что два блоба хранят одно и то же — одинаковый текст с разными nonce даёт разные блобы. Заодно отваливается корреляционная атака «эти двое хранят одинаковое», на которой строится половина деанонимизации.

Место, время, открытые токены, источник с репутацией, частота и паттерн обращений при этом видны полностью — Prism, Echo, Instinct, Deduction и Fusion работают по метаданным на всю глубину. Больница ищет корреляции по ["pain","chest","night"] и локации clinic/cardiology, а имя пациента, диагноз и текст заметок лежат в blind_payload и невидимы для её собственной инфраструктуры.

Сверху Black Box Contract, который проверяется протоколом:

Вы можете скрыть, что внутри. Вы не можете скрыть, что вы здесь были.

С blind_payload обязательны непустой location и timestamp в пределах ±5 минут от серверного — иначе можно подсунуть старое перехваченное событие. На любой запрос система отвечает одно: «Что-то здесь было. Это место. Это время.»

И сразу про границу доверия, которая у этой схемы одна:

Client Trust Boundary. Всё, что гарантирует INDB, кончается на вашем устройстве. Сервер блоб не прочитает и ключ не держит, но клиентский код обязан не утащить ключ в логи, крашрепортер или аналитический SDK — за этой чертой мы ничего доказать не можем.

Grain: любая верификация — это сигнал в шуме

Строгий Ed25519 — уровень штрихкода, шума не терпит вообще. Для аксиом правильно, для памяти нет: цитаты бывают частичными, экспорт бьётся, поверхность меняется. Штрихкод, QR, биометрия подписи и водяные знаки вроде SynthID лежат на одной оси устойчивости к шуму, каждый в своей точке — Grain держит всю ось в одном модуле ядра:

Тир

Аналог

Устойчивость

Механизм

exact

штрихкод EAN-13

~0–5%

Ed25519 / key_id

redundant

QR (Reed–Solomon)

~30%

N-of-M кластер подписанных событий

resonant

рукописная подпись

~30–50%

Echo × репутация источника

statistical

SynthID

p-value

отпечаток распределения n-грамм

tier: auto выбирает тир по доступным доказательствам, tolerance крутит FAR/FRR.

curl https://api.indb.tech/api/v2/grain/tiers

В ядре, а не четырьмя SDK: внешний инструмент проверяет изолированный артефакт, Grain — внутри того же конвейера, который принимает, сливает и репликует, с репутацией в момент верификации.

Fusion: память растёт в интеллекте, а не в размере

Повторение — не данные, а паттерн. Три ["home","arrived"] сливаются в одно с fusion_count: 3, а ["alarm","triggered"] в три ночи остаётся отдельной аксиомой. Дедупликация семантическая, DBSCAN, сжатие на тестовых данных 35:1. Быстрый повторный ингест штрафуется, иначе вес сигнала накачивается флудом.

Репутация работает как гравитация:

Mass = Count × Reputation²

Тысяча ботов с репутацией 0.01 даёт массу 0.1, один подписанный сенсор с 0.99 — массу 0.98. Отсюда Reality Guard: 10 000 сообщений «сервер лежит» против одного heartbeat «работает» дают «конфликт данных», и аксиома стоит.

Где это нужнее всего

У агентных систем есть простой: пользователь молчит, лимиты свободны, система не делает ничего. Индустрия предлагает заполнять его саморефлексией — мета-агент читает логи, критик судит воркера, LLM переписывает себе промпты. Не работает: модели с разными паттернами контекста мешают друг другу, координатор сверху даёт тот же испорченный телефон, только дороже по токенам. И главное — рассинхронизация: агент предложил, человек поправил руками и не сказал, агент живёт со своим слепком, контекст оперирует контекстом вместо среды. LLM-критик смотрит на тот же искажённый контекст, который ошибку и породил.

Работает детерминированная сверка состояния с фактами, и модель INDB подходит сюда структурно.

В активном режиме всё летит событиями, а не лентой чата: агент вызвал инструмент → событие, человек поправил файл → событие с более высоким весом источника, API вернул 500 → событие. У каждого место (файл, путь, hermes://…), время и источник с репутацией, ничего не перезаписывается.

В простое ядро делает Exhale: Fusion сжимает повторы и обесценивает неподтверждённые ветки, Echo ищет диссонанс с текущим состоянием места, Deduction находит обрыв цепочки, Prism считает perception_gap, Slice гоняет контрфактуал, не загрязняя основную память. На выходе не новый промпт от агента, а срез: в src/api.py после правки человеком в 14:32 цепочки агента от 14:28 помечены устаревшими, perception_gap = 0.87, обрыв причинной цепочки на событии X.

Это не RAG: векторный кэш при правке файла не знает, что мир изменился, а здесь инвалидация идёт по месту, детерминированно и с подписью. Коннектор — Hermes через MCP. Код в проде INDB не патчит и промпты без человека не переписывает: находит точку рассинхронизации и отдаёт срез правды.

Цифры

Standalone: ингест <1ms, запрос <10ms на тысяче событий. Модули — Prism ~20ms, Echo <30ms, Instinct ~25ms, Deduction <50ms. Кластер из трёх узлов — 99.7% успеха (997 из 1000), латентность 50–250ms, ноль перевыборов лидера за пятиминутный прогон.

Устойчивый throughput кластера — 19–28 событий в секунду. Не опечатка, а цена синхронных коммитов Raft: нужны десятки тысяч вставок — берите профильное решение.

Коэффициенты «прироста качества/стоимости» для LLM x1.25–x1.75 с лендинга — полевые оценки по нашим прогонам, а не воспроизводимый бенчмарк на публичном датасете. Читайте как порядок величины.

Кому подойдёт, а кому нет

Подойдёт, где нужна подписанная история, устойчивая к подделке; где надо доказать присутствие, не раскрывая содержимое; где противоречия показывают, а не схлопывают; где верификация должна терпеть шум. Конкретно — юридические доказательства, медицинские аудит-трейлы, защита источников, IoT с UDP-ингестом, память агентов через MCP.

Не подойдёт при CRUD со стабильной предметной областью: берите Postgres.

Заменой PostgreSQL это не будет, категория другая. И это не open source: ядро проприетарное, API, документация и архитектурные гарантии открыты, self-host через Docker Compose работает. Для части читателей — стоп-фактор, и это нормально.

indb.tech