# Key rotation, fork и логические ссылки Этот документ фиксирует протокольную семантику fork. API-последовательность ротации описана отдельно в `docs/API/19_Key_Rotation_API.md`. ## 1. Идентичности - Пользователь: `login`. - Физическая ветка: `login-forkNumber` (`1..999`, формат имени строго три цифры: `001..999`; fork `1000` и выше запрещён). - Активный fork определяется текущим PDA. - Исторические fork остаются проверяемыми. ## 2. HEADER Block 0 новой пользовательской истории — `HEADER`: ```text SHiNE + login + initialBlockchainKey32 ``` `initialBlockchainKey32` — public blockchain-signing key fork №1. Это только историческая запись происхождения цепочки. При смене ключа сохранённый префикс, включая HEADER, перепубликуется с тем же Frame; поле остаётся исходным ключом и не сравнивается с текущим ключом fork. Текущий ключ конкретного fork определяется подписью/owner и PDA. ## 3. Внешний target Для REPLY, RATING, REPOST, LIKE/UNLIKE, CONNECTION, STATUS_ACTION: ```text [1] toLoginLen [N] toLogin UTF-8 [2] toForkNumber uint16 [4] toBlockGlobalNumber [32] toBlockHash32 ``` `toForkNumber` — информационная историческая метка: fork, на который смотрел автор действия. Допустимы только реальные fork `1..999`; `0` запрещён. Поле не участвует в identity и не должно сравниваться с текущим active fork как условие валидности. Логическая identity цели: ```text toLogin + toBlockGlobalNumber + toBlockHash32 ``` Если сохранённый префикс перепубликован в новом fork байт-в-байт, номер блока и SHA-256(Frame) совпадают, поэтому внешняя ссылка продолжает указывать на тот же логический блок. ## 4. Собственный edit EDIT_POST и EDIT_REPLY относятся только к собственному blockchain и используют: ```text [4] toBlockGlobalNumber [32] toBlockHash32 ``` Login/fork не хранятся. Целевой оригинальный блок должен существовать в текущей ветке с тем же hash. Блок, отброшенный rollback и отсутствующий в новом active fork, редактировать из новой ветки нельзя. ## 5. CONNECTION на пользователя Связь на пользователя всегда указывает на его реальный HEADER: ```text toLogin = target login toBlockGlobalNumber = 0 toBlockHash32 = SHA-256(target HEADER Frame) ``` Нулевой hash как sentinel запрещён. ## 6. Что переносится при fork Для сохранённого префикса Frame не меняется. Могут измениться внешняя ANS-104 подпись, owner/DataItem ID, но SHiNE block hash (`SHA-256(Frame)`) остаётся прежним. Поэтому `number + hash` является устойчивой частью ссылки. `toForkNumber` старого действия не переписывается после fork: это исторический факт момента создания действия. ## 7. Серверная модель Stage 2 Stage 2 больше не хранит physical target name как identity. `blocks_store` хранит физическую ветку как `(login, fork_number)`, а `reactions_state`, `message_stats`, `connections_state` и просмотры адресуют цель логически через `login + blockNumber + hash`. Поэтому при смене active fork никакого массового rebind `old_bch_name -> new_bch_name` не выполняется. Если `number + hash` сохранились после fork, внешние состояния продолжают относиться к той же цели автоматически. Если hash изменился после rollback, это новая логическая цель.