clone

nostr relays on demand at <name>.bind.ws: claim one with your key, pay in zaps past the free allowance

nip11: Git acceptance describes eligible authors and guest exceptions so clients can classify hosting

Dami committed edb792b
commit
edb792b450c28a2c30c022aaf9066f0d9f8739bd
parent
dbf2b597c6a3ecc6e160509932593630b3e3ab85
author
Dami <dami.etoile@gmail.com>
3 files changed, +57 -2
Mdocs/22-grasp-01-git-hosting.md10++++++++-
Msrc/nip11.ts15++++++++++++-
Mtest/object/nip11.test.ts34++++++++++++++++++++++++++++++
M docs/22-grasp-01-git-hosting.md +9 -1
M src/nip11.ts +14 -1
@@ -6,6 +6,7 @@ import type { Relay } from "./relay.ts";
66 import { now } from "./event.ts";77 import { SUCCESSION_WARN_DAYS, featureOn, FEATURE_NAMES, type Feature } from "./settings.ts";88 import { SITE_KINDS } from "./sites.ts";9+import { KIND_REPO } from "./kinds.ts";910 import { nip11Views } from "./views.ts";1011 1112 // The less obvious numbers: 43 is added once the relay has an identity; 62
@@ -68,7 +69,19 @@ export function nip11(relay: Relay, host: string) {
6869 if (relay.settings.isLeased() && p.lease) doc.lease = { expires_at: p.lease.until, holder: p.lease.holder || undefined, claim_url: host ? "https://" + host + "/" : undefined };6970 if (featureOn(p, "grasp") && p.reads === "open") {7071 doc.supported_grasps = ["GRASP-01"];71- doc.repo_acceptance_criteria = "Repository announcements name this service in clone and relays; the relay write rule, bans, proof of work and fuel apply. At most 16 repositories, 4 MiB per pack, 16 MiB packed history and 128 Git transactions per unmigrated format-1 repository. Explicitly migrated format-2 repositories retain at most 128 unique packs.";72+ const access = {73+ open: "Anyone may announce a repository.",74+ allowlist: "Allowlist hosting: only the relay owner and members may announce repositories.",75+ owner: "Curated hosting: only the relay owner may announce repositories.",76+ wot: "Curated hosting: the relay owner, members and people they follow may announce repositories.",77+ };78+ const eligibility = relay.settings.isUnclaimed() ? "Repository hosting is unavailable until this relay is claimed."79+ : relay.settings.leaseExpired(now()) ? "Repository hosting is unavailable because this relay's lease has expired."80+ : !relay.settings.kindAllowed(KIND_REPO) ? "Curated hosting: kind 30617 is restricted; only the relay owner's repository announcements pass the kind rule."81+ : p.writes !== "open" && p.openKinds.includes(KIND_REPO) ? "Anyone may announce a repository through the guest exception for kind 30617."82+ : access[p.writes];83+ const guests = p.writes !== "open" && p.openKinds.length ? ` Guest write exceptions apply to kinds ${p.openKinds.join(", ")}.` : "";84+ doc.repo_acceptance_criteria = `${eligibility} Repository announcements name this service in clone and relays. State and collaboration events follow the relay write rule (${p.writes}) and kind rules; bans, proof of work and fuel apply.${guests} At most 16 repositories, 4 MiB per pack, 16 MiB packed history and 128 Git transactions per unmigrated format-1 repository. Explicitly migrated format-2 repositories retain at most 128 unique packs.`;7285 if (p.writes !== "open" || p.blockedWords.length) doc.curation = "The relay's configured write rule and blocked topics apply to Nostr repository and collaboration events.";7386 }7487 if (featureOn(p, "sites")) doc.nsites = {
M test/object/nip11.test.ts +34 -0
@@ -6,6 +6,40 @@ import { generateSecretKey } from "nostr-tools/pure";
66 import { rpc, info } from "../helpers/relay.ts";77 88 describe("NIP-11 extras", () => {9+ it("describes Git admission from current write rules without hiding guest or kind restrictions", async () => {10+ const host = "git-policy-info.bind.ws";11+ const owner = generateSecretKey();12+ await rpc(host, owner, "claim");13+ for (const [writes, eligibility] of [14+ ["open", "Anyone may announce a repository."],15+ ["allowlist", "Allowlist hosting: only the relay owner and members may announce repositories."],16+ ["owner", "Curated hosting: only the relay owner may announce repositories."],17+ ["wot", "Curated hosting: the relay owner, members and people they follow may announce repositories."],18+ ]) {19+ expect((await rpc(host, owner, "setpolicy", { features: { grasp: true }, writes })).status).toBe(200);20+ const doc = await info(host);21+ expect(doc.repo_acceptance_criteria.startsWith(eligibility)).toBe(true);22+ expect(doc.repo_acceptance_criteria).toContain(`write rule (${writes}) and kind rules`);23+ expect(doc.supported_grasps).toEqual(["GRASP-01"]);24+ }25+ await rpc(host, owner, "setpolicy", { writes: "allowlist", openKinds: [30617] });26+ let doc = await info(host);27+ expect(doc.repo_acceptance_criteria).toContain("Anyone may announce a repository through the guest exception for kind 30617.");28+ expect(doc.repo_acceptance_criteria).toContain("Guest write exceptions apply to kinds 30617.");29+ expect(doc.repo_acceptance_criteria).toContain("write rule (allowlist)");30+ await rpc(host, owner, "disallowkind", 30617);31+ doc = await info(host);32+ expect(doc.repo_acceptance_criteria).toContain("only the relay owner's repository announcements pass the kind rule");33+ expect(doc.repo_acceptance_criteria).not.toContain("Anyone");34+ await rpc(host, owner, "unrulekind", 30617);35+ await rpc(host, owner, "setpolicy", { writes: "open", openKinds: [] });36+ expect((await info(host)).repo_acceptance_criteria).toMatch(/^Anyone may announce/);37+ await rpc(host, owner, "setpolicy", { reads: "members" });38+ expect((await info(host)).repo_acceptance_criteria).toBeUndefined();39+ await rpc(host, owner, "setpolicy", { reads: "open", features: { grasp: false } });40+ expect((await info(host)).repo_acceptance_criteria).toBeUndefined();41+ });42+943 it("publishes the policy links and lists once set, validated", async () => {1044 const host = "eleven.bind.ws";1145 const owner = generateSecretKey();