Skip to main content

chronix_security/tenant/
error.rs

1//! Tenant-related error types.
2
3use thiserror::Error;
4
5/// Tenant / namespace errors.
6#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum TenantError {
9    /// Namespace not found.
10    #[error("namespace not found: {0}")]
11    NamespaceNotFound(String),
12
13    /// Namespace already exists.
14    #[error("namespace already exists: {0}")]
15    NamespaceAlreadyExists(String),
16
17    /// A namespace quota has been exceeded.
18    ///
19    /// # Information Disclosure
20    ///
21    /// The error message deliberately includes `current` and `limit`
22    /// values. This is acceptable because:
23    ///
24    /// The error is only returned to **authenticated, namespace-scoped**
25    ///   callers who already have write access and can trivially infer
26    ///   their own usage.
27    /// Operators need these values for capacity-planning and debugging.
28    /// The HTTP layer maps this to a 429 response with a generic
29    ///   message; the detailed fields are only visible in server logs
30    ///   and metrics (not forwarded to the end-user response body).
31    #[error("quota exceeded for namespace '{namespace}': {resource} ({current}/{limit})")]
32    QuotaExceeded {
33        /// The namespace that exceeded the quota.
34        namespace: String,
35        /// Which resource hit the limit (e.g. `series_count`).
36        resource: String,
37        /// Current usage value.
38        current: u64,
39        /// Configured limit.
40        limit: u64,
41    },
42
43    /// Invalid namespace configuration.
44    #[error("invalid namespace config: {0}")]
45    InvalidConfig(String),
46
47    /// Schema validation error from chronix-core.
48    #[error("schema error: {0}")]
49    Schema(#[from] chronix_core::SchemaError),
50
51    /// The registry could not be persisted.
52    ///
53    /// Its own variant because it is the **server's** fault and every other
54    /// variant here is the caller's. They shared `InvalidConfig`, so a full
55    /// disk reached an operator as `400 invalid namespace config` — a
56    /// message that sends them to re-read the request body while the
57    /// problem is the volume.
58    #[error("cannot persist the namespace registry: {0}")]
59    Persist(String),
60}
61
62/// A specialised `Result` type for tenant operations.
63pub type Result<T> = std::result::Result<T, TenantError>;