1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 Pierre Gronau, ndaal in Cologne
//! Compile-time invariants for `csaf-crud`, per `skills/rust-static-assertions`.
//!
//! `AppState` is the type axum clones into every request handler and holds
//! across every `.await`. Axum's `FromRequestParts` / `Handler` machinery
//! requires it to be `Clone + Send + Sync + 'static`, and when that bound is
//! lost the compiler does not point at the line that broke it. It points at
//! the router, with a multi-screen trait-resolution error mentioning types
//! nobody wrote. Engineers then "fix" it by restructuring the router.
//!
//! These assertions move that failure back to its cause: change the shape of
//! `AppState` in a way that breaks the contract, and the build fails HERE,
//! naming this file.
use AppState;
use Lang;
use ;
// ---------------------------------------------------------------------------
// 1. The axum shared-state contract
// ---------------------------------------------------------------------------
//
// Every one of these is required by axum's `with_state`. `Clone` in
// particular must stay CHEAP — `AppState` is cloned per request, which is why
// it is a single `Arc<AppStateInner>` and not a struct of owned fields. A
// refactor that flattens the inner Arc away would still satisfy `Clone` and
// still compile, but would deep-copy settings and config on every request.
// That is a performance cliff no test would catch, so it is called out here
// even though the type system cannot enforce it.
assert_impl_all!;
// `'static` is what lets the state be moved into a spawned task. Asserting it
// explicitly documents that any future borrowed field is a breaking change.
//
// `assert_impl_all!` takes traits, not lifetime bounds, so this is the
// hand-rolled equivalent: it is evaluated at compile time and costs nothing
// at runtime.
const _: fn = ;
// ---------------------------------------------------------------------------
// 2. Settings cross the RwLock boundary by value
// ---------------------------------------------------------------------------
//
// `AppState::settings()` returns an owned `Settings` clone rather than a
// guard. That is deliberate: handing a `RwLockReadGuard` to a handler would
// let it be held across an `.await`, which deadlocks the writer. The return
// type being the owned value — not a guard — is the invariant.
assert_type_eq_all!;
/// Local witness trait: pins the *return type* of `AppState::settings()` so
/// that changing it to a guard breaks the build here rather than deadlocking
/// under load. Implemented by hand so `assert_type_eq_all!` has a name to
/// compare against.
// ---------------------------------------------------------------------------
// 3. The Lang enum's shape and menu contract
// ---------------------------------------------------------------------------
//
// `Lang` is copied into every request and matched against three exhaustive
// tables; it must stay a payload-free fieldless enum. A variant that grows a
// payload would still compile everywhere `Lang` is matched — these pin the
// consequences instead.
assert_impl_all!;
// Fieldless with <= 256 variants — one byte, and the niche keeps
// `Option<Lang>` at one byte too (no hidden regression in the per-request
// footprint or in struct layouts that embed it).
assert_eq_size!;
assert_eq_size!;
// Adding a language without wiring it through `all()` fails the BUILD, not a
// runtime test. 46 European (skills/languages-europe-rust) + 3 Asian —
// Chinese, Hindi, Urdu (skills/languages-asia) = 49.
const_assert!;
// The first five menu positions are a UI contract (this product's historical
// order — En, De, Fr, Es, It). Reordering them fails the build here.
const_assert!;
const_assert!;
const_assert!;
const_assert!;
const_assert!;