rebased for readability - #7
Merged
Merged
Conversation
No backward compatibility needed - this feature hasn't shipped. Replaces
JSON as the sole format for the ```poll fenced Markdown block on both
sides:
- Frontend: parsePollDefinition (types.ts) now parses with the `yaml`
package instead of JSON.parse; CreatePollDialog serializes with
YAML.stringify instead of JSON.stringify, producing exactly the target
block shape (id/question/type/options as a plain mapping, options as a
block sequence).
- Backend: poll_definition.go's rawPollDefinition struct tags switch from
`json:"..."` to `yaml:"..."`, and findPollDefinitionInContent unmarshals
with gopkg.in/yaml.v3 (already a direct dependency) instead of
encoding/json.
Everything the task asked to keep intact is untouched: the nested voting
route (/api/v1/memos/{memoUid}/polls/{pollUid}/votes) and
EnsurePollBinding's memo-authorization flow, the strict pollUIDPattern
UUID regex, and deletePollDataByMemoIDsTx's user/memo-cascade cleanup
(store/db/{sqlite,postgres,mysql}/user_delete.go - this is the actual name
of the cleanup function the task referred to as
deletePollVotesByVoterTx; it deletes both poll and poll_vote rows by
memo_id, not by voter, and was not touched by this change).
While preserving pollDefinitionHash's canonical/injective requirement,
switching formats surfaced a real pre-existing bug worth fixing here:
the hash wrote a bare NUL byte as a separator between options with no
length prefix, which is not actually injective - an option string that
itself contains a NUL byte reproduces that exact separator byte sequence,
so e.g. options ["ab", "c"] and a single option "ab\x00c" hashed
identically. YAML permits arbitrary control characters in a quoted
scalar, so this was reachable from memo content, not just internal data,
and a collision here would let an edited option set silently keep votes
that should have been reset as stale. Replaced the separator with a
fixed-width big-endian length prefix per field (Type and each Option),
which is unambiguous regardless of content - this is what "canonical/
injective serialization" actually requires, and is why option identity in
this hash was still separator-based rather than delimiter-free lengths
even in the JSON version's design intent.
Added tests for both: server/router/api/v1/poll_definition_test.go covers
YAML parsing (block/flow style, defaulting to single-choice, UID
mismatch, malformed YAML, too few options) and the hash property directly
(formatting-invariance, the concatenation collision the length prefix
fixes, and the NUL-byte-smuggling case specifically) - the NUL-smuggling
test fails against the pre-fix hash implementation, confirming it
exercises the real bug. web/tests/poll-definition.test.ts covers the
same parsing surface from the frontend side.
Verified end to end against a live server: created a memo whose content
is exactly the target YAML block example, confirmed it round-trips
through save untouched, voted through the nested route, read back
matching tallies, and deleted the memo (exercising the poll/poll_vote
cascade cleanup) without error. Full go test ./... and the full frontend
vitest suite (1127 tests) both pass.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016UZX8r5o3xdW8uKDTQv6Mb
…leanup
Two gaps found while rebasing the YAML-format refactor onto commits pushed
directly to this branch in parallel:
1. store/migration/postgres/0.32/01__poll_definition.sql was deleted
("no need for this file."). That file is the actual fix for the
"column memo_id does not exist" bug reported earlier on this branch: a
Postgres database that already recorded schema version 0.32.1 from the
original poll_vote-only migration has no path to the poll table or
poll_vote.memo_id without it, since editing the already-applied 0.32/00
file in place (what an earlier commit had done) has no effect on a
database that already ran it - schema version tracking is a monotonic
per-version marker, not a per-file-content hash. Deleting 0.32/01
silently drops GetCurrentSchemaVersion's computed target for Postgres
back to 0.32.1 too, so Migrate() sees current == target and skips
migration entirely - such a database would stay stuck exactly at the
bug's original broken state. Restored the file (byte-identical to what
was verified end-to-end in this branch's earlier fix: built the pre-fix
binary, created a poll_vote row under the old schema, then ran the
fixed binary against that same data directory and confirmed both the
migration and the previously-failing memo delete succeed).
2. deletePollVotesByVoterTx (added to store/db/postgres/user_delete.go in
a parallel commit) was Postgres-only. It's a real, distinct gap from
deletePollDataByMemoIDsTx: that function only cleans up poll data for
memos the deleted user owns, so a vote the user cast on someone *else's*
memo survives deletion as a poll_vote row whose voter_id no longer
resolves to any user. Mirrored the same function (with an explanatory
comment) to store/db/{sqlite,mysql}/user_delete.go, matching this
codebase's established pattern of giving every driver equivalent
treatment. Extended TestDeleteUserCleansRelatedData
(store/test/user_delete_test.go) with exactly this scenario - the
deleted user and a peer both vote on the peer's memo poll - and
confirmed only the deleted user's vote is gone; verified the assertion
actually exercises the fix by reverting the SQLite half of it locally,
watching the test fail, then restoring it.
Full go test ./... and frontend tsc --noEmit pass.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016UZX8r5o3xdW8uKDTQv6Mb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
had to start over with some stuff but everything should work now.