Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The backend inside a workspace is pluggable. OpenClaw is one example runtime. An

> Spritz is in active development and should be treated as alpha software. APIs, CRDs, Helm values, and UI details may still change while the deployment model is being hardened.

[Deployment Spec](docs/2026-02-24-simplest-spritz-deployment-spec.md) · [ACP Architecture](docs/2026-03-09-acp-port-and-agent-chat-architecture.md) · [Portable Auth](docs/2026-02-24-portable-authentication-and-account-architecture.md) · [External Provisioners](docs/2026-03-11-external-provisioner-and-service-principal-architecture.md) · [OpenClaw Integration](OPENCLAW.md)
[Deployment Spec](docs/2026-02-24-simplest-spritz-deployment-spec.md) · [ACP Architecture](docs/2026-03-09-acp-port-and-agent-chat-architecture.md) · [Portable Auth](docs/2026-02-24-portable-authentication-and-account-architecture.md) · [External Provisioners](docs/2026-03-11-external-provisioner-and-service-principal-architecture.md) · [External Identity Resolution](docs/2026-03-12-external-identity-resolution-api-architecture.md) · [OpenClaw Integration](OPENCLAW.md)

## Vision

Expand Down
26 changes: 24 additions & 2 deletions api/create_request_normalization.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type createRequestError struct {
status int
message string
data any
err error
}

Expand All @@ -34,9 +35,21 @@ func newCreateRequestError(status int, err error) error {
}
}

func newCreateRequestErrorWithData(status int, message string, data any, err error) error {
return &createRequestError{
status: status,
message: message,
data: data,
err: err,
}
}

func writeCreateRequestError(c echo.Context, err error) error {
var requestErr *createRequestError
if errors.As(err, &requestErr) {
if requestErr.data != nil {
return writeJSendFailData(c, requestErr.status, requestErr.data)
}
return writeError(c, requestErr.status, requestErr.message)
}
return writeError(c, http.StatusInternalServerError, err.Error())
Expand Down Expand Up @@ -73,11 +86,20 @@ func (s *server) normalizeCreateRequest(_ context.Context, principal principal,
}
requestedNamespace := s.namespaceOverrideRequested(body.Namespace, namespace)

owner, err := normalizeCreateOwner(&body, principal, s.auth.enabled())
owner, err := normalizeCreateOwnerRequest(&body, principal, s.auth.enabled())
if err != nil {
if errors.Is(err, errForbidden) {
return nil, newCreateRequestError(http.StatusForbidden, err)
}
return nil, newCreateRequestError(http.StatusBadRequest, err)
}
body.Spec.Owner = owner
if body.OwnerRef != nil && strings.EqualFold(strings.TrimSpace(body.OwnerRef.Type), "external") {
if !principal.isService() {
return nil, newCreateRequestError(http.StatusForbidden, errForbidden)
}
} else {
body.Spec.Owner = owner
}
fingerprintRequest := body

requestedImage := strings.TrimSpace(body.Spec.Image) != ""
Expand Down
Loading
Loading