generated from coulomb/repo-seed
- T01: Go module (keycape), full directory skeleton, Makefile, CI workflow - T02: spec/canonical-model.yaml with 6 entities + Go domain types - T03: spec/ldap-schema.yaml + validator binary with structural/semantic rules - T04: Error taxonomy — 4 stable error types, JSON format, HTTP helpers 28 tests pass, go vet clean, go build clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
86 lines
2.8 KiB
Go
86 lines
2.8 KiB
Go
// Package errors implements the KeyCape error taxonomy from spec §5.
|
|
// All profile errors are structured and machine-readable.
|
|
// Errors MUST NOT be silent — every unsupported or misused feature returns a typed error.
|
|
package errors
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
)
|
|
|
|
// ErrorType is a stable string identifier for profile error categories.
|
|
type ErrorType string
|
|
|
|
const (
|
|
// ErrFeatureNotSupported is returned when a feature is outside the NetKingdom IAM Profile.
|
|
ErrFeatureNotSupported ErrorType = "feature_not_supported_by_profile"
|
|
|
|
// ErrKeycloakModeOnly is returned when a feature exists only in expanded (Keycloak) mode.
|
|
ErrKeycloakModeOnly ErrorType = "available_in_keycloak_mode_only"
|
|
|
|
// ErrRejectedForSafety is returned when a feature is intentionally blocked for security reasons.
|
|
ErrRejectedForSafety ErrorType = "rejected_for_profile_safety"
|
|
|
|
// ErrInvalidProfileUsage is returned when a supported endpoint/feature is used incorrectly.
|
|
ErrInvalidProfileUsage ErrorType = "invalid_profile_usage"
|
|
)
|
|
|
|
// ProfileError is a structured error per spec §5.2.
|
|
// JSON format: {"error": "...", "description": "...", "feature": "..."}
|
|
type ProfileError struct {
|
|
Error ErrorType `json:"error"`
|
|
Description string `json:"description"`
|
|
Feature string `json:"feature,omitempty"`
|
|
}
|
|
|
|
// Write writes the error as JSON with the given HTTP status code.
|
|
func (e *ProfileError) Write(w http.ResponseWriter, status int) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(e)
|
|
}
|
|
|
|
// GoError implements the standard error interface.
|
|
func (e *ProfileError) GoError() string {
|
|
if e.Feature != "" {
|
|
return string(e.Error) + ": " + e.Description + " [feature=" + e.Feature + "]"
|
|
}
|
|
return string(e.Error) + ": " + e.Description
|
|
}
|
|
|
|
// FeatureNotSupported constructs a feature_not_supported_by_profile error.
|
|
func FeatureNotSupported(description, feature string) *ProfileError {
|
|
return &ProfileError{
|
|
Error: ErrFeatureNotSupported,
|
|
Description: description,
|
|
Feature: feature,
|
|
}
|
|
}
|
|
|
|
// KeycloakModeOnly constructs an available_in_keycloak_mode_only error.
|
|
func KeycloakModeOnly(description, feature string) *ProfileError {
|
|
return &ProfileError{
|
|
Error: ErrKeycloakModeOnly,
|
|
Description: description,
|
|
Feature: feature,
|
|
}
|
|
}
|
|
|
|
// RejectedForSafety constructs a rejected_for_profile_safety error.
|
|
func RejectedForSafety(description, feature string) *ProfileError {
|
|
return &ProfileError{
|
|
Error: ErrRejectedForSafety,
|
|
Description: description,
|
|
Feature: feature,
|
|
}
|
|
}
|
|
|
|
// InvalidProfileUsage constructs an invalid_profile_usage error.
|
|
func InvalidProfileUsage(description, feature string) *ProfileError {
|
|
return &ProfileError{
|
|
Error: ErrInvalidProfileUsage,
|
|
Description: description,
|
|
Feature: feature,
|
|
}
|
|
}
|