oficina / calendar Public

Advance cancellation revisions and document data key recovery

Paul Campbell pushed by paul@keymail.dev 10212c522c1876786383c2742fc0a089f6df6afb parent cde0d6f
3 files changed, +8 −2
  • AGENTS.md +2 −0
  • internal/calendar/release_repairs_test.go +5 −0
  • internal/calendar/store_event_write.go +1 −2

CI passed — run details

diff --git a/AGENTS.md b/AGENTS.md
index 7561bf2..a54894b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -259,3 +259,5 @@ reviewed. A review by a weaker model than the author is not a review.
๐Ÿค– / ๐Ÿ‘จ markers, `Co-Authored-By:` trailers. AI is a guest with a name
tag: opt-in, disclosed, and every path works with it switched off.
+
+Startup verifies the configured data key against `meta.sealed_key_check_v1`, or existing encrypted calendar names on first adoption. A refusal requires restoring the correct key/database pair. Never delete or replace the sentinel to make an unreadable database start.
diff --git a/internal/calendar/release_repairs_test.go b/internal/calendar/release_repairs_test.go
index d62d616..943700b 100644
--- a/internal/calendar/release_repairs_test.go
+++ b/internal/calendar/release_repairs_test.go
@@ -57,6 +57,11 @@ func TestFeedExportsOneMasterAndAllOverrides(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ for _, row := range rows {
+ if row.ID == overrideID && row.Sequence <= master.Sequence+1 {
+ t.Fatal("cancellation did not supersede the live override")
+ }
+ }
if !strings.Contains(WriteICS("Test", rows, false), "STATUS:CANCELLED") {
t.Fatal("deleted override resurrected")
}
diff --git a/internal/calendar/store_event_write.go b/internal/calendar/store_event_write.go
index b703f44..b924fec 100644
--- a/internal/calendar/store_event_write.go
+++ b/internal/calendar/store_event_write.go
@@ -135,11 +135,10 @@ func (s *Store) DeleteEvent(ctx context.Context, personID, eventID int64) error
// told about, and its CANCEL ICS must outrank the REQUEST, so
// the soft-deleted row takes one more revision (booking spec
// ยง5.5).
- updates := map[string]any{"deleted_at": now}
+ updates := map[string]any{"deleted_at": now, "updated_at": now, "sequence": gorm.Expr("sequence + 1")}
if _, booked, err := bookingFor(tx, eventID); err != nil {
return err
} else if booked {
- updates["sequence"] = gorm.Expr("sequence + 1")
if err := cancelBookingsForEvent(tx, eventID, now); err != nil {
return err
}