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
//! macOS LocalAuthentication (`LAContext`) implementation of [`Biometric`].
//!
//! **`[host]` — not exercised by automated tests.** Showing a Touch ID dialog
//! requires real hardware and a real human finger; this path is validated by a
//! human on an M4 (KOV-15 checklist). The OS-independent contract (rendering,
//! timeout⇒deny, no-self-approve, no leak) is covered by mock-based tests in the
//! parent module and in `render`. Everything here is the thin native bridge.
//!
//! ## Threading (KOV-15 decision 1)
//!
//! `LAContext evaluatePolicy:localizedReason:reply:` is **non-blocking**: it
//! returns immediately and invokes `reply` later "on a private queue internal to
//! the framework, in an unspecified threading context" (Apple docs). It does
//! **not** require the caller to pump a runloop — the framework owns the queue
//! that fires the callback. So we deliberately do **not** build a dedicated
//! runloop pump (decision 1). Instead:
//!
//! - We call this from the CLI **main thread** (the CLI is synchronous; `kovra
//! run` / `kovra show` block here).
//! - The reply block signals a `std::sync::mpsc` channel; we block the main
//! thread on `recv_timeout(timeout)`.
//! - We keep a strong reference to the `LAContext` for the whole wait (Apple:
//! "keep a strong reference while evaluation is in progress").
//! - On `recv_timeout` elapsing we return [`ConfirmOutcome::TimedOut`] (deny, §8);
//! the dropped context cancels the in-flight evaluation.
//!
//! The reply is an **`RcBlock`** (heap-allocated, reference-counted), not a
//! `StackBlock`: `evaluatePolicy:…:reply:` is an *escaping* async callback, so
//! the block must outlive this stack frame. On timeout we return (unwinding the
//! frame) while the framework may still hold the queued reply; a heap `RcBlock`
//! stays valid for that late call (a stack block could be a use-after-free).
//!
//! ## `extern "C"` shim (KOV-15 decision 2)
//!
//! Not needed. `objc2-local-authentication` 0.3.2 exposes `LAContext::new`,
//! `canEvaluatePolicy:`, and `evaluatePolicy:localizedReason:reply:` (with the
//! `block2` feature) — the full surface this Confirmer needs. No private shim is
//! required.
use mpsc;
use Duration;
use RcBlock;
use Retained;
use Bool;
use ;
use ;
use ;
use craterender;
/// `LAPolicyDeviceOwnerAuthenticationWithBiometrics` — biometrics only (no
/// passcode fallback). The **default** for secret deliveries (`high` reveal /
/// inject): we want the attended *biometric* gesture (§8 / I3), not a typed
/// passcode that an agent-driven keystroke could supply. The generic, secret-
/// independent `kovra confirm` action gate opts into the password fallback via
/// [`ConfirmRequest::allow_password`] (see [`policy_for`]).
const BIOMETRICS_ONLY: LAPolicy = DeviceOwnerAuthenticationWithBiometrics;
/// The `LAPolicy` to evaluate for `req`. Secret deliveries stay biometrics-only;
/// a generic action gate (`allow_password`, set only by
/// [`ConfirmRequest::for_action`]) also accepts the OS device password — still
/// attended (the user is at the keyboard) and not something the agent knows.
/// Cheap, dialog-free capability probe: can we evaluate the biometric policy on
/// this host right now (hardware present, user enrolled)?
///
/// `[host]` — depends on the machine. Returns `false` when biometrics is absent
/// or not enrolled, which drives the CLI's fallback to the file broker.
pub
/// The real `LAContext`-backed biometric prompt.
pub
/// Hold a value until this call returns; documents the "keep `LAContext` alive
/// during evaluation" requirement at the use site.