// AUTO-GENERATED by scripts/gen-errors.mjs — do not edit by hand. // Source: stapel-auth canonical errors.json (backend codegen artifact). // Regenerate: pnpm gen:errors · Drift gate: pnpm gen:errors:check /** * Remediation vocabulary (frontend-core-architecture §2.5). Declared by the * backend on the error registry and consumed verbatim from its `errors.json` * artifact. A host maps it to UX — retryable → "try again"; `wait_and_retry` → * timer from `params.retry_after_minutes`; `verify` → the step-up seam; * `fix_input` → highlight the offending field. */ export type Remediation = | "retry" | "wait_and_retry" | "reauthenticate" | "verify" | "fix_input" | "contact_support" | "bug"; export interface CategoriesErrorSpec { /** HTTP status the backend raises this key with. */ readonly status: number; /** `{param}` interpolation slots present in the message. */ readonly params: readonly string[]; /** Remediation hint declared by the backend (see {@link Remediation}). */ readonly remediation: Remediation; /** English fallback (source: stapel-auth errors.json). */ readonly en: string; } /** * The CATEGORIES_ERRORS map — every `error.*` key stapel-auth can raise, keyed by its * canonical code. The single source of truth behind the en fallback bundle, the * remediation lookup, and the manifest `errors` block. */ export const CATEGORIES_ERRORS = { "error.400.bad_request": { status: 400, params: [], remediation: "fix_input", en: "Bad request" }, "error.400.captcha_invalid": { status: 400, params: [], remediation: "retry", en: "Captcha verification failed. Please try again." }, "error.400.captcha_required": { status: 400, params: [], remediation: "retry", en: "Captcha token is required." }, "error.400.categories_config_required": { status: 400, params: [], remediation: "fix_input", en: "A config object is required" }, "error.400.categories_database_error": { status: 400, params: [], remediation: "fix_input", en: "Database error while applying changes" }, "error.400.categories_duplicate_slug": { status: 400, params: ["slug"], remediation: "fix_input", en: "A feature with slug '{slug}' already exists" }, "error.400.categories_expected_list": { status: 400, params: [], remediation: "fix_input", en: "Expected a list of objects" }, "error.400.categories_feature_editor_invalid": { status: 400, params: ["reason"], remediation: "fix_input", en: "Invalid feature editor request: {reason}" }, "error.400.categories_invalid_conversion": { status: 400, params: [], remediation: "fix_input", en: "Invalid type conversion (only select<->string is supported)" }, "error.400.categories_not_deleted": { status: 400, params: [], remediation: "fix_input", en: "Category is not deleted" }, "error.400.description_too_long": { status: 400, params: ["max_length"], remediation: "fix_input", en: "Description must be at most {max_length} characters" }, "error.400.description_too_short": { status: 400, params: ["min_length"], remediation: "fix_input", en: "Description must be at least {min_length} characters" }, "error.400.expected_list": { status: 400, params: [], remediation: "fix_input", en: "Expected a list of items" }, "error.400.feature_above_maximum": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is above maximum for {feature}" }, "error.400.feature_below_minimum": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is below minimum for {feature}" }, "error.400.feature_invalid_config": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid config for {feature}" }, "error.400.feature_invalid_format": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid format for {feature}" }, "error.400.feature_invalid_rules": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid rules for {feature}" }, "error.400.feature_invalid_type": { status: 400, params: ["feature"], remediation: "fix_input", en: "Invalid type for {feature}" }, "error.400.feature_mandatory_missing": { status: 400, params: ["feature"], remediation: "fix_input", en: "Mandatory feature {feature} is required" }, "error.400.feature_not_allowed": { status: 400, params: ["feature"], remediation: "fix_input", en: "Feature {feature} is not allowed here" }, "error.400.feature_not_in_options": { status: 400, params: ["feature"], remediation: "fix_input", en: "Value is not in allowed options for {feature}" }, "error.400.feature_unknown": { status: 400, params: ["feature"], remediation: "fix_input", en: "Unknown feature {feature}" }, "error.400.feature_unknown_type": { status: 400, params: ["feature"], remediation: "fix_input", en: "Unknown feature type for {feature}" }, "error.400.field.blank": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} may not be blank" }, "error.400.field.does_not_exist": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} does not exist" }, "error.400.field.invalid": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is invalid" }, "error.400.field.invalid_choice": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is not a valid choice" }, "error.400.field.max_length": { status: 400, params: ["field","max_length"], remediation: "fix_input", en: "{field} must be at most {max_length} characters" }, "error.400.field.max_value": { status: 400, params: ["field","max_value"], remediation: "fix_input", en: "{field} must be at most {max_value}" }, "error.400.field.min_length": { status: 400, params: ["field","min_length"], remediation: "fix_input", en: "{field} must be at least {min_length} characters" }, "error.400.field.min_value": { status: 400, params: ["field","min_value"], remediation: "fix_input", en: "{field} must be at least {min_value}" }, "error.400.field.null": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} may not be null" }, "error.400.field.required": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} is required" }, "error.400.field.unique": { status: 400, params: ["field"], remediation: "fix_input", en: "{field} must be unique" }, "error.400.invalid_ad_id": { status: 400, params: [], remediation: "fix_input", en: "Invalid advertisement ID" }, "error.400.validation_error": { status: 400, params: [], remediation: "fix_input", en: "Validation error" }, "error.400.verification_failed": { status: 400, params: [], remediation: "verify", en: "Verification failed" }, "error.400.verification_invalid_factor": { status: 400, params: [], remediation: "verify", en: "This verification factor is not available" }, "error.401.unauthorized": { status: 401, params: [], remediation: "reauthenticate", en: "Authentication required" }, "error.402.payment_required": { status: 402, params: [], remediation: "retry", en: "Payment required" }, "error.403.forbidden": { status: 403, params: [], remediation: "retry", en: "You do not have permission to perform this action" }, "error.403.network_blocked": { status: 403, params: [], remediation: "contact_support", en: "Requests from this network are not allowed" }, "error.403.verification_enrollment_required": { status: 403, params: [], remediation: "verify", en: "Verification factor enrollment required" }, "error.403.verification_required": { status: 403, params: [], remediation: "verify", en: "Additional verification required" }, "error.404.ad_not_found": { status: 404, params: [], remediation: "retry", en: "Listing not found" }, "error.404.categories_slug_not_found": { status: 404, params: ["slug"], remediation: "retry", en: "No category with slug '{slug}'" }, "error.404.not_found": { status: 404, params: [], remediation: "retry", en: "Requested resource not found" }, "error.404.verification_challenge_not_found": { status: 404, params: [], remediation: "verify", en: "Verification challenge not found or expired" }, "error.405.method_not_allowed": { status: 405, params: [], remediation: "retry", en: "Method not allowed" }, "error.406.not_acceptable": { status: 406, params: [], remediation: "retry", en: "Not acceptable" }, "error.408.request_timeout": { status: 408, params: [], remediation: "retry", en: "Request timeout" }, "error.409.categories_feature_editor_conflict": { status: 409, params: ["expected","actual"], remediation: "fix_input", en: "Category was modified by another editor (expected revision {expected}, now {actual}); reload and retry" }, "error.409.conflict": { status: 409, params: [], remediation: "fix_input", en: "Resource already exists" }, "error.410.gone": { status: 410, params: [], remediation: "retry", en: "Resource has been permanently removed" }, "error.413.payload_too_large": { status: 413, params: [], remediation: "retry", en: "Request body is too large" }, "error.415.unsupported_media_type": { status: 415, params: [], remediation: "retry", en: "Unsupported media type" }, "error.422.unprocessable_entity": { status: 422, params: [], remediation: "wait_and_retry", en: "Unprocessable entity" }, "error.423.locked": { status: 423, params: [], remediation: "wait_and_retry", en: "Resource is locked" }, "error.423.verification_locked": { status: 423, params: [], remediation: "wait_and_retry", en: "Too many failed attempts — verification locked" }, "error.429.rate_limit": { status: 429, params: ["retry_after_minutes"], remediation: "wait_and_retry", en: "Too many attempts. Try again in {retry_after_minutes} minutes." }, "error.429.too_many_requests": { status: 429, params: [], remediation: "wait_and_retry", en: "Too many requests. Please try again later." }, "error.500.internal": { status: 500, params: [], remediation: "contact_support", en: "Something went wrong" }, "error.503.mandate_unavailable": { status: 503, params: [], remediation: "retry", en: "Cannot verify workspace mandate right now" }, } as const; export type CategoriesErrorCode = keyof typeof CATEGORIES_ERRORS; /** Every backend error code this module can surface, sorted. */ export const CATEGORIES_ERROR_CODES: readonly CategoriesErrorCode[] = [ "error.400.bad_request", "error.400.captcha_invalid", "error.400.captcha_required", "error.400.categories_config_required", "error.400.categories_database_error", "error.400.categories_duplicate_slug", "error.400.categories_expected_list", "error.400.categories_feature_editor_invalid", "error.400.categories_invalid_conversion", "error.400.categories_not_deleted", "error.400.description_too_long", "error.400.description_too_short", "error.400.expected_list", "error.400.feature_above_maximum", "error.400.feature_below_minimum", "error.400.feature_invalid_config", "error.400.feature_invalid_format", "error.400.feature_invalid_rules", "error.400.feature_invalid_type", "error.400.feature_mandatory_missing", "error.400.feature_not_allowed", "error.400.feature_not_in_options", "error.400.feature_unknown", "error.400.feature_unknown_type", "error.400.field.blank", "error.400.field.does_not_exist", "error.400.field.invalid", "error.400.field.invalid_choice", "error.400.field.max_length", "error.400.field.max_value", "error.400.field.min_length", "error.400.field.min_value", "error.400.field.null", "error.400.field.required", "error.400.field.unique", "error.400.invalid_ad_id", "error.400.validation_error", "error.400.verification_failed", "error.400.verification_invalid_factor", "error.401.unauthorized", "error.402.payment_required", "error.403.forbidden", "error.403.network_blocked", "error.403.verification_enrollment_required", "error.403.verification_required", "error.404.ad_not_found", "error.404.categories_slug_not_found", "error.404.not_found", "error.404.verification_challenge_not_found", "error.405.method_not_allowed", "error.406.not_acceptable", "error.408.request_timeout", "error.409.categories_feature_editor_conflict", "error.409.conflict", "error.410.gone", "error.413.payload_too_large", "error.415.unsupported_media_type", "error.422.unprocessable_entity", "error.423.locked", "error.423.verification_locked", "error.429.rate_limit", "error.429.too_many_requests", "error.500.internal", "error.503.mandate_unavailable", ]; /** * English fallback bundle — one string per backend key, so a `StapelApiError.code` * never renders as a raw key. Merged UNDER the hand-polished UI copy in * {@link authI18nBundleEn} (polish wins; this guarantees coverage). */ export const categoriesErrorBundleEn: Record = { "error.400.bad_request": "Bad request", "error.400.captcha_invalid": "Captcha verification failed. Please try again.", "error.400.captcha_required": "Captcha token is required.", "error.400.categories_config_required": "A config object is required", "error.400.categories_database_error": "Database error while applying changes", "error.400.categories_duplicate_slug": "A feature with slug '{slug}' already exists", "error.400.categories_expected_list": "Expected a list of objects", "error.400.categories_feature_editor_invalid": "Invalid feature editor request: {reason}", "error.400.categories_invalid_conversion": "Invalid type conversion (only select<->string is supported)", "error.400.categories_not_deleted": "Category is not deleted", "error.400.description_too_long": "Description must be at most {max_length} characters", "error.400.description_too_short": "Description must be at least {min_length} characters", "error.400.expected_list": "Expected a list of items", "error.400.feature_above_maximum": "Value is above maximum for {feature}", "error.400.feature_below_minimum": "Value is below minimum for {feature}", "error.400.feature_invalid_config": "Invalid config for {feature}", "error.400.feature_invalid_format": "Invalid format for {feature}", "error.400.feature_invalid_rules": "Invalid rules for {feature}", "error.400.feature_invalid_type": "Invalid type for {feature}", "error.400.feature_mandatory_missing": "Mandatory feature {feature} is required", "error.400.feature_not_allowed": "Feature {feature} is not allowed here", "error.400.feature_not_in_options": "Value is not in allowed options for {feature}", "error.400.feature_unknown": "Unknown feature {feature}", "error.400.feature_unknown_type": "Unknown feature type for {feature}", "error.400.field.blank": "{field} may not be blank", "error.400.field.does_not_exist": "{field} does not exist", "error.400.field.invalid": "{field} is invalid", "error.400.field.invalid_choice": "{field} is not a valid choice", "error.400.field.max_length": "{field} must be at most {max_length} characters", "error.400.field.max_value": "{field} must be at most {max_value}", "error.400.field.min_length": "{field} must be at least {min_length} characters", "error.400.field.min_value": "{field} must be at least {min_value}", "error.400.field.null": "{field} may not be null", "error.400.field.required": "{field} is required", "error.400.field.unique": "{field} must be unique", "error.400.invalid_ad_id": "Invalid advertisement ID", "error.400.validation_error": "Validation error", "error.400.verification_failed": "Verification failed", "error.400.verification_invalid_factor": "This verification factor is not available", "error.401.unauthorized": "Authentication required", "error.402.payment_required": "Payment required", "error.403.forbidden": "You do not have permission to perform this action", "error.403.network_blocked": "Requests from this network are not allowed", "error.403.verification_enrollment_required": "Verification factor enrollment required", "error.403.verification_required": "Additional verification required", "error.404.ad_not_found": "Listing not found", "error.404.categories_slug_not_found": "No category with slug '{slug}'", "error.404.not_found": "Requested resource not found", "error.404.verification_challenge_not_found": "Verification challenge not found or expired", "error.405.method_not_allowed": "Method not allowed", "error.406.not_acceptable": "Not acceptable", "error.408.request_timeout": "Request timeout", "error.409.categories_feature_editor_conflict": "Category was modified by another editor (expected revision {expected}, now {actual}); reload and retry", "error.409.conflict": "Resource already exists", "error.410.gone": "Resource has been permanently removed", "error.413.payload_too_large": "Request body is too large", "error.415.unsupported_media_type": "Unsupported media type", "error.422.unprocessable_entity": "Unprocessable entity", "error.423.locked": "Resource is locked", "error.423.verification_locked": "Too many failed attempts — verification locked", "error.429.rate_limit": "Too many attempts. Try again in {retry_after_minutes} minutes.", "error.429.too_many_requests": "Too many requests. Please try again later.", "error.500.internal": "Something went wrong", "error.503.mandate_unavailable": "Cannot verify workspace mandate right now", };