<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/src, branch v1.0.0</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.0</id>
<link rel='self' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/atom?h=v1.0.0'/>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/'/>
<updated>2026-02-25T15:07:40+00:00</updated>
<entry>
<title>drop nostr-db backend support, keep only lmdb and memory</title>
<updated>2026-02-25T15:07:40+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-25T15:07:40+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=5ad9d9093fcbe7037e5474a9d8fa20a0b64fb79a'/>
<id>urn:sha1:5ad9d9093fcbe7037e5474a9d8fa20a0b64fb79a</id>
<content type='text'>
</content>
</entry>
<entry>
<title>add background job to clean up grasp-audit test events and git repos</title>
<updated>2026-02-24T12:45:26+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-24T12:45:26+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=3f4dc8e1bc07f88c064d4734f5cc3ee87b1497e4'/>
<id>urn:sha1:3f4dc8e1bc07f88c064d4734f5cc3ee87b1497e4</id>
<content type='text'>
Spawns a tokio task that runs every 30 minutes and removes all events
tagged 'grasp-audit-test-event' older than 2 hours from the LMDB
database, along with their associated bare git repositories on disk.
</content>
</entry>
<entry>
<title>remove dead code: get_authorization_from_db and collect_all_authorized_maintainers</title>
<updated>2026-02-24T11:39:55+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-24T11:39:55+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=aa40780d6f1710a386dcaa2e73730ba50634eaed'/>
<id>urn:sha1:aa40780d6f1710a386dcaa2e73730ba50634eaed</id>
<content type='text'>
Both were pub functions with no callers. Clippy doesn't flag dead pub
items because the compiler treats them as potentially used by external
crates - only private items trigger the dead_code lint.
</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>clarify DB-only count in fetch_repository_data log message</title>
<updated>2026-02-24T10:20:55+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-24T10:20:55+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=5efdf431a1481f6fb7a17190b62588b81c5b1e65'/>
<id>urn:sha1:5efdf431a1481f6fb7a17190b62588b81c5b1e65</id>
<content type='text'>
</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>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>feat: handle deletion of PR/PR-update events from purgatory</title>
<updated>2026-02-23T13:46:57+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T13:46:57+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=f19b424e01fc5a682778c5e2bb194d242efd6987'/>
<id>urn:sha1:f19b424e01fc5a682778c5e2bb194d242efd6987</id>
<content type='text'>
Kind 5 deletion events referencing a PR or PR-update event by e-tag now
remove the matching purgatory entry, provided the deletion author matches
the PR event author. Placeholders (git data arrived before the event) are
not removed since they have no author to verify against.

PR purgatory is keyed by event ID hex so this is an O(1) lookup, checked
before the O(n) announcement and state event scans.
</content>
</entry>
<entry>
<title>fix: rewrite deletion integration tests to avoid shared-state side effects</title>
<updated>2026-02-23T13:42:57+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-23T13:42:57+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=0c71e191963bec729c3ca13c212b231af7582f06'/>
<id>urn:sha1:0c71e191963bec729c3ca13c212b231af7582f06</id>
<content type='text'>
The previous tests deleted purgatory announcements (kind 30617) and checked
for bare-repo absence via git ls-remote, which would corrupt shared-mode
test state by destroying repos other tests depend on.

New approach tests deletion of purgatory state events (kind 30618) instead:

- e-tag test: promotes a repo, creates a unique commit locally, submits a
  state event pointing to it (enters purgatory), deletes the state event by
  event ID, then verifies git push of that commit is rejected.

- a-tag coordinate test: promotes a repo, generates a fresh maintainer
  keypair, sends a replacement announcement adding that maintainer, submits
  a state event signed by the new maintainer (enters purgatory), deletes by
  coordinate 30618:&lt;new_maintainer_pubkey&gt;:&lt;identifier&gt;, then verifies git
  push is rejected.

Also extends DeletionPolicy to handle kind 30618 state events in purgatory
for both e-tag (event ID) and a-tag (coordinate) deletion paths.
</content>
</entry>
</feed>
