fix(site-call-audit): composite keyset cursor eliminates the single-timestamp reconciliation pin; pinned state now a published event

Reconciliation cursor becomes composite (UpdatedAtUtc, TrackedOperationId);
IPullSiteCallsClient/GrpcPullSiteCallsClient forward the Task-15 after_id keyset
(additive param, null preserves the legacy inclusive >= contract). A burst
sharing one exact UpdatedAtUtc now drains via the id tiebreak instead of pinning
forever. A legacy site that ignores after_id is latched + published as
SiteCallReconciliationPinnedChanged on the EventStream (transition-only),
replacing the prior silent log line.
This commit is contained in:
Joseph Doherty
2026-07-09 08:44:07 -04:00
parent 1f4c0b67ca
commit 20098c6108
9 changed files with 324 additions and 66 deletions
+8
View File
@@ -278,6 +278,14 @@ non-draining (e.g., telemetry actor wedged), central issues a
are flipped to `ForwardState = 'Reconciled'` site-side. Same self-healing
pattern as Site Call Audit's reconciliation of `SiteCalls`.
> **Cursor keyset (tracked follow-up).** The `PullAuditEvents` cursor is still a
> single `sinceUtc` timestamp. Site Call Audit's pull now uses a composite
> `(UpdatedAtUtc, TrackedOperationId)` keyset to avoid a single-timestamp pin
> (see Component-SiteCallAudit.md → Reconciliation). The same keyset should be
> applied here, but it is lower urgency because the audit cursor already re-pulls
> idempotently on `EventId` — a saturated single-timestamp window re-inserts
> harmless no-ops rather than losing rows.
### Central direct-write (central-originated events)
Events originating at central never touch site SQLite. Inbound API writes one