Skip to content

C-84/#224: make the 2026-11-17 key expiry fire on its own - #289

Merged
Polichinel merged 3 commits into
developmentfrom
feat/c84-expiry-tripwire
Aug 19, 2026
Merged

Polichinel merged 3 commits into
developmentfrom
feat/c84-expiry-tripwire

Conversation

@Polichinel

Copy link
Copy Markdown
Collaborator

What I did not build, and why that matters here

#224 says "what is asked of this repo: nothing yet", and C-84 goes further:

"The honest position is that this is a date to act on, not a mechanism to build, and inventing a mechanism would be building the wrong thing to feel busy."

That verdict is about a key-validity preflight — an authenticated call at startup — and it stands. This is not that. No authenticated call, no credential, no network.

What was actually missing

C-84's own trigger:

"Act when the un_fao delivery is next scheduled within a month of it, or when anyone plans a rotation, whichever is first."

That is a trigger nobody can notice. It fires in someone's memory or not at all. This repository has written that down twice already — ADR-014 §4, and the withdrawn third arm of C-94's trigger, dropped for precisely this reason. A foreseeable total outage, known 90 days in advance, should not depend on anyone remembering it.

The tripwire

tests/test_credential_expiry.py declares both expiries and fails from 30 days out, naming:

  • the dates, and the 3h35m gap — which is C-84's actual finding. It is not a stagger: neither key can carry traffic while the other is replaced, so a rotation assuming a window has none.
  • that this repo cannot rotate anything and must not hold credentials (þing-01 D3) — the owner is the operator (views-appwrite#12; split at views-faoapi#338).
  • the two honest ways to make it pass: rotate and update the constant, or update the constant if a key was replaced early. Deleting the test is the third way, and the message says it is the one that produces the outage.

The dates cannot be derived from anywhere. The coordinate registry records secret slots, never values or their lifetimes — which is #224's closing observation: no amount of drift detection will surface this one. They come from the operator console read of 2026-08-05 (þing-02 A3(i)). A second test pins both datetimes and the gap against C-84, so a typo fails rather than quietly moving the tripwire.

Verification

Simulated the clock at 2026-10-25 — fires with the full message, 23 days out. Passes today at 90 days.

the platform Appwrite keys expire in 23 days:
    VIEWS Pipeline Core    2026-11-17 12:35
    UN FAO                 2026-11-17 16:10

Both of this repository's delivery paths — un_fao and crafd — authenticate with
'VIEWS Pipeline Core', the earlier one. The two keys are 3:35:00 apart, which is not
a stagger...

Suite: 463 passed, 3 skipped, 37 xfailed. ruff clean.

The honest objection, stated

A test that goes red on a date is a time bomb in CI. That is the design, not a side effect — and the cost is real: after rotation someone must update the constant or the build stays red. The message says so, and updating it is part of rotating. Worth it against a Tier 2 foreseeable total outage; say so on this PR if you disagree and I will drop it.

Polichinel and others added 3 commits August 19, 2026 11:51
#224 says "what is asked of this repo: nothing yet", and C-84 goes further:

  "The honest position is that this is a date to act on, not a mechanism to
   build, and inventing a mechanism would be building the wrong thing to feel
   busy."

That verdict is about a key-VALIDITY preflight — an authenticated call at
startup — and it stands. This is not that. No authenticated call, no credential,
no network: a calendar and two declared datetimes.

What it fixes is C-84's own trigger. Its first arm reads "act when the un_fao
delivery is next scheduled within a month of it", which is a trigger nobody can
notice: it fires in someone's memory or not at all. This repository has already
written that down twice — ADR-014 §4, and the withdrawn third arm of C-94's
trigger. A foreseeable total outage 90 days out deserves better than memory.

tests/test_credential_expiry.py declares both expiries and fails from 30 days
before the earlier one, naming the dates, the 3h35m gap (which is C-84's actual
finding — it is not a stagger, neither key can carry traffic while the other is
replaced), who owns the rotation (operator; views-appwrite#12, split at
views-faoapi#338), and the two honest ways to make it pass: rotate and update the
constant, or update the constant if a key was replaced early. Deleting the test
is the third way and the message says it is the one that produces the outage.

The dates cannot be derived from anywhere — the coordinate registry records
secret SLOTS, never values or their lifetimes, which is #224's closing
observation: no amount of drift detection surfaces this one. They come from the
operator console read of 2026-08-05 (þing-02 A3(i)), and a second test pins them
and the gap against C-84 so a typo fails rather than quietly moving the tripwire.

Verified by simulating the clock at 2026-10-25: fires with the full message,
23 days out. Passes today at 90 days.

Suite: 463 passed, 3 skipped, 37 xfailed. ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two findings on my own tripwire.

1. THE FIRING BRANCH WAS UNPROVEN. The guard's failing path would first have
   executed in October, live, on the day it matters — which is C-102's exact
   lesson: a guard that has never run is unproven however carefully it was
   written. The decision and the message are now pure functions of a date
   (`days_until_earliest_expiry`, `expiry_warning`), and the failing branch is
   exercised against a simulated 2026-10-25. A third test asserts silence well
   outside the window, because a tripwire that is always red is one nobody reads.

2. Naive datetimes, now documented as deliberate rather than left to look like an
   oversight: the console reports local time and the window is 30 days, so an
   hour either way changes nothing. Adding tzinfo would imply a precision the
   source does not have.

Mutation-proven in both directions, and the second one caught a hole I had made
myself: shrinking LEAD_DAYS to 0 silently neuters the tripwire, and my first pass
did not catch it because I had deleted the assertion that would — mid-cleanup, as
a half-written line. Restored: a date 23 days out must be inside the window.

  LEAD_DAYS = 0    -> 1 failed
  LEAD_DAYS = 400  -> 2 failed
  typo an expiry   -> 2 failed

Suite: 465 passed, 3 skipped, 37 xfailed. ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Six findings. Two were design faults that would each have ended with the test
deleted, which for a tripwire is the only failure mode that matters.

1. HIGH — the pin made the tripwire's own prescribed fix impossible. Its message
   says "rotate, then update KEY_EXPIRY"; a second test hardcoded the current
   literals and would have failed on exactly that edit, with a message saying
   "re-read the entry rather than adjusting the constant to match". Measured:
   setting the constant to a rotated date turned 2 tests and 5 assertions red.
   A guard that refuses its own documented remediation is worse than no guard,
   and in November it lands on the one person who cannot route around it. The
   pin is gone; verified that a simulated rotation now passes.

3. MEDIUM (and the one that would have got it deleted) — from 2026-10-18 the
   gate goes red for EVERY unrelated pull request, clearable only by an operator
   console action this repository cannot perform. That is what pyproject.toml
   already says about ruff, citing ADR-014 §3: a gate that starts red gets
   switched off. `ACKNOWLEDGED_UNTIL` is the in-repo escape — a declared,
   reviewed, dated edit meaning "seen, and being acted on" — and it cannot be
   set on or after the expiry, so it postpones attention and never replaces it.
   Verified both ways: setting it clears the gate; setting it past the expiry
   fails.

2. MEDIUM — the firing-branch proof hardcoded 2026-10-25 / 23 days, both derived
   from today's constant, so after any legitimate rotation the probe would fall
   outside the window and the C-102 claim would be void. The probe is now derived
   from KEY_EXPIRY and survives rotation.

4. LOW — the LEAD_DAYS guard only caught shrinking below 23; 23 through 30 all
   passed, so a week could be shaved with a green suite. Floored at 30, with
   widening left free.

5. LOW — the register claimed the datetimes were "pinned against this entry".
   Nothing reads the register; it was same-file literal duplication. Claim
   removed along with the pin.

6. LOW — after the expiry the message read "expire in -3 days", and the gap
   rendered "3:35:00" where the entry title says 3h35m. Now "TODAY" / "3 days
   ago — the seam is already dead", and "3h35m". This is the text an operator
   reads while the seam is down.

Suite: 467 passed, 3 skipped, 37 xfailed. ruff clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Polichinel

Copy link
Copy Markdown
Collaborator Author

Review round — /review-diff + /code-review high

Eight findings. Two were design faults that would each have ended with this test deleted — which, for a tripwire, is the only failure mode that matters.

1 — The pin made the tripwire's own prescribed fix impossible (HIGH)

The message says "rotate, then update KEY_EXPIRY". A second test hardcoded the current literals and would have failed on exactly that edit, with a message saying "re-read the entry rather than adjusting the constant to match".

Measured: setting the constant to a rotated date turned 2 tests and 5 assertions red, and neither failure mentioned the other. A guard that refuses its own documented remediation is worse than no guard — and in November it lands on the one person who cannot route around it.

The pin is gone. Verified: a simulated rotation now passes cleanly.

3 — From 2026-10-18 it holds every unrelated PR hostage

Red on every push and PR to main and development, clearable only by an operator console action this repository cannot perform. That is precisely what pyproject.toml already says about ruff, citing ADR-014 §3:

a gate that starts red gets switched off

ACKNOWLEDGED_UNTIL is the in-repo escape — a declared, reviewed, dated edit meaning "seen, and being acted on" — and it cannot be set on or after the expiry, so it postpones attention and can never replace it.

probe result
rotate + update KEY_EXPIRY passes
ACKNOWLEDGED_UNTIL = 2026-11-01 passes — gate cleared
ACKNOWLEDGED_UNTIL = 2027-01-01 (past expiry) fails

The rest

# finding fix
2 the C-102 firing proof hardcoded 2026-10-25 / 23 days, both derived from today's constant — so after any legitimate rotation the probe falls outside the window and the proof is void probe derived from KEY_EXPIRY; survives rotation
4 the LEAD_DAYS guard only caught shrinking below 23 — 23 through 30 all passed, so a week could be shaved with a green suite floored at 30 (widening left free). Now fails at 29, 23 and 0
5 the register claimed the datetimes were "pinned against this entry". Nothing reads the register — it was same-file literal duplication claim removed with the pin
6 after the expiry the message read "expire in -3 days", and the gap rendered 3:35:00 where the entry title says 3h35m "TODAY" / "3 days ago — the seam is already dead", and 3h35m. This is the text an operator reads while the seam is down

Note on what this deliberately is not

C-84 rejected a key-validity preflight — "a date to act on, not a mechanism to build" — and that verdict stands. No authenticated call, no credential, no network here; only a calendar. What was missing was that C-84's own trigger ("act when the delivery is next scheduled within a month of it") is a trigger nobody can notice, which is the defect ADR-014 §4 forbids and which withdrew the third arm of C-94's trigger.

CI: 491 passed, 5 skipped, 37 xfailed, 0 failed.

@Polichinel
Polichinel merged commit 25e8abc into development Aug 19, 2026
4 checks passed
@Polichinel
Polichinel deleted the feat/c84-expiry-tripwire branch August 19, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant