From 904206013aadd7dca5851cb15cace61880a6a14d Mon Sep 17 00:00:00 2001 From: Jared Schoeny Date: Sat, 3 Oct 2026 04:54:35 -0600 Subject: [PATCH] Treat a custom author name alone as a display name, not an upload on someone's behalf (#103) Creators who were given a custom original_author (e.g. a team name) without a permission source were asked for "Where the creator gave permission" in Listing health, and their details sheet refused to save. Only hacks with permission_from are on someone's behalf now. Co-authored-by: Claude Opus 5.5 (1M context) --- src/app/hack/actions.ts | 3 ++- src/app/submit/actions.ts | 3 +-- src/components/Hack/Draft/DraftDetails.tsx | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/hack/actions.ts b/src/app/hack/actions.ts index 04e1f5c..539ad94 100644 --- a/src/app/hack/actions.ts +++ b/src/app/hack/actions.ts @@ -97,7 +97,8 @@ export async function updateHack(args: { if (args.box_art !== undefined) updatePayload.box_art = args.box_art; if (args.social_links !== undefined) updatePayload.social_links = args.social_links; if (args.original_author !== undefined || args.permission_from !== undefined) { - if (!hack.original_author) { + // A custom display name alone (original_author without permission_from) isn't an upload on someone's behalf. + if (!hack.permission_from) { return { ok: false, error: "This hack was not uploaded on someone else's behalf" } as const; } if (args.original_author?.trim() === "" || args.permission_from?.trim() === "") { diff --git a/src/app/submit/actions.ts b/src/app/submit/actions.ts index 128e0c7..d10ad67 100644 --- a/src/app/submit/actions.ts +++ b/src/app/submit/actions.ts @@ -318,7 +318,7 @@ export async function createDraft(formData: FormData) { export async function getDraftChecklist(slug: string) { const supabase = await createClient(); const [{ data: hack }, { count: covers }, { count: tags }] = await Promise.all([ - supabase.from("hacks").select("base_rom,summary,description,completion_status,language,original_author,permission_from,ai_disclosed_at,current_patch").eq("slug", slug).maybeSingle(), + supabase.from("hacks").select("base_rom,summary,description,completion_status,language,ai_disclosed_at,current_patch").eq("slug", slug).maybeSingle(), supabase.from("hack_covers").select("id", { count: "exact", head: true }).eq("hack_slug", slug), supabase.from("hack_tags").select("tag_id", { count: "exact", head: true }).eq("hack_slug", slug), ]); @@ -334,7 +334,6 @@ export async function getDraftChecklist(slug: string) { { key: "shots", label: "At least one screenshot", done: (covers ?? 0) > 0 }, { key: "tags", label: "At least one tag", done: (tags ?? 0) > 0 }, { key: "ai", label: "AI label filled in", done: !!hack.ai_disclosed_at }, - ...(hack.original_author ? [{ key: "permission", label: "Where the creator gave permission", done: !!hack.permission_from }] : []), ]; const recommended = [ { key: "tags3", label: "Add at least 3 tags so players can find it", done: (tags ?? 0) >= 3 }, diff --git a/src/components/Hack/Draft/DraftDetails.tsx b/src/components/Hack/Draft/DraftDetails.tsx index 9ced53a..3d78a27 100644 --- a/src/components/Hack/Draft/DraftDetails.tsx +++ b/src/components/Hack/Draft/DraftDetails.tsx @@ -17,8 +17,8 @@ export interface DraftDetailsValues { completion_status: Completion | null; box_art: string | null; social_links: Social | null; - /** Set on hacks uploaded on someone else's behalf; shows the creator fields. */ original_author: string | null; + /** Set on hacks uploaded on someone else's behalf; shows the creator fields. An original_author alone is just a custom display name. */ permission_from: string | null; /** Left out once the hack is listed, since admins only read it during review. */ verification_contact_info?: string | null; @@ -99,7 +99,7 @@ export default function DraftDetails({ values, baseLocked, children }: DraftDeta { setApplied(form);