montana/Монтана-Протокол/Код/AUDIT.md

470 lines
48 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Montana Reference Implementation — Audit Package
**Spec target:** Montana v35.23.0 (2026-05-02) — см. [VERSION.md](VERSION.md)
**Last verified:** 2026-05-02 (M1-F + M2 + M3 + M4 + M5 audit prep + M6 transport closure + critic-fix bundle 13 findings + Phase C.0-C.4 e2e two-node communication)
**Audit-ready status:** **M1 + M2 + M3 + M4 + M5 layers — READY FOR EXTERNAL AUDIT** (13 крейтов, ~11190 LOC, 255 invariants, 40/40 findings closed: 20 internal + 8 external #3 (M3-A-1..M3-A-5 + F-5 + AUDIT-sync) + 2 external #3 VERIFIED (P-C-1 F-19 reopen + P-C-2 audit history) + 10 external #4 (M4-MED-1/2 + M4-LOW-3..7 + M5-LOW-8 + M4-INFO-10) + spec v33→v34 monetary refactor + spec v34 → v35.3.2 patch series)
---
## TL;DR — что готово к внешнему аудиту
| Layer | Готов? | Крейты | LOC | Tests + invariants | Open findings |
|-------|--------|--------|-----|---------------------|---------------|
| **M1 foundational** (cryptography + identity recovery) | ✅ **READY** | mt-codec, mt-crypto, mt-crypto-native, mt-mnemonic | ~2000 | 100+ unit + 13 security + 51 NIST KAT byte-exact | 0 (12/12 closed) |
| **M2 state foundation** (consensus state primitives) | ✅ **READY** | mt-merkle, mt-genesis, mt-state, mt-timechain | 1821 | 95+ unit + 60 determinism invariants | 0 (4/4 closed) |
| **M3 apply_proposal layer** (account operations + emission + state transition) | ✅ **READY** | mt-account | 2556 | 89 unit + 29 determinism invariants | 0 (3/3 internal closed: M3-1/M3-2/M3-3 + 10/10 external #3+VERIFIED closed: M3-A-1..M3-A-5 / F-5 / M3-A-3 / AUDIT-sync / P-C-1 F-19 reopen / P-C-2 history; M2-3/M2-13 superseded v34 monetary refactor) |
| **M4 consensus mechanics** (lottery + proposal acceptance + node admission) | ✅ **READY** | mt-lottery, mt-consensus, mt-entry | 3858 | 187 unit + 85 determinism invariants | 0 (1/1 internal closed: M4-1; 7/7 external #4 closed: M4-MED-1/2 + M4-LOW-3..7 + M4-INFO-10) |
| **M5 persistence** (filesystem state + proposal archive + crash recovery) | ✅ **READY** | mt-store | 955 | 27 unit + 17 determinism invariants | 0 (manual scan clean; v34 monetary refactor удалила MonetaryState persistence) |
| **Cross-implementation conformance** | ✅ **READY** | Domain registry sync (spec ↔ code, см. VERSION.md) | — | NIST ACVP 66 byte-exact (KeyGen 50 + SigGen 15 + ctx-equivalence 1) + Recovery flow | 0 (F-1 spec patch closed) |
| **M6 network layer** (wire format + transport + IBT + Dandelion + mesh + SF) | ✅ **READY** | mt-net, mt-net-transport | ~3300 | 110 unit + 14 transport (включая 3 e2e two-node) | 0 (P-C1..P-C8 critic-fix bundle закрыт) |
| **M9 conformance suite** | ✅ **READY** | mt-conformance | ~150 | 2 unit byte-exact verify | 0 (envelope A1-A3 + PoW F1-F2 + IBT B1) |
| **M7 Fast Sync** | ⏳ TODO | mt-sync | — | — | (не реализовано) |
| **M8 Node binary** (montana-node SPEC_DEVIATIONS rewrite) | 🔄 in progress | montana-node | ~600 | partial | DEV-001..009 open |
**Audit firm engagement:** возможен прямо сейчас на полный scope **M1 + M2 + M3 + M4 + M5 + M6** (15 крейтов = 13 предыдущих + mt-net + mt-net-transport + mt-conformance). M7 Fast Sync + M8 montana-node binary — defer to отдельной audit фазы.
**iOS application audit:** см. отдельный package `iOS/Apps/Montana/AUDIT.md` — Phase 2 in progress, требует Phase 2.1+ implementation (4-6 недель) перед external firm engagement.
---
---
## TL;DR — M6 Phase C closure (2026-05-02)
**mt-net-transport** (~470 LOC) — libp2p-based transport layer:
- `src/codec.rs` — MontanaCodec для libp2p request-response с MAX_PROTOCOL_PAYLOAD_BYTES enforcement (Genesis Decree authoritative bound)
- `src/behaviour.rs` — MontanaBehaviour wrapper (request-response для FastSync/PeerList/BatchLookup/RangeSubscribe; one-way gossip — Phase C.5+)
- `src/transport.rs` — build_swarm() helper с TCP→TLS 1.3 (rustls)→Noise→Yamux upgrade chain
- `src/ibt_upgrade.rs` — classify_proof() для access level determination (Node/Candidate/Account)
- `tests/e2e_two_node_handshake.rs` — Manual Validation Gate scenario 6 PASS (Ping/Pong через full transport chain)
- `tests/e2e_proposal_exchange.rs` — scenario 7 PASS (synthetic Proposal payload + 512 KiB boundary test)
**mt-conformance** (~150 LOC) — M9 standalone test vectors crate для cross-implementation verification:
- VectorEnvelope (A1/A2/A3 byte-exact)
- VectorIbtSeed (B1 после P-C2 rename mt-tunnel→mt-tunnel-online)
- VectorPow (F1/F2 target derivation)
- Public API: `all_envelope_vectors()`, `all_pow_vectors()`, `ibt_b1_online_proof()`
**Capability checklist [C-5] для libp2p 0.56.0:** 8/8 PASS (TCP+TLS 1.3+Noise+Yamux+Swarm primitives; async tokio; rustls + snow constant-time; Linux+macOS+Windows; IPFS+Filecoin+Polkadot 5+ years production; MIT/Apache 2.0; ~120 transitive deps acceptable за изоляцию через own crate).
---
## 1. Audit Chain
Hybrid Rust + C architecture для cryptography (M1). Pure Rust для state foundation (M2). Three layers, each auditable independently.
### M1 — Foundational cryptography + identity recovery
#### Layer 1 — Rust shim (own audit responsibility)
| Crate | Path | Lines (exact) | Scope |
|-------|------|---------------|-------|
| `mt-codec` | [crates/mt-codec/src/lib.rs](crates/mt-codec/src/lib.rs) | ~290 | Canonical encoding traits + Domain separators registry (32 domains, sync с актуальным spec target из VERSION.md byte-exact). Все consensus hash compositions через explicit domain separator + NUL byte (`SHA-256(domain ‖ 0x00 ‖ parts)` self-delimiting per P1 external finding). |
| `mt-crypto` | [crates/mt-crypto/src/lib.rs](crates/mt-crypto/src/lib.rs) | **662** | Public API: `PublicKey`, `SecretKey`, `Signature`, `Mlkem*`, `keypair_from_seed`, `keypair_from_seed_mlkem`, `sign`, `verify`, `hash`, `sha256_raw`. `CryptoError` enum + `Result<_, CryptoError>` API. **Heap-allocated SK через `Box<[u8; N]>` + `mlock` против swap-out + `Drop+zeroize`** для secret types. Все **7** `unsafe` blocks с `// SAFETY:` комментариями: 4 FFI sites (`keypair_from_seed`, `sign`, `verify`, `keypair_from_seed_mlkem`) + 3 mlock/munlock (`Drop for SecretKey`, `alloc_locked_secret_box`, `Drop for MlkemSecretKey`). Test-only `keypair()` через OS CSPRNG (`getrandom`). |
| `mt-crypto-native` (Rust binding) | [crates/mt-crypto-native/src/lib.rs](crates/mt-crypto-native/src/lib.rs) | 49 | `extern "C"` декларации FFI к Layer 2. Только `pub const` константы и FFI signatures, никакой логики. Включает `mt_sign_mldsa_ctx` для FIPS context support. |
| `mt-mnemonic` | [crates/mt-mnemonic/src](crates/mt-mnemonic/src) | 937 | 24-word mnemonic recovery flow: PBKDF2-HMAC-SHA-256 (iter=2²⁰), HKDF-Expand per-role derivation, ML-DSA seed (32B) + ML-KEM seed (64B) generation. Wordlist binding SHA-256 verified. |
#### Layer 2 — Own thin C wrapper (own audit responsibility)
| File | Lines (exact) | Scope |
|------|---------------|-------|
| [crates/mt-crypto-native/csrc/mt_crypto.c](crates/mt-crypto-native/csrc/mt_crypto.c) | 457 | Wrapping OpenSSL EVP_PKEY API: `mt_keypair_from_seed_mldsa`, `mt_keypair_from_seed_mlkem`, `mt_sign_mldsa`, `mt_sign_mldsa_ctx` (FIPS context support), `mt_verify_mldsa`, `mt_self_test`. Использует `OSSL_PKEY_PARAM_ML_DSA_SEED` (FIPS 204 §3.1 ξ ∈ B³²) и `OSSL_PKEY_PARAM_ML_KEM_SEED` (FIPS 203 §6.1 d ‖ z, 64B) для deterministic KeyGen. `OSSL_SIGNATURE_PARAM_DETERMINISTIC=1` для FIPS 204 Algorithm 2 deterministic Sign. |
| [crates/mt-crypto-native/csrc/mt_crypto.h](crates/mt-crypto-native/csrc/mt_crypto.h) | 67 | C API declarations + размеры primitives + 13 status codes (1 success + 12 errors). |
| [crates/mt-crypto-native/build.rs](crates/mt-crypto-native/build.rs) | 45 | Vendored OpenSSL build через `openssl-src`, `cc::Build` с `-Wall -Wextra -Wpedantic -Werror`, cross-compile корректность через `CARGO_CFG_TARGET_OS`. |
**Total own audit surface (Layer 1 + Layer 2): 1280 lines** (662 Rust shim + 49 FFI bindings + 457 C wrapper + 67 C header + 45 build script). Verify counts:
```
cd "<repo-root>" && wc -l crates/mt-crypto/src/lib.rs crates/mt-crypto-native/src/lib.rs crates/mt-crypto-native/csrc/mt_crypto.c crates/mt-crypto-native/csrc/mt_crypto.h crates/mt-crypto-native/build.rs
```
#### Layer 3 — Underlying production C library (vendor audit responsibility)
| Component | Version | Source | Audit history |
|-----------|---------|--------|---------------|
| OpenSSL | 3.5.5 LTS | [openssl-src 300.5.5+3.5.5](https://crates.io/crates/openssl-src) — vendored, byte-pinned exact version | OpenSSL Foundation governance, FIPS 140-3 validated, decades production deployment в TLS world (Apache HTTP, nginx, OpenSSH, Linux kernel, …), supported до **April 2030** (LTS) |
**Layer 3 НЕ в нашем audit scope** — auditor проверяет только наш способ использования OpenSSL EVP API (Layer 2), не реализацию самих ML-DSA/ML-KEM/SHA-256.
### M2 — State foundation (audit-ready 2026-04-26)
| Crate | Path | Lines | Scope | Audit findings |
|-------|------|-------|-------|----------------|
| `mt-merkle` | [crates/mt-merkle/src/lib.rs](crates/mt-merkle/src/lib.rs) | 474 | Sparse Merkle Tree (depth 256), `empty_internal()` precomputed cache (OnceLock), `leaf_hash`/`internal_hash` (SHA-256 domain-separated через mt-codec::domain), `SparseMerkleTree::insert/root` через `BTreeMap` для canonical iteration order, `verify_proof` для inclusion + absence proofs. **0 unsafe blocks. 0 panic!. 0 f32/f64. 0 SystemTime/RNG. BTreeMap не HashMap.** | Pass 1-12 clean (manual scan); 10 automated determinism invariants |
| `mt-genesis` | [crates/mt-genesis/src/lib.rs](crates/mt-genesis/src/lib.rs) | **353** | Genesis Decree + `ProtocolParams` SSOT (4094B encoded), `genesis_app_id()` (SHA-256 domain-separated), `genesis_params()` через `OnceLock` (singleton, thread-safe), `compute_genesis_state_hash()`. Const `emission_moneta = 13 × 10⁹ nɈ` per spec v34+. **0 unsafe. 0 panic. Только read-only constants + deterministic hash.** | Pass 1-12 clean; automated determinism invariants |
| `mt-state` | [crates/mt-state/src/lib.rs](crates/mt-state/src/lib.rs) | **647** | AccountTable (2059B records) / NodeTable (2098B) / CandidatePool (2082B) через `BTreeMap<id, Record>` + `SparseMerkleTree`, `derive_account_id` / `derive_node_id` (SHA-256 domain-separated), `compute_state_root` (SHA-256 of node_root ‖ candidate_root ‖ account_root), `is_active` predicate. **0 unsafe. 0 panic! 0 HashMap (BTreeMap canonical sort). 0 f64.** | Pass 1-12 clean; automated determinism invariants |
| `mt-timechain` | [crates/mt-timechain/src/lib.rs](crates/mt-timechain/src/lib.rs) | 347 | TimeChain VDF (`vdf_step` = SHA-256^d, `vdf_verify` re-computes), `next_d` Adaptive D через participation-ratio feedback (integer permille per [I-9]), `cemented_bundle_aggregate(W, node_ids)` per [I-8] Network-Bound Unpredictability (3 ветви: genesis 0×32, empty marker, sorted node_ids hash). **0 unsafe. 0 panic. 0 HashMap. 0 f64. Все integer арифметика per [I-9].** | Pass 1-12 clean; 19 automated determinism invariants |
**Total M2 audit surface:** 1821 lines code + 60 automated determinism invariants.
### M3 — apply_proposal layer (audit-ready 2026-04-27)
| Crate | Path | Lines | Scope | Audit findings |
|-------|------|-------|-------|----------------|
| `mt-account` | [crates/mt-account/src/lib.rs](crates/mt-account/src/lib.rs) | **2556** | 4 user opcodes (`Transfer 0x02` / `ChangeKey 0x03` / `Anchor 0x04` / `TransferActivation 0x0A`) с byte-exact canonical encoding (TRANSFER_SIZE / CHANGE_KEY_SIZE / ANCHOR_SIZE / TRANSFER_ACTIVATION_SIZE). `validate_*` для каждого opcode (full validation per spec table). `apply_*` с **checked arithmetic** (`checked_sub`/`checked_add` + descriptive panic для protocol invariant breach). `op_hash` через R2 SHA-256(`mt-op` ‖ signed_scope), signature excluded. `settle_window(cemented_ops)` сортирует по `op_hash` lex asc. `apply_proposal` orchestrates Steps 2/3.5/3.6/4 (steps 1, 3a, 3b stubbed → M4 mt-entry). `apply_emission` зачисляет `EMISSION_moneta` (const) operator-у winner-узла. `reward_moneta(params) = params.emission_moneta`, `supply_moneta(W) = emission × (W+1)` closed-form. `build_genesis_state` + `genesis_state_root` для bootstrap. **0 unsafe. 0 panic! без `protocol invariant` justification. 0 HashMap. 0 f64. 0 SystemTime.** | Pass 1-12 clean; automated determinism invariants |
**Total M3 audit surface:** 2556 lines code + 29 automated determinism invariants.
### M4 — Consensus mechanics (audit-ready 2026-04-27)
| Crate | Path | Lines | Scope | Audit findings |
|-------|------|-------|-------|----------------|
| `mt-lottery` | [crates/mt-lottery/src/lib.rs](crates/mt-lottery/src/lib.rs) | **1715** | BundledConfirmation R1/R2 (signed_scope + bundle_hash через `mt-bundle` domain), VdfReveal R1/R2 (`mt-vdf-reveal` domain), `compute_endpoint` lottery formula (`mt-lottery` domain) с [I-8] cemented_bundle_aggregate(W-2) binding, validate_bundle/validate_reveal с full structural + signature verification, `log2_q64` (Q64.64 fixed-point integer log с degree-3 Remez minimax polynomial, max error 2^-10.62, binding coefficients B0..B3), `ln_q64`, `weighted_ticket_node` u128 integer division, `determine_winner` argmin canonical rule (ticket asc, class asc, id lex asc), `quorum` 67% ceiling integer formula `(67×X+99)/100`, `is_cemented`. **0 unsafe. 0 panic!. 2 controlled `expect()` (try_into на slice длины 16 — protocol invariant). 0 HashMap. 0 f64. 0 SystemTime.** | M4-1 closure (Vec.len() as u16 silent truncation → BundleError::TooManyOps/TooManyReveals + validate cap + debug_assert defense-in-depth); 34 automated determinism invariants |
| `mt-consensus` | [crates/mt-consensus/src/lib.rs](crates/mt-consensus/src/lib.rs) | **1089** | ProposalHeader R1/R2 (3722 B fixed-size, 17 полей, signed_scope без signature, `mt-proposal` domain), validate_header (a-f структурные правила: fallback_depth ≥ 1, window_index = prev+1, protocol_version monotone + ≤ local_max, proposer registered + Mldsa65 suite, signature verify), canonical_proposer / fallback_proposer (Lookback Leadership: proposer_W = winner_{W-2}; genesis bootstrap; cascade by depth), compute_control_set (filter cemented_window > prev AND ≤ W, sort by (window asc, op_hash lex asc)), validate_proposer_is_canonical / validate_bundles_threshold / validate_included_reveals / validate_winner (Canonical acceptance), finalization_status (Cemented/Rejected per is_cemented), leader_penalty_excluded_node. **0 unsafe. 0 panic. 0 prod unwrap/expect. 0 HashMap. 0 f64. 0 SystemTime.** | Pass 1-12 clean (manual scan); 27 automated determinism invariants |
| `mt-entry` | [crates/mt-entry/src/lib.rs](crates/mt-entry/src/lib.rs) | **1054** | NodeRegistration R1/R2 (5344 B, opcode 0x11, `mt-nodereg` domain), validate_noderegistration (3 структурные правила: suite supported, signature verify, node_id unique в Node Table + Candidate Pool, operator account exists + не is_node_operator), `candidate_vdf_init` per [I-8] (`mt-candidate-vdf-init` domain composing T_r + cba(W-2) + node_id), `compute_expiry_window` 3τ₂, `apply_candidate_expiry` (apply_proposal Step 3a), selection_slots (1% cap через ADMISSION_DIVISOR=130), `selection_sort_key` (`mt-selection` domain), rank_candidates_for_selection (canonical sort), `apply_selection_event` (apply_proposal Step 3b: insert into Node Table + mark operator + remove from Candidate Pool), `required_vdf_length` (Adaptive VDF integer permille per [I-9]), `nr_sort_key` (`mt-nodereg-sort` domain), `apply_noderegistrations_batch` (apply_proposal Step 1: incremental sort+apply с pending growth). **0 unsafe. 0 panic. 0 prod unwrap/expect. 0 HashMap. 0 f64.** | Pass 1-12 clean; 24 automated determinism invariants |
**Total M4 audit surface:** 3858 lines code + 85 automated determinism invariants. Domain separators: `mt-bundle`, `mt-vdf-reveal`, `mt-lottery`, `mt-proposal`, `mt-nodereg`, `mt-candidate-vdf-init`, `mt-selection`, `mt-nodereg-sort` — все consensus-critical hash compositions через canonical domains (per [I-8] + [I-10] SSOT).
### M5 — Persistence (audit-ready 2026-04-27)
| Crate | Path | Lines | Scope | Audit findings |
|-------|------|-------|-------|----------------|
| `mt-store` | [crates/mt-store/src/lib.rs](crates/mt-store/src/lib.rs) | **955** | Filesystem-backed state persistence (pure std::fs, без RocksDB/sled — minimum deps): `FsStore::open` (создаёт `proposals/` subdirectory), save/load AccountTable / NodeTable / CandidatePool через canonical_encode/decode pair (round-trip byte-exact verified), Proposal archive (`proposals/{window:020}.bin`, `archive_proposal` + `get_proposal_by_window` byte-exact decode), Crash recovery (`meta_last_cemented.bin` u64 LE; `verify_consistency` проверяет что meta-указанный proposal существует в archive — иначе StoreError::NotFound), Pruning (`prune_proposals_before` удаляет файлы window < threshold). Все decode_X функции проверяют `bytes.len() != EXPECTED_SIZE` ДО чтения (StoreError::CorruptedLength). **0 unsafe. 0 panic. 0 prod unwrap/expect. 0 HashMap. 0 f64.** | Pass 1-12 clean; automated determinism invariants |
**Total M5 audit surface:** 955 lines code + 17 automated determinism invariants.
**M3 + M4 + M5 orchestration ordering** (важно для каллера):
1. M3: `settle_window(account_table, cemented_user_ops, window_w)` apply cemented user ops к state
2. M4: `apply_noderegistrations_batch` (Step 1) `apply_candidate_expiry` (Step 3a) `apply_selection_event` (Step 3b) node admission flow
3. M3: `apply_proposal(account_table, node_table, candidate_pool, input, params)` Steps 2 (emission) 3.5 (chain_length++) 3.6 (checkpoint rotation) 4 (state_root)
4. M5: `archive_proposal(header)` `save_meta_last_cemented(window)` `save_account_table` / `save_node_table` / `save_candidate_pool` persist на disk
Settle разделено от apply_proposal (M3 design choice); steps 1/3a/3b делегированы M4 mt-entry. M5 finalization атомарность через meta-pointer pattern (если crash между archive и meta verify_consistency detects).
**M3 apply_proposal orchestration ordering** (важный invariant для каллера):
1. `settle_window(account_table, cemented_user_ops, window_w)` apply cemented ops к state (Transfer/Anchor/ChangeKey/TransferActivation) **ДО** apply_proposal
2. `apply_proposal(account_table, node_table, candidate_pool, input, params)` Steps 2 (emission) 3.5 (chain_length++) 3.6 (checkpoint rotation) 4 (state_root)
Settle разделено от apply_proposal по design orchestration ordering invariant виден каллеру explicitly, скрытие в одной функции рискует silent fork. Документировано в module-level comment перед `pub fn apply_proposal`.
---
## 2. Conformance Proofs
### NIST FIPS 204/203 byte-exact conformance (M1)
**66 differential test cases** vs NIST CAVP ACVP-Server published vectors:
| Test | Source | Cases | Status |
|------|--------|-------|--------|
| ML-DSA-65 KeyGen byte-exact | [NIST ACVP-Server](https://github.com/usnistgov/ACVP-Server) `gen-val/json-files/ML-DSA-keyGen-FIPS204` | 25 | PASS |
| ML-KEM-768 KeyGen byte-exact | [NIST ACVP-Server](https://github.com/usnistgov/ACVP-Server) `gen-val/json-files/ML-KEM-keyGen-FIPS203` | 25 | PASS |
| ML-DSA-65 SigGen deterministic external pure (1 empty + 14 non-empty context, 0..255B) | [NIST ACVP-Server](https://github.com/usnistgov/ACVP-Server) `gen-val/json-files/ML-DSA-sigGen-FIPS204` tgId=3 | **15** | PASS |
| `mt_sign_mldsa` `mt_sign_mldsa_ctx` (empty ctx) equivalence | own correctness check | 1 | PASS |
**Reproduction:**
```
cd "<repo-root>" && cargo test -p mt-crypto-native --test nist_acvp_kat -- --nocapture
```
**Fixtures location:** [crates/mt-crypto-native/tests/fixtures/nist_acvp/](crates/mt-crypto-native/tests/fixtures/nist_acvp/)
### SHA-256 NIST FIPS 180-4 conformance (M1)
| Test | Source | Status |
|------|--------|--------|
| SHA-256("abc") == ba7816bf...15ad | FIPS 180-4 §B.1 | PASS (in `mt-crypto/src/lib.rs::tests::hash_nist_vector_abc`) |
### Internal correctness baselines (M1)
| Test | Path | Status |
|------|------|--------|
| ML-DSA-65 zero-seed deterministic baseline | [crates/mt-crypto-native/tests/regression_baselines.rs](crates/mt-crypto-native/tests/regression_baselines.rs) | PASS |
| ML-KEM-768 zero-seed + ones-seed deterministic baselines | same | PASS |
| ML-DSA-65 sign roundtrip + tamper detection | same | PASS |
| 5 mt-mnemonic KAT vectors (entropy mnemonic master_seed per-role keypair) | [crates/mt-mnemonic/tests/keygen_vectors.rs](crates/mt-mnemonic/tests/keygen_vectors.rs) | PASS |
| End-to-end recovery flow (entropy identity round-trip) | [crates/mt-mnemonic/tests/e2e_recovery.rs](crates/mt-mnemonic/tests/e2e_recovery.rs) | PASS |
| `mt_crypto::self_test()` (KeyGen determinism + Sign/Verify + KAT 1 byte-exact conformance check) | [crates/mt-crypto/src/lib.rs](crates/mt-crypto/src/lib.rs) | PASS |
### Security invariants (M1, Pass 17 enforcement через automated tests)
Regression detection для security-critical properties если будущий рефакторинг ломает invariant, тест fails в CI ДО merge.
| Invariant | Test | Status |
|-----------|------|--------|
| `SecretKey: !Clone` (no accidental copies) | [crates/mt-crypto/tests/security_invariants.rs](crates/mt-crypto/tests/security_invariants.rs)::secret_key_is_not_clone | |
| `MlkemSecretKey: !Clone` | same::mlkem_secret_key_is_not_clone | |
| `SecretKey: !PartialEq` (no timing leak via ==) | same::secret_key_no_partial_eq_to_prevent_timing_leak | |
| `MlkemSecretKey: !PartialEq` | same::mlkem_secret_key_no_partial_eq_to_prevent_timing_leak | |
| `SecretKey` heap-allocated (size = pointer) | same::secret_key_is_heap_allocated | |
| `MlkemSecretKey` heap-allocated | same::mlkem_secret_key_is_heap_allocated | |
| `SecretKey` имеет Drop impl | same::secret_key_needs_drop | |
| `MlkemSecretKey` имеет Drop impl | same::mlkem_secret_key_needs_drop | |
| FFI fills SK с non-zero bytes | same::secret_key_filled_by_ffi_keygen | |
| FFI fills MlkemSK с non-zero bytes | same::mlkem_secret_key_filled_by_ffi_keygen | |
| No `println!`/`log::*` macros на SK bytes в lib коде | same::no_println_or_log_on_secret_bytes_in_lib_code | |
| `PublicKey: Clone` (sanity public material clone-able) | same::public_key_can_be_cloned | |
| `Signature: Clone` (sanity) | same::signature_can_be_cloned | |
**13/13 security invariants PASS.**
### Determinism invariants (M2 — все 4 crates)
Automated regression detection per [I-3] determinism + [I-9] integer arithmetic + [I-10] SSOT + [I-8] Network-Bound Unpredictability.
| Crate | Test file | Cases | Status |
|-------|-----------|-------|--------|
| `mt-merkle` | [tests/determinism_invariants.rs](crates/mt-merkle/tests/determinism_invariants.rs) | 10 | PASS (empty_internal determinism + level uniqueness, leaf/internal hash determinism, internal_hash order-sensitivity, SMT empty root + insertion-order-independent root, root-changes-on-insert, type sizes) |
| `mt-genesis` | [tests/determinism_invariants.rs](crates/mt-genesis/tests/determinism_invariants.rs) | 7 | PASS (genesis_app_id determinism, genesis_params singleton stable pointer, ProtocolParams encoded size constant + encoding determinism, compute_genesis_state_hash determinism + dependence on state_root, SSOT singleton consistency) |
| `mt-state` | [tests/determinism_invariants.rs](crates/mt-state/tests/determinism_invariants.rs) | | PASS (derive_account_id / derive_node_id determinism + dependence + cross-distinctness, ACCOUNT/NODE/CANDIDATE_RECORD_SIZE matches encoded, encoding determinism, AccountTable/NodeTable/CandidatePool insertion-order-independent root, compute_state_root determinism + order-sensitivity + dependence на каждый input root, is_active boundary at 2×τ inclusive + saturating_sub safety, WINNER_CLASS_NODE SSOT, empty tables consistent root, insert/remove inverse) |
| `mt-timechain` | [tests/determinism_invariants.rs](crates/mt-timechain/tests/determinism_invariants.rs) | 19 | PASS (vdf_step zero=identity + determinism + dependence на iterations и prev, vdf_verify accept/reject correct/wrong claim/iteration count, vdf_chain composition associative, next_d dead-zone unchanged + above-high-increases + below-low-decreases + determinism, cemented_bundle_aggregate window<2 = genesis zero, empty marker distinct from non-empty, change-on-window/node_ids, **canonical sort input-order independence per [I-8]**) |
**60/60 M2 invariants PASS.**
### Spec ↔ Code byte-exact alignment (M0+M1+M2)
Verified per critic audit (commit `9387900`):
| Проверка | Spec value | Code value | Status |
|----------|-----------|-----------|--------|
| ML-DSA-65 pubkey size | 1952B | `PUBLIC_KEY_SIZE = 1952` | |
| ML-DSA-65 secretkey | 4032B | `SECRET_KEY_SIZE = 4032` | |
| ML-DSA-65 signature | 3309B | `SIGNATURE_SIZE = 3309` | |
| ML-DSA-65 seed | 32B | `KEYPAIR_SEED_SIZE = 32` | |
| ML-KEM-768 ek | 1184B | `MLKEM_PUBLIC_KEY_SIZE = 1184` | |
| ML-KEM-768 dk | 2400B | `MLKEM_SECRET_KEY_SIZE = 2400` | |
| ML-KEM-768 seed | 64B (dz) | `MLKEM_SEED_SIZE = 64` | |
| AccountRecord size | 2059B | `ACCOUNT_RECORD_SIZE = 2059` | |
| NodeRecord size | 2098B | `NODE_RECORD_SIZE = 2098` | |
| CandidateRecord size | 2082B | `CANDIDATE_RECORD_SIZE = 2082` | |
| ProposalHeader size | 3722B | `PROPOSAL_HEADER_SIZE = 3722` | |
| ProtocolParams size | 4094B (spec v34) | `PARAMS_ENCODED_SIZE = 4094` | |
| Sparse Merkle Tree depth | 256 | `TREE_DEPTH = 256` | |
| Emission pin | 13 Ɉ const per окно | `emission_moneta = 13_000_000_000` | |
| Domain registry sync (32 domains) | spec list | code mt-codec const list | |
### Security Cards per crypto primitive (M1)
Каждый primitive с secret material имеет detailed Security Card в [docs/security-cards.md](docs/security-cards.md). Cards covered:
| Primitive | Card | Status |
|-----------|------|--------|
| `SecretKey` (ML-DSA-65) | Card 1 8/8 Pass 17 checks closed | closed |
| `MlkemSecretKey` (ML-KEM-768) | Card 2 8/8 closed | closed |
| `keypair_from_seed` (ML-DSA KeyGen) | Card 3 heap+mlock+stack hygiene closed | closed |
| `keypair_from_seed_mlkem` (ML-KEM KeyGen) | Card 4 heap+mlock+stack hygiene closed | closed |
| `sign` (ML-DSA-65 deterministic) | Card 5 8/8 closed | closed |
| `verify` (ML-DSA-65) | Card 6 no secret material, minimal card | closed |
---
## 3. Threat Model & Scope Boundaries
### In scope — что аудитор должен проверить
**M1 — cryptography + identity:**
1. **FFI memory safety** Layer 1 `unsafe` blocks (4 sites), buffer sizes, pointer validity
2. **OpenSSL EVP API misuse** параметры EVP_PKEY_CTX_set_params, error handling, EVP_DigestSignInit determinism flag
3. **Secret hygiene** `Drop+zeroize` для `SecretKey`/`MlkemSecretKey`, no `Clone`/`Copy` на secret types, no leak в logs/dumps, **heap-allocated bytes (Box) с mlock** против swap-out, **stack hygiene** FFI пишет напрямую в heap-allocated locked Box, никаких stack temporary buffers с secret bytes (см. [docs/security-cards.md](docs/security-cards.md) Cards 1-6)
4. **Result API correctness** `sign`/`keypair_from_seed` corruption resistance: malformed SK через `from_array(arbitrary_bytes)` `Err(CryptoError::InvalidSecretKey)`, не panic
5. **Deterministic semantics** FIPS 204 Algorithm 2 deterministic Sign correctly invoked via `OSSL_SIGNATURE_PARAM_DETERMINISTIC=1` (consensus determinism per Montana [I-3])
6. **Recovery flow correctness** mnemonic master_seed (PBKDF2-HMAC-SHA-256) per-role HKDF derivation byte-exact reproducible identity (Montana spec sections "Ключи Мнемоника и seed", "Per-role key derivation")
7. **Cross-compile correctness** build.rs использует `CARGO_CFG_TARGET_OS` env var (не `cfg!(target_os)`)
8. **Reproducible builds** Docker container с pinned base image (`debian:bookworm-slim@sha256:40b107342c492725bc7aacbe93a49945445191ae364184a6d24fedb28172f6f7`), byte-identical между независимыми runs (CI gate `reproducible_release`)
**M2 — state foundation:**
9. **Sparse Merkle Tree correctness** empty_internal level uniqueness + cache consistency + verify_proof для inclusion + absence proofs
10. **Genesis Decree SSOT** ProtocolParams singleton consistency, encoded size invariance под struct changes, frozen constants
11. **State table determinism** BTreeMap canonical sort guarantee для AccountTable / NodeTable / CandidatePool, insertion-order-independent state_root
12. **Account/Node ID derivation** SHA-256 domain-separated через mt-codec::ACCOUNT / ::NODE registry, cross-distinctness same pubkey
13. **Monetary policy correctness** const emission `reward_moneta = EMISSION_moneta = 13 × 10⁹ nɈ` per spec «Эмиссия», closed-form `supply_moneta(W) = EMISSION_moneta × (W + 1)`
14. **TimeChain VDF correctness** vdf_step composition associativity, vdf_verify byte-exact against re-computed chain
15. **Adaptive D feedback** next_d dead-zone semantics + integer permille arithmetic per [I-9]
16. **cemented_bundle_aggregate per [I-8]** Network-Bound Unpredictability через canonical sort node_ids + window binding, защита от input-order grinding
### Out of scope — НЕ предмет этого аудита
1. **OpenSSL internal correctness** вне scope; ответственность OpenSSL Foundation. Аудитор может предположить FIPS 204/203 Algorithm 1/2/16 implementations OpenSSL корректны (audited+deployed at scale)
2. **Consensus protocol correctness M3-M5** отдельные layers (mt-account, mt-consensus, mt-lottery, mt-entry, mt-store) internal-tested 255+ tests green, но не audit-prepared (TODO для следующих audit phases)
3. **Network protocol** M6+ (mt-net не существует)
4. **Application layer** отдельный workspace в будущем (Juno agent, messaging, файловое хранилище)
5. **Hardware side-channel attacks** software-only assumption; embedded deployment audit отдельный
### Known limitations (deferred с обоснованием)
0. **Genesis bootstrap ceremony pending** (M2-1 finding из external audit Claude Opus 4.7 #2) 4 поля `ProtocolParams` хранят placeholder zeros и финализируются только при Genesis ceremony перед mainnet:
- `bootstrap_account_pubkey: [0u8; PUBLIC_KEY_SIZE]`
- `bootstrap_node_pubkey: [0u8; PUBLIC_KEY_SIZE]`
- `target_zero: [0u8; 32]` (initial VDF target)
- `genesis_content_data_hash: [0u8; 32]`
**Severity:** блокер mainnet, **НЕ блокер аудита кода**. Layout / encoding / SSOT / singleton корректны и audit-ready. Финализация = выбор seed, генерация keypairs через `mt_crypto::keypair_from_seed`, безопасное хранение privkey (multi-party ceremony либо single trusted party design decision автора).
**Programmatic check:** `mt_genesis::is_genesis_bootstrap_finalized(params) -> bool` для operator deployment scripts. Test `bootstrap_keypairs_finalized` остаётся `#[ignore]` до ceremony, после ceremony снимается ignore. Pre-ceremony test `is_genesis_bootstrap_finalized_pre_ceremony_returns_false` явно фиксирует текущее состояние.
**Closure path:** Genesis ceremony plan отдельный milestone в `ROADMAP.md` перед mainnet.
1. **Sign with non-empty context** текущий `mt_sign_mldsa` API не принимает context parameter, использует empty context (соответствует Montana usage pattern, но не FIPS 204 full API surface). NIST ACVP cases с context bytes (14/15 в external pure deterministic group) не проверяются. Closure path: расширить FFI signature, когда понадобится FIPS context support (M6+).
2. **Verify NIST KAT** отдельный test set для FIPS 204 SigVer не добавлен в этой session (sign-baseline + sign-NIST KAT byte-exact match косвенно подтверждает Verify correctness через round-trip, но direct Verify NIST KAT остаётся как enhancement).
3. **ML-KEM-768 Encapsulate/Decapsulate NIST KAT** текущий M1-F scope только KeyGen (Encapsulate/Decapsulate понадобятся в M6+ application layer encryption). NIST KAT для encapDecap имеется в fixtures dir, тесты добавляются когда понадобится.
---
## 4. Build & Reproduction
### Toolchain
```
rustc 1.70+ (pinned via rust-toolchain.toml)
Cargo workspace
OpenSSL 3.5.5 LTS (vendored через openssl-src)
```
### Optional security audit tooling (для Step H verification)
```
cargo install cargo-audit --locked
```
Один раз на audit machine. После команда `cargo audit` доступна.
### Build from source
```
cd "<repo-root>"
cargo build --all --release
```
Все 4 обязательные проверки CI:
```
cargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all
cargo build --all --release
```
### Reproducible release build (Docker)
**Prerequisites:** Docker 20.10 installed and running, ~30 минут wall-clock для двух clean builds, ~5 GB free disk.
```
docker build --file docker/release-build.dockerfile --tag montana-release:audit .
```
CI gate `reproducible_release` (см. [.github/workflows/ci.yml](.github/workflows/ci.yml)) выполняет два независимых build с `--no-cache`, asserts byte-identity hashes на каждом push в main. Auditor может верифицировать через CI history без локального запуска (избегая Docker prerequisite).
### Run audit-relevant tests
**M1 NIST ACVP KAT (cross-implementation conformance):**
```
cd "<repo-root>" && cargo test -p mt-crypto-native --test nist_acvp_kat -- --nocapture
```
**M1 Internal correctness baselines:**
```
cd "<repo-root>" && cargo test -p mt-crypto-native --test kat_independent -- --nocapture
cd "<repo-root>" && cargo test -p mt-crypto -- --nocapture
cd "<repo-root>" && cargo test -p mt-mnemonic --test keygen_vectors -- --nocapture
cd "<repo-root>" && cargo test -p mt-mnemonic --test e2e_recovery -- --nocapture
```
**M1 Security invariants (Pass 17):**
```
cd "<repo-root>" && cargo test -p mt-crypto --test security_invariants -- --nocapture
```
**M2 Determinism invariants:**
```
cd "<repo-root>" && cargo test -p mt-merkle --test determinism_invariants -- --nocapture
cd "<repo-root>" && cargo test -p mt-genesis --test determinism_invariants -- --nocapture
cd "<repo-root>" && cargo test -p mt-state --test determinism_invariants -- --nocapture
cd "<repo-root>" && cargo test -p mt-timechain --test determinism_invariants -- --nocapture
```
**Полный M1+M2 audit chain:**
```
cd "<repo-root>" && cargo test -p mt-codec -p mt-crypto-native -p mt-crypto -p mt-mnemonic -p mt-merkle -p mt-genesis -p mt-state -p mt-timechain
```
---
## 5. Audit History
| Date | Audit | Findings | Closure |
|------|-------|----------|---------|
| 2026-04-27 | **Spec bump v33.1.6 → v34.0.0** major monetary policy refactor (geometric step-up baseline const linear emission) | Architectural simplification, не security audit findings | ProtocolParams удалены 4 поля (`r_genesis_moneta`, `monetary_epoch_windows`, `inflation_num`, `inflation_den`) + добавлен `emission_moneta: u128 = 13×10⁹ nɈ`. PARAMS_ENCODED_SIZE 4118 4094. mt-state удалена `MonetaryState` struct + carry-recurrence machinery. mt-account `apply_emission` упрощён: `reward = params.emission_moneta` const, `monetary_epoch_tick` удалён. `supply_moneta(W) = E × (W+1)` closed-form O(1) eliminates class of bugs (epoch boundary off-by-one, carry overflow). 288/288 affected tests PASS. Driver: упрощение audit surface для production firm engagement. |
| 2026-04-27 | **External audit #4 Claude Opus 4.7 (1M context)** incremental M4+M5 scope (mt-lottery, mt-consensus, mt-entry, mt-store) independent SHA-256 oracle (Python hashlib) cross-check 4 hash compositions + ad-hoc ln_q64 mathematical verification (T141253) | 10 findings (0 CRITICAL/HIGH, 2 MEDIUM, 5 LOW, 3 INFO); score **8.5/10**; 325/325 M4+M5 tests PASS под single-core/single-process | **All 10 findings closed конструкцией.** Commits: `cb81d4c` M4-MED-1 window_index u32u64 unification (spec v33.1.4v33.1.5), `f46d48a` M4-LOW-7 3 hardcoded const ProtocolParams [C-1] SSOT (spec v33.1.5v33.1.6 + admission_divisor field), `64cefca` M4-MED-2 validate_winner genesis-aware contract docs, `53ba832` M4-LOW-3 log2_q64 panic-free byte extraction, `e8450bb` M4-LOW-4 checked_add validate_header window monotone, `c41f043` M4-LOW-5 saturating_mul quorum, `845d74d` M4-LOW-6 positive functional tests TooManyOps/TooManyReveals, `bcf5e9b` M5-LOW-8 cleanup orphan .tmp at FsStore::open + anti-regression test, `022c5ff` M4-INFO-10 canonical_proposer degraded-mode docs. |
| 2026-04-27 | **External audit #3 VERIFIED Claude Opus 4.7 (1M context)** incremental M3 mt-account scope + полная zero-trust verification закрытий M1/M2 + fresh NIST CAVP source download (T124438; supersedes incomplete first pass T121239 в которой аудитор по собственному признанию срезал углы). 785/785 cargo test --all PASS. | 10 findings: 8 из incomplete first pass (1 HIGH M3-A-4, 3 LOW M3-A-1/M3-A-2/F-5, 4 INFO M3-A-3/M3-A-5/M3-A-7/M3-A-8) + 2 из VERIFIED pass (P-C-1 F-19 reopen HIGH, P-C-2 audit history sync MEDIUM). Score **8.5/10**; expected 9/10 после P-C-1 + P-C-2. | **All 10 findings closed конструкцией.** Commits: `4c14685` M3-A-4 ValidationContext, `047cc45` M3-A-1+M3-A-2 checked arithmetic, `66df1a1` M3-A-5+F-5 docs/telemetry TODO, `e61c479` M3-A-3 binding test vector, `5d3506c` Cargo.lock sync, `b96085d` P-C-1 SAFETY convention для 4 const-cast sites + Rust shim cross-references, `<this>` P-C-2 audit history sync. **131 tests PASS** в mt-account (96 unit + 35 determinism); 4 anti-regression теста (validate_dispatcher cooldown enforcement, apply_chain_length overflow panic, apply_checkpoint_rotation underflow panic, genesis_candidate_root binding `empty_internal(256)`). |
| 2026-04-26 | **External audit #2 Claude Opus 4.7 (1M context)** incremental M2 scope (mt-merkle, mt-genesis, mt-state, mt-timechain) | 17 findings (1 HIGH M2-1 Genesis bootstrap pubkeys placeholder, 5 MEDIUM, 11 LOW/INFO); score **8/10**; 60/60 determinism invariants verified | M2-3 + M2-13 изначально закрыты в M3 milestone (binding test pin 41/40 + MonetaryState в compute_state_root). **Superseded** spec bump v33.1.6 v34.0.0 monetary policy refactor (geometric step-up const linear emission): pin 41/40 inflation_num/den и MonetaryState carry-recurrence удалены как artifacts old policy. Новые equivalent invariants: `reward_moneta(W) = EMISSION_moneta` const closed-form, `supply_moneta(W) = EMISSION × (W+1)` linear closed-form. M2-1 re-classified как known limitation (mainnet deployment blocker, не code audit blocker). Остальные documentation-only findings закрыты в audit-package iterations. |
| 2026-04-26 | **External audit #1 Claude Opus 4.7 (1M context)** initial M1 layer (mt-crypto, mt-crypto-native, mt-mnemonic) independent NIST CAVP source download + byte-exact verification | 19 findings (3 HIGH + 4 MEDIUM + 12 LOW/INFO); score **8/10**; 0 cryptographic vulnerabilities | **14/19 closed конструкцией** (commit `6ff26b3` + closure доделан в `b96085d` для F-19): F-2 cargo fmt clean, F-3 stale RustCrypto refs cleanup, F-4 SAFETY comments к 3 mlock/munlock blocks, F-5 расширенный SAFETY-комментарий, F-6 keypair() переход на OS CSPRNG (`getrandom`), F-7 zeroize intermediate PBKDF2/HKDF/HMAC buffers, F-8 SigGen NIST KAT расширен 115 cases с новым `mt_sign_mldsa_ctx` API, F-9 rename kat_independent regression_baselines, F-12 split_whitespace вместо split(' '), F-18 cc parallel feature removed, F-19 const-cast OpenSSL convention в SAFETY (изначально incomplete; полностью закрыт `b96085d` после VERIFIED audit reopen). **5 deferred** с явным rationale (F-10 NIST в self_test, F-14 formal constant-time, F-15 cargo-fuzz infrastructure, F-16 threshold sigs M6+, F-17 serde_json dev-dep auditor сам "не приоритетно"). Expected score после closure: 9/10. |
| 2026-04-26 | M0+M1+M2 critic spec-vs-code audit (`Протокол/Код/CRITIC.md` v1.6.0) verification полного соответствия кода M0/M1/M2 спеке v33.1.2 | 4 findings (F-1 mt-recovery-fingerprint domain spec drift, F-2 stale VERSION.md Implementation field, F-3 false positive snyат критиком, F-4 controlled halts documentation) | All 4 closed (commit `9387900`): F-1 spec patch v33.1.2 v33.1.3 (Domain registry sync), F-2 VERSION.md updated на «M0..M5 closed», F-4 audit-checklist §K Controlled halts section |
| 2026-04-26 | M1-F audit package critic review (`Протокол/Код/CRITIC.md` v1.4.0) verification of AUDIT.md + reproduction commands + claims accuracy | 5 findings (F-A1..F-A5) все documentation-only, не security | All 5 closed: F-A1 unsafe count 34 (verify added in list), F-A2 cargo audit verified+install instructions, F-A3 line counts exact (568/40/375/56/45=1084), F-A4 print_sk gate accurately described (env var M1_DUMP_SK=1), F-A5 Docker reproduction prerequisites added |
| 2026-04-26 | M1-F internal critic audit (`Протокол/Код/CRITIC.md` v1.4.0) | 7 findings (F-1..F-7) | 6 closed конструкцией, F-3 closed через NIST ACVP differential testing **all 7 closed**. Commits: `9f2ba93` (F-4 cross-compile), `71896f6` (F-6 separate error codes), `3333738` (F-1 zeroize), `e1164ad` (F-2 Result API + F-5 cfg-gate keypair + F-7 implicit), `6b7ff30` (F-3 NIST KAT) |
| 2026-04-26 | M2 batch 2+3 audit prep manual critic Pass 1-12 для mt-state + mt-timechain | 0 findings (manual scan clean) | 24 + 19 automated determinism invariants добавлены |
| 2026-04-26 | M2 batch 1 audit prep manual critic Pass 1-12 для mt-merkle + mt-genesis | 0 findings (manual scan clean) | 10 + 7 automated determinism invariants добавлены |
| 2026-04-21 | External critic finding domain separation prefix-collision | 5 findings (P1-P5) | All closed: NUL separator pattern, SK leak gate, label coherence, empty_internal binding, stale RECOVERY disclosure. Commit `d762cec`, spec v29.13.0. |
**Audit-ready status (2026-04-27):** **zero open code-side findings** в M1 + M2 + M3 layers across **3 independent external audits** (T201805 + T232707 + T124438 by Claude Opus 4.7 1M; T124438 VERIFIED replacement of incomplete first-pass T121239). Total cumulative **46 findings** across audits all code-side closed конструкцией; deferred items explicitly classified (M2-1 Genesis bootstrap pubkeys = mainnet deployment, не code audit; F-14/F-15 formal verification + fuzzing = post-MVP scope). M3 score 8.5/10 9/10 ready после P-C-1 + P-C-2 closures (commits `b96085d` + this). Documentation accuracy verified through 3 incremental audits включая VERIFIED zero-trust pass. Cross-implementation conformance verified через spec code byte-exact alignment + independent NIST CAVP source download (65 KAT cases byte-exact с fresh source 2026-04-27).
---
## 6. Spec & Documentation
| Document | Path | Scope |
|----------|------|-------|
| Protocol spec | см. `VERSION.md` (Spec target / Spec path) авторитетный источник | Полный protocol specification, источник истины |
| App spec | `Протокол/Montana App v3.9.2.md` (актуальный на дату; см. историю VERSION.md) | Application layer specification |
| Architect role | [CLAUDE.md](CLAUDE.md) | Code architect role definition (v1.12.0) |
| Critic role | [CRITIC.md](CRITIC.md) | Code critic role definition (v1.6.0 Pass 17 Security Card mandatory) |
| Roadmap | [ROADMAP.md](ROADMAP.md) | Implementation roadmap, milestones, status |
| Spec version SSOT | [VERSION.md](VERSION.md) | Single source of truth для spec target version |
| Pre-audit checklist | [docs/audit-checklist.md](docs/audit-checklist.md) | 11 категорий self-attestation (A-K) + reproduction one-liners для аудитора + sign-off table |
| Security Cards | [docs/security-cards.md](docs/security-cards.md) | Pass 17 mandatory Security Cards для 6 crypto primitives |
---
## 7. Pre-audit self-attestation
Перед началом external audit см. [docs/audit-checklist.md](docs/audit-checklist.md) для полного 11-категорийного чеклиста.
**M1 + M2 final closure self-attestation (2026-04-26):**
**Findings closure:**
- [x] Все 7 M1-F audit findings закрыты конструкцией (F-1..F-7)
- [x] Все 5 audit-package findings закрыты (F-A1..F-A5)
- [x] Все 4 M0+M1+M2 critic spec-vs-code findings закрыты (F-1..F-4)
- [x] **Total: 16/16 findings closed, 0 открытых блокеров**
**Conformance:**
- [x] NIST ACVP differential testing PASS (51/51 KAT byte-exact)
- [x] Spec code byte-exact alignment verified (16 ключевых constants/sizes table)
- [x] Domain registry sync (актуальный spec target mt-codec, см. VERSION.md)
**Security:**
- [x] 13/13 security invariants PASS (Pass 17 enforcement)
- [x] 6/6 Security Cards заполнены и closed (`docs/security-cards.md`)
- [x] Heap+mlock+zeroize для secret types verified
**Determinism:**
- [x] 60/60 M2 determinism invariants PASS
- [x] 0 HashMap (real usage) в consensus path; BTreeMap canonical sort
- [x] 0 SystemTime/Instant::now/RNG в consensus path
- [x] 0 f32/f64 в consensus path
**Build & CI:**
- [x] `cargo audit` clean (verified 2026-04-26: 0 vulnerabilities, 0 warnings, 39 deps)
- [x] `cargo fmt --all -- --check` clean
- [x] `cargo clippy --all-targets -- -D warnings` clean
- [x] `cargo test --all` 564+ PASS / 0 FAIL
- [x] `cargo build --all --release` clean
- [x] Reproducible builds verified through CI gate `reproducible_release`
**Documentation:**
- [x] Public API stable (mt-crypto types/signatures unchanged через M1-E + M1-F migrations)
- [x] Audit chain documented (Layer 1/2/3 explicit, exact line counts)
- [x] Threat model documented (in/out of scope explicit)
- [x] Known limitations documented с closure path
- [x] Reproduction commands verified working (each one tested 2026-04-26)
- [x] Documentation accuracy verified through critic review of audit package itself
---
## Contact
Audit findings, questions, reports fork репозиторий, open PR с patch + reproduction instructions.
Architect role + critic role files в репозитории peer-reviewable methodology.