- commit
- f919153bb9862cc760b7a86e503a316168b27c55
- parent
- dbc664c37157583038672ace3cf09e825b88f08a
- author
- Dami <dami.etoile@gmail.com>
| M | README.md | 7 | ++- |
| M | docs/ | 2 | +- |
| M | docs/ | 6 | +- |
| M | docs/ | 12 | +++- |
| M | docs/ | 90 | ++++++++++++++++++++++++------ |
@@ -84,7 +84,12 @@ npm run deploy
8484 8585 NIP-01, 05, 09, 11, 13, 17, 29, 40, 42, 43, 45, 46 transport, 50, 56, 57, 59, 62, 66, 67, 70, 77, 86, 94, 96, 98, Marmot transport and Blossom BUD-01, 02, 04, 06, 08, 09. A relay's information document lists what its owner left on.8686 87-NIP-5A site discovery uses the `nsites` field. GRASP advertises `supported_grasps: ["GRASP-01"]` only while enabled with open reads. Later GRASP specifications and server-side MLS group management are outside this implementation.87+NIP-5A site discovery uses the `nsites` field. GRASP advertises only locally88+validated, enabled profiles. GRASP-01 and validated GRASP-06 are currently89+advertised; GRASP-02/03/05 are bounded opt-in previews pending interoperability90+and conformance review. `grasp02` and `grasp06` require `grasp`, while91+`grasp03` and `grasp05` require `grasp02`. Private repositories and any92+profile without its dependencies remain outside the advertised capabilities.8893 8994 ## License9095 @@ -47,7 +47,7 @@ Under **Dumps**, choose daily or weekly and how many to keep, seven by default.
4747 4848 ## Portable backups4949 50-On the Data tab, **Create and download** makes a private archive with configuration, signed events, saved list history, hidden and pending state, site/media blobs and Git objects. Existing archives can be downloaded or deleted. Each binary object and the archive have SHA-256 integrity checks; event signatures are checked on restore. Stored archives count toward fuel.50+On the Data tab, **Create and download** makes a private archive with configuration, signed events, saved list history, hidden and pending state, site/media blobs and Git objects. It also preserves optional GRASP PR expiry rows (`state.prRefs`), including deletion tombstones with `until: 0`, so deadlines survive restore. Existing archives can be downloaded or deleted. Each binary object and the archive have SHA-256 integrity checks; event signatures are checked on restore. Stored archives count toward fuel. Older archives without `state.prRefs` remain readable.5151 5252 Open a fresh, unclaimed relay and choose the archive in **Restore a backup**. Sign with the original owner's key, preview its source identity, counts and configuration, then restore. The target must be empty and unleased. Restore stages files before applying the database in one transaction. The source identity is recorded; the target gets a new relay key. Signed site and Git references still name their original URLs, so publish updated service references from your client after moving.5353 @@ -127,8 +127,10 @@ authorization pure, while the Git door owns Smart HTTP and the object-store
127127 seam. The accepted kind 30618 state is the complete ref map the door may128128 serve. Keep the Git path separate from relay and NIP-5A routing, and record129129 any new GRASP capability in the information document and the numbered draft130-specification. GRASP-02, GRASP-03, GRASP-05, GRASP-06 and GRASP-08 need their131-own design and must not be implied by a GRASP-01 change.130+specification. GRASP-02, GRASP-03, GRASP-05 and GRASP-06 are independently131+gated extensions with dependency checks. GRASP-02/03/05 are bounded previews132+and are not advertised until interoperability and conformance review; GRASP-08133+remains outside this implementation.132134 133135 ## The signer bundle134136 @@ -39,8 +39,10 @@ management stay open.
3939 4040 A door that belongs to a feature the owner switched off (Relay configuration, Rules) answers 404: names, files (Blossom and NIP-96), pages and the feed. `supported_nips` drops the numbers of features that are off.4141 42-When GRASP-01 is on and reads are open, NIP-11 also has43-`supported_grasps: ["GRASP-01"]`, a `repo_acceptance_criteria` string and, only42+When GRASP is on and reads are open, NIP-11 also has a `supported_grasps` list43+containing `GRASP-01` and validated `GRASP-06` when enabled. GRASP-02/03/0544+remain bounded previews pending interoperability and conformance review. The45+document also has a `repo_acceptance_criteria` string and, only4446 for policy beyond ordinary spam controls, `curation`. See [GRASP-01 Git4547 hosting](22-grasp-01-git-hosting.md) for the acceptance and Git protocol rules.4648 @@ -119,6 +121,12 @@ cooldown; a Durable Object restart or eviction resets that cooldown.
119121 |---|---|---|---|---|120122 | `gitstorage` | repository owner hex pubkey, identifier | NIP-98, owner with the storage action | bounded physical and live inventory, reservations and limits | 200; 400 invalid parameters; 403 inactive, fuel or role; 404 feature or repository unavailable; 413 inventory limit; 429 cooldown or another repository operation; 503 storage unavailable |121123 124+The owner-only `storagestats` method also includes `result.graspSync` when125+GRASP synchronization is configured. It reports `enabled`, `partial`, event126+counts (`jobs`, `failed`, `history`, `due`) and Git counts (`jobs`, `failed`,127+`due`). `due` is the earliest Unix timestamp or `null`; `failed` counts rows128+with durable error details, and `history` counts unfinished history windows.129+122130 ## Custom domains123131 124132 These NIP-86 methods are owner-only and use the relay's normal NIP-98 RPC@@ -13,18 +13,21 @@ The Nostr relay remains the source of authorization and discussion events.
1313 This document tracks the GRASP-01 specification at [commit1414 f35b4f9a4ed2f0aaaf46926e4b1733c79e21b377](https://github.com/DanConwayDev/grasp/tree/f35b4f9a4ed2f0aaaf46926e4b1733c79e21b377),1515 checked on 2026-09-04. The implementation is bounded to the core service. It16-does not claim GRASP-02 proactive sync,17-GRASP-03 discussion sync, GRASP-05 archive, GRASP-06 alternative PR hosting or18-GRASP-08 private repositories.16+The later extensions are independently opt-in: `grasp02`, `grasp03`,17+`grasp05` and `grasp06`. GRASP-02 and GRASP-06 require `grasp`; GRASP-03 and18+GRASP-05 require GRASP-02. These switches default off, so enabling `grasp`19+alone preserves GRASP-01 behavior. This document describes the host20+implementation and does not claim an upstream audit or complete conformance.1921 2022 ## Turn it on2123 2224 The `grasp` feature is off unless the owner enables it. The **Git repositories** preset23-turns on open reads and the GRASP Git door. The repository still applies its25+turns on open reads and the GRASP Git door. The later flags are separately26+opt-in and the dependency rules above apply. The repository still applies its2427 ordinary fuel, storage and event rules, and the information document lists25-the exact acceptance criteria. The relay advertises `GRASP-01` in26-`supported_grasps` only while the feature is on and reads are open, because27-GRASP-01's Git service is public.28+the exact acceptance criteria. The relay advertises `GRASP-01` and, when29+validated and enabled, `GRASP-06` in `supported_grasps`. GRASP-02/03/05 remain30+bounded opt-in previews pending interoperability and conformance review.2831 2932 The [relay templates](../relay-templates/README.md) include a GRASP template3033 for a relay whose public purpose is hosting NIP-34 repositories. A template@@ -53,8 +56,9 @@ private repository hosting is GRASP-08 and remains outside this feature.
5356 The accepted announcement's address is5457 `30617:<owner-pubkey>:<identifier>`. NIP-34 issues, patches, pull requests and5558 updates that refer to an accepted address can be stored by the normal relay56-rules. An event that has no accepted repository relationship remains subject57-to the ordinary policy.59+rules. GRASP-06 pull requests may arrive before the announcement: they must60+still name a syntactically valid repository coordinate and remain in purgatory61+until their matching Git data arrives.5862 5963 ## Publish a state6064 @@ -79,6 +83,17 @@ new tip's objects arrive.
7983 8084 ## Pull requests and purgatory8185 86+The alternative PR endpoint is `/prs/<signer-npub>/<percent-encoded-identifier>.git`.87+It is a public, empty repository namespace with at most 16 hosted namespaces88+and 1,024 refs per namespace. Only `refs/nostr/<event-id>` refs are accepted;89+ordinary branches, tags and client deletions are refused. A pre-announcement90+PR must carry the exact signer PR clone URL and a valid repository coordinate91+with the same identifier. The signed PR or update and its `c` tip authorize the92+ref. Unknown events may upload first, but remain hidden until the event is93+accepted; their deadline is fixed at 20 minutes. Expiry removes refs, while94+immutable WAL packs and orphaned objects remain retained and charged because95+the service has no garbage collector.96+8297 Promotion checks for relevant pending events before loading Git packs. An8398 empty queue or another repository's pending work does not trigger that read.8499 A retried Git write still completes any pending promotion left by an earlier@@ -175,13 +190,53 @@ event writes and configuration changes receive a retry response while a scan
175190 owns the relay. See [HTTP reference](14-http-reference.md) for the method and176191 [Costs and margins](15-costs-and-margins.md) for its host costs and limits.177192 193+## Proactive synchronization and archive194+195+With `grasp02`, the relay performs repository-scoped historic and bounded live196+event synchronization from accepted announcement relay lists. Missing Git data197+is queued from signed state and accepted PR/update clone sources with an hourly198+target subject to queued work, fuel and size limits. At most 16 Git sources are199+considered; each connected round is bounded to 10 seconds. Failures retry after200+five minutes before returning to the hourly schedule. Packs are limited to201+4 MiB, with approximately 4.25 MiB of wire response allowance. Remote202+advertisements never authorize refs; signed state and accepted events are203+rechecked under the repository fence. PR objects already uploaded to this204+relay through GRASP-06 are copied locally into the target repository, without205+a self-fetch. Multiple clone URLs in a single tag are considered.206+207+History uses durable cursors with inclusive timestamp overlap and a 256-event208+page cap. A source page cap is surfaced as partial history rather than silently209+reported complete. Up to 512 durable sync jobs and 128 history windows are210+retained. Restarts resume unfinished history before following the bounded 1.5211+second live tail.212+213+With `grasp03`, accepted issue, patch and PR threads are expanded through the214+authors' kind 10002 write relays. Replies may use `#e` or `#E` and do not need215+a new repository coordinate; the accepted parent thread remains the scope216+boundary. Only write relays from kind 10002 outbox lists are used. Metadata217+refresh is limited to kinds 0, 10002 and 10317, with the same bounded source218+and job limits.219+220+With `grasp05`, the relay may admit announcements that omit its own clone and221+relay URLs. Archive admission still consumes the normal repository quota and222+storage accounting, and depends on GRASP-02. Immutable packs remain retained223+and charged; expiry does not provide garbage collection.224+225+The owner can inspect synchronization through `storagestats`. Its226+`graspSync` result records whether synchronization is enabled, whether source227+or scope caps made the result partial, event and Git job counts, durable error228+counts, unfinished history windows, and the earliest due Unix timestamp (or229+`null`). Error details remain in durable SQL rows. Backups preserve optional230+`state.prRefs` rows, including `until: 0` tombstones for accepted or deleted231+events; backups made before this field was added remain readable.232+178233 ## Information document and limits179234 180235 When GRASP is on and reads are open, NIP-11 includes:181236 182237 | Field | Meaning |183238 |---|---|184-| `supported_grasps` | `GRASP-01` for this service |239+| `supported_grasps` | Lists only locally validated and enabled profiles; dependencies still apply. |185240 | `repo_acceptance_criteria` | who may announce repositories under the current write and kind rules, guest exceptions, required relay listing and storage limits |186241 | `curation` | omitted unless the owner applies curation beyond generic spam, bans or fuel rules |187242 @@ -193,8 +248,7 @@ events still follow their own rules. A blocked announcement kind preserves
193248 the owner's existing kind-rule exemption. Changing a rule changes the194249 description without granting any new permission.195250 196-NIP-11 does not list GRASP-02, GRASP-03, GRASP-05, GRASP-06 or GRASP-08. A197-relay's regular read rule still governs the Nostr side, and turning GRASP off251+NIP-11 never claims GRASP-08. A relay's regular read rule still governs the Nostr side, and turning GRASP off198252 removes its Git door and advertisement without changing the NIP-5A site199253 origins.200254 @@ -213,12 +267,12 @@ assume that a rejected receive-pack changed refs.
213267 214268 ## What this does not promise215269 216-GRASP-01 does not synchronize repositories between relays, fetch Git data217-hourly, host private repositories, accept PRs for an unannounced repository,218-or preserve an archive after ordinary retention. Those behaviors belong to219-the later GRASP specifications and need separate storage and policy work.220-The repository's Git object store is an implementation detail; clients rely on221-the NIP-34 events and the GRASP HTTP contract, not on a particular backend.270+The preview extensions do not promise complete history, uninterrupted live271+connections, unconditional hourly Git work, private repositories, or an272+upstream conformance result. Work is bounded by queued jobs, fuel, source,273+window, byte and storage limits. The repository's Git object store is an274+implementation detail; clients rely on the NIP-34 events and GRASP HTTP275+contract, not on a particular backend.222276 223277 See [Your relay on the web](05-your-relay-on-the-web.md) for the user-facing224278 site and domain doors, [Architecture](10-architecture.md) for the Worker and