From 56ef27ebbdf162b0ee2f0c94bc988f72c0dcd98d Mon Sep 17 00:00:00 2001 From: Ludovic Marie <136255825+ludovic111@users.noreply.github.com> Date: Wed, 28 Oct 2026 00:50:51 +0100 Subject: [PATCH] Mod policy page, who made each project, and the registry and Kira in the privacy page - /mods/policy shows the registry's MOD-POLICY.md, with the takedown form and the private contact; - every project page says who made it: Horizon for official projects (author Horizon, source in horizon-rust), otherwise its authors, who own it and answer for it, not made or endorsed by the Horizon project; - the list page says a listing is not an endorsement; the submit form's required box accepts the policy; - privacy: the registry's sign-in cookie, and what Kira keeps on Discord (and that questions to her go to the Claude API). Co-Authored-By: Claude Opus 5.5 --- build.mjs | 21 +++++++++++++++++++-- src/mods.js | 13 ++++++++++++- src/mods.test.mjs | 13 +++++++++++++ src/privacy.html | 6 +++++- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/build.mjs b/build.mjs index 170f54e..543c32b 100644 --- a/build.mjs +++ b/build.mjs @@ -78,6 +78,17 @@ try { console.warn(`mod index: ${e.message}; the pages will load it themselves`); } +// The mod policy (who owns and answers for a listed project, takedowns): the registry's MOD-POLICY.md, shown at +// /mods/policy. Without it the page links to the file on GitHub. +let modPolicy = null; +try { + const res = await fetch("https://raw.githubusercontent.com/horizon-rust/horizon-mods/main/MOD-POLICY.md", { signal: AbortSignal.timeout(15000) }); + if (!res.ok) throw new Error(`${res.status}`); + modPolicy = await res.text(); +} catch (e) { + console.warn(`MOD-POLICY.md: ${e.message}; /mods/policy links to it on GitHub`); +} + // An optional token (a Railway variable, or `gh auth token` locally) lifts the rate limit. const githubHeaders = { Accept: "application/vnd.github+json", ...(process.env.GITHUB_TOKEN ? { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } : {}) }; // Every release (the Releases page lists them all), a page of 100 at a time. @@ -518,11 +529,17 @@ ${KINDS.map(([k, label]) => `

`; diff --git a/src/mods.test.mjs b/src/mods.test.mjs index c546ce3..e1f4f2a 100644 --- a/src/mods.test.mjs +++ b/src/mods.test.mjs @@ -108,3 +108,16 @@ test("rating: a sign-in link signed out, stars signed in, none for the project's assert.ok(mine.includes('data-stars="3" aria-pressed="true"')); assert.ok(rateHtml(p, { login: "bob" }, null).includes("Rate it")); }); + +test("a project's page says who made it: Horizon, or its authors with the policy's disclaimer", async () => { + const { ownerNote, isOfficial } = await import("./mods.js"); + const official = { authors: ["Horizon"], source: "https://github.com/horizon-rust/horizon-mod-zoom" }; + const theirs = { authors: ["levzzz5154"], source: "https://github.com/levzzz5154/horizon-veinminer" }; + assert.equal(isOfficial(official), true); + assert.equal(isOfficial(theirs), false); + assert.equal(isOfficial({ authors: ["Horizon"], source: "https://github.com/someone/horizon-thing" }), false, "the name alone is not enough"); + assert.match(ownerNote(official), /Made by Horizon\./); + assert.match(ownerNote(theirs), /Made by levzzz5154\. Its authors own it and answer for it\. Not made or endorsed by the Horizon project\./); + assert.match(ownerNote(theirs), /href="\/mods\/policy"/); + assert.match(ownerNote({ authors: ["x"], source: "" }), /<b>x<\/b>/); +}); diff --git a/src/privacy.html b/src/privacy.html index 57feee7..8ec1258 100644 --- a/src/privacy.html +++ b/src/privacy.html @@ -59,9 +59,13 @@

Deleting your data

Settings → Data collection → Delete my data, or horizon-launcher data delete. The server deletes everything sent under your install ID, your share of the totals is recomputed, anything waiting on your computer is removed, and you get a new install ID. You can also turn everything off, or delete the telemetry/ folder.

+

The mod registry

+

To submit a project you sign in with GitHub. The submission service at playhorizon.dev/api/mods keeps a signed session cookie (hm_session, only for that address, 12 hours or until you sign out) and keeps no other data. What you submit becomes a public pull request on horizon-rust/horizon-mods, under your GitHub name, and stays in its history.

+

Discord and Kira

+

On Horizon's Discord server, the Kira bot keeps what it needs to run the server, linked to your Discord ID: your XP and level, warnings and timeouts, the GitHub name you link with /link-github, your bug reports, claims and agent tokens. For moderation, the mods' private log keeps joins (with the invite used), leaves, and the text of deleted and edited messages; a DM to Kira is shown to the mods as a thread. A bug report you post becomes a public GitHub issue on Horizon's repository. When you ask Kira a question, the question and up to four messages it replies to are sent to Anthropic's Claude API to write the answer. Discord's own privacy policy covers everything else on Discord.

Your rights and contact

Horizon is made by Ludovic Marie, who is responsible for this data. To ask for a copy of what was sent under your install ID, have it corrected or deleted, or ask anything about it, write through lu4ovic.com (give your install ID, shown in Settings → Data collection). You can also complain to the data protection authority where you live.

-

This website itself sets no cookies and has no analytics; its footer says what it loads from GitHub.

+

Apart from the registry's sign-in cookie, this website sets no cookies and has no analytics; its footer says what it loads from GitHub.

Back to Horizon

Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.