Контракты между сессиями
Каждая сессия правит только свой раздел. Ломающее изменение — новая версия + запись во «Входящие» другой сессии.
A →
B: C ABI ядра (kernel/crates/meridian-ffi,
include/meridian.h)
Версия: 0.4 (2026-10-04) — рендер документов и книги
Sheets работают; ABI MERIDIAN_ABI_VERSION = 1 (добавления
совместимы). v0.3 добавила оглавление, новый документ по локали и
pub const MERIDIAN_EMU_PER_POINT в Rust-части. Имена
совпадают с shell/src/kernel/meridian_render.h: без
заглушки он просто подключает meridian.h.
MeridianDoc— непрозрачный;meridian_doc_open(const char *path_utf8, MeridianDoc **out) -> int32_t(docx, формат по содержимому; MOP.mwx— с кодеком MOP),meridian_doc_new(MeridianDoc **out)(одна пустая страница),meridian_doc_free(MeridianDoc *)(NULL допустим);meridian_doc_page_count(const MeridianDoc *) -> uint32_t; страницы нумеруются с нуля;meridian_doc_page_size(doc, page, int64_t *w_emu, int64_t *h_emu) -> int32_t;MERIDIAN_EMU_PER_POINT= 12 700;meridian_doc_render_page(doc, page, float scale, uint8_t *rgba, uint32_t stride, uint32_t w, uint32_t h) -> int32_t: RGBA8888 premultiplied, sRGB,strideв байтах (≥ w×4), строки сверху вниз (=QImage::Format_RGBA8888_Premultiplied);scale— пикселей на пункт, 0 < scale ≤ 100; страница от (0,0), остаток буфера — белый;meridian_doc_export_pdf(doc, const char *path_utf8) -> int32_t— PDF/A-2b со слоем текста;meridian_doc_new_locale(const char *locale_bcp47, MeridianDoc **out)(v0.3) — пустой документ с бумагой по локали:ru-RU→ A4 с полями Word 3/1,5/2/2 см, другие A4-страны → A4 с полями 2,54 см,en-US/en/Канада/Мексика и т. п. → Letter; NULL или""— какmeridian_doc_new;meridian_doc_outline_count(doc) -> uint32_t,meridian_doc_outline_item(doc, i, *level, *page, buf, cap, *written)(v0.3) — оглавление для панели «Навигация»: уровень 1–9 (w:outlineLvl+ 1), страница с нуля, текст UTF-8 без NUL; мал буфер —MERIDIAN_E_ARGUMENT, но*level,*page,*writtenзаполнены;meridian_last_error(void) -> const char *— текст последней ошибки этого потока (UTF-8, до следующего вызова в потоке, не освобождать);- коды: 0 — успех;
MERIDIAN_E_IO−1,MERIDIAN_E_FORMAT−2,MERIDIAN_E_ARGUMENT−3,MERIDIAN_E_PAGE−4,MERIDIAN_E_PANIC−5 (паника ядра перехвачена, через границу не проходит); - потоки: документ можно рендерить из рабочего потока; вызовы для одного документа — последовательные;
- шрифты: комплект
kernel/fonts/(Liberation, Carlito) вшит в библиотеку, системные шрифты не нужны; - пример на C:
kernel/crates/meridian-ffi/examples/c/render_page.c, собирается и запускается тестомcargo test -p meridian-ffi --test c_example. - книги Sheets (v0.4) —
MeridianBook, свой движок формулmeridian-calcи свой xlsx:meridian_book_new(locale, **out)(один лист «Лист1»/«Sheet1»),meridian_book_open(path, locale, **out)(xlsx, пересчёт своим движком),meridian_book_save_xlsx(book, path)(значения, формулы, имена, числовые форматы),meridian_book_free; листы —sheet_count,sheet_name(book, sheet, buf, cap, *written),add_sheet(book, name|NULL, *index);used_range(book, sheet, *rows, *cols)(от A1, 0×0 — пусто); ячейки (лист, строка, столбец с нуля, предел ExcelMERIDIAN_MAX_ROWS×MERIDIAN_MAX_COLS):cell_text— текст для сетки по числовому формату в локали (1 234,50,ИСТИНА,#ДЕЛ/0!),cell_input— для строки формул (=СУММ(A1:A2;0,25),'007,04.10.2026),cell_value(*kind, *number)(MERIDIAN_CELL_*),set_input(book, sheet, row, col, text)— ввод как с клавиатуры в локали книги, затем пересчёт зависимых; ошибка в формуле —MERIDIAN_E_FORMAT, ячейка не меняется;set_format/cell_format— код Excel как в файле (#,##0.00,dd.mm.yyyy,0%; у «Общего»cell_formatотдаёт"", v0.4.1). Строки — вbuf/cap,*written— нужная длина (мал буфер —MERIDIAN_E_ARGUMENT, длина заполнена). Пример на C:examples/c/book.c(тот же тестc_example). Прежние функцииmeridian_version*,meridian_abi_version,meridian_document_*(заготовка текста) сохранены.
B → A: токены дизайна
(spec/design-tokens.json)
Формат W3C DTCG; генерация в QML-синглтон и CSS — у B. A использует только для цветов отрисовки служебных элементов (выделение, курсор) через FFI-параметры.
B → A: API
лицензий (kernel/crates/meridian-license)
Features::has(Feature::X) — единственная точка проверки
редакции. Ядро (A) не проверяет лицензии само; оболочка (B) передаёт в
ядро набор включённых функций при открытии документа (будущий параметр
FFI). Файл .mlic v1 (2026-10-04, B5):
meridian_license::SignedLicense::decode →
verify(&verifier, &TrustedKeys) →
LicenseDocument → to_license() для проверок
сроков; формат — детерминированный CBOR, подпись Ed25519 над
"MOFC-LIC-v1" ‖ payload, ключи подписи по строковому
key_id (mo-lic-<8hex>). Выпускает
license-service (moffice-api.24oros.ru — стенд с тестовыми
ключами).
A → B:
формат пакета MOP (docs/04-file-formats.md,
spec/formats/)
Владелец формата — A; изменения схем отражаются в
spec/formats/ через запрос B (владелец
spec/).
B → A:
шифрование пакетов MOP (kernel/crates/meridian-crypto)
Версия формата: 1 — spec/formats/mop-encryption.md
(нормативно), векторы
spec/formats/vectors/mop-encryption-v1.json. Крейт не знает
о ZIP и модели документа: кодек MOP (A) собирает контейнер из трёх
записей — mimetype =
meridian_crypto::ENCRYPTED_MIME (stored, первая),
package.bin (stored), encryption.xml.
- запись:
meridian_crypto::seal(plain_package: impl Read, package_bin: impl Write, password, &SealOptions::new(inner_mime)) -> Sealed { header, recovery_code };encryption.xml=header.to_xml()(готов после потока — писать послеpackage.bin); - чтение:
EncryptionHeader::from_xml(bytes)?→open(&header, package_bin, plain_out, Unlock::Password(pw))(илиUnlock::RecoveryCode); оболочка может держатьFileKeysизunlock()и читать повторноopen_with_keys(); - смена пароля без перешифровки:
change_password(&header, old, new, &kdf) -> EncryptionHeader; - ошибки —
CryptoError::code()(CRYPTO_WRONG_PASSWORD,CRYPTO_HEADER_TAMPERED,CRYPTO_CORRUPTED, …). Открытый текст пишется вplain_outтолько после проверки тега чанка; при ошибке результат не использовать.