1use axum::http::StatusCode;
6
7#[derive(Debug, Clone, Copy)]
9pub struct ProblemDef {
10 pub slug: &'static str,
12 pub status: StatusCode,
13 pub title: &'static str,
15 pub description: &'static str,
17}
18
19pub struct Slugs {
21 pub validation_failed: ProblemDef,
23 pub captcha_failed: ProblemDef,
25 pub invalid_token: ProblemDef,
27 pub unknown_product: ProblemDef,
30 pub admin_unauthorized: ProblemDef,
33 pub admin_forbidden: ProblemDef,
35 pub request_too_large: ProblemDef,
37 pub rate_limited: ProblemDef,
39 pub not_found: ProblemDef,
41 pub internal: ProblemDef,
43 pub mail_not_configured: ProblemDef,
46 pub not_ready: ProblemDef,
49 pub sidecar_unavailable: ProblemDef,
52 pub sidecar_contract_mismatch: ProblemDef,
55}
56
57pub const SLUGS: Slugs = Slugs {
58 validation_failed: ProblemDef {
59 slug: "validation-failed",
60 status: StatusCode::BAD_REQUEST,
61 title: "Request validation failed",
62 description: "The request body or query did not deserialize into a valid request.",
63 },
64 captcha_failed: ProblemDef {
65 slug: "captcha-failed",
66 status: StatusCode::BAD_REQUEST,
67 title: "Captcha verification failed",
68 description: "The captcha token was missing or rejected; retry the challenge.",
69 },
70 invalid_token: ProblemDef {
71 slug: "invalid-token",
72 status: StatusCode::BAD_REQUEST,
73 title: "Invalid or expired token",
74 description: "A signed link or token is malformed, tampered with, or expired.",
75 },
76 unknown_product: ProblemDef {
77 slug: "unknown-product",
78 status: StatusCode::BAD_REQUEST,
79 title: "Unknown product",
80 description: "The named product is not on this waitlist.",
81 },
82 admin_unauthorized: ProblemDef {
83 slug: "admin-unauthorized",
84 status: StatusCode::UNAUTHORIZED,
85 title: "Admin access unauthorized",
86 description: "Admin endpoints are disabled or the request has no bearer token.",
87 },
88 admin_forbidden: ProblemDef {
89 slug: "admin-forbidden",
90 status: StatusCode::FORBIDDEN,
91 title: "Admin token rejected",
92 description: "The presented admin token is wrong.",
93 },
94 request_too_large: ProblemDef {
95 slug: "request-too-large",
96 status: StatusCode::PAYLOAD_TOO_LARGE,
97 title: "Request body too large",
98 description: "The request body exceeded the 64 KiB limit for /v1 endpoints.",
99 },
100 rate_limited: ProblemDef {
101 slug: "rate-limited",
102 status: StatusCode::TOO_MANY_REQUESTS,
103 title: "Rate limit exceeded",
104 description: "Too many requests from this IP or address; retry after the pause.",
105 },
106 not_found: ProblemDef {
107 slug: "not-found",
108 status: StatusCode::NOT_FOUND,
109 title: "Not found",
110 description: "No route matched the request.",
111 },
112 internal: ProblemDef {
113 slug: "internal",
114 status: StatusCode::INTERNAL_SERVER_ERROR,
115 title: "Internal error",
116 description: "Unhandled error; no internals are exposed in the body.",
117 },
118 mail_not_configured: ProblemDef {
119 slug: "mail-not-configured",
120 status: StatusCode::SERVICE_UNAVAILABLE,
121 title: "Mail is not configured",
122 description: "No sending domain is verified; use the direct address shown by the form.",
123 },
124 not_ready: ProblemDef {
125 slug: "not-ready",
126 status: StatusCode::SERVICE_UNAVAILABLE,
127 title: "Service not ready",
128 description: "Readiness probe failed: the database is missing, erroring or too slow.",
129 },
130 sidecar_unavailable: ProblemDef {
131 slug: "sidecar-unavailable",
132 status: StatusCode::SERVICE_UNAVAILABLE,
133 title: "Sidecar module unavailable",
134 description: "A sidecar-mounted module could not be reached; other modules are unaffected.",
135 },
136 sidecar_contract_mismatch: ProblemDef {
137 slug: "sidecar-contract-mismatch",
138 status: StatusCode::SERVICE_UNAVAILABLE,
139 title: "Sidecar contract mismatch",
140 description: "A sidecar answers a different HARNESS_API than this harness speaks.",
141 },
142};
143
144pub fn registry() -> Vec<&'static ProblemDef> {
146 vec![
147 &SLUGS.validation_failed,
148 &SLUGS.captcha_failed,
149 &SLUGS.invalid_token,
150 &SLUGS.unknown_product,
151 &SLUGS.admin_unauthorized,
152 &SLUGS.admin_forbidden,
153 &SLUGS.request_too_large,
154 &SLUGS.rate_limited,
155 &SLUGS.not_found,
156 &SLUGS.internal,
157 &SLUGS.mail_not_configured,
158 &SLUGS.not_ready,
159 &SLUGS.sidecar_unavailable,
160 &SLUGS.sidecar_contract_mismatch,
161 ]
162}