1use axum::http::StatusCode;
9
10#[derive(Debug, Clone, Copy)]
12pub struct ProblemDef {
13 pub slug: &'static str,
15 pub status: StatusCode,
16 pub title: &'static str,
18 pub description: &'static str,
20}
21
22pub struct Slugs {
24 pub validation_failed: ProblemDef,
26 pub captcha_failed: ProblemDef,
28 pub invalid_token: ProblemDef,
30 pub unknown_product: ProblemDef,
33 pub unauthenticated: ProblemDef,
39 pub admin_unauthorized: ProblemDef,
42 pub api_key_unauthorized: ProblemDef,
46 pub api_key_forbidden: ProblemDef,
49 pub admin_forbidden: ProblemDef,
51 pub sidecar_unauthorized: ProblemDef,
55 pub not_production_ready: ProblemDef,
59 pub request_too_large: ProblemDef,
61 pub rate_limited: ProblemDef,
63 pub not_found: ProblemDef,
65 pub internal: ProblemDef,
67 pub mail_not_configured: ProblemDef,
70 pub not_ready: ProblemDef,
73 pub unknown_tenant: ProblemDef,
78 pub sidecar_unavailable: ProblemDef,
81 pub sidecar_contract_mismatch: ProblemDef,
84 pub tenant_degraded: ProblemDef,
89}
90
91pub const SLUGS: Slugs = Slugs {
92 validation_failed: ProblemDef {
93 slug: "validation-failed",
94 status: StatusCode::BAD_REQUEST,
95 title: "Request validation failed",
96 description: "The request body or query did not deserialize into a valid request.",
97 },
98 captcha_failed: ProblemDef {
99 slug: "captcha-failed",
100 status: StatusCode::BAD_REQUEST,
101 title: "Captcha verification failed",
102 description: "The captcha token was missing or rejected; retry the challenge.",
103 },
104 invalid_token: ProblemDef {
105 slug: "invalid-token",
106 status: StatusCode::BAD_REQUEST,
107 title: "Invalid or expired token",
108 description: "A signed link or token is malformed, tampered with, or expired.",
109 },
110 unknown_product: ProblemDef {
111 slug: "unknown-product",
112 status: StatusCode::BAD_REQUEST,
113 title: "Unknown product",
114 description: "The named product is not on this waitlist.",
115 },
116 unauthenticated: ProblemDef {
117 slug: "unauthenticated",
118 status: StatusCode::UNAUTHORIZED,
119 title: "Not authenticated",
120 description: "A credential was presented and did not verify, or none was presented where one is required.",
121 },
122 admin_unauthorized: ProblemDef {
123 slug: "admin-unauthorized",
124 status: StatusCode::UNAUTHORIZED,
125 title: "Admin access unauthorized",
126 description: "Admin endpoints are disabled or the request has no bearer token.",
127 },
128 api_key_unauthorized: ProblemDef {
129 slug: "api-key-unauthorized",
130 status: StatusCode::UNAUTHORIZED,
131 title: "API key unauthorized",
132 description: "The request's API key was missing, malformed, unknown, revoked or invalid; one uniform answer for all five.",
133 },
134 api_key_forbidden: ProblemDef {
135 slug: "api-key-forbidden",
136 status: StatusCode::FORBIDDEN,
137 title: "API key lacks the required scope",
138 description: "The presented API key is valid but does not carry the scope this route requires.",
139 },
140 admin_forbidden: ProblemDef {
141 slug: "admin-forbidden",
142 status: StatusCode::FORBIDDEN,
143 title: "Admin token rejected",
144 description: "The presented admin token is wrong.",
145 },
146 sidecar_unauthorized: ProblemDef {
147 slug: "sidecar-unauthorized",
148 status: StatusCode::UNAUTHORIZED,
149 title: "Unauthorized sidecar caller",
150 description: "A request to a sidecar-guarded route could not be established as coming from the trusted gateway.",
151 },
152 not_production_ready: ProblemDef {
153 slug: "not-production-ready",
154 status: StatusCode::SERVICE_UNAVAILABLE,
155 title: "Not ready for production traffic",
156 description: "This deployment declares production but cannot satisfy the abuse controls its routes declare.",
157 },
158 request_too_large: ProblemDef {
159 slug: "request-too-large",
160 status: StatusCode::PAYLOAD_TOO_LARGE,
161 title: "Request body too large",
162 description: "The request body exceeded the 64 KiB limit for /v1 endpoints.",
163 },
164 rate_limited: ProblemDef {
165 slug: "rate-limited",
166 status: StatusCode::TOO_MANY_REQUESTS,
167 title: "Rate limit exceeded",
168 description: "Too many requests from this IP or address; retry after the pause.",
169 },
170 not_found: ProblemDef {
171 slug: "not-found",
172 status: StatusCode::NOT_FOUND,
173 title: "Not found",
174 description: "No route matched the request.",
175 },
176 unknown_tenant: ProblemDef {
177 slug: "unknown-tenant",
178 status: StatusCode::NOT_FOUND,
179 title: "Unknown tenant",
180 description: "The request's host resolves to no tenant in the registry.",
181 },
182 internal: ProblemDef {
183 slug: "internal",
184 status: StatusCode::INTERNAL_SERVER_ERROR,
185 title: "Internal error",
186 description: "Unhandled error; no internals are exposed in the body.",
187 },
188 mail_not_configured: ProblemDef {
189 slug: "mail-not-configured",
190 status: StatusCode::SERVICE_UNAVAILABLE,
191 title: "Mail is not configured",
192 description: "No sending domain is verified; use the direct address shown by the form.",
193 },
194 not_ready: ProblemDef {
195 slug: "not-ready",
196 status: StatusCode::SERVICE_UNAVAILABLE,
197 title: "Service not ready",
198 description: "Readiness probe failed: the database is missing, erroring or too slow.",
199 },
200 sidecar_unavailable: ProblemDef {
201 slug: "sidecar-unavailable",
202 status: StatusCode::SERVICE_UNAVAILABLE,
203 title: "Sidecar module unavailable",
204 description: "A sidecar-mounted module could not be reached; other modules are unaffected.",
205 },
206 sidecar_contract_mismatch: ProblemDef {
207 slug: "sidecar-contract-mismatch",
208 status: StatusCode::SERVICE_UNAVAILABLE,
209 title: "Sidecar contract mismatch",
210 description: "A sidecar answers a different HARNESS_API than this harness speaks.",
211 },
212 tenant_degraded: ProblemDef {
213 slug: "tenant-degraded",
214 status: StatusCode::SERVICE_UNAVAILABLE,
215 title: "Tenant is degraded",
216 description: "The tenant's schema is behind or its database is unreachable; its neighbours are unaffected.",
217 },
218};
219
220pub fn registry() -> Vec<&'static ProblemDef> {
222 vec![
223 &SLUGS.validation_failed,
224 &SLUGS.captcha_failed,
225 &SLUGS.invalid_token,
226 &SLUGS.unknown_product,
227 &SLUGS.unauthenticated,
228 &SLUGS.admin_unauthorized,
229 &SLUGS.api_key_unauthorized,
230 &SLUGS.api_key_forbidden,
231 &SLUGS.admin_forbidden,
232 &SLUGS.sidecar_unauthorized,
233 &SLUGS.not_production_ready,
234 &SLUGS.request_too_large,
235 &SLUGS.rate_limited,
236 &SLUGS.not_found,
237 &SLUGS.unknown_tenant,
238 &SLUGS.internal,
239 &SLUGS.mail_not_configured,
240 &SLUGS.not_ready,
241 &SLUGS.sidecar_unavailable,
242 &SLUGS.sidecar_contract_mismatch,
243 &SLUGS.tenant_degraded,
244 ]
245}