Files
key-cape/src/internal/errors/taxonomy.go
tegwick 329e996619 feat: implement T01-T04 — Go module, canonical model, LDAP validator, error taxonomy
- 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>
2026-03-13 01:27:54 +01:00

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,
}
}