<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/src/git/sync.rs, branch v1.0.2</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/atom?h=v1.0.2</id>
<link rel='self' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/atom?h=v1.0.2'/>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/'/>
<updated>2026-02-26T15:42:09+00:00</updated>
<entry>
<title>chore: apply cargo fmt and fix clippy warnings</title>
<updated>2026-02-26T15:42:09+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T15:42:09+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=9d86cf15f0275ffeee4519bd054e3b61dc8992ac'/>
<id>urn:sha1:9d86cf15f0275ffeee4519bd054e3b61dc8992ac</id>
<content type='text'>
Fix pre-existing clippy lints:
- &amp;PathBuf -&gt; &amp;Path in audit_cleanup.rs
- too_many_arguments on process_newly_available_git_data,
  process_purgatory_announcements, and HttpService::new
- clone_on_copy for PublicKey (Copy type) in purgatory cleanup loop
</content>
</entry>
<entry>
<title>rename: fetch_repository_data -&gt; fetch_repository_data_{excluding,with}_purgatory</title>
<updated>2026-02-24T11:36:39+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-24T11:36:39+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=c31a313ccf781e54fa15942bc882c1b113d3f590'/>
<id>urn:sha1:c31a313ccf781e54fa15942bc882c1b113d3f590</id>
<content type='text'>
The old name was ambiguous - it wasn't clear whether purgatory was
included or not. The two variants are now explicitly named:
- fetch_repository_data_excluding_purgatory: DB only
- fetch_repository_data_with_purgatory: DB + purgatory overlay

SyncContext trait method also renamed to fetch_repository_data_with_purgatory
to match the free function it delegates to.
</content>
</entry>
<entry>
<title>Fix purgatory announcement not promoted when OIDs arrive via cross-owner state event copy</title>
<updated>2026-02-24T09:19:02+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-24T09:19:02+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=0b9861e14f23cc615d33ebd8845a36b40516a8a5'/>
<id>urn:sha1:0b9861e14f23cc615d33ebd8845a36b40516a8a5</id>
<content type='text'>
When git data is fetched into owner A's repo and a state event for owner B
is released from purgatory (copying OIDs from A's repo to B's repo via
process_state_with_git_data), owner B's purgatory announcement was never
promoted. process_purgatory_announcements only promotes the announcement
for the owner derived from source_repo_path (owner A), so owner B's
announcement stayed in purgatory with its 30-minute expiry timer running.

30 minutes later the cleanup task would soft-expire owner B's entry,
deleting the bare repository even though the announcement had been
effectively satisfied.

Fix: after a state event is successfully saved to the database, iterate
over all announcements in db_repo_data and promote any purgatory
announcement for owners whose repos received OIDs via the copy (i.e.
repos other than source_repo_path).
</content>
</entry>
<entry>
<title>Merge master into 3ca0-announcements-purgatory</title>
<updated>2026-02-23T15:20:59+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T15:20:59+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=113928aa84894ea8f65c247d9987527e792b32a9'/>
<id>urn:sha1:113928aa84894ea8f65c247d9987527e792b32a9</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix: re-process hot-cache maintainer announcements after git push promotion</title>
<updated>2026-02-23T12:05:29+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T11:17:10+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=70749ea9df1f6061c332112c617b615f91d79d48'/>
<id>urn:sha1:70749ea9df1f6061c332112c617b615f91d79d48</id>
<content type='text'>
When an owner announcement is promoted from purgatory via a git push,
any maintainer announcements sitting in the rejected_events_index hot
cache were never re-processed. The invalidate_and_get call only existed
in SyncManager::process_event_static (the nostr sync path); the git push
promotion path (http -&gt; handlers -&gt; git::sync) had no access to the
rejected_events_index at all.

Thread rejected_events_index and write_policy through the git push path:
- process_purgatory_announcements: after saving the promoted announcement,
  parse its maintainers tag and call invalidate_and_get() for each, then
  re-process any returned hot-cache events via admit_event + save
- process_newly_available_git_data: accept optional write_policy and
  rejected_events_index, pass them through to process_purgatory_announcements
- handle_receive_pack: accept Arc&lt;Nip34WritePolicy&gt; and
  Arc&lt;RejectedEventsIndex&gt;, pass them to process_newly_available_git_data
- HttpService / run_server: carry the two new fields, clone into each
  handle_receive_pack call
- main.rs: obtain rejected_events_index from sync_manager before moving
  it into its task; wrap write_policy in Arc for the HTTP server
- RealSyncContext::process_newly_available_git_data: pass None for both
  new params (purgatory sync path already handles this via
  SyncManager::process_event_static)

Also rewrite the maintainer_reprocessing integration tests to correctly
exercise the hot-cache path now that announcements require git data
before being released from purgatory:
- Start relay_b with relay_a as bootstrap so its SyncManager syncs
  maintainer announcements via negentropy before the owner git push
- Use push_unique_git_data_to_relay (new helper) to give each maintainer
  a distinct commit hash, preventing git from skipping pack transfer
