audit 4: cards ordered by number, a notification owed to each recipient
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
The cards layout (owner, 2026-10-13; the mockup first, b90a2f0): box_open
writes data-order for a box with InCards and a number, and panel.css orders
by it up to twelve - Health's eight and the kit's three.
TestCardsBoxesCarryTheirNumberAsTheirOrder reads the rendered pages.
Notifications (owner, 2026-10-14): migration 0011, notify_addressees. open
sends a subject's first message to every recipient and records who was
handed it; followUp, on every check while the subject is open and still
wrong, hands it to the owed and untold who are still recipients; closed
sends the end to the told (all recipients for a subject from before the
table). Tests: a failed copy goes out at the next check, once; the hourly
ceiling holds one back; a user added mid-subject hears nothing of it.
Also in the roadmap, from the owner today: dns-record-collapse,
notification-mail-recheck, settings-save-row (agreed, design first).
Tested on the test server: go vet + go test of 25 packages, make e2e (all
pass, 644 s) on this tree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -127,11 +127,69 @@ func (s *Store) SetNotifyState(st NotifyState) error {
|
||||
}
|
||||
|
||||
// DeleteNotifyState forgets a subject: nothing is wrong with it any more, or
|
||||
// it no longer exists.
|
||||
// it no longer exists. Who it was owed to goes with it.
|
||||
func (s *Store) DeleteNotifyState(key string) error {
|
||||
if _, err := s.db.Exec("DELETE FROM notify_state WHERE key = ?", key); err != nil {
|
||||
tx, err := s.db.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete notify state %s: %w", key, err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
for _, stmt := range []string{"DELETE FROM notify_addressees WHERE key = ?", "DELETE FROM notify_state WHERE key = ?"} {
|
||||
if _, err := tx.Exec(stmt, key); err != nil {
|
||||
return fmt.Errorf("delete notify state %s: %w", key, err)
|
||||
}
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("delete notify state %s: %w", key, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NotifyAddressees returns who the subject's message is owed to, each with
|
||||
// whether they were handed a copy (migration 0011). None for a subject not
|
||||
// said yet, or said before 2.5.4.
|
||||
func (s *Store) NotifyAddressees(key string) (map[string]bool, error) {
|
||||
rows, err := s.db.Query("SELECT address, told_at FROM notify_addressees WHERE key = ?", key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("notify addressees %s: %w", key, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
out := map[string]bool{}
|
||||
for rows.Next() {
|
||||
var addr, toldAt string
|
||||
if err := rows.Scan(&addr, &toldAt); err != nil {
|
||||
return nil, fmt.Errorf("notify addressees %s: %w", key, err)
|
||||
}
|
||||
out[addr] = toldAt != ""
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// SetNotifyAddressees records who the subject's message is owed to: owed
|
||||
// maps an address to whether it was handed a copy, and replaces what was
|
||||
// recorded. The told are dated at, the time of this record: the date is
|
||||
// for a person reading the table, the code asks only whether.
|
||||
func (s *Store) SetNotifyAddressees(key string, owed map[string]bool, at time.Time) error {
|
||||
tx, err := s.db.Begin()
|
||||
if err != nil {
|
||||
return fmt.Errorf("set notify addressees %s: %w", key, err)
|
||||
}
|
||||
defer tx.Rollback()
|
||||
if _, err := tx.Exec("DELETE FROM notify_addressees WHERE key = ?", key); err != nil {
|
||||
return fmt.Errorf("set notify addressees %s: %w", key, err)
|
||||
}
|
||||
for addr, told := range owed {
|
||||
toldAt := ""
|
||||
if told {
|
||||
toldAt = at.UTC().Format(time.RFC3339)
|
||||
}
|
||||
if _, err := tx.Exec("INSERT INTO notify_addressees (key, address, told_at) VALUES (?, ?, ?)", key, addr, toldAt); err != nil {
|
||||
return fmt.Errorf("set notify addressees %s: %w", key, err)
|
||||
}
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
return fmt.Errorf("set notify addressees %s: %w", key, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user