Skip to main content

apcore_toolkit/
conformance.rs

1//! Cross-adapter conformance checks for registry writers.
2//!
3//! Call from an adapter's tests to assert that registering a scanned module
4//! **preserves its behavioral annotations**. Approval and ACL gating key on
5//! `requires_approval` (and read `destructive`); a writer that drops
6//! annotations during registration silently disables that gate — no error, no
7//! warning. This helper turns that otherwise-invisible regression into a
8//! failing test.
9
10use apcore::Registry;
11
12use crate::types::ScannedModule;
13use crate::RegistryWriter;
14
15/// Register `module` via `writer` into `registry` and assert its governance
16/// annotations (`requires_approval`, `destructive`) survive `get_definition`.
17///
18/// Panics on a dropped or changed field, so it reads naturally inside a
19/// `#[test]`. `module.annotations` must be `Some(..)` — that is what the
20/// round-trip verifies.
21pub fn assert_annotations_preserved(
22    writer: &RegistryWriter,
23    module: &ScannedModule,
24    registry: &Registry,
25) {
26    let source = module
27        .annotations
28        .as_ref()
29        .expect("assert_annotations_preserved expects module.annotations to be set");
30
31    writer.write(std::slice::from_ref(module), registry, false, false, None);
32
33    let descriptor = registry
34        .get_definition(&module.module_id)
35        .expect("get_definition failed")
36        .unwrap_or_else(|| {
37            panic!(
38                "conformance: module '{}' was not registered",
39                module.module_id
40            )
41        });
42
43    let registered = descriptor.annotations.as_ref().unwrap_or_else(|| {
44        panic!(
45            "conformance: module '{}' lost its annotations during registration — \
46             approval/ACL gating that keys on requires_approval will silently never fire",
47            module.module_id
48        )
49    });
50
51    assert_eq!(
52        registered.requires_approval, source.requires_approval,
53        "conformance: module '{}' annotation 'requires_approval' changed during registration",
54        module.module_id
55    );
56    assert_eq!(
57        registered.destructive, source.destructive,
58        "conformance: module '{}' annotation 'destructive' changed during registration",
59        module.module_id
60    );
61}