harden: address adversarial review of Pods CRUD

Backend: atomic create with insert-retry-on-duplicate-key (removes slug
TOCTOU race + wrong 400s), resilient per-index creation so a unique-index
failure can't silently drop the constraint or block seeding, idempotent
race-safe seeding via $setOnInsert, type validation + size caps on all pod
fields/members, removeMember no-ops without a write, /api/outcome guarded.
Frontend: per-pod busy state (one mutation no longer disables every card),
joined pod derived from the list (can't go stale), create keeps inputs on error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kartikeya
2026-06-27 16:02:40 -07:00
parent 4ddc59be08
commit 7ff750ad5e
5 changed files with 163 additions and 78 deletions
+17 -12
View File
@@ -6,7 +6,7 @@ export function CreatePodForm({
onCreate,
}: {
busy: boolean;
onCreate: (input: PodInput) => void;
onCreate: (input: PodInput) => Promise<void>;
}) {
const [open, setOpen] = useState(false);
const [name, setName] = useState('');
@@ -14,18 +14,23 @@ export function CreatePodForm({
const [description, setDescription] = useState('');
const [firstMember, setFirstMember] = useState('');
function submit() {
async function submit() {
if (!name.trim()) return;
onCreate({
name: name.trim(),
repo: repo.trim(),
description: description.trim(),
members: firstMember.trim() ? [firstMember.trim()] : [],
});
setName('');
setDescription('');
setFirstMember('');
setOpen(false);
try {
await onCreate({
name: name.trim(),
repo: repo.trim(),
description: description.trim(),
members: firstMember.trim() ? [firstMember.trim()] : [],
});
// only clear + close on success; on error keep the user's input
setName('');
setDescription('');
setFirstMember('');
setOpen(false);
} catch {
/* error surfaced by parent; keep inputs so nothing is lost */
}
}
if (!open) {