Feature и Machine
Как несколько проверенных Feature составляют CAP Machine без смены её State и Trace authority.
Feature и Machine
Feature — единица авторства Capkin. Machine — исполняемая граница CAP:
она владеет State, допустимыми Transition и последовательным Trace. Новый
локальный профиль feature-module-v1 позволяет описать несколько Scenario в
одном Feature и собрать непересекающиеся Scenario нескольких Feature в одну
Machine. Один Feature может затронуть разные Machine; общего Trace от этого
не возникает.
Feature: Приём сервисной заявки
# @profile:feature-module-v1
# @feature:CAPKIN-FEATURE-SERVICE-INTAKE
# @registry:CAPKIN-FEATURE-INTAKE-CASE-001
Scenario: CAPKIN-FEATURE-INTAKE-CASE-001
Given machine ServiceCase initial New
And principal Office
And capability Office may commit OpenCase
And capability Office may evaluate OpenCase
And capability Office may commit CaseOpened
Given Office commits OpenCase
When Office evaluates guard CaseReady
Then the machine transitions from New to Open
And Office may commit CaseOpened
And the trace proof verifies every commitmentFeature: — читаемое название. # @feature: — стабильный ID источника;
# @registry: связывает точный ID Scenario. Given machine ... initial ...
задаёт Machine и её начальное State для каждого Scenario. Остальные шаги
используют ту же закрытую семантику, что machine-v1. Неизвестная фраза
отклоняется.
cargo run -p cap-cli --bin capkin -- feature-assemble \
--file fixtures/feature-module-v1/intake.feature \
--file fixtures/feature-module-v1/assignment.featureОтвет tyapkin-feature-assembly-v1 содержит Feature ID и title, Machine
contracts, CAP IR digests и происхождение каждого Scenario: Feature ID,
Scenario ID и SHA-256 исходника. Порядок файлов не меняет результат.
Пересечение (Machine, from State, Input), разные initial State для одной
Machine, повторные ID и неверные Principal/Capability блокируют всю сборку.
Разные Guard не разрешают владеть одним маршрутом одновременно.
Этот результат — локальная проверенная сборка; он сам по себе не даёт
права автора изменять Machine. Точный набор источников выбирает вызывающая
сторона; approval владельца Machine и release policy проверяются отдельно.
Runtime исполняет
обычный Machine IR через decide и verify_trace; неподготовленный Input
получает отказ. Между Machine нужен отдельный Flow profile, если требуется
причинный переход Output → Input.
Проверенная локальная публикация
Rust API FeaturePackageStore принимает tyapkin-feature-package-v1 с
точными исходниками, SHA-256 каждого source, сборкой и Machine IR digest,
версиями профиля/компилятора, exact closure расширений и решением владельца
для каждой Machine. Перед записью SQLite он повторно компилирует исходники,
сверяет все digest, установленные bytes расширений и вызывает предоставленный
хостом FeatureOwnerAuthority. Один текст approved в пакете права не даёт.
Один ID/version принимает только одни и те же bytes; при повторном чтении
проверки выполняются снова. Это отдельный формат: старые
tyapkin-contract-package-v1…v6 не перезаписываются.
tyapkin-feature-package-v2 дополнительно закрепляет точные опубликованные
TypeRef и Flow refs вместе с транзитивными imports. Публикация получает
read-only ContractStore, сверяет bytes/digest всех зависимостей,
проверяет TypeRef в type index и Flow как экспорт проверенной декларации.
Оба Flow endpoint должны соответствовать Output и Input собранных Machine.
Совпадение именованных портов ещё не доказывает совместимость полей:
schema binder и release preflight проверяются отдельно. V1 продолжает
читаться без новых полей и без ContractStore.
Новый opt-in tyapkin-feature-package-v3 добавляет для опубликованного
flow-v1 проверку связанного tyapkin-port-binding-ir-v1. Source/target
payload TypeRef должны быть явно закреплены в dependencies; binder сверяет
их protobuf descriptor, message, поле, тип, cardinality и покрытие всех
полей target Input с проверенным Flow. V2 остаётся прежним профилем без
этой гарантии. Для CEL и других Flow ABI нужен отдельный binder profile;
его отсутствие приводит к отказу v3, а не к пропуску проверки.
Опциональный tyapkin-feature-package-v4 требует явные установленные
профили protobuf TypeRef, exact imports и каждого Flow root. Его binder
проверяет flow-v1 field-copy и flow-cel-v1/flow-cel-v2: expression,
engine, causation и поля source/target TypeRef проходят повторную проверку
перед публикацией и чтением. Неподдерживаемый профиль, отсутствующий модуль
или изменённый digest приводят к отказу. flow-v2 пока не имеет binder в
Feature v4. Этот срез не меняет CAP kernel и прежние package bytes.
Проверенный локальный consumer bundle Allium закреплён на более раннем
Tyapkin source и поддерживает v1–v3; v4 ещё не активирован в Allium.
Это Rust API с отдельным локальным crate bundle для потребителя Allium.
Bundle содержит упакованные crates, offline Cargo source и независимую
conformance-проверку; это не опубликованный registry SDK и не process ABI.
Сборка, SHA-256 pin и откат описаны в
docs/runbooks/tyapkin-consumer-bundle.md.
Тестовый owner verifier подтверждает только поведение интерфейса; реальный
trust root и активацию release должен предоставить host. В
feature-module-v1 не содержит межпакетных imports: v2 dependency manifest
явно добавляется при публикации, а не исполняется как новый Step.
Теперь FeaturePackageStore::describe[_with_dependencies] перечитывает
пакет через те же проверки и отдаёт типизированную read-only проекцию
tyapkin-feature-describe-v1: Feature, Scenario, Machine, маршруты,
Input/Output, owner decision ID и exact dependencies. Уровень evidence
явно говорит published-checked и not-observed; исполнение и доставку
показывает отдельно host. Для TypeRef и Flow dependencies предусмотрены
namespaced sections (tyapkin.type-ref.v1, tyapkin.flow.v1); их
отсутствие у старого package означает пустой набор, а не ошибку.
Публичный Rust FeaturePublisherV1 выполняет immutable publication через
host authority. FeatureConsumerV1::check_sources предварительно собирает
Feature без проверки package dependencies; затем publisher проверяет их при
публикации. describe, decide и verify_trace используют точный
FeatureMachinePinV1. Pin содержит
формат, package ID/version/digest, Machine ID и IR digest. Перед каждым
решением и проверкой Trace consumer перечитывает опубликованный пакет и
повторно сверяет зависимости и owner decision. Он возвращает CAP результат
вызывающему host; хранение checkpoint и Output intentions остаётся за host.
Независимый crate bundle собирается командой pnpm build:consumer:bundle и
проверяется в чистом Cargo checkout без path dependency на Tyapkin. Ошибки
фасада возвращают FeatureConsumerErrorV1 с машинным code; текст ошибки
предназначен только для диагностики. Wire schema для удалённого Allium host
этот artifact не вводит.
Старый machine-v1 сохраняет правило Feature == MachineId и один Scenario.
Новый профиль выбирается явно и не меняет старые source, IR или Trace.
Локальное демо
pnpm demo:capkin:federation открывает существующий браузерный стенд Tyapkin.
Первый блок «Feature → Machine» читает два fixture Feature, вызывает Rust
feature-assemble и показывает связь каждого Scenario с маршрутом Machine.
Кнопка запуска заставляет Rust runner заново прочитать те же source bytes,
принять один Input для Asset и два последовательных Input для ServiceCase,
затем проверить обе полные цепочки через verify_trace. UI сверяет digest
исполненного IR с отображённой сборкой. Запись Playwright сохраняет видео,
trace, screenshot и JSON результата. Ниже в том же стенде остаются старые
закреплённые Flow releases как отдельная проверка совместимости.
Guard evidence этого примера локально синтетический. Браузерное демо
исполняется в процессе и сохраняет JSON проверки; оно пока не вызывает
FeaturePackageStore, не пишет SQLite для этих двух Machine и не делает
межмашинную доставку.