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
//! Capabilities a service provides to other services.
//!
//! Dispatch sites that ask "is service X installed?" almost always actually
//! mean "is there an installed service that *plays role Y*?" — modeling
//! that question as a typed [`Capability`] lookup decouples integration
//! glue from hardcoded service names. New providers (a different reverse
//! proxy, a different OIDC IdP, an external SMTP relay) drop in without
//! the auth bridge / Caddy patcher / network-join logic having to learn
//! their names.
//!
//! Today the provider→capability mapping comes from
//! [`crate::WellKnownService::capabilities`] (a static map). Step 2 of
//! the migration moves the declaration into each service's `service.toml`
//! and persists it through `metadata.toml` so [`InstalledService`] can
//! report capabilities without core knowing the service name.
use crateInstalledService;
/// A role a service can play for other services. Pattern-match exhaustively
/// — adding a new variant forces every dispatch site to think about it.
///
/// Serializes as a kebab-case string so it round-trips cleanly through
/// `service.toml` (`provides = ["reverse-proxy", …]`) and through
/// `metadata.toml` (per-install snapshot).
/// Whether a service named `name` provides the given capability,
/// resolved by reading its `[capabilities] provides` declaration from
/// the bundled registry.
///
/// Returns `false` if the registry isn't available, the service isn't
/// in the bundled registry, or the file fails to parse — capability
/// dispatch on uninstalled, unknown names is not a query we answer.
/// Call sites that already hold a [`crate::registry::service_def::ServiceDef`]
/// should call [`def_provides`] instead to skip the round-trip.
/// Capability list declared by a [`ServiceDef`]. Use this when the def
/// is already in scope (e.g. in `add_service` after `find_service`) —
/// it avoids the registry round-trip that [`service_provides`] does.
/// Whether an `InstalledService` provides the given capability. Reads
/// from the persisted snapshot in `metadata.toml` (hydrated into
/// [`InstalledService::provides`] at [`crate::list_installed`] time).
/// Read `[capabilities] provides` for a registry-known service. Returns
/// `None` if the registry isn't extracted yet, the service isn't in the
/// bundled registry, or the file fails to parse — callers fall back to
/// the static well-known map.
/// Find an installed service that provides the given capability. Returns
/// the first match — capabilities like [`Capability::ReverseProxy`] are
/// expected to have at most one provider installed at a time, but we
/// don't enforce that yet (a future "multiple OIDC providers" world is
/// the caller's problem to resolve).
/// Convenience: check live install state via [`crate::list_installed`]
/// for whether *any* provider of `cap` is currently installed. Use this
/// at planning sites that don't already have an `installed: &[…]` slice
/// in scope — anything inside [`crate::auth_bridge`] takes the slice as
/// a parameter and should call [`find_installed_provider`] instead.