Coverage for node / src / stigmem_node / federation / dnssec / epoch.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-06-18 05:34 +0000

1"""Per-host monotonic epoch pin + sticky-signedness (Rev 6 I4 / build-phase 3b.5). 

2 

3State for the ``dnssec_epoch_pins`` table (migration 054), keyed by **host** (the 

4canonical host derived from the signed wire ``entity_uri`` per I3) — *not* by 

5identity. The epoch floor and the signed-delegation fact are properties of the 

6zone, so a host that serves more than one ``node_id`` shares one floor: a second 

7node arriving under the same host at a lower epoch is a rollback, never a fresh 

8first-contact (Rev 6 plan TB-5). 

9 

10Two pieces of state live here: 

11 

12 * **Monotonic epoch** — ``accept_epoch(conn, host, epoch)`` enforces that a 

13 host's ``max_epoch_seen`` never decreases. First contact (no row) takes the 

14 handed epoch and pins it (honestly unauthenticated as to recency, §15.3); 

15 ``epoch < max_epoch_seen`` is rejected (``dnssec_epoch_rollback``); 

16 ``epoch >= max_epoch_seen`` is accepted and advances the floor. 

17 * **Sticky-signedness** — ``mark_signed_delegation`` records that a signed 

18 delegation has been observed for a host; once set it never clears, so a 

19 later authenticated "absent" can be treated as an attack by the caller (I2). 

20 

21These are off-path DB primitives: nothing here is wired into the resolver yet 

22(that is a later 3b task). All helpers take an open ``sqlite3``-style connection 

23and participate in its transaction; the caller owns commit/rollback. No DNSSEC / 

24``dnspython`` import is reachable from this module (I11). 

25""" 

26 

27from __future__ import annotations 

28 

29from datetime import UTC, datetime 

30from typing import Any 

31 

32# An epoch-only upsert needs a placeholder validation timestamp for the 

33# NOT NULL last_validated_at column on a fresh row. The real first-trust ladder 

34# stamps the genuine validation time; for these primitives "now" suffices and is 

35# advanced on every accepted epoch. 

36 

37 

38def _now_iso() -> str: 

39 return datetime.now(UTC).isoformat() 

40 

41 

42def accept_epoch(conn: Any, host: str, epoch: int) -> bool: 

43 """Apply the monotonic-epoch rule for ``host`` (Rev 6 I4). 

44 

45 * No prior row (first contact) -> accept, pin ``max_epoch_seen=epoch``, True. 

46 * ``epoch < max_epoch_seen`` -> reject (``dnssec_epoch_rollback``), the 

47 stored floor is left unchanged, return False. 

48 * ``epoch >= max_epoch_seen`` -> accept, advance the floor to ``epoch``, 

49 refresh ``last_validated_at``, return True. 

50 

51 Keyed by ``host`` only (TB-5): a different ``node_id`` under the same host is 

52 governed by the same floor and cannot reset it by being "new". 

53 

54 The caller owns the transaction; this never commits. 

55 """ 

56 row = conn.execute( 

57 "SELECT max_epoch_seen FROM dnssec_epoch_pins WHERE host=?", (host,) 

58 ).fetchone() 

59 

60 if row is None: 

61 # First contact: take the handed epoch and pin it. signed_delegation_seen 

62 # defaults to 0 (migration 054); the caller marks it separately. 

63 conn.execute( 

64 "INSERT INTO dnssec_epoch_pins " 

65 "(host, max_epoch_seen, signed_delegation_seen, last_validated_at) " 

66 "VALUES (?, ?, 0, ?)", 

67 (host, epoch, _now_iso()), 

68 ) 

69 return True 

70 

71 current = row[0] 

72 if epoch < current: 

73 # Rollback: leave the floor untouched and reject. 

74 return False 

75 

76 # Equal or higher: advance (or hold) the floor; refresh the validation time. 

77 # signed_delegation_seen is deliberately NOT touched here so the sticky flag 

78 # survives ordinary epoch advances. 

79 conn.execute( 

80 "UPDATE dnssec_epoch_pins SET max_epoch_seen=?, last_validated_at=? WHERE host=?", 

81 (epoch, _now_iso(), host), 

82 ) 

83 return True 

84 

85 

86def mark_signed_delegation(conn: Any, host: str) -> None: 

87 """Record (stickily) that a signed delegation has been observed for ``host``. 

88 

89 Idempotent: once ``signed_delegation_seen`` is 1 it stays 1. Creates the row 

90 if the host has not been seen yet (with ``max_epoch_seen=0`` as a neutral 

91 floor that any real first-contact epoch will meet-or-exceed). The caller owns 

92 the transaction. 

93 """ 

94 row = conn.execute( 

95 "SELECT host FROM dnssec_epoch_pins WHERE host=?", (host,) 

96 ).fetchone() 

97 if row is None: 

98 conn.execute( 

99 "INSERT INTO dnssec_epoch_pins " 

100 "(host, max_epoch_seen, signed_delegation_seen, last_validated_at) " 

101 "VALUES (?, 0, 1, ?)", 

102 (host, _now_iso()), 

103 ) 

104 else: 

105 conn.execute( 

106 "UPDATE dnssec_epoch_pins SET signed_delegation_seen=1 WHERE host=?", 

107 (host,), 

108 ) 

109 

110 

111def signed_delegation_seen(conn: Any, host: str) -> bool: 

112 """Return whether a signed delegation has ever been observed for ``host``. 

113 

114 False when the host has no row yet (never observed signed).""" 

115 row = conn.execute( 

116 "SELECT signed_delegation_seen FROM dnssec_epoch_pins WHERE host=?", (host,) 

117 ).fetchone() 

118 return bool(row[0]) if row is not None else False