initial commit

This commit is contained in:
2026-08-16 21:18:45 -05:00
commit 1e05a01bcf
122 changed files with 29178 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
// Package app is the service layer. It holds every business operation the
// management interface offers, so the HTML handlers and the REST API share one
// implementation of validation, auditing and cache invalidation rather than
// each growing their own.
package app
import (
"errors"
"fmt"
"net/http"
)
// Error is a user-facing failure with an HTTP status attached.
//
// Messages are written for an administrator reading them in a toast or a JSON
// response: they say what went wrong and, where useful, what to do about it.
// Internal detail goes in the wrapped error, which is logged but never shown.
type Error struct {
Status int
Message string
Err error
}
func (e *Error) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %v", e.Message, e.Err)
}
return e.Message
}
func (e *Error) Unwrap() error { return e.Err }
// Invalid reports a client mistake such as a malformed record.
func Invalid(format string, args ...any) *Error {
return &Error{Status: http.StatusBadRequest, Message: fmt.Sprintf(format, args...)}
}
// NotFound reports a missing object.
func NotFound(format string, args ...any) *Error {
return &Error{Status: http.StatusNotFound, Message: fmt.Sprintf(format, args...)}
}
// Conflict reports a uniqueness violation.
func Conflict(format string, args ...any) *Error {
return &Error{Status: http.StatusConflict, Message: fmt.Sprintf(format, args...)}
}
// Forbidden reports an operation the caller may not perform.
func Forbidden(format string, args ...any) *Error {
return &Error{Status: http.StatusForbidden, Message: fmt.Sprintf(format, args...)}
}
// Internal wraps an unexpected failure. The message is safe to show; err is
// logged server-side.
func Internal(err error, format string, args ...any) *Error {
return &Error{Status: http.StatusInternalServerError, Message: fmt.Sprintf(format, args...), Err: err}
}
// StatusOf maps any error to an HTTP status code.
func StatusOf(err error) int {
var e *Error
if errors.As(err, &e) {
return e.Status
}
return http.StatusInternalServerError
}
// MessageOf returns the user-facing message for an error, falling back to a
// generic sentence so internal detail never leaks into a response.
func MessageOf(err error) string {
var e *Error
if errors.As(err, &e) {
return e.Message
}
return "An unexpected error occurred. Check the server log for details."
}
// IsInternal reports whether an error should be logged with its full detail.
func IsInternal(err error) bool { return StatusOf(err) >= 500 }