Tyapkin
Runtime

Переносимая граница CAP

Канонический Machine IR, чистые decide/verify и границы доверия.

Переносимая граница CAP

Tyapkin задаёт протокол Machine, Principal, Capability, State, Input, Guard, Transition, Output, Commitment и Trace. protocol-core предоставляет чистые Rust-операции CapIrV1::from_contract, decide и verify_trace: они не открывают БД, не вызывают адаптеры и не знают coffee/printing. Хост может встроить эту библиотеку в процесс или обернуть её сервисом/worker. Wire DTO описаны в proto/cap/v1/decision.proto; transport в этом срезе не реализован.

Capkin source -> MachineContract -> CapIrV1 + digest
                                  -> decide(checkpoint, claims) -> commitments + new checkpoint
                                  -> verify_trace(checkpoint, commitments) -> verified checkpoint

CapIrV1 фиксирует структуру Machine, а не опубликованный package: manifest, схемы Input, adapter bindings и QA cases должны получать отдельный digest пакета. Host приложения в Allium закрепляет свой package digest и вызывает decide/verify_trace через версионированную границу. Форматы старого aggregation evidence и их совместимый reader принадлежат Allium.

Канонические байты

IR v1: CAP-IR-v1\0, затем machine_id, initial_state; затем массивы principals, capabilities, states, guards, transitions, outputs в этом порядке. Строка — UTF-8 с длиной u32 big endian; массив — число элементов u32 big endian. Массивы сортируются по полному кортежу полей; дубли и неоднозначные переходы отклоняются. CapabilityOperation: Commit=1, Evaluate=2. Для Transition кортеж: (from_state, input_type, guard_id, to_state); для Output: (principal_id, output_type, allowed_state). Digest — SHA-256 ровно этих байтов. Нормализация Unicode и пробелов не выполняется.

Commitment v2: CAP-COMMITMENT-v2\0, затем length-prefixed trace_id, machine_id, principal_id, один байт типа (Capability=1, Input=2, Guard=3, Transition=4, Output=5), sequence как u64 big endian, затем optional state_before, state_after, input_type, guard_id, output_type. Optional кодируется байтом 0 или байтом 1 и обычной строкой. Далее идут 32 сырых байта payload_hash и optional previous_commitment_hash как строка. SHA-256 этих байтов записывается строчными hex; ID имеет префикс cap:v2. Время, payload_ref, подписи, refs и protobuf wire bytes в этот hash не входят.

Старое строковое кодирование cap:v1 не меняется. Для новых решений v2 отличает, например, поля a|b/c от a/b|c, которые давали одинаковый v1 hash input. Общие векторы лежат в fixtures/protocol/portable-v1-v2.txt; Rust и Node вычисляют их независимо через pnpm test:protocol:conformance.

Decide и Verify

decide принимает digest IR, доверенный checkpoint с тем же IR digest, ожидаемую голову и утверждения Input, Guard, Transition и Output. Он проверяет Capability, совпадение Input/Guard, допустимый Transition, State и Output. Положительное утверждение Guard приводит к записям Input -> Guard -> Transition -> Output*; отрицательное или ошибка не выдаёт частичный результат. Output — намерение, не доказательство исполнения. expected_head сравнивается с переданным checkpoint; хост обязан загрузить его из своего авторитетного хранилища и проверить актуальность в той же транзакции, где сохраняет commitments, новый checkpoint и доменные данные.

verify_trace переигрывает эту последовательность от доверенного checkpoint, проверяет поля, Capability, State, sequence, v2 ID и hash chain. Он может проверить сегмент из нескольких завершённых решений. Сам checkpoint должен быть получен из доверенного хранилища либо проверенного предшествующего Trace: verify_trace не доказывает происхождение подставленной головы.

Внешний host устанавливает личность Principal, вычисляет предметный Guard, подписывает/удостоверяет evidence, исполняет Output и фиксирует Observation. Хеш Guard.evidence_hash лишь связывает переданное утверждение с Trace. Структурно верный Trace не доказывает истинность Guard, подлинность Principal, доставку сообщения или существование внешнего исполнителя. Локальная запись NotifyRequester остаётся локальным Observation.

Текущие пределы

  • DecisionRequest принимает один булев Guard verdict; отрицательное утверждение отклоняет шаг, не формируя отдельный outcome Transition. Составные Guards и graph evidence ports описаны в следующем этапе kernel.
  • Core допускает массив Output claims, но локальный Capkin action/host пока создаёт не более одного Output intent. Внешнего ExecutionReceipt protocol и durable outbox нет.
  • Публичный интерфейс реализован как Rust-библиотека; сервис, Node binding и worker будут адаптерами над теми же типами и conformance vectors.
  • Proto задаёт DTO, но генерация клиентов и сетевой endpoint пока не включены.
  • v2 decision не порождает отдельный CapabilityCommitted: Capability проверяется и выводится из Machine. Старые v1 записи этого типа продолжают проверяться старым путём; v2 verifier принимает только форму решения выше.
  • Нет протокольной подписи, trust registry, распределённой финальности и аутентификации. Это отдельные интерфейсы и будущие решения.

On this page