diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index a3d4658..9383af7 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -54,3 +54,35 @@ {"id":"int-b09e978b3baf1464ca5a83acbe78aca1","kind":"field_change","created_at":"2026-07-26T01:12:00.183044Z","actor":"dawn","issue_id":"hydrant-4xh","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented and benchmarked bounded discovery lookahead"}} {"id":"int-f94c2f4d9a604bad85e37f5e2a349d35","kind":"field_change","created_at":"2026-07-26T02:19:30.894005Z","actor":"dawn","issue_id":"hydrant-7bb","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Benchmark found no beneficial fairness-preserving DID order"}} {"id":"int-791e1391001df4d33ca5d8e77e7fba95","kind":"field_change","created_at":"2026-07-26T08:46:35.184013Z","actor":"dawn","issue_id":"hydrant-90c","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented and verified opt-in relay-first deep discovery"}} +{"id":"int-67b072505a3ef91c2db038cd21b5ccda","kind":"field_change","created_at":"2026-08-04T09:43:07.770144Z","actor":"dawn","issue_id":"hydrant-6vo","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"implemented in f332596: replay policy = resolve via records/history at inflation (Ptr-only StoredData, Block variant removed); version-keyed bodies in history; ephemeral expiry gc via db::expiry"}} +{"id":"int-e8e986d1eee79fe3ceef56a3631fd7de","kind":"field_change","created_at":"2026-08-04T09:43:32.520656Z","actor":"dawn","issue_id":"hydrant-715","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"implemented in f332596: record bodies stored inline in records, cids recomputed on read (cid_from_record_value); superseded bodies versioned in history by death rev"}} +{"id":"int-53c4b2718e2425a9d79ca282eb339032","kind":"field_change","created_at":"2026-08-04T14:35:40.513543Z","actor":"dawn","issue_id":"hydrant-dte","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-7d5297acd3d89842d62955f3d3bca23c","kind":"field_change","created_at":"2026-08-04T14:35:40.979682Z","actor":"dawn","issue_id":"hydrant-wyz","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-c40b4e0979136f385a3204ea1a257fa2","kind":"field_change","created_at":"2026-08-04T14:35:41.444775Z","actor":"dawn","issue_id":"hydrant-m1k","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-d2be0ec0d725374e86b656c507cda75d","kind":"field_change","created_at":"2026-08-04T14:35:41.905024Z","actor":"dawn","issue_id":"hydrant-s2w","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-44627fcadedd4fbfcdf0050459bac98e","kind":"field_change","created_at":"2026-08-04T14:35:42.371067Z","actor":"dawn","issue_id":"hydrant-5jy","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-2dea50d4724ffdd947a941fb183e631c","kind":"field_change","created_at":"2026-08-04T14:35:42.842168Z","actor":"dawn","issue_id":"hydrant-bgk","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-ac70db8b6c546d91ed2c76fb6ebcf19d","kind":"field_change","created_at":"2026-08-04T14:35:43.306866Z","actor":"dawn","issue_id":"hydrant-s2g","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-88c101852700d08fcadd8c0221c2f4d2","kind":"field_change","created_at":"2026-08-04T14:35:43.773997Z","actor":"dawn","issue_id":"hydrant-8wn","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-682b031c4f73fb410a92008e0d37a55b","kind":"field_change","created_at":"2026-08-04T14:35:44.242014Z","actor":"dawn","issue_id":"hydrant-95y","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-ba97c96e74d8b43031736829262e93bc","kind":"field_change","created_at":"2026-08-04T14:35:44.700977Z","actor":"dawn","issue_id":"hydrant-pkq","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-4b70f3c4a31f3d6726e063561d9afdde","kind":"field_change","created_at":"2026-08-04T14:35:45.144829Z","actor":"dawn","issue_id":"hydrant-68p","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-b7b43097a0e32a322dde432352ec19b7","kind":"field_change","created_at":"2026-08-04T14:35:45.601611Z","actor":"dawn","issue_id":"hydrant-18e","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} +{"id":"int-441489c25879543bfe19dd44035dfeaf","kind":"field_change","created_at":"2026-08-04T15:46:16.654434Z","actor":"dawn","issue_id":"hydrant-br2","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Review complete; actionable findings reproduced or traced and filed."}} +{"id":"int-e3633aca4e00defd1359024b30eb445a","kind":"field_change","created_at":"2026-08-04T15:48:41.5613Z","actor":"dawn","issue_id":"hydrant-kgh","extra":{"field":"priority","new_value":"1","old_value":"2"}} +{"id":"int-48a0a70f17eb6a63b893c0476faf4b8e","kind":"field_change","created_at":"2026-08-04T18:24:19.87492Z","actor":"dawn","issue_id":"hydrant-2m4","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Duplicate of hydrant-6vo.1 and incorrect scope: operator erasure stays on the private REST management API; no com.atproto.repo.deleteRecord XRPC."}} +{"id":"int-059a0476704b98cf5d5fefeda55b0b1c","kind":"field_change","created_at":"2026-08-04T19:57:42.63491Z","actor":"dawn","issue_id":"hydrant-6vo.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-e1e1c82f7a547fe603f7884daa72f465","kind":"field_change","created_at":"2026-08-04T19:57:42.859027Z","actor":"dawn","issue_id":"hydrant-ara","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-f910c2ce5e3970afdaa4bc460e60e84c","kind":"field_change","created_at":"2026-08-04T19:57:43.053914Z","actor":"dawn","issue_id":"hydrant-0ch","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-65b4ebc407f10d6bc79a929ed408e7ea","kind":"field_change","created_at":"2026-08-04T19:57:43.248943Z","actor":"dawn","issue_id":"hydrant-b3x","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-b0e9d94aa9b941850ed1b01d23a86158","kind":"field_change","created_at":"2026-08-04T19:57:43.441968Z","actor":"dawn","issue_id":"hydrant-bmm","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-3eb84bb7e4c4fbb16394fdabd4383eca","kind":"field_change","created_at":"2026-08-04T19:57:43.640007Z","actor":"dawn","issue_id":"hydrant-7oh","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"implemented and verified by library suites, API integration, and the 13-combination feature matrix"}} +{"id":"int-c5b7583f00350a0200945b602ba66619","kind":"field_change","created_at":"2026-08-04T19:57:44.242864Z","actor":"dawn","issue_id":"hydrant-6vo","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"retired legacy blocks with bounded v12 migration and verified durable operator redaction semantics"}} +{"id":"int-38168424a32deca0fb58036e1a83de3b","kind":"field_change","created_at":"2026-08-04T20:11:39.563066Z","actor":"dawn","issue_id":"hydrant-iv6","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"legacy marker adoption now uses constant/cheap migration-specific proofs and never reruns the all-repo v8 rebuild or current v10 pass"}} +{"id":"int-6828db596b2578b756aa4285991d9124","kind":"field_change","created_at":"2026-08-04T20:27:19.841311Z","actor":"dawn","issue_id":"hydrant-6vo","extra":{"field":"status","new_value":"in_progress","old_value":"closed"}} +{"id":"int-6eee58e0219f03afafa110afc5d03a39","kind":"field_change","created_at":"2026-08-04T20:51:47.545017Z","actor":"dawn","issue_id":"hydrant-6vo","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"retired legacy blocks in one final v10 migration and verified operator deletion semantics"}} +{"id":"int-c0741f817921b110897e00af00ecc349","kind":"field_change","created_at":"2026-08-05T00:14:20.548028Z","actor":"dawn","issue_id":"hydrant-6vo.1.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"operator deletion is now ordered after commit-coupled body broadcasts"}} +{"id":"int-09e1aac49c25bce98cd75ee897845e6a","kind":"field_change","created_at":"2026-08-05T01:20:08.275853Z","actor":"dawn","issue_id":"hydrant-6vo.2","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Migration copy and all requested invariants validated; full non-credentialed integration suite passes."}} +{"id":"int-31e5dd29f03926cd1b773b3379c0ddb3","kind":"field_change","created_at":"2026-08-05T13:28:53.901038Z","actor":"dawn","issue_id":"hydrant-adq","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented and fully validated on the final working tree."}} +{"id":"int-d47b701c216df2d75a8351144aa4e648","kind":"field_change","created_at":"2026-08-05T13:28:54.108148Z","actor":"dawn","issue_id":"hydrant-0gg","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented and fully validated on the final working tree."}} +{"id":"int-a476263d50fdc6414edb9ac747ba69b6","kind":"field_change","created_at":"2026-08-05T13:28:54.314066Z","actor":"dawn","issue_id":"hydrant-4hr","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Implemented and fully validated on the final working tree."}} diff --git a/src/config.rs b/src/config.rs index d320e37..8b6d7a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -434,6 +434,16 @@ impl Config { )); } + // backlinks hooks are compiled directly into every record mutation; + // `enable_backlinks` does not disable them at runtime. without its own + // retention machinery an ephemeral window would leak stale entries. + #[cfg(feature = "backlinks")] + if self.ephemeral { + return Err(miette::miette!( + "the backlinks feature is not supported with HYDRANT_EPHEMERAL / ephemeral" + )); + } + #[cfg(feature = "relay")] if self.only_index_links { return Err(miette::miette!( @@ -464,6 +474,33 @@ mod tests { assert!(config.validate().is_ok()); } + #[test] + #[cfg(feature = "backlinks")] + fn ephemeral_rejected_when_backlinks_feature_enabled() { + let mut config = Config::default(); + config.ephemeral = true; + config.enable_backlinks = false; + let res = config.validate(); + assert!(res.is_err()); + let err = res.unwrap_err().to_string(); + assert!(err.contains("HYDRANT_EPHEMERAL") || err.contains("ephemeral")); + assert!(err.contains("backlinks feature")); + + config.enable_backlinks = true; + assert!(config.validate().is_err()); + + config.ephemeral = false; + assert!(config.validate().is_ok()); + } + + #[test] + #[cfg(all(feature = "indexer_stream", not(feature = "backlinks")))] + fn ephemeral_allowed_when_backlinks_feature_disabled() { + let mut config = Config::default(); + config.ephemeral = true; + assert!(config.validate().is_ok()); + } + #[test] #[cfg(all(feature = "indexer", not(feature = "indexer_stream")))] fn ephemeral_requires_stream_storage() {