- Make wait_for_event_on_relay poll in a retry loop so transient timing
  gaps between DB write and query do not cause false negatives
</content>
</entry>
<entry>
<title>Revert "feat: upgrade repo to Full sync and trigger PR event subscription after announcement promotion"</title>
<updated>2026-02-18T19:28:28+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-18T19:28:28+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=3d9359d5ac0045fb93fd8732160e0de8413d6881'/>
<id>urn:sha1:3d9359d5ac0045fb93fd8732160e0de8413d6881</id>
<content type='text'>
This reverts commit d76003b629a4a03dba23a8a1c41da6e4ac4c30cf.
</content>
</entry>
<entry>
<title>feat: upgrade repo to Full sync and trigger PR event subscription after announcement promotion</title>
<updated>2026-02-18T17:12:17+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-18T17:12:17+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=d76003b629a4a03dba23a8a1c41da6e4ac4c30cf'/>
<id>urn:sha1:d76003b629a4a03dba23a8a1c41da6e4ac4c30cf</id>
<content type='text'>
When git data arrives for a purgatory announcement and promotes it to the
database, the relay now:

1. Upgrades the announcement's sync level in RepoSyncIndex from StateOnly
   to Full (git/sync.rs: process_purgatory_announcements)
2. Sends AddFilters actions to SyncManager for all connected relays, using
   Full sync filters (Layer 2 #a/#A/#q) to subscribe to PR events
   (purgatory/sync/context.rs: RealSyncContext.process_newly_available_git_data)
3. For user-submitted purgatory announcements, registers the repo in
   RepoSyncIndex with StateOnly level and sends AddFilters to SyncManager
   so it discovers and connects to relays listed in the announcement tags
   (nostr/builder.rs: handle_announcement AcceptPurgatory path)

The RealSyncContext now accepts optional repo_sync_index and sync_action_tx
parameters. main.rs wires these up from SyncManager. PolicyContext gains
repo_sync_index and sync_action_tx fields for the write policy path.
</content>
</entry>
<entry>
<title>docs: clarify why fetch_repository_data excludes purgatory</title>
<updated>2026-02-17T11:43:40+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-17T11:43:40+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=cad58fccae7ed84bb033e56de0f1323b714a854d'/>
<id>urn:sha1:cad58fccae7ed84bb033e56de0f1323b714a854d</id>
<content type='text'>
Add comments explaining that PR event processing (both incoming and
purgatory) should only use database announcements, not purgatory ones.

This is intentional because:
- Incoming PR events should only be accepted for validated announcements
- Purgatory PR events should only be released when announcement is promoted
- This prevents accepting PR events for announcements that fail validation

Differs from state event processing which uses fetch_repository_data_with_purgatory
because state events check authorization without releasing from purgatory.
</content>
</entry>
<entry>
<title>fix: include purgatory announcements in state event authorization</title>
<updated>2026-02-17T10:58:01+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-17T10:58:01+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=efbbcc49ae8e8f598a24c939b35ad9cda0541663'/>
<id>urn:sha1:efbbcc49ae8e8f598a24c939b35ad9cda0541663</id>
<content type='text'>
When processing state events from purgatory, we need to check
authorization against announcements that may still be in purgatory
(not yet promoted to the database).

Previously, process_purgatory_state_events() used fetch_repository_data()
which only queries the database. This caused authorization failures when:
1. Git data arrives
2. Announcement is promoted from purgatory to database
3. State events are processed from purgatory
4. But db_repo_data was fetched BEFORE the announcement promotion

Now uses fetch_repository_data_with_purgatory() to include both
database and purgatory announcements, ensuring authorization works
correctly regardless of promotion timing.
</content>
</entry>
<entry>
<title>feat: implement announcement purgatory core (breaks archive sync test)</title>
<updated>2026-02-13T17:29:23+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-13T13:24:46+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=1d09e4bdea7e328cf2740818df9df660c5532a99'/>
<id>urn:sha1:1d09e4bdea7e328cf2740818df9df660c5532a99</id>
<content type='text'>
Route new announcements to purgatory instead of accepting immediately.
Announcements are promoted to the database when git data arrives,
ensuring we only serve announcements for repos with actual content.

Implemented:
- AnnouncementPurgatoryEntry type and DashMap store
- Route new announcements to purgatory (replacement announcements skip)
- Promote announcements on git data arrival (process_purgatory_announcements)
- Authorization checks purgatory announcements (fetch_repository_data_with_purgatory)
- State policy uses purgatory announcements for maintainer validation
- Cleanup task handles announcement expiry
- Updated count()/cleanup() to 3-tuples

Known broken:
- test_archive_read_only_creates_bare_repo fails: sync module does not
  treat purgatory announcements as confirmed repos, so per-repo sync
  (state events, PRs) is never triggered for purgatory announcements
- Announcement persistence (save/restore) not implemented
- SyncLevel (StateOnly vs Full) not implemented
- Soft expiry two-phase not implemented
- Expiry extension on state event / git auth not wired up
</content>
</entry>
</feed>
