Files
pieced-portal/src/app/api/admin/openclaw/route.ts
admin b58bdadad4
All checks were successful
Build and Push / build (push) Successful in 1m52s
feat(openclaw): per-tenant tag override + platform default ConfigMap (tag-only)
2026-05-10 21:15:53 +02:00

76 lines
2.3 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { getSessionUser } from "@/lib/session";
import { getOpenClawDefaults, setOpenClawDefaults } from "@/lib/k8s";
import { safeError } from "@/lib/errors";
/**
* Platform-wide default OpenClaw image tag (admin-only).
*
* GET — read the current default tag from the
* `pieced-openclaw-config` ConfigMap. Can be empty string if no
* default is configured; the operator uses its built-in fallback
* in that case.
*
* PATCH — update the tag. Send "" to clear. The operator watches
* this ConfigMap and re-enqueues all tenants without a per-tenant
* override on change, so existing tenants roll forward to the new
* default automatically. Tenants WITH an override are unaffected.
*
* Tag-only by design — see operator notes.
*/
const patchSchema = z.object({
defaultTag: z.string().trim().max(256),
});
export async function GET() {
const user = await getSessionUser();
if (!user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (!user.isPlatform) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
try {
return NextResponse.json(await getOpenClawDefaults());
} catch (e: any) {
console.error("Failed to read openclaw defaults:", e);
return NextResponse.json(
{ error: safeError(e, "Failed to read defaults") },
{ status: 500 }
);
}
}
export async function PATCH(req: NextRequest) {
const user = await getSessionUser();
if (!user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
if (!user.isPlatform) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const body = await req.json().catch(() => null);
const parsed = patchSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json(
{ error: "Invalid input", details: parsed.error.flatten() },
{ status: 400 }
);
}
try {
const next = await setOpenClawDefaults({
defaultTag: parsed.data.defaultTag,
});
return NextResponse.json(next);
} catch (e: any) {
console.error("Failed to update openclaw defaults:", e);
return NextResponse.json(
{ error: safeError(e, "Failed to update defaults") },
{ status: 500 }
);
}
}