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
//! Deny-overrides composition of multiple [`AuthzDecisionHook`] impls.
//!
//! [`CompositeAuthzHook`] is an opt-in utility for deployments that combine
//! several independent ABAC overlays (e.g. an ITAR predicate from one
//! extension and a classification predicate from another) without either
//! extension needing to know about the other. The composite iterates its
//! hooks in order, short-circuits on the first `Deny`, and otherwise returns
//! `Allow`. Composition is pure data: callers build the `Vec` themselves at
//! their binary entry point and pass the result to
//! `AppContextBuilder::with_authz_hook`. Core never auto-composes.
//!
//! # Audit semantics
//!
//! Each *evaluated* hook records its own audit row through whatever
//! `AuthzAuditSink` it was constructed with, keyed by `trace_id`. An audit
//! reader reconstructs the composite's behaviour for a single request by
//! grouping rows on `trace_id`: an N-hook composite produces between one and
//! N rows, depending on where (or whether) a deny short-circuited the chain.
//!
//! Hooks that the short-circuit skipped are not consulted and produce no
//! row — intentional: the composite's contract is "the first deny is the
//! final word", and a skipped hook has nothing to say. The composite itself
//! does NOT record a "composite fired" row — there is no composer-level
//! audit. A deployment that wants one wraps the composite in its own
//! logging hook.
//!
//! If every hook must fire regardless of an earlier deny, do not use this
//! type — write a custom composer.
use async_trait;
use ;
use ;