fix(db,topics): time.Time params for TIMESTAMP + comment-aware SQL split

Two fixes surfaced by sim e2e test (which otherwise passed full
lifecycle: created → signup_open → 3 signups → allocator → debating
→ arguments → verdict gate (409 early, 201 after debate_end_at) →
completed).

1) MySQL TIMESTAMP rejects RFC3339-with-Z strings — passing those as
   sqlx parameters fails with "Incorrect datetime value". Changed
   CreateTopicInput lifecycle fields from string to time.Time; the
   handler parses+UTCs in validateLifecycleTimes (which now returns
   the parsed array along with the validation result) and passes
   time.Time to the store. The mysql driver formats correctly.

2) splitSQL was naive `strings.Split(s, ";")` which split inside
   comments — the 001 migration had a few `--` lines containing `;`
   ("signup_close_at; immutable", etc) which broke. Migration text
   tidied to not use `;` inside comments, AND splitSQL upgraded to
   skip both `-- ...` and `/* ... */` comment regions before splitting.

Sim verified — clean apply on fresh MySQL.
This commit is contained in:
h z
2026-05-23 12:24:13 +01:00
parent 57a1fa1b33
commit 03b89a547c
4 changed files with 54 additions and 26 deletions

View File

@@ -1,7 +1,7 @@
-- 001_init.sql — Dialectic v2 schema (greenfield, replaces Python v1).
-- See /home/hzhang/arch/DIALECTIC-V2-DESIGN.md for the design.
-- Verdict schemas — declared at topic-creation time; judge produces output matching.
-- Verdict schemas — declared at topic-creation time, judge produces output matching.
CREATE TABLE verdict_schemas (
id VARCHAR(64) NOT NULL PRIMARY KEY,
description TEXT NOT NULL,
@@ -60,7 +60,7 @@ CREATE TABLE signups (
-- Camps: the post-allocation assignment. One row per (topic, camp) with
-- the locked-in agent. Written by camp-allocation algorithm at
-- signup_close_at; immutable afterwards (no drop-out / replacement in v1).
-- signup_close_at immutable afterwards (no drop-out / replacement in v1).
CREATE TABLE camps (
id CHAR(36) NOT NULL PRIMARY KEY,
topic_id CHAR(36) NOT NULL,
@@ -73,7 +73,7 @@ CREATE TABLE camps (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Rounds: chronological partition of arguments. Each topic has N rounds
-- (typically 3-5); round 0 is the opening. Round transitions are driven
-- (typically 3-5), round 0 is the opening. Round transitions are driven
-- by the orchestrator on a schedule (or all-participants-posted).
CREATE TABLE rounds (
id CHAR(36) NOT NULL PRIMARY KEY,
@@ -86,7 +86,7 @@ CREATE TABLE rounds (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Arguments: an individual contribution within a round by a camp's agent.
-- For pro/con these are claims/rebuttals; for judge these are clarifying
-- For pro/con these are claims/rebuttals for judge these are clarifying
-- questions (judge is silent observer in v1 except for clarifications).
CREATE TABLE arguments (
id CHAR(36) NOT NULL PRIMARY KEY,
@@ -118,7 +118,7 @@ CREATE TABLE verdicts (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Agent API keys: provisioned per agent at recruitment time. Stored as
-- sha256(pepper || raw); pepper rotation invalidates all keys.
-- sha256(pepper || raw) pepper rotation invalidates all keys.
CREATE TABLE agent_keys (
agent_id VARCHAR(64) NOT NULL PRIMARY KEY,
key_hash CHAR(64) NOT NULL UNIQUE,