Repository navigation
Record, tally and delete cosigns of conference testimony - #2314
Draft
fastfadingviolets wants to merge 7 commits into
Draft
fastfadingviolets wants to merge 7 commits into
fastfadingviolets wants to merge 7 commits into
Conversation
Draft 1 of the cosign feature requirements: triggers, functional and non-functional requirements, failure behaviour and what is out of scope. The UI it describes is the client designer's /cosign-viz mockup, pinned at k-g-k/maple-conference@19bd101. Closes #91 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cosign is conference testimony that names the publication it seconds, by id and author, in two new fields that are both set or both null. It is published through the same path as other testimony: publish reads the parent in its transaction, refuses a parent that is gone, the cosigner's own, itself a cosign, or on another conference, and copies the parent's position on first publish and keeps it on every edit. A published cosign stays a cosign of that parent, and plain testimony stays plain. A cosign's note may be empty, and it takes no attachment; other testimony still needs content. The Firestore rules already allow an empty draft, so they are unchanged. Existing testimony has no reference and reads as before. Closes #93 Verified: yarn test:integration-ci on the six suites CI runs (83 passed), including new cosign cases for filing, note edits keeping the copied position after the parent changes, a double submit leaving one cosign, and each refusal; functions unit tests from src (128 passed); type checks (root errors only in untracked local scratch scripts); prettier check; lint on the changed files. Not verified: a cosign published against the dev backend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
publishedAt moves with every edit, so nothing on a publication said when it was first filed. Publish now sets firstPublishedAt on a first publication and keeps it through edits. Editing older testimony that lacks it leaves it missing rather than stamping the edit time, so the functions deploy and the backfill can run in either order. backfillTestimonyFirstPublishedAt fills it from the archive, which every publish has written to since 2022 and deletes keep. It takes the earliest archived version with the publication's id, or, for archives from before July 2022 that carry no id, with the same bill, court and target; the earlier wins. A version 1 publication with no archive is its own first. It has --dry-run, skips documents already set, and is listed in scripts/README.md; its integration test joins the CI list. Verified: yarn test:integration-ci on the six CI suites plus the new backfill suite (94 passed), including first publication kept through an edit, older testimony left for the backfill, and the backfill's id, pre-July-2022 scope, admin-deleted republish, version 1, already-set and dry-run cases; functions type check; root type check; prettier; lint on the changed files. Not verified: the backfill against dev or prod data, including how many publications it leaves with no first publication found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cosigned testimony now carries how many have cosigned it, how many distinct Senate and House districts they come from, and when the latest cosign was first published. A trigger on published testimony recounts them from the cosigns whenever a write changes what a cosign contributes, inside a transaction that reads the parent and every cosign of it. Retried or reordered events therefore land on the same figures, and an edit to a note writes nothing. A cosigner with no district on file counts toward the total only. The recount reads cosigns through a new collection-group index on cosignOfId. Publish replaces the publication on every version, so it now carries the tally across when the parent's author edits. It also records the author's districts, which it never had: it read profile fields that don't exist rather than the district on the profile's senator and representative. Closes #94 Verified: yarn test:integration-ci on the six CI suites plus the backfill suite, with Typesense running as in CI (94 passed), including the tally following cosigns published from shared and distinct districts and with none, a note edit not counting as a new cosign, an admin deleting the newest cosign, the parent's author editing, and districts recorded on plain testimony; cosignTally unit tests and the rest of functions src (132 passed); functions and root type checks; prettier; lint on the changed files. Not verified: the trigger or the cosignOfId index on the dev backend, or under a burst of concurrent cosigns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Deleting testimony now deletes its cosigns, each through the same performDeleteTestimony as any other delete, so each cosign comes off the conference's totals and its cosigner's draft loses its published version. The sweep runs after the parent is gone, when publish already refuses new cosigns, and runs even if the parent was already deleted, so deleting it again finishes a cascade that stopped partway. Moderation removal now deletes inside resolveReport through the same function. It used to resolve the report and then call a Next API route that deleted the publication without touching the bill or conference counts. The route came from codeforboston#1046, written while the deleteTestimony callable was disabled by policy and could only delete the caller's own testimony. The admin version of the callable merged the same day, but the moderation page kept calling the route, so moderator removals have left counts high since. The route, its client helper and the extra archive copy it wrote are gone, since publish already archives every version. The cosign tally trigger reads the parent first and stops when it is gone, rather than reading every remaining cosign on each delete of a cascade. Closes #95 Verified: yarn test:integration-ci on the seven CI suites with Typesense (97 passed), including a parent with two cosigns deleted by an admin and removed by a moderator (no cosigns left, drafts cleared, conference totals back to zero), one cosign deleted leaving the parent and the other, and the existing moderation case now checking the publication is gone; testimony and moderation suites again after the tally change (72 passed); functions unit tests from src (132 passed); functions type check; root type check (errors only in untracked local scratch scripts); prettier check; eslint on the changed files. Not verified: the cascade or the moderation removal against the dev backend, or a parent with thousands of cosigns, which are deleted one at a time within the callable's timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The report list and detail showed an archive id read from resolution.archiveTestimonyId, a field nothing writes; resolveReport wrote archivedTestimonyId instead. Since removal no longer writes a separate archive copy, that value was only the testimony id the report already carries, so the column, its label and the field are gone. RemoveTestimony also loses imports and a type it never used, among them firebase-admin, a server package, in a browser component. Verified: moderation integration suite (5 passed); root type check (errors only in untracked local scratch scripts); functions type check; eslint on the changed files; prettier check. Not verified: the moderation report pages in a browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The trigger that records a notification event for each new publication crashed when a publication lacked the court, bill title or author: court.toString() threw, and add() rejects undefined fields. Each crash restarts the emulator's function worker. It now skips a publication whose event would have an undefined field, logging which ones. On every other write it queried notificationEvents before checking the version, so each cosign tally update and backfilled document paid a query. It now returns before the query when the version is unchanged. The handler is split out from the trigger, as the ballot question trigger does, so it can be unit tested. Closes #114 Verified: unit tests cover a complete creation, creations missing billTitle, court or authorUid, a tally-only update (no database call) and a version change. The testimony and firstPublishedAt backfill integration suites pass (71) with no crash from this trigger; 193 writes returned at the version check and one incomplete fixture was skipped. Not verified: on the dev project. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| @@ -1,67 +0,0 @@ | |||
| import { NextApiRequest, NextApiResponse } from "next" | |||
Contributor
Author
There was a problem hiding this comment.
this was a second delete route that reimplemented testimony deletion in a different way and would've had to be updated to cascade the cosign deletes. I don't think this code is being used, so it seemed easier to just drop it.
fastfadingviolets
force-pushed
the
cosign-data
branch
from
October 27, 2026 19:42
4fb760f to
a9a87d8
Compare
This branch was successfully deployed
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.
This branch adds the data layer for cosigning conference testimony, as specified in the requirements it opens with. A cosign is published like any other testimony but names the publication it seconds and keeps that publication's position. Cosigned testimony carries a tally of its cosigners and their districts, and deleting or moderating away a publication now takes its cosigns with it. Along the way it records when testimony was first published, and stops the testimony notification trigger from crashing on incomplete publications and querying on every write.
Closes hyphacoop#91
Closes hyphacoop#93
Closes hyphacoop#94
Closes hyphacoop#95
Closes hyphacoop#114
What's in it
Not verified
🤖 Generated with Claude Code