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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
//! Procedural macros for the antigen crate.
//!
//! This crate provides the five attribute macros that constitute the antigen
//! API surface:
//!
//! - [`#[antigen(...)]`](macro@antigen) — declare a named failure-class with a
//! structural fingerprint (ADR-001, ADR-010)
//! - [`#[presents(...)]`](macro@presents) — mark code as exhibiting an antigen's
//! structural pattern (vulnerability declaration)
//! - [`#[immune(...)]`](macro@immune) — declare immunity with a witness reference
//! (test, proptest, phantom-type proof, or external-tool delegation)
//! - [`#[descended_from(...)]`](macro@descended_from) — propagate antigen markers
//! through an inheritance chain (ADR-013, ADR-018 §propagation)
//! - [`#[antigen_tolerance(...)]`](macro@antigen_tolerance) — document an
//! intentional opt-out with required rationale (ADR-011)
//!
//! Users typically import these via the [`antigen`](https://docs.rs/antigen)
//! crate (`use antigen::{antigen, presents, immune, descended_from,
//! antigen_tolerance};`) rather than depending on `antigen-macros` directly.
//!
//! ## Design philosophy (v1)
//!
//! The macros are **mostly identity transformations**. Their job is to validate the
//! attribute syntax at compile time and pass the input through unchanged. The
//! semantic work — scanning the codebase, matching presentations against
//! immunities, validating witnesses — lives in the `cargo-antigen` tooling, which
//! parses source AST independently via `syn`.
//!
//! This keeps runtime overhead at zero (the macros generate no code beyond the
//! original input) and means antigen declarations don't affect compilation speed,
//! linker behavior, or binary size. The cost lives entirely at `cargo antigen scan`
//! time, which runs out-of-band.
//!
//! See ADR-010 (fingerprint grammar v1) and the project's `docs/expedition/`
//! directory for the design rationale.
//!
//! ## Known v1 limitations
//!
//! 1. **Macros are pure pass-through**: the proc-macros parse + validate the
//! attribute syntax and emit the original item unchanged (ADR-001 identity
//! transform). Cross-crate antigen discovery in v0.1.0-rc.1 works via
//! source-walking the `.cargo/registry` tree (A3 sweep). A future ADR
//! amendment may add metadata-emitting transforms (e.g.,
//! `<!-- antigen:metadata:v1 {...} -->` doc-comment markers, or
//! `#[cfg(doc)] pub static __ANTIGEN_META_*`) for the no-source-access
//! case — verified-viable but post-A5 ADR territory per the A3 scope-lock.
//!
//! Span-aware error pointing (W4) and trybuild fixtures (A2 ratification)
//! both shipped in v0.1.0-rc.1.
use TokenStream;
use quote;
use parse_macro_input;
/// Declare a named failure-class with a structural fingerprint.
///
/// # Arguments
///
/// - `name = "..."` (required) — kebab-case identifier for the failure-class
/// - `fingerprint = "..."` (required) — structural pattern (see ADR-010)
/// - `family = "..."` (optional) — parent class, typically one of the 8
/// first-principles failure classes
/// - `summary = "..."` (optional) — human-readable description
/// - `references = [...]` (optional) — open-vocabulary list of references
/// (URLs, ADR/DEC IDs, CVE numbers, RFC numbers, etc.)
///
/// # Examples
///
/// Layer 1 (minimum viable — just `name` and `fingerprint`):
///
/// ```ignore
/// use antigen::antigen;
///
/// #[antigen(
/// name = "panicking-in-drop",
/// fingerprint = "impl Drop with unwrap/expect/panic in body",
/// )]
/// pub struct PanickingInDrop;
/// ```
///
/// Layer 2 (enriched — adds `family`, `summary`, `references`):
///
/// ```ignore
/// #[antigen(
/// name = "panicking-in-drop",
/// family = "boundary-violation",
/// fingerprint = "impl Drop with unwrap/expect/panic in body",
/// summary = "Drop impls must not panic; double-panic causes process abort.",
/// references = ["https://doc.rust-lang.org/std/ops/trait.Drop.html#panics"],
/// )]
/// pub struct PanickingInDrop;
/// ```
///
/// The struct must be declared as a unit struct (no fields). The macro validates
/// the attribute arguments and passes the struct through unchanged.
/// Mark code as exhibiting a known antigen's structural pattern (vulnerability
/// declaration).
///
/// # Arguments
///
/// Single positional argument: the antigen type name.
///
/// # Example
///
/// ```ignore
/// use antigen::presents;
///
/// #[presents(PanickingInDrop)]
/// impl Drop for MyType {
/// fn drop(&mut self) { /* might panic */ }
/// }
/// ```
///
/// `cargo antigen scan` flags every `#[presents]` site that lacks a corresponding
/// `#[immune]` declaration. This declaration is the *vulnerability surface* — it
/// says "this code exhibits the structural pattern."
///
/// To express both vulnerability AND verified immunity, apply both attributes to
/// the same item:
///
/// ```ignore
/// #[presents(PanickingInDrop)]
/// #[immune(PanickingInDrop, witness = no_panic_test)]
/// impl Drop for SafeType { ... }
/// ```
/// Declare immunity to a known antigen, with a witness that proves the immunity.
///
/// # Arguments
///
/// - The antigen type name (positional)
/// - `witness = ...` (required) — reference to a test, proptest, lint, formal-
/// verification proof, or phantom-type construction that proves immunity
/// - `rationale = "..."` (optional) — human-readable description of why the
/// witness applies
///
/// # Example
///
/// ```ignore
/// use antigen::immune;
///
/// #[immune(
/// PanickingInDrop,
/// witness = no_panic_in_drop_test,
/// rationale = "SafeType::drop uses Result-returning paths only.",
/// )]
/// impl Drop for SafeType { ... }
/// ```
///
/// `cargo antigen scan` validates that the witness identifier resolves to a real
/// test/proptest/lint/proof. Witnesses that don't exist or don't run successfully
/// invalidate the immunity claim.
///
/// `#[immune]` does not require `#[presents]` on the same item. Pre-emptive
/// immunity is acceptable: declaring immunity to ensure future modifications stay
/// covered, even when the current code doesn't structurally match the antigen.
/// Propagate antigen markers from a parent function/type/method to a derived one.
///
/// # Arguments
///
/// Single positional argument: a path to the parent item.
///
/// # Example
///
/// ```ignore
/// use antigen::descended_from;
///
/// #[descended_from(crate::other_module::parent_function)]
/// fn refined_function(...) { ... }
/// ```
///
/// **v0.1 status**: `#[descended_from]` is recognized and parsed but
/// propagation is not yet implemented. In v0.1, this attribute compiles
/// cleanly and is recorded by `cargo antigen scan` for future use.
/// Chain-walking and marker propagation (`#[presents]` / `#[immune]`
/// inheritance with witness re-validation) arrive in A3.
/// Mark a site as a deliberate, non-vulnerable match against an antigen's
/// fingerprint. Per ADR-011.
///
/// # Arguments
///
/// - The antigen type name (positional)
/// - `rationale = "..."` (required) — human-readable justification; empty
/// string is rejected
/// - `until = "..."` (optional) — expiry tag (e.g., `"v1.0"`); empty string
/// is rejected (per aristotle reciprocal Phase 1-8)
/// - `see = [...]` (optional) — open-vocabulary string array of references
///
/// # Example
///
/// ```ignore
/// use antigen::antigen_tolerance;
///
/// #[antigen_tolerance(
/// PolarityInvertedClassMeet,
/// rationale = "This test fixture deliberately constructs the failure \
/// pattern to verify the witness catches it.",
/// until = "v1.0",
/// see = ["GAP-BIT-EXACT-1"],
/// )]
/// fn test_polarity_inversion_caught() { /* ... */ }
/// ```
///
/// `cargo antigen scan` recognizes tolerance markers as explicit
/// acknowledgments of fingerprint matches; tolerated sites are reported in
/// a separate category from unaddressed presentations.