<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/src/purgatory/mod.rs, branch master</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/atom?h=master</id>
<link rel='self' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/atom?h=master'/>
<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>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>persist and restore announcement events across graceful restarts</title>
<updated>2026-02-23T15:08:37+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T15:08:37+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=26f608e5011b9d1ad6036da75b89272835e69695'/>
<id>urn:sha1:26f608e5011b9d1ad6036da75b89272835e69695</id>
<content type='text'>
Extends purgatory persistence to include announcement purgatory entries.
On graceful shutdown, non-soft-expired announcements are serialised to
purgatory-state.json alongside state/PR/expired events; on startup they
are restored, skipping any entry whose bare repo path no longer exists.

Updates purgatory-design.md to reflect that purgatory persists through
graceful shutdown and documents the new PurgatoryState disk format.

Adds create_announcement_event helper to purgatory_helpers and three new
integration tests in purgatory_persistence covering the full save/restore
cycle, missing-repo skip, and the combined roundtrip with all entry types.
</content>
</entry>
<entry>
<title>fix: only soft-expire announcement when bare repo deletion succeeds</title>
<updated>2026-02-23T13:04:07+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T13:04:07+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=c368f9132a16d45a17ad55943e4b68ba85a6835b'/>
<id>urn:sha1:c368f9132a16d45a17ad55943e4b68ba85a6835b</id>
<content type='text'>
If remove_dir_all fails, leave the entry untouched so the next cleanup
cycle retries the deletion automatically. Previously a failed deletion
would still set soft_expired=true and extend the expiry, meaning the
bare repo would never be retried.
</content>
</entry>
<entry>
<title>feat: implement soft expiry and revival for purgatory announcements</title>
<updated>2026-02-23T12:53:18+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T12:53:18+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=f659ac657bbce1aec423815c184255bb50652ba3'/>
<id>urn:sha1:f659ac657bbce1aec423815c184255bb50652ba3</id>
<content type='text'>
Two-phase expiry for announcement purgatory entries:
- Phase 1 (initial 30min timeout): delete bare repo, set soft_expired=true,
  extend expiry by 24h so the event is retained for potential revival
- Phase 2 (24h extended timeout): fully remove from purgatory

Revival: extend_announcement_expiry() now recreates the bare git repo
when called on a soft-expired entry (triggered by state event or git auth),
clearing soft_expired and resetting the expiry window.
</content>
</entry>
<entry>
<title>fix: replace repo_sync_index wiring with purgatory announcement sync timer</title>
<updated>2026-02-18T20:32:13+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-18T20:32:13+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=ee113a654e2971a6ebdb07398cc5638dbe59b48c'/>
<id>urn:sha1:ee113a654e2971a6ebdb07398cc5638dbe59b48c</id>
<content type='text'>
Instead of threading repo_sync_index through PolicyContext/builder.rs/main.rs
to handle user-submitted purgatory announcements, add a simple background
timer (run_purgatory_announcement_sync, every 5s) that scans the purgatory
for announcement entries and registers them in repo_sync_index as StateOnly.

This is simpler and covers both flows:
- Sync-path announcements: inline registration still happens during event
  processing (sync/mod.rs:1839+), timer provides a safety net
- User-submitted announcements: SelfSubscriber never sees them (rejected
  from DB), timer is the primary registration path

The timer calls sync_purgatory_announcements_to_index() which:
1. Snapshots purgatory via new announcements_for_sync() public method
2. Or_inserts StateOnly entries (never downgrades Full entries)
3. Detects newly added relay URLs and calls handle_new_sync_filters to
   connect and subscribe - fixing the failing test that expected relay
   discovery from a user-submitted purgatory announcement

Removes: repo_sync_index field from PolicyContext, set/get_repo_sync_index
methods, set_repo_sync_index on Nip34WritePolicy, wiring in main.rs, and
the inline AcceptPurgatory registration block in builder.rs.
</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>
<entry>
<title>feat: add diagnostic logging for partial state event matches</title>
<updated>2026-02-03T21:41:19+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-03T21:21:33+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=d392f0bc14bcd687e918d4653ae016226496b4c4'/>
<id>urn:sha1:d392f0bc14bcd687e918d4653ae016226496b4c4</id>
<content type='text'>
Improves observability when pushes are rejected due to state events that
only partially match the pushed refs. Previously, logs only showed 'No
state event found' even when state events existed but didn't match.

Changes:
- Add diagnose_state_mismatch() to explain why state events don't match
- Log specific reasons: missing refs, wrong SHAs, or extra refs
- Update rejection message to 'No matching state event found' (more accurate)
- Add 4 unit tests for diagnostic function

Example diagnostic output:
  WARN State event abc123 from authorized author doesn't match push:
       refs/heads/main missing (state declares 9cc3d93b)

This addresses the issue where a push with only refs/heads/test was
rejected because the state event also declared refs/heads/main, but
logs didn't explain why the match failed.
</content>
</entry>
<entry>
<title>Merge relay.ngit.dev migration: bug fixes and migration tooling</title>
<updated>2026-02-03T15:18:23+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-03T14:50:22+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=874a8abe1d076cfafd9baf919ec23d7d58200698'/>
<id>urn:sha1:874a8abe1d076cfafd9baf919ec23d7d58200698</id>
<content type='text'>
This merge includes critical bug fixes and comprehensive migration tooling
developed during the relay.ngit.dev migration effort.

Bug Fixes:
- Fix git protocol error handling to return HTTP 200 with ERR pkt-line
- Fix naughty list false positives and DNS failure identification
- Fix database query filters in load_existing_events (remove .since())
- Fix OID fetch tracking to distinguish 0 OIDs from successful fetches
- Fix purgatory event source tracking for filtered expiry logging
- Implement OID retry logic for 'not our ref' errors

Migration Tools &amp; Documentation:
- Complete 5-phase migration analysis pipeline with orchestration script
- Phase 1: Event fetching from source relay
- Phase 2: Git sync verification
- Phase 3: Categorization and relay comparison
- Phase 4: Log extraction (parse failures, purgatory expiry)
- Phase 5: Action classification for migration decisions
- Comprehensive migration guide with lessons learned
- Troubleshooting guide for permission and corruption issues

Configuration:
- Add NGIT_LOG_LEVEL configuration option
- Update git throttle limits to 60/minute
- Improve logging throughout for better observability
</content>
</entry>
<entry>
<title>feat(purgatory): track event source for filtered expiry logging</title>
<updated>2026-01-28T21:00:14+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-01-28T21:00:14+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=f148b3a0e4b032c0acf835cda6d2935e19b9f67e'/>
<id>urn:sha1:f148b3a0e4b032c0acf835cda6d2935e19b9f67e</id>
<content type='text'>
Add EventSource enum (Direct/Sync) to purgatory entries to distinguish
between user-submitted events and sync-fetched events. This enables:

- WARN-level logging for direct submissions that expire (user should know)
- DEBUG-level logging for sync-fetched expirations (expected behavior)
- Source upgrade from Sync→Direct if user submits after sync
- Expiry timer reset on source upgrade (fresh 30-min window for user)

The source is included in [PURGATORY_EXPIRED] logs as source=direct or
source=sync for easy filtering.
</content>
</entry>
</feed>
