polish(gov+attestation): test de empate en finalize + ancla SSOT de attestation
Polish pass MEDIUM/LOW post-audit (2 items limpios + triage de los invasivos): governance — cobertura del desempate (consenso-relevante, sin cobertura previa): - scenario_8b_finalize_tie_rejected_canonical: yes==nay ⇒ `yes > nay` es false ⇒ Rejected. Fija que se exige MAYORÍA ESTRICTA (el empate favorece el status quo). Entre scenario_7 (yes-majority→Approved) y scenario_8 (nay-majority→Rejected) faltaba justo el borde del empate. origin-chain-types — SSOT de attestation ahora que el crate aterrizó: - `arkhe-noesis-attestation-types` ya existe (crate standalone no_std + feature scale en el monorepo). El vendor-copy SE QUEDA como type-mirror deliberado: el chain es submódulo y depender del crate del monorepo invierte la dep-direction (submódulo→monorepo = ILEGAL). La SSOT se preserva por los golden vectors del oráculo real (decode_golden_vector_1/3/4), no por Cargo. - attestation_verify: §SSOT parity anchor doc — documenta que esos vectores pinnean el decoder al field-order de `SigningPayload` y cómo regenerar ante deriva. - attestation.rs: comentario del mirror actualizado (el crate aterrizó; diferencia conocida schema_version [u8;8] vs String es irrelevante — el mirror no serializa el wire; el decoder secuencial sí es byte-fiel al postcard, probado por vectores). Triage documentado (items considerados y DIFERIDOS con rationale, no olvidados): - register_agent_did unbounded Vec: bound del arg a ConstU32<10> movería el rechazo a decode-time, volvería AgentChainOverflow inalcanzable + rompería el test de overflow + exigiría spec bump — invasivo para un DoS ya mitigado por length-fee + límite de bloque. Diferido. - SS58 prefix (42): NO es bug — placeholder testnet correcto, gated en un DC de ss58-registry pre-mainnet. Sin cambio. - no-author path (emission): requiere un FindAuthor mock que devuelva None (segundo runtime o toggle) — ripple > valor. Diferido. Verificado: origin-chain-types 77 tests verde (incl. golden parity) + tie test verde. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
c7fc6a88fc
commit
266ee4084d
3 files changed
+60
-2
No files matched your search
@@ -222,6 +222,37 @@ fn scenario_8_finalize_rejected_nay_majority_canonical() {
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Scenario 8b: Finalize con EMPATE (yes == nay) → Rejected ────────
|
||||
// Polish audit: documenta la semántica del desempate. `finalize_proposal` usa
|
||||
// `yes_weight > nay_weight` (mayoría ESTRICTA); un empate NO alcanza el umbral
|
||||
// y la propuesta se RECHAZA. Esto es intencional (una propuesta necesita más
|
||||
// síes que noes para pasar; el empate favorece el status quo). El gate estaba
|
||||
// sin cobertura — este test lo fija como comportamiento consensuado.
|
||||
|
||||
#[test]
|
||||
fn scenario_8b_finalize_tie_rejected_canonical() {
|
||||
new_test_ext().execute_with(|| {
|
||||
let id = submit_default(alice_origin());
|
||||
|
||||
// EMPATE exacto: Aye 500 == Nay 500.
|
||||
assert_ok!(Governance::cast_vote(bob_origin(), id, VoteStance::Aye, 500));
|
||||
assert_ok!(Governance::cast_vote(charlie_origin(), id, VoteStance::Nay, 500));
|
||||
|
||||
run_to_block(200);
|
||||
|
||||
assert_ok!(Governance::finalize_proposal(alice_origin(), id));
|
||||
|
||||
let proposal = Proposals::<Test>::get(id).unwrap();
|
||||
assert_eq!(proposal.yes_weight, 500);
|
||||
assert_eq!(proposal.nay_weight, 500);
|
||||
// yes(500) > nay(500) es FALSE ⇒ Rejected (mayoría estricta requerida).
|
||||
assert!(
|
||||
matches!(proposal.status, ProposalStatus::Rejected),
|
||||
"empate debe rechazar: se exige mayoría estricta"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Scenario 9: Vote closed period rejected canonical ──────────────
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user