Summary
Several mutation operations accept inputs that violate basic invariants and persist them. This is on top of #108 (validate phase doesn't validate) — these cases reproduce even on phase: "execute".
All reproduce against production eagles.kychon.com.
Cases
1. forum.topics.create accepts entirely empty input
As active_member with input: {}:
{
"result": {
"id": 10128,
"category_id": null,
"title": "Untitled",
"body": "",
...
}
}
Creates an "Untitled" topic with no category, no body. Members can spam orphan topics with no required fields.
Expected: validation.failed requiring at least category_id + title.
2. events.create accepts backwards dates (ends_at < starts_at)
As admin:
-d '{"...input":{"title":"foo","starts_at":"2099-12-31T23:59:59Z","ends_at":"2026-01-01T00:00:00Z"}}'
Event is created with ends_at ~74 years before starts_at.
Expected: validation.failed on the date ordering.
3. events.create accepts negative capacity
-d '{"...input":{"title":"foo","capacity":-100,"starts_at":"2099-...","ends_at":"2099-..."}}'
Capacity -100 persists as-is.
Expected: validation.failed or coerce to 0.
4. rsvps.setStatus accepts arbitrary status string
As active_member:
-d '{"...input":{"event_id":6754,"status":"hacking_attempt"}}'
Returns ok: true with status: "hacking_attempt" stored. No enum check.
Expected: validation.failed requiring status in (going, not_going, maybe, cancelled — whatever the agreed enum is).
5. events.create / tiers.create with garbage types return opaque internal.error
-d '{"...operation":"events.create","input":{"title":"x","starts_at":"not-a-date","ends_at":"banana"}}'
# → {"ok":false,"error":{"code":"internal.error","message":"Execution failed for events.create.","retryable":true}}
Bad type should return validation.failed with the offending field; instead it returns internal.error with retryable: true (which is wrong — same input will fail the same way).
Why this matters
- Forum data quality (orphan "Untitled" topics).
- Calendar correctness (negative-duration events break list/render code).
- Capacity logic (negative numbers break "available seats" math).
- Audit/analytics on RSVP states is meaningless if the status column is free-form text.
retryable: true on validation-class errors causes well-behaved clients to retry indefinitely.
Suggested approach
Add a per-operation input schema (Zod or similar) wired through executeMutation and createActionPlan (so validate enforces the same — see #108). Map schema failures to validation.failed with structured detail.
Summary
Several mutation operations accept inputs that violate basic invariants and persist them. This is on top of #108 (validate phase doesn't validate) — these cases reproduce even on
phase: "execute".All reproduce against production
eagles.kychon.com.Cases
1.
forum.topics.createaccepts entirely empty inputAs active_member with
input: {}:{ "result": { "id": 10128, "category_id": null, "title": "Untitled", "body": "", ... } }Creates an "Untitled" topic with no category, no body. Members can spam orphan topics with no required fields.
Expected:
validation.failedrequiring at leastcategory_id+title.2.
events.createaccepts backwards dates (ends_at < starts_at)As admin:
-d '{"...input":{"title":"foo","starts_at":"2099-12-31T23:59:59Z","ends_at":"2026-01-01T00:00:00Z"}}'Event is created with
ends_at~74 years beforestarts_at.Expected:
validation.failedon the date ordering.3.
events.createaccepts negative capacity-d '{"...input":{"title":"foo","capacity":-100,"starts_at":"2099-...","ends_at":"2099-..."}}'Capacity
-100persists as-is.Expected:
validation.failedor coerce to 0.4.
rsvps.setStatusaccepts arbitrary status stringAs active_member:
-d '{"...input":{"event_id":6754,"status":"hacking_attempt"}}'Returns
ok: truewithstatus: "hacking_attempt"stored. No enum check.Expected:
validation.failedrequiring status in (going,not_going,maybe,cancelled— whatever the agreed enum is).5.
events.create/tiers.createwith garbage types return opaqueinternal.errorBad type should return
validation.failedwith the offending field; instead it returnsinternal.errorwithretryable: true(which is wrong — same input will fail the same way).Why this matters
retryable: trueon validation-class errors causes well-behaved clients to retry indefinitely.Suggested approach
Add a per-operation input schema (Zod or similar) wired through
executeMutationandcreateActionPlan(sovalidateenforces the same — see #108). Map schema failures tovalidation.failedwith structureddetail.