diff --git a/vti-common/src/acl/mod.rs b/vti-common/src/acl/mod.rs index 36c0b7c6b..98709deea 100644 --- a/vti-common/src/acl/mod.rs +++ b/vti-common/src/acl/mod.rs @@ -118,8 +118,19 @@ pub enum ServiceKind { /// produces a sensible default from the existing role (Admin gets /// everything, Reader gets only `vault-read`, etc.) so existing ACL /// behaviour is preserved bit-for-bit. +/// **Non-exhaustive on purpose.** This list grows every time the agent gains a +/// power worth gating separately, and each addition used to be a breaking change +/// for anyone matching on it — which is exactly what happened: `MemoryRead`, +/// `MemoryWrite`, `RoomPresent` and `RoomOpen` went out in `vti-common` 0.16.2, a +/// patch release, and any downstream exhaustive `match` stopped compiling on a +/// routine `cargo update`. +/// +/// Downstream code must carry a `_ =>` arm. That is the point: a capability this +/// consumer has never heard of is precisely the one it must not silently treat as +/// granted, and a wildcard arm forces that decision to be written down. #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "kebab-case")] +#[non_exhaustive] pub enum Capability { VaultRead, VaultWrite, diff --git a/vti-common/src/audit/event.rs b/vti-common/src/audit/event.rs index f5bc1fe5b..71584bfa6 100644 --- a/vti-common/src/audit/event.rs +++ b/vti-common/src/audit/event.rs @@ -43,8 +43,17 @@ pub const REDACTED_MARKER: &str = ""; /// Audit-event payload. Tagged on `type` with the variant name and /// the variant's data under `data`. Phase-0 vocabulary only; /// Phase-1+ adds variants alongside the features that emit them. +/// **Non-exhaustive on purpose**, and for the reason the doc comment above already +/// states: variants arrive alongside the features that emit them, so the set is +/// designed to grow. `RoomOperation` shipped in `vti-common` 0.16.2 — a patch — and +/// broke every downstream exhaustive `match`. +/// +/// A consumer that cannot name an event still has to record it; a `_ =>` arm is the +/// honest shape for that, and dropping an unrecognised event on the floor is the +/// failure this prevents being silent. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "type", content = "data")] +#[non_exhaustive] pub enum AuditEvent { /// Bootstrap completed — the first admin DID was written into the /// ACL and the install carve-out was permanently closed.