refactor(telemetry): replace consent day-stamp with explicit intervals

Structural fix after five review rounds put four blockers in the same
subsystem. The root cause was representational: consent history is a
sequence of on/off intervals, but it was stored as ONE moving day-stamp
plus a revoked flag. Every fix had to mutate that scalar at exactly the
right moment from exactly the right place, and each round the mutation
was missing from some reachable path (write-once stamp in R3; recorded
inside a loop that never runs when sending is off in R4; dead code
whenever collection was off in R5).

Consent is now recorded as explicit intervals (send_consent_windows) and
eligibility is a pure derivation: a package is sent only when its whole
period falls inside a recorded window. One writer -
reconcile_send_consent - derives window state from an observation of
(config, now). It is idempotent and order-independent, so the wizard,
the relay, and the mid-pass check all call the same function and cannot
disagree; there are no edges to detect and no ordering between writers
to get wrong. The relay reconciles once per process BEFORE the
collection gate, which fixes round-5 D1 (enabled:false made the only
idle-path observer unreachable). The claim reads the table and never
writes it, removing the read-path mutation (D2's rewrite vector).

Timestamp discipline, each rule load-bearing and mutation-tested:
- 'obs' high-water mark: monotonic, advanced only by observations;
  confirms an open window forward (last_confirmed_at).
- 'data' high-water mark: advanced only by stored package period_end;
  clamps window OPENS so a rolled-back clock cannot slide a window
  under refused packages already on disk (round-5 D2).
- A close stamps last_confirmed_at, never "now": consent is asserted
  only for observed time, so a hand-edited config with no process
  running for 90 days fails closed (round-5 D1 strongest form).
- The gate requires period containment, not period_start >=, so an
  intra-day revoke/re-enable holds back the day package (round-5 D3).
- Unlike the day-stamp, a revoke/re-enable cycle no longer destroys the
  undelivered backlog from the earlier consented window (round-5 D4).

The redesign was validated BEFORE implementation against all 13
reproduced defect scenarios on a real store; the first two drafts each
failed scenarios in that harness (v1 leaked the unobserved-gap case by
closing at "now"; v2 leaked refused windows by letting data stamps
confirm consent). The harness ships as
tests/hermes_cli/test_shared_metrics_consent_windows.py.

Deleted: OPT_IN_PERIOD_KEY, SEND_REVOKED_KEY, LAST_SEEN_SEND_KEY,
opt_in_period(), record_revoked(), the relay edge detector body, and the
setup wizard's key bookkeeping (~170 lines of transition machinery).
Schema: two additive tables, version deliberately unchanged; verified
against a copy of the real production DB (13 rows intact, reopen no-op).

Also kills round-5's M8 survivor: the seen-exclusion mutation now fails
the suite. New mutation sweep: 8/8 killed, including one vacuous test of
my own this round (obs-mark monotonicity was covered only by
coincidence of the data mark; now pinned directly).

Documented cost: a fresh package waits at most one process start after
its period completes before release (fail-closed direction).

270 tests pass; ruff and windows-footguns clean. Staging E2E re-run
through the interval gate: both packages 202.
This commit is contained in:
Ben Barclay
2026-08-27 10:42:31 +10:00
parent 613849c190
commit 5e380d95ba
12 changed files with 702 additions and 264 deletions
+23 -9
View File
@@ -301,10 +301,20 @@ telemetry:
- Like `enabled`, `send` is profile-owned and is not overridden by
managed-scope configuration.
**Only packages for periods on or after the opt-in day are ever sent.** The
opt-in day (UTC) is recorded when `send` first becomes true, and any package
whose `period_start` predates it is permanently excluded, however late it was
created.
**A package is only sent when its whole period falls inside a recorded
consent window.** Consent is stored as explicit intervals in the shared-
metrics SQLite store (`send_consent_windows`): a window opens when `send:
true` is first observed, is confirmed forward by every later observation,
and closes — at the last *confirmed* moment, never at the wall clock — when
`send: false` is observed. A single reconciler derives this table from the
config on every process start, so wizard changes, hand-edits to
`config.yaml`, and mid-pass revocations all take the same path, and no
transition can be missed by any of them.
Any package whose period predates the first window, falls between windows,
or runs past the newest confirmed moment is excluded — the gate fails
closed. A fresh package therefore waits at most one process start after its
period completes before becoming eligible.
The gate is on the **period**, not on the package's creation time. One period
is split across several packages created on different days: a day's first
@@ -389,11 +399,15 @@ before every package, so a pass already in flight stops after the package it
is currently sending rather than draining its whole batch. It does not delete
previously transmitted packages, and it does not stop local collection.
Turning sending off also **closes the consent window**. Packages collected
while it was off are never transmitted, even if sending is later re-enabled —
re-enabling starts a new window from that day. Without this, a write-once
opt-in date would have retroactively released the entire refused period the
next time the user changed their mind.
Turning sending off also **closes the consent window** — at the last moment
consent was actually observed, not at the wall clock. Packages whose periods
fall between one window and the next are never transmitted, even if sending
is later re-enabled, and this holds for any number of on/off cycles, across
hand-edits with no process running, and under a clock that jumps backwards
(window opens are clamped above every timestamp already in the store).
Unlike the earlier single moving opt-in date, closing and reopening does NOT
discard the still-undelivered backlog from a previous consented window —
those packages stay inside their own interval and remain eligible.
### A.5 Retention
+4 -3
View File
@@ -3334,9 +3334,10 @@ DEFAULT_CONFIG = {
# Transmit exported packages to the Nous telemetry service.
# Requires ``enabled``: it never switches collection on by itself,
# and ``send`` without ``enabled`` is logged as an error rather
# than silently doing nothing. Only packages whose period starts
# on or after the opt-in day are ever sent, so data collected
# before consent stays local.
# than silently doing nothing. A package is only sent when its
# whole period falls inside a recorded consent window, so data
# collected before consent — or while it was withdrawn — stays
# local.
"send": False,
# Ingest endpoint. Production by default; override for staging or
# a local test server. Deliberately NOT overridable by an
@@ -1084,60 +1084,26 @@ class _Runtime:
self._safe(self._send_exported_packages)
def _observe_send_consent(self, send_enabled: bool) -> None:
"""Close the consent window on a true->false transition.
"""Reconcile consent windows with the observed config state.
Persists the last-seen send state so a change is detected even though
this runs in a fresh process each time. Only the falling edge matters:
opening a new window is the sender's job, on the next enabled pass.
Thin wrapper over the SINGLE consent writer. The old edge-detection
body (last-seen key, rising/falling branches) is gone: reconciliation
derives the correct window state from what it observes, so there is
no transition to miss and no ordering between callers to get wrong.
Failures here must never break the export hook, but they are logged at
Failures must never break the export hook, but they are logged at
warning rather than debug: silently failing to close a consent window
is a privacy-relevant event, not routine bookkeeping.
"""
try:
from hermes_cli.observability.shared_metrics_sender import (
LAST_SEEN_SEND_KEY,
opt_in_period,
record_revoked,
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
current = "1" if send_enabled else "0"
with self.subscriber.store._connection() as connection:
with write_txn(connection):
row = connection.execute(
"SELECT value FROM telemetry_state WHERE key = ?",
(LAST_SEEN_SEND_KEY,),
).fetchone()
previous = str(row[0]) if row is not None else None
if send_enabled:
# Open the window HERE, on the rising edge, rather than
# leaving it to the sender's first claim. The sender
# only runs when there is something to send, so a user
# who opts in and then opts out before any package
# exists would otherwise have no window to close, and
# record_revoked (which requires one) would no-op.
opt_in_period(connection)
elif previous == "1":
# `previous == "1"` is the true falling edge. Widening
# this to an unconditional else would be behaviourally
# equivalent today — record_revoked is idempotent and
# no-ops without an open window — so no test can tell
# the two apart. It is written as an edge anyway
# because that is the property intended, and a future
# change to record_revoked should not silently turn
# every disabled pass into a revocation.
record_revoked(connection)
if previous != current:
connection.execute(
"""
INSERT INTO telemetry_state(key, value) VALUES (?, ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value
""",
(LAST_SEEN_SEND_KEY, current),
)
reconcile_send_consent(connection, send_enabled)
except Exception:
logger.warning(
"Unable to record a shared-metrics consent transition",
@@ -1259,8 +1225,54 @@ def handles_hook(hook_name: str) -> bool:
return hook_name in HANDLED_HOOKS and enabled()
_consent_reconcile_done = False
def _reconcile_send_consent_once() -> None:
"""Reconcile consent windows with config, once per process.
Runs BEFORE and INDEPENDENT of the collection gate — that placement is
the fix for the round-5 D1 leak, where the only idle-path consent
observer sat behind ``handles_hook()`` and became dead code the moment
``enabled: false`` was set. A user with collection off still gets their
send-consent windows reconciled here.
Skipped only when there is no store on disk AND consent is off: with no
store there are no packages, so there is nothing a window could protect,
and creating ``~/.hermes/telemetry`` for every fully-disabled user would
be a behaviour change in the wrong direction.
"""
global _consent_reconcile_done
if _consent_reconcile_done:
return
_consent_reconcile_done = True
try:
from hermes_cli.config import read_raw_config_readonly
from hermes_cli.observability.shared_metrics import SharedMetricsStore
from hermes_cli.observability.shared_metrics_send_config import (
resolve_send_config,
)
from hermes_cli.observability.shared_metrics_sender import (
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
resolved = resolve_send_config(read_raw_config_readonly() or {})
store = SharedMetricsStore()
if not resolved.send and not store.database_path.exists():
return
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, resolved.send)
except Exception:
logger.warning(
"Unable to reconcile shared-metrics send consent", exc_info=True
)
def observe_lifecycle(hook_name: str, **kwargs: Any) -> None:
"""Project one Hermes lifecycle event into the core Relay integration."""
_reconcile_send_consent_once()
if not handles_hook(hook_name):
return
if not relay_runtime.relay_instrumentation_enabled():
@@ -338,6 +338,7 @@ class SharedMetricsStore:
"""
)
SharedMetricsStore._add_send_columns(connection)
SharedMetricsStore._add_consent_tables(connection)
connection.execute(
"""
INSERT INTO telemetry_state(key, value)
@@ -383,6 +384,55 @@ class SharedMetricsStore:
f"ALTER TABLE package_outbox ADD COLUMN {column} {declaration}"
)
@staticmethod
def _add_consent_tables(connection: sqlite3.Connection) -> None:
"""Create the consent-window tables, idempotently.
Additive like ``_add_send_columns`` — the schema version is
deliberately NOT bumped, and old readers never touch these tables.
``send_consent_windows`` records consent as explicit intervals rather
than a moving day-stamp: a window is opened when send consent is
observed, heartbeat-confirmed on every later observation, and closed
at the LAST CONFIRMED moment (never "now") when consent is observed
withdrawn. Consent is asserted only for time that was actually
observed, so unobserved gaps — a hand-edited config with no process
running — fail closed by construction.
``consent_marks`` holds two monotonic high-water marks with strictly
separated roles:
- ``obs``: the latest observation stamp ever seen. Advanced only by
the reconciler. Confirms consent and clamps window closes.
- ``data``: the latest package ``period_end`` ever stored. Advanced
only by the package writer. Clamps window OPENS, so a rolled-back
clock can never open a window underneath packages that already
exist on disk.
The separation is load-bearing: letting data stamps confirm consent
re-created a refused-window leak (packages stored during an off
window would vouch for it), and letting observation stamps clamp
opens is not enough on its own to stop a rollback sliding a window
under existing refused data.
"""
connection.execute(
"""
CREATE TABLE IF NOT EXISTS send_consent_windows (
opened_at TEXT NOT NULL,
last_confirmed_at TEXT NOT NULL,
closed_at TEXT
)
"""
)
connection.execute(
"""
CREATE TABLE IF NOT EXISTS consent_marks (
name TEXT PRIMARY KEY CHECK (name IN ('obs', 'data')),
stamp TEXT NOT NULL
)
"""
)
@staticmethod
def _create_counter_aggregates_table(connection: sqlite3.Connection) -> None:
connection.execute(
@@ -617,6 +667,16 @@ class SharedMetricsStore:
payload["generated_at"],
),
)
# Advance the data high-water mark. This is the ONLY writer of the
# 'data' mark: it clamps consent-window opens so a rolled-back clock
# can never open a window underneath packages that already exist.
connection.execute(
"""
INSERT INTO consent_marks(name, stamp) VALUES ('data', ?)
ON CONFLICT(name) DO UPDATE SET stamp = MAX(stamp, excluded.stamp)
""",
(payload["period_end"],),
)
for row in rows:
connection.execute(
"""
@@ -17,7 +17,10 @@ file. See Appendix A.7 of ``docs/observability/relay-shared-metrics.md``.
**Consent is gated on the package's PERIOD, not its creation time.** One
period is split across packages created on different days, so a created-at
gate would send a period's tail while dropping its head and silently
undercount the opt-in day.
undercount the first consented day. The gate itself is interval containment:
the period must fall entirely inside a recorded consent window
(``send_consent_windows``), maintained by the single ``reconcile_send_consent``
writer below.
"""
from __future__ import annotations
@@ -88,18 +91,6 @@ _PERMANENT_STATUSES = frozenset({400, 413})
#: doomed package at the head of the queue.
MAX_SEND_ATTEMPTS = 25
OPT_IN_PERIOD_KEY = "send_opt_in_period"
#: Set when sending is turned off, cleared by the next enabled pass (which
#: also advances OPT_IN_PERIOD_KEY). This is what makes consent revocation
#: permanent for the packages collected while it was off.
SEND_REVOKED_KEY = "send_revoked"
#: Last send-consent state this machine observed ("1"/"0"). Persisted because
#: each hook fires in a fresh process, so a true->false edge is only visible
#: by comparing against what was recorded last time.
LAST_SEEN_SEND_KEY = "send_last_seen"
def _utc_now() -> datetime:
return datetime.now(timezone.utc)
@@ -173,46 +164,86 @@ def _retry_after_seconds(value: str | None, default: int) -> int:
return default
def opt_in_period(connection: sqlite3.Connection, *, now: datetime | None = None) -> str:
"""Return the day (UTC) from which packages may be sent.
def reconcile_send_consent(
connection: sqlite3.Connection,
send_enabled: bool,
*,
now: datetime | None = None,
) -> None:
"""Reconcile the consent-window table with the observed config state.
Must run inside a write transaction.
THE ONLY writer of consent state. Must run inside a write transaction.
A pure function of (config, now, store): call it from anywhere, any
number of times, in any order — the resulting windows are the same. This
replaces the previous edge-detection design, whose three partial
observers (wizard, relay, mid-pass) each covered a different subset of
transitions and repeatedly leaked the transitions between the subsets.
This is the CURRENT consent window's start, not a permanent first-ever
opt-in date. If the user previously turned sending off, ``record_revoked``
stamps that; the next enabled pass advances the gate to the day sending
resumed, so packages collected during the opted-out window are never
transmitted. Without that advance, re-enabling would retroactively release
the entire period the user had explicitly refused.
Timestamp discipline (each rule is load-bearing; see the validation
harness in tests/hermes_cli/test_shared_metrics_consent_windows.py):
- The 'obs' mark advances to every observation stamp, monotonically.
An open window's ``last_confirmed_at`` follows it: consent is asserted
only for time that was actually observed.
- A close is stamped at ``last_confirmed_at`` — never "now" — so an
unobserved gap (hand-edited config, machine off for 90 days) is never
inside a window and fails closed.
- An open clamps to ``max(now, obs, data)``: a rolled-back clock cannot
open a window underneath refused packages already on disk, and cannot
make the new window adjacent to the previous close.
"""
today = (now or _utc_now()).date().isoformat()
stamp = _isoformat(now or _utc_now())
connection.execute(
"""
INSERT INTO consent_marks(name, stamp) VALUES ('obs', ?)
ON CONFLICT(name) DO UPDATE SET stamp = MAX(stamp, excluded.stamp)
""",
(stamp,),
)
marks = dict(
connection.execute("SELECT name, stamp FROM consent_marks").fetchall()
)
obs = marks["obs"] # >= stamp; immune to clock rollback
data = marks.get("data")
revoked = _state_get(connection, SEND_REVOKED_KEY)
if revoked:
# Sending resumed after a revocation: the new window starts today.
_state_set(connection, OPT_IN_PERIOD_KEY, today)
open_row = connection.execute(
"SELECT rowid FROM send_consent_windows WHERE closed_at IS NULL"
).fetchone()
if send_enabled:
if open_row is None:
opened = max(x for x in (obs, data) if x is not None)
connection.execute(
"INSERT INTO send_consent_windows(opened_at, last_confirmed_at)"
" VALUES (?, ?)",
(opened, opened),
)
else:
connection.execute(
"UPDATE send_consent_windows"
" SET last_confirmed_at = MAX(last_confirmed_at, ?)"
" WHERE rowid = ?",
(obs, open_row[0]),
)
elif open_row is not None:
connection.execute(
"DELETE FROM telemetry_state WHERE key = ?", (SEND_REVOKED_KEY,)
"UPDATE send_consent_windows SET closed_at = last_confirmed_at"
" WHERE rowid = ?",
(open_row[0],),
)
return today
existing = _state_get(connection, OPT_IN_PERIOD_KEY)
if existing:
return existing
_state_set(connection, OPT_IN_PERIOD_KEY, today)
return today
def record_revoked(connection: sqlite3.Connection) -> None:
"""Mark that sending was turned off, closing the current consent window.
Idempotent. The marker is only cleared by the next enabled pass, which
also advances the gate — so any package collected between the two events
stays local permanently.
"""
if _state_get(connection, OPT_IN_PERIOD_KEY):
_state_set(connection, SEND_REVOKED_KEY, "1")
#: Claim-time consent predicate: the package's period must fall entirely
#: inside SOME recorded consent window. An open window vouches only up to its
#: last confirmed moment, so a package whose period runs past it waits for
#: the next reconcile heartbeat (fail-closed; released within one hook fire).
CONSENT_GATE_SQL = """EXISTS (
SELECT 1 FROM send_consent_windows w
WHERE package_outbox.period_start >= w.opened_at
AND package_outbox.period_end <=
CASE WHEN w.closed_at IS NULL THEN w.last_confirmed_at
ELSE w.closed_at END
)"""
def _state_get(connection: sqlite3.Connection, key: str) -> str | None:
@@ -278,7 +309,6 @@ class SharedMetricsSender:
"""
with self._store._connection() as connection:
with write_txn(connection):
period = opt_in_period(connection, now=now)
stamp = _isoformat(now)
lease_until = now + timedelta(seconds=_CLAIM_LEASE_SECONDS)
@@ -286,6 +316,10 @@ class SharedMetricsSender:
exclusion = (
f" AND package_id NOT IN ({placeholders})" if seen else ""
)
# Consent is a READ here — the claim must never mutate the
# window table. The old design's opt_in_period() call at this
# exact spot meant selecting a row could rewrite what was
# permitted to be sent (and did, under a rolled-back clock).
row = connection.execute(
f"""
SELECT package_id, payload_json, sent_install_id
@@ -293,13 +327,13 @@ class SharedMetricsSender:
WHERE exported_at IS NOT NULL
AND (send_state IS NULL OR send_state = 'pending')
AND (next_attempt_at IS NULL OR next_attempt_at <= ?)
AND substr(period_start, 1, 10) >= ?
AND {CONSENT_GATE_SQL}
AND send_attempts < ?
{exclusion}
ORDER BY created_at, package_id
LIMIT 1
""",
(stamp, period, MAX_SEND_ATTEMPTS, *sorted(seen)),
(stamp, MAX_SEND_ATTEMPTS, *sorted(seen)),
).fetchone()
if row is None:
return None
@@ -523,13 +557,12 @@ class SharedMetricsSender:
for _ in range(MAX_PACKAGES_PER_PASS):
if not self._still_consented():
# The user turned sending off while this pass was running.
# Stop without transmitting anything further, and close the
# consent window. This covers only the mid-pass case; a
# revocation made while no pass is running is caught by the
# relay's edge detector before it early-returns, because this
# loop would never run to observe it.
# Stop without transmitting anything further, and reconcile
# so the window closes at its last confirmed moment. This is
# the same single writer every other observation point uses —
# not a separate recording mechanism.
logger.info("Shared-metrics sending disabled mid-pass; stopping")
self._record_revocation()
self._reconcile(send_enabled=False)
break
try:
package = self._claim_next(self._now(), seen)
@@ -561,14 +594,18 @@ class SharedMetricsSender:
outcome.deferred += 1
return outcome
def _record_revocation(self) -> None:
"""Close the consent window after an observed revocation."""
def _reconcile(self, *, send_enabled: bool) -> None:
"""Run the single consent writer from within a pass."""
try:
with self._store._connection() as connection:
with write_txn(connection):
record_revoked(connection)
reconcile_send_consent(
connection, send_enabled, now=self._now()
)
except Exception:
logger.debug("Unable to record consent revocation", exc_info=True)
logger.warning(
"Unable to reconcile shared-metrics consent", exc_info=True
)
def _still_consented(self) -> bool:
"""Re-read profile-owned send consent.
+10 -25
View File
@@ -2481,43 +2481,28 @@ def setup_telemetry(config: dict):
def _record_send_consent_change(*, enabled: bool) -> None:
"""Persist a consent transition at the moment the user makes it.
"""Reconcile consent windows at the moment the user decides.
Enabling stamps the day so the gate excludes anything collected earlier.
Disabling stamps a revocation so that if the user ever re-enables, the
packages collected while sending was off are never released — the doc
promises `send: false` means no further packages leave the machine, and
that has to survive a later change of mind.
Same single writer as the relay and the sender — reconciliation derives
the window state from the observation, so wizard, relay, and mid-pass
callers cannot disagree. The relay's once-per-process reconcile would
catch this on the next hook fire anyway; running it here just makes the
wizard's effect immediate.
"""
try:
from hermes_cli.observability.shared_metrics import SharedMetricsStore
from hermes_cli.observability.shared_metrics_sender import (
LAST_SEEN_SEND_KEY,
opt_in_period,
record_revoked,
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
store = SharedMetricsStore()
with store._connection() as connection:
with write_txn(connection):
if enabled:
opt_in_period(connection)
else:
record_revoked(connection)
# Keep the relay's edge detector in step. Without this the
# wizard's change looks like "no transition" on the next hook
# fire, and a later true->false edge could be missed.
connection.execute(
"""
INSERT INTO telemetry_state(key, value) VALUES (?, ?)
ON CONFLICT(key) DO UPDATE SET value = excluded.value
""",
(LAST_SEEN_SEND_KEY, "1" if enabled else "0"),
)
reconcile_send_consent(connection, enabled)
except Exception:
# Never block the wizard on telemetry bookkeeping. The sender records
# the same transitions on its next pass.
# Never block the wizard on telemetry bookkeeping. The relay runs the
# same reconciliation on the next lifecycle hook.
logger.debug("Unable to record shared-metrics consent change", exc_info=True)
+31 -6
View File
@@ -62,6 +62,31 @@ def main() -> int:
)
today = datetime.now(timezone.utc).date().isoformat()
# The generator only exports COMPLETED periods, so the realistic E2E
# package is yesterday's. It also has to be: the consent gate only
# releases a package once its whole period is confirmed consented, and
# today's period cannot be confirmed before it ends.
from datetime import timedelta
period_day = (
datetime.now(timezone.utc).date() - timedelta(days=1)
).isoformat()
# Open the consent window before the period, confirm it after — exactly
# what the runtime reconciler does across two days of hook fires.
from hermes_cli.observability.shared_metrics_sender import (
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(
connection,
True,
now=datetime.now(timezone.utc) - timedelta(days=2),
)
reconcile_send_consent(connection, True)
real_install_id = str(uuid.uuid4())
packages = []
@@ -77,8 +102,8 @@ def main() -> int:
"generated_at": datetime.now(timezone.utc).isoformat().replace(
"+00:00", "Z"
),
"period_start": f"{today}T00:00:00Z",
"period_end": f"{today}T23:59:59Z",
"period_start": f"{period_day}T00:00:00Z",
"period_end": f"{period_day}T23:59:59Z",
"resource": {
"hermes_version": "e2e-test",
"os_family": "macos",
@@ -105,11 +130,11 @@ def main() -> int:
""",
(
package_id,
f"{today}T00:00:00Z",
f"{today}T23:59:59Z",
f"{period_day}T00:00:00Z",
f"{period_day}T23:59:59Z",
json.dumps(payload),
f"{today}T0{index}:00:00Z",
f"{today}T0{index}:00:01Z",
f"{period_day}T0{index}:00:00Z",
f"{period_day}T0{index}:00:01Z",
),
)
packages.append((package_id, metric_count))
+11 -11
View File
@@ -33,7 +33,10 @@ def test_disabling_collection_closes_the_send_consent_window(monkeypatch, tmp_pa
package collected in between.
"""
from hermes_cli.observability.shared_metrics import SharedMetricsStore
from hermes_cli.observability.shared_metrics_sender import SEND_REVOKED_KEY
from hermes_cli.observability.shared_metrics_sender import (
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
store = SharedMetricsStore(
database_path=tmp_path / "m.db", outbox_directory=tmp_path / "o"
@@ -48,24 +51,21 @@ def test_disabling_collection_closes_the_send_consent_window(monkeypatch, tmp_pa
"hermes_cli.setup.prompt_yes_no", lambda _question, default: False
)
config = {"telemetry": {"shared_metrics": {"enabled": True, "send": True}}}
# Consent was granted earlier, so a window is already open — that is
# precisely the state whose closure must be recorded.
from hermes_cli.sqlite_util import write_txn
from hermes_cli.observability.shared_metrics_sender import opt_in_period
# Consent was granted earlier, so a window is open — that is precisely
# the state whose closure must be recorded.
with store._connection() as connection:
with write_txn(connection):
opt_in_period(connection)
reconcile_send_consent(connection, True)
setup_telemetry(config)
assert config["telemetry"]["shared_metrics"]["enabled"] is False
assert config["telemetry"]["shared_metrics"]["send"] is False
with store._connection() as connection:
row = connection.execute(
"SELECT value FROM telemetry_state WHERE key = ?", (SEND_REVOKED_KEY,)
).fetchone()
assert row is not None and row[0] == "1", (
open_windows = connection.execute(
"SELECT COUNT(*) FROM send_consent_windows WHERE closed_at IS NULL"
).fetchone()[0]
assert open_windows == 0, (
"disabling collection left the send consent window open"
)
@@ -0,0 +1,221 @@
"""Property tests for the consent-interval model.
Ported from the /tmp validation harness that gated the redesign: every
scenario here is a defect that actually occurred (rounds 3-5) or a clock
adversary the day-stamp model could not survive. The v1 and v2 drafts of the
redesign each FAILED scenarios in this file before shipping — that is the
harness working, and why these run against the real store and the real
reconciler rather than a model of them.
"""
from __future__ import annotations
import json
from datetime import datetime, timedelta, timezone
import pytest
from hermes_cli.observability.shared_metrics import SharedMetricsStore
from hermes_cli.observability.shared_metrics_sender import (
CONSENT_GATE_SQL,
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
T0 = datetime(2026, 8, 1, tzinfo=timezone.utc)
def ts(days=0, hours=0):
return (T0 + timedelta(days=days, hours=hours)).isoformat().replace(
"+00:00", "Z"
)
def dt(days=0, hours=0):
return T0 + timedelta(days=days, hours=hours)
@pytest.fixture
def store(tmp_path):
return SharedMetricsStore(
database_path=tmp_path / "m.db", outbox_directory=tmp_path / "o"
)
def _add(store, pid, start, end):
"""Store a package the way the generator does: at period end."""
with store._connection() as connection:
with write_txn(connection):
connection.execute(
"INSERT INTO package_outbox(package_id, period_start, period_end,"
" payload_json, created_at, exported_at) VALUES (?, ?, ?, ?, ?, ?)",
(pid, start, end, json.dumps({"package_id": pid}), end, end),
)
connection.execute(
"""INSERT INTO consent_marks(name, stamp) VALUES ('data', ?)
ON CONFLICT(name) DO UPDATE SET stamp = MAX(stamp, excluded.stamp)""",
(end,),
)
def _observe(store, send_enabled, when):
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, send_enabled, now=when)
def _eligible(store):
with store._connection() as connection:
return sorted(
row[0]
for row in connection.execute(
f"SELECT package_id FROM package_outbox WHERE {CONSENT_GATE_SQL}"
)
)
def _windows(store):
with store._connection() as connection:
return [
tuple(row)
for row in connection.execute(
"SELECT opened_at, last_confirmed_at, closed_at"
" FROM send_consent_windows ORDER BY opened_at"
)
]
class TestRefusedWindowIsNeverReleased:
def test_on_off_on_with_realistic_interleaving(self, store):
"""Rounds 3 and 5: the refused middle must never transmit, and
neither consented era may be lost."""
_observe(store, True, dt(0))
for n in range(5):
_add(store, f"d{n:02d}", ts(days=n), ts(days=n + 1))
_observe(store, True, dt(days=n + 1))
_observe(store, False, dt(5))
for n in range(5, 10):
_add(store, f"d{n:02d}", ts(days=n), ts(days=n + 1))
_observe(store, True, dt(10))
for n in range(10, 15):
_add(store, f"d{n:02d}", ts(days=n), ts(days=n + 1))
_observe(store, True, dt(days=n + 1))
eligible = _eligible(store)
assert not [p for p in eligible if 5 <= int(p[1:]) < 10], eligible
assert [f"d{n:02d}" for n in range(5)] == eligible[:5], (
"pre-revocation consented backlog was destroyed"
)
assert [f"d{n:02d}" for n in range(10, 15)] == eligible[5:], eligible
def test_hand_edit_with_a_90_day_silent_gap(self, store):
"""Round 5 D1, strongest form: NOTHING observes the off window.
The close back-dates to the last confirmed moment, so the unobserved
gap is outside every window and fails closed.
"""
_observe(store, True, dt(0))
_add(store, "consented", ts(0, 1), ts(0, 2))
_observe(store, True, dt(0, 6))
for n in range(1, 90, 10):
_add(store, f"REFUSED-d{n}", ts(days=n), ts(days=n, hours=1))
_observe(store, False, dt(90)) # first observation: boot on day 90
_observe(store, True, dt(91))
_observe(store, True, dt(92))
eligible = _eligible(store)
assert not [p for p in eligible if p.startswith("REFUSED")], eligible
assert "consented" in eligible, (
"the confirmed-morning package must survive the reconciliation"
)
class TestClockAdversaries:
def test_rollback_at_re_enable_releases_nothing(self, store):
"""Round 5 D2: the data mark clamps opens above existing packages."""
_observe(store, True, dt(0))
_observe(store, True, dt(5))
_observe(store, False, dt(5))
for n in range(1, 4):
_add(store, f"REFUSED-{n}", ts(days=5, hours=n), ts(days=5, hours=n + 1))
_observe(store, True, dt(-12)) # 12-day rollback at re-enable
_observe(store, True, dt(-11))
during = [p for p in _eligible(store) if p.startswith("REFUSED")]
assert not during, f"rollback released refused packages: {during}"
_observe(store, True, dt(20)) # clock recovers
_observe(store, True, dt(21))
after = [p for p in _eligible(store) if p.startswith("REFUSED")]
assert not after, f"recovery released refused packages: {after}"
def test_recovery_does_not_wedge_future_sending(self, store):
_observe(store, True, dt(0))
_observe(store, False, dt(5))
_observe(store, True, dt(-12))
_observe(store, True, dt(20))
_add(store, "post-recovery", ts(21), ts(21, 4))
_observe(store, True, dt(22))
assert "post-recovery" in _eligible(store)
class TestSubDayGranularity:
def test_intra_day_refusal_holds_back_the_whole_day_package(self, store):
"""Round 5 D3: a day package spanning a refused stretch must wait."""
_observe(store, True, dt(0))
_observe(store, True, dt(10, 9))
_observe(store, False, dt(10, 9))
_observe(store, True, dt(10, 18))
_observe(store, True, dt(11, 2))
_add(store, "halfday", ts(10), ts(11))
assert "halfday" not in _eligible(store)
class TestReconcilerProperties:
def test_idempotent_under_replay(self, store):
for _ in range(4):
_observe(store, True, dt(0))
_observe(store, False, dt(2))
for _ in range(5):
_observe(store, False, dt(3))
_observe(store, True, dt(4))
for _ in range(3):
_observe(store, True, dt(5))
assert len(_windows(store)) == 2
def test_the_observation_mark_is_monotonic(self, store):
"""A rolled-back clock must never lower the observation high-water.
Every downstream guarantee leans on this: closes clamp to it via
last_confirmed_at, and opens clamp to max(obs, data). Found as a
surviving mutant (obs upsert rewritten from MAX to overwrite) —
the leak scenarios happen to be covered by the data mark whenever a
leakable package exists, but the property itself must hold on its
own, not by coincidence of the sibling mark.
"""
_observe(store, True, dt(5))
_observe(store, True, dt(0)) # rollback
with store._connection() as connection:
stamp = connection.execute(
"SELECT stamp FROM consent_marks WHERE name = 'obs'"
).fetchone()[0]
assert stamp == ts(5), f"obs mark moved backwards: {stamp}"
def test_the_gate_is_read_only(self, store):
_observe(store, True, dt(0))
before = _windows(store)
for _ in range(10):
_eligible(store)
assert _windows(store) == before
def test_no_window_fails_closed(self, store):
_add(store, "orphan", ts(0), ts(1))
assert _eligible(store) == []
def test_fresh_package_waits_one_heartbeat_then_releases(self, store):
"""The documented latency cost of confirmation-based windows."""
_observe(store, True, dt(0))
_add(store, "fresh", ts(0, 1), ts(0, 2))
assert _eligible(store) == []
_observe(store, True, dt(0, 3))
assert _eligible(store) == ["fresh"]
@@ -209,13 +209,13 @@ class TestInteractivePathIsNotBlocked:
runtime._join_send_thread(timeout=5)
class TestConsentRevocationWindow:
"""The falling edge must close the window even with no pass running.
class TestConsentWindows:
"""Consent reconciliation must work from the relay, in any order.
Round 3 recorded revocation inside the send loop, which cannot fire for
the dominant case: the user turns sending off while idle, so the relay
early-returns and no sender is ever built. Re-enabling then released
every package collected during the refused window.
Round 4's edge detector missed the idle-revocation path; round 5 found it
was also dead code whenever collection was off (handles_hook gated it).
These tests drive the relay entry points against the single reconciler
and assert on the interval table — the only consent state that exists.
"""
def _runtime(self, tmp_path):
@@ -223,20 +223,19 @@ class TestConsentRevocationWindow:
runtime.subscriber.store = RealBackedStore(tmp_path)
return runtime
def _state(self, runtime, key):
def _windows(self, runtime):
with runtime.subscriber.store._connection() as connection:
row = connection.execute(
"SELECT value FROM telemetry_state WHERE key = ?", (key,)
).fetchone()
return row[0] if row else None
return [
tuple(row)
for row in connection.execute(
"SELECT opened_at, last_confirmed_at, closed_at"
" FROM send_consent_windows ORDER BY opened_at"
)
]
def test_revoking_while_idle_closes_the_window(
self, monkeypatch, tmp_path, capture_sender
):
from hermes_cli.observability.shared_metrics_sender import (
SEND_REVOKED_KEY,
)
runtime = self._runtime(tmp_path)
_set_config(monkeypatch, _config(enabled=True, send=True))
@@ -247,88 +246,101 @@ class TestConsentRevocationWindow:
for _ in range(6):
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) == "1", (
"revoking while no pass was running left the consent window open"
windows = self._windows(runtime)
assert windows and all(w[2] is not None for w in windows), (
f"revoking while idle left a window open: {windows}"
)
def test_no_spurious_revocation_when_nothing_changes(
def test_replayed_observations_create_no_junk_windows(
self, monkeypatch, tmp_path, capture_sender
):
"""The detector must key on an EDGE, not on every disabled pass.
A level trigger re-closes a window the user has since REOPENED: each
later disabled pass stamps revoked again, so the next enabled pass
advances the gate and silently drops packages the user did consent to.
Mutation-checked — an earlier version of this test used a
never-consented store, where record_revoked no-ops regardless, and so
could not tell an edge trigger from a level trigger.
"""
from hermes_cli.observability.shared_metrics_sender import (
OPT_IN_PERIOD_KEY,
SEND_REVOKED_KEY,
)
"""Reconciliation is idempotent — there is no edge to double-count."""
runtime = self._runtime(tmp_path)
_set_config(monkeypatch, _config(enabled=True, send=True))
runtime._send_exported_packages()
for _ in range(4):
runtime._send_exported_packages()
_set_config(monkeypatch, _config(enabled=True, send=False))
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) == "1"
# User changes their mind and re-enables.
for _ in range(4):
runtime._send_exported_packages()
_set_config(monkeypatch, _config(enabled=True, send=True))
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) is None, (
"re-enabling must clear the revocation marker"
)
reopened = self._state(runtime, OPT_IN_PERIOD_KEY)
# Further ENABLED passes must not disturb the reopened window.
for _ in range(4):
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) is None, (
"a steady enabled state re-closed the consent window"
)
assert self._state(runtime, OPT_IN_PERIOD_KEY) == reopened
assert len(self._windows(runtime)) == 2
def test_a_never_consented_user_is_never_marked_revoked(
def test_a_never_consented_user_gets_no_window(
self, monkeypatch, tmp_path, capture_sender
):
from hermes_cli.observability.shared_metrics_sender import (
SEND_REVOKED_KEY,
)
runtime = self._runtime(tmp_path)
_set_config(monkeypatch, _config(enabled=True, send=False))
for _ in range(5):
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) is None
assert self._windows(runtime) == []
def test_re_enabling_after_an_idle_revocation_starts_a_new_window(
def test_re_enabling_opens_a_new_window_after_the_refusal(
self, monkeypatch, tmp_path, capture_sender
):
from hermes_cli.observability.shared_metrics_sender import (
OPT_IN_PERIOD_KEY,
SEND_REVOKED_KEY,
)
"""The refused gap must fall BETWEEN the two windows."""
runtime = self._runtime(tmp_path)
_set_config(monkeypatch, _config(enabled=True, send=True))
runtime._send_exported_packages()
first_window = self._state(runtime, OPT_IN_PERIOD_KEY)
_set_config(monkeypatch, _config(enabled=True, send=False))
runtime._send_exported_packages()
assert self._state(runtime, SEND_REVOKED_KEY) == "1"
# Re-enabling must not simply resume the original window.
_set_config(monkeypatch, _config(enabled=True, send=True))
runtime._send_exported_packages()
assert first_window is not None
windows = self._windows(runtime)
assert len(windows) == 2
first, second = windows
assert first[2] is not None, "first window must be closed"
assert second[2] is None, "second window must be open"
assert second[0] >= first[2], (
f"new window may not overlap the refused gap: {windows}"
)
def test_reconcile_runs_even_when_collection_is_disabled(
self, monkeypatch, tmp_path
):
"""Round-5 D1: enabled:false must not make consent handling dead code.
The module-level once-per-process reconciler must close the window
regardless of handles_hook(). Drives the real observe_lifecycle gate
path: handles_hook is False throughout.
"""
from hermes_cli.observability.shared_metrics import SharedMetricsStore
from hermes_cli.observability.shared_metrics_sender import (
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
store = SharedMetricsStore(
database_path=tmp_path / "m.db", outbox_directory=tmp_path / "o"
)
# A consent window is open from an earlier consented era.
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, True)
monkeypatch.setattr(
"hermes_cli.observability.shared_metrics.SharedMetricsStore",
lambda *a, **k: store,
)
_set_config(monkeypatch, _config(enabled=False, send=False))
monkeypatch.setattr(mod, "_consent_reconcile_done", False)
# The full lifecycle entry point, with collection OFF.
mod.observe_lifecycle("finish_task")
with store._connection() as connection:
open_windows = connection.execute(
"SELECT COUNT(*) FROM send_consent_windows WHERE closed_at IS NULL"
).fetchone()[0]
assert open_windows == 0, (
"enabled:false made the consent reconciler unreachable (D1)"
)
class TestFailureIsolation:
+95 -42
View File
@@ -19,12 +19,11 @@ from hermes_cli.observability.shared_metrics_sender import (
MAX_ATTEMPTS,
MAX_PACKAGES_PER_PASS,
MAX_SEND_ATTEMPTS,
OPT_IN_PERIOD_KEY,
REQUEST_TIMEOUT_SECONDS,
SharedMetricsSender,
opt_in_period,
record_revoked,
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
INSTALL_ID = "12a73e97-4de9-4766-830d-9ca1192c0420"
NOW = datetime(2026, 8, 26, 12, 0, tzinfo=timezone.utc)
@@ -61,10 +60,45 @@ class FakeTransport:
@pytest.fixture
def store(tmp_path):
return SharedMetricsStore(
"""A store with a broad consent window already open.
Most tests exercise claiming/retry/transport, not the consent gate, and
the interval gate fails closed with no window. One window opened before
every test package and confirmed well past NOW keeps those tests about
what they are about. Gate tests clear it via _clear_consent.
"""
built = SharedMetricsStore(
database_path=tmp_path / "metrics.sqlite3",
outbox_directory=tmp_path / "outbox",
)
_grant_consent(built)
return built
def _grant_consent(
store,
opened=datetime(2026, 8, 20, tzinfo=timezone.utc),
confirmed_through=datetime(2026, 10, 1, tzinfo=timezone.utc),
):
"""Open a consent window and heartbeat it forward, via the real writer."""
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, True, now=opened)
reconcile_send_consent(connection, True, now=confirmed_through)
def _revoke_consent(store, at):
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, False, now=at)
def _clear_consent(store):
"""Remove all consent state, for tests of the fail-closed default."""
with store._connection() as connection:
with write_txn(connection):
connection.execute("DELETE FROM send_consent_windows")
connection.execute("DELETE FROM consent_marks")
def _add_package(store, package_id, period_day, *, exported=True, install_id=INSTALL_ID):
@@ -231,6 +265,9 @@ class TestContractResponses:
class TestConsentGate:
def test_packages_from_before_opt_in_are_never_sent(self, store):
# Consent opens on Aug 24; the "old" package's period predates it.
_clear_consent(store)
_grant_consent(store, opened=datetime(2026, 8, 24, tzinfo=timezone.utc))
_add_package(store, "old", "2026-08-20")
_add_package(store, "new", "2026-08-26")
transport = FakeTransport(FakeResponse(202))
@@ -245,19 +282,27 @@ class TestConsentGate:
_sender(store, transport).send_pending()
assert sorted(b["package_id"] for b in transport.bodies) == ["head", "tail"]
def test_opt_in_day_is_recorded_once_and_does_not_move(self, store):
def test_opt_in_is_immortalised_as_a_window_not_a_day(self, store):
"""The window survives replayed observations without moving."""
with store._connection() as connection:
first = opt_in_period(connection, now=NOW)
later = opt_in_period(connection, now=NOW + timedelta(days=10))
assert first == later == "2026-08-26"
def test_opt_in_day_is_persisted(self, store):
rows = connection.execute(
"SELECT opened_at, closed_at FROM send_consent_windows"
).fetchall()
assert len(rows) == 1 and rows[0][1] is None
_grant_consent(store) # replay: must not create a second window
with store._connection() as connection:
opt_in_period(connection, now=NOW)
value = connection.execute(
"SELECT value FROM telemetry_state WHERE key = ?", (OPT_IN_PERIOD_KEY,)
count = connection.execute(
"SELECT COUNT(*) FROM send_consent_windows"
).fetchone()[0]
assert value == "2026-08-26"
assert count == 1
def test_no_consent_window_means_nothing_is_sent(self, store):
"""The gate fails closed: absence of a window is absence of consent."""
_clear_consent(store)
_add_package(store, "pkg-1", "2026-08-26")
transport = FakeTransport(FakeResponse(202))
_sender(store, transport).send_pending()
assert transport.calls == []
def test_unexported_packages_are_skipped(self, store):
_add_package(store, "pending-export", "2026-08-26", exported=False)
@@ -266,32 +311,31 @@ class TestConsentGate:
assert transport.calls == []
def test_revoking_then_re_enabling_never_releases_the_off_window(self, store):
"""Regression: re-opt-in retroactively transmitted the refused window.
"""The R3/R5 leak: re-opt-in must not release the refused interval.
opt_in_period was write-once, so packages collected while the user had
send: false still had period_start >= the ORIGINAL opt-in day. Turning
sending back on released the entire opted-out window — contradicting
the documented promise that `send: false` means no further packages
leave the machine.
Under the interval model the refused days fall BETWEEN two windows;
no later observation can place them inside one, so the property holds
for any number of on/off cycles — not just the single cycle the old
moving day-stamp was patched to survive.
"""
_add_package(store, "consented", "2026-08-26")
with store._connection() as connection:
with __import__(
"hermes_cli.sqlite_util", fromlist=["write_txn"]
).write_txn(connection):
opt_in_period(connection, now=NOW)
_clear_consent(store)
_grant_consent(store, opened=NOW - timedelta(days=2), confirmed_through=NOW)
_add_package(store, "consented", "2026-08-25")
# User turns sending off; packages keep being collected.
with store._connection() as connection:
with __import__(
"hermes_cli.sqlite_util", fromlist=["write_txn"]
).write_txn(connection):
record_revoked(connection)
# User turns sending off; packages keep being collected for 3 days.
_revoke_consent(store, at=NOW)
for day in ("2026-08-27", "2026-08-28", "2026-08-29"):
_add_package(store, f"refused-{day}", day)
# User re-enables a few days later.
# User re-enables 5 days later; heartbeat confirms past the horizon.
later = NOW + timedelta(days=5)
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, True, now=later)
reconcile_send_consent(
connection, True, now=later + timedelta(days=30)
)
transport = FakeTransport(*[FakeResponse(202)] * 10)
SharedMetricsSender(
store, ENDPOINT, post=transport, sleep=lambda _s: None, now=lambda: later
@@ -301,21 +345,30 @@ class TestConsentGate:
assert not any("refused" in pid for pid in sent), (
f"transmitted packages collected while sending was off: {sent}"
)
# And the interval model's improvement over the day-stamp: the
# pre-revocation consented package is NOT collateral damage.
assert "consented" in sent, (
"the consented backlog was destroyed by the revoke/re-enable cycle"
)
def test_a_package_from_after_re_enabling_is_sent(self, store):
"""The revocation fix must not wedge sending off permanently."""
with store._connection() as connection:
with __import__(
"hermes_cli.sqlite_util", fromlist=["write_txn"]
).write_txn(connection):
opt_in_period(connection, now=NOW)
record_revoked(connection)
"""The revocation handling must not wedge sending off permanently."""
_clear_consent(store)
_grant_consent(store, opened=NOW - timedelta(days=2), confirmed_through=NOW)
_revoke_consent(store, at=NOW)
later = NOW + timedelta(days=5)
_add_package(store, "after-re-optin", later.date().isoformat())
with store._connection() as connection:
with write_txn(connection):
reconcile_send_consent(connection, True, now=later)
reconcile_send_consent(
connection, True, now=later + timedelta(days=10)
)
_add_package(store, "after-re-optin", (later + timedelta(days=1)).date().isoformat())
transport = FakeTransport(FakeResponse(202))
SharedMetricsSender(
store, ENDPOINT, post=transport, sleep=lambda _s: None, now=lambda: later
store, ENDPOINT, post=transport, sleep=lambda _s: None,
now=lambda: later + timedelta(days=2),
).send_pending()
assert len(transport.calls) == 1
@@ -77,10 +77,28 @@ def server():
@pytest.fixture
def store(tmp_path):
return SharedMetricsStore(
built = SharedMetricsStore(
database_path=tmp_path / "metrics.sqlite3",
outbox_directory=tmp_path / "outbox",
)
# Open a consent window covering the fixture packages; the interval gate
# fails closed without one, and this file tests transport, not consent.
from datetime import datetime, timezone
from hermes_cli.observability.shared_metrics_sender import (
reconcile_send_consent,
)
from hermes_cli.sqlite_util import write_txn
with built._connection() as connection:
with write_txn(connection):
reconcile_send_consent(
connection, True, now=datetime(2026, 8, 20, tzinfo=timezone.utc)
)
reconcile_send_consent(
connection, True, now=datetime(2026, 10, 1, tzinfo=timezone.utc)
)
return built
def _endpoint(server):