<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/CHANGELOG.md, 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-04-10T20:39:10+00:00</updated>
<entry>
<title>release: v1.0.2</title>
<updated>2026-04-10T20:39:10+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-04-10T20:15:58+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=dd9a69e6fe79e866004ed7366093bf82030b02eb'/>
<id>urn:sha1:dd9a69e6fe79e866004ed7366093bf82030b02eb</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix: purgatory replacement announcements leaked into DB without git data</title>
<updated>2026-04-10T18:20:23+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-04-10T18:20:23+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=2161e3c0a8169a85111cd6dc01ffe2b0fed1493f'/>
<id>urn:sha1:2161e3c0a8169a85111cd6dc01ffe2b0fed1493f</id>
<content type='text'>
When a replacement 30617 announcement arrived for an entry already in
purgatory (e.g. the same event fetched from a second relay during sync,
or a user re-submitting a slightly updated announcement), the policy
returned Accept instead of AcceptPurgatory. This caused the event to be
saved to the database immediately, bypassing the purgatory gate, without
the corresponding git data or state events ever arriving.

Fix: return AcceptPurgatory when replacing a purgatory entry so the
updated event stays in purgatory until git data arrives. The purgatory
entry is still updated with the newer event via replace_purgatory_announcement
before the return.
</content>
</entry>
<entry>
<title>fix: accept any d-tag identifier; percent-encode in URLs</title>
<updated>2026-04-10T16:42:35+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-04-10T16:42:35+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=dfd20a39a7ddaea07103cac45d4d79bc7e6ce0d7'/>
<id>urn:sha1:dfd20a39a7ddaea07103cac45d4d79bc7e6ce0d7</id>
<content type='text'>
NIP-01 places no restriction on d tag characters and NIP-34 only
recommends kebab-case without mandating it. Rejecting identifiers with
whitespace or other URL-unsafe characters was therefore overly strict.

The correct approach (per NIP-34 PR #2312 and GRASP-01) is to store
identifiers verbatim on disk and percent-encode them when constructing
URLs. The previous commit already handled the incoming direction
(percent-decoding URL paths before filesystem lookup); this commit
handles the outgoing direction and removes the validation restriction.

Changes:
- validate_identifier: drop whitespace rejection; only reject chars
  that are unsafe as filesystem directory names (/, \, null, . / ..)
- git/mod.rs: add percent_encode() alongside percent_decode()
- landing.rs: percent-encode identifier in nostr:// clone URL and
  gitworkshop link (also fixes a pre-existing bug where the clone URL
  displayed literal '{npub}' / '{identifier}' instead of the values)
</content>
</entry>
<entry>
<title>chore: remove arbitrary default max connections limit</title>
<updated>2026-03-25T07:19:26+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-03-25T07:19:26+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=28168a7701c897a5b6af13bc472d6f5902e0a96d'/>
<id>urn:sha1:28168a7701c897a5b6af13bc472d6f5902e0a96d</id>
<content type='text'>
When NGIT_MAX_CONNECTIONS is unset the relay imposes no connection cap,
deferring to OS fd limits and infrastructure controls. The option remains
available for operators who want an explicit ceiling.
</content>
</entry>
<entry>
<title>release: v1.0.1</title>
<updated>2026-02-27T18:05:03+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-27T18:05:03+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=05b7edb5f5797100d8e0f59905e16488680928ec'/>
<id>urn:sha1:05b7edb5f5797100d8e0f59905e16488680928ec</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix: ignore peeled tag entries (^{}) in state event ref parsing</title>
<updated>2026-02-26T15:38:51+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T15:38:51+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=a2ecfc5a63311570f0f90c7ee40117e289639cb8'/>
<id>urn:sha1:a2ecfc5a63311570f0f90c7ee40117e289639cb8</id>
<content type='text'>
State events (kind 30618) can include refs/tags/&lt;name&gt;^{} entries which
are git's notation for the dereferenced commit behind an annotated tag.
These are not real git refs and are never sent as part of a push.

extract_refs_from_state and RepositoryState::from_event were treating
them as real refs, causing can_satisfy_state to reject valid annotated
tag pushes: the would-be state after the push lacked the spurious ^{}
entry, so the exact-equality check always failed.
</content>
</entry>
<entry>
<title>send auth rejection reason to git client via ERR pkt-line</title>
<updated>2026-02-26T12:19:31+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T12:19:06+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=b13c6d924f7de5ff34405254b8bb21adf33c78c0'/>
<id>urn:sha1:b13c6d924f7de5ff34405254b8bb21adf33c78c0</id>
<content type='text'>
Previously push auth failures returned HTTP 403 which git clients
display as a generic transport error. Now they return HTTP 200 with
an ERR pkt-line containing the rejection reason (e.g. 'authorisation
failed: No state events in purgatory'), which git displays directly.

Remove GitError::Unauthorized as it is no longer used. GitError
variants now represent only transport/infrastructure failures; app-level
rejections use ERR pkt-line responses.
</content>
</entry>
<entry>
<title>release: v1.0.0</title>
<updated>2026-02-26T09:27:13+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T09:26:01+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1tkq8unhsd5jqx6ueex5lcpsgknrpquxuk44ftpjlpm3ulaake7xs76txrw/ngit-grasp-mirror/commit/?id=fd6b098f41baf8621551f15114c50891642b5872'/>
<id>urn:sha1:fd6b098f41baf8621551f15114c50891642b5872</id>
<content type='text'>
</content>
</entry>
</feed>
