Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

feat: Verified mods listing #87

Closed

Conversation

Alystrasz
Copy link
Contributor

@Alystrasz Alystrasz commented Aug 24, 2022

This adds a /client/verifiedmods resource that lists manually-validated mods. Just like the main menus promos, those mods are listed in a JSON file, that can be updated without restarting the server for it to be taken into account.

This resource will be used to automatically download mods when joining a server that requires some; manual mods validation prevents Northstar from downloading malicious mods to people' computers.

I added a very strong ratelimit on the resource (1 request per minute), the idea being that clients should only request mods list once, when game is started; checking mods can then be done client-side by checking local mods list reference.


Prerequisites for mod to be listed

  1. Mod source code is publicly available
  2. Mod is automatically updated to Thunderstore via continous deployment (Github action example)
  3. Mod follows semantic versioning

Maybe we should also enforce using a certain type of licence?


Current mods list format
{
    "Mod Settings":
    {
        "1.0.0": "example-1.0.0",
        "1.1.0": "example-1.1.0"
    },
    "Moblin.Archon":
    {
        "1.3.0": "example2-1.3.0",
        "1.3.1": "example2-1.3.1"
    }
}

TODOs
  • Validate mod entries format (regex magic?)
  • Remove duplicated entries
Questions
  • Should we commit validated mods list to Github or not?
  • Should I add a webpage describing how to get a mod validated?
  • Make server return required server mods formatted as dependency strings? Currently, we don't enforce any format while naming mods, which prevents us from checking if a mod present in a server's list is also present in verified mods list.

More about mod name formatting

Thunderstore

Once stored through Thunderstore API, mods will have a dependency string with UploadTeamName-ModName-X.Y.Z format (e.g. "EladNLG-ModSettings-1.1.2"), which enables verifying mod versions individually.

Northstar

No particular format is required for mod naming. We sometimes tell people to use Author.ModName format, but this isn't enforced at all (e.g. "name": "ModSettings"), thus loosing author name information.


Related pull requests

Launcher: R2Northstar/NorthstarLauncher#262
Modding docs: R2Northstar/ModdingDocs#74

@Alystrasz Alystrasz marked this pull request as ready for review August 25, 2022 22:36
@Alystrasz
Copy link
Contributor Author

@GeckoEidechse do you have any answer to my multiple questions? 😏

@GeckoEidechse
Copy link
Member

Should we commit validated mods list to Github or not?

Using some form of version control for validated mods (maybe together with CI to ensure valid JSON format) is probably preferred over hand-editing the file on server. Also make it easy to accept other contributions via CI and checking who verified a mod using git blame.

Thing is adding it to this repo might add too much noise to commit history. Maybe a separate repo for it?

Should I add a webpage describing how to get a mod validated?

Hmm, maybe wiki might be a better place for it? The requirements also aren't out yet but a draft wouldn't hurt :P

Make server return required server mods formatted as dependency strings? Currently, we don't enforce any format while naming mods, which prevents us from checking if a mod present in a server's list is also present in verified mods list.

Definitely yes. We need some common dependency string format that is consistent between server, client, MS, and Thunderstore. Using the Thunderstore string as the ground truth is probably the way to go ^^

@Alystrasz
Copy link
Contributor Author

Alystrasz commented Aug 26, 2022

Thing is adding it to this repo might add too much noise to commit history. Maybe a separate repo for it?

Good idea, I'll let you create the repo :)

Hmm, maybe wiki might be a better place for it?

I'll create another pull request there, then.


About mod naming, we need to have the dependency string client-side (as you said); where should we put this information?

  • mod.json: Adding a "DependencyString" would allow launcher to compare mod directly with verified mods list, but it would introduce data duplication (with "Name" and "Version" fields)
  • manifest.json: I don't think this can be accessed by launcher?

@ASpoonPlaysGames
Copy link
Contributor

  • manifest.json: I don't think this can be accessed by launcher?

Unfortunately due to how thunderstore packages are formatted, the manifest.json won't be in the mod's folder.

image

Therefore any thunderstore mod that is installed will replace that file, meaning we can't use it.

  • mod.json: Adding a "DependencyString" would allow launcher to compare mod directly with verified mods list, but it would introduce data duplication (with "Name" and "Version" fields)

Would that even be necessary? If we have the name of the mod, surely we can use that to get the dependancy string or download link just through the MS verified mods list? Worst case scenario is that the server owner renames a mod and it makes clients auto-download a (verified) mod that doesn't match with the server's? I don't think we expose any security issues because the client would still be downloading a verified mod, and the server could just run malicious code on a non-RequiredOnClient mod, spoofing a verified mod on server-side doesn't accomplish anything for the server

@Alystrasz
Copy link
Contributor Author

Alystrasz commented Aug 26, 2022

If we have the name of the mod, surely we can use that to get the dependancy string or download link just through the MS verified mods list?

We would have to do the dependency string reconstruction on the launcher; example with mod settings mod:

{
    "Name": "Mod Settings",
    "Version": "1.0.0",
    "Description": "pain",
    "LoadPriority": 2
}

We'd have to manually convert spaces to _, so we could get a substring of the dependency string (here, Mod_Settings-1.0.0).
Worst that could happen here is downloading another mod (with the same name, just from another author), so I suppose it is okay.

We would have to enforce using the same name in mod.json and manifest.json though.

As an example, Mod_Settings-1.0.0 would not be validated by launcher, because Thunderstore dependency string is "EladNLG-ModSettings-1.1.2", ModSettings being the "name" field of manifest.json, as opposed to "Name" field of mod.json.

This would also prevent uploading several mods in the same Thunderstore package.

@ASpoonPlaysGames
Copy link
Contributor

We would have to do the dependency string reconstruction on the launcher

But why though? Can we not just do this on MS?

Example:

  1. Client gets list of required mods for server
  2. Client makes a MS request, checking if the mods are verified by sending the mod names and mod versions, in a JSON object similar to this:
{
    "Mods":
    [
        {
            "Name": "Mod Settings",
            "Version": "1.0.0"
        },
        {
            "Name": "Moblin.Archon",
            "Version": "1.3.0"
        }
    ]
}
  1. MS returns the thunderstore dependency string for all of the different verified mods in the array, something like this:
{
    "Mods":
    [
        {
            "Name": "Mod Settings",
            "Version": "1.0.0",
            "DependencyString": "example-1.0.0"
        },
        {
            "Name": "Moblin.Archon",
            "Version": "1.3.0",
            "DependencyString": "example2-1.3.0"
        }
    ]
}
  1. Client uses the dependency strings to download the mods from thunderstore

And on the MS we store the name of the verified mods, along with their versions and their dependency strings, allowing us to match a name and version to a dependency string for thunderstore.

Example of JSON object for MS verified mods list:

{
    "Mod Settings":
    {
        "1.0.0": "example-1.0.0",
        "1.1.0": "example-1.1.0"
    },
    "Moblin.Archon":
    {
        "1.3.0": "example2-1.3.0",
        "1.3.1": "example2-1.3.1"
    }
}

@Alystrasz
Copy link
Contributor Author

I got your point! The "ModName to dependency" relation can be established MS-side by humans (who commit new entries to verified mods list). I might rework my PR to match this.

Is step 3 needed though? I thought of sending verified mods list only once from MS to client (at boot), not to overload MS.

@ASpoonPlaysGames
Copy link
Contributor

Is step 3 needed though? I thought of sending verified mods list only once from MS to client (at boot), not to overload MS.

Looking more into the code on MS side, nah it's not rly needed. My first impressions were that client would make a request for each mod when they need it, as opposed to being sent it all one time. But my point about making the name + version -> dependency string connection manually when verifying the mod is still relevant, even if we opt to do the parsing of that on launcher.

In theory could we skip the dependency string step entirely, and simply send the actual thunderstore download link?

Potentially (not rly going to ever happen) the verified mods list gets too large to the point where clients cannot feasibly get the entire list, but I'd say thats a non-issue, at least for now.

@Alystrasz
Copy link
Contributor Author

Alystrasz commented Aug 26, 2022

In theory could we skip the dependency string step entirely, and simply send the actual thunderstore download link?

I don't think so, we can save some space by not storing download URL on MS; besides that, download URL is static, and can easily be rebuild from dependency string (e.g. GalacticMoblin-MoblinArchon-1.3.0 => https://northstar.thunderstore.io/package/download/GalacticMoblin/MoblinArchon/1.3.0/).

I believe the format you proposed suits all our needs:

{
    "Mod Settings":
    {
        "1.0.0": "EladNLG-ModSettings-1.0.0",
        "1.1.0": "EladNLG-ModSettings-1.1.0"
    },
    "Moblin.Archon":
    {
        "1.3.0": "GalacticMoblin-MoblinArchon-1.3.0",
        "1.3.1": "GalacticMoblin-MoblinArchon-1.3.1"
    }
}

We could even optimize it a bit:

{
    "Mod Settings":
    {
        "DependencyPrefix": "EladNLG-ModSettings",
        "Versions": [ "1.0.0", "1.1.0" ]
    },
    "Moblin.Archon":
    {
        "DependencyPrefix": "GalacticMoblin-MoblinArchon",
        "Versions": [ "1.3.0", "1.3.1" ]
    }
}

A bit more work for the launcher, but less space required on MS :)

@ASpoonPlaysGames
Copy link
Contributor

ASpoonPlaysGames commented Aug 26, 2022

We could even optimize it a bit:

{
    "Mod Settings":
    {
        "DependencyPrefix": "EladNLG-ModSettings",
        "Versions": [ "1.0.0", "1.1.0" ]
    },
    "Moblin.Archon":
    {
        "DependencyPrefix": "GalacticMoblin-MoblinArchon",
        "Versions": [ "1.3.0", "1.3.1" ]
    }
}

A bit more work for the launcher, but less space required on MS :)

I think this is probably the best way to store on MS. A bit more work for launcher isn't a big deal really since its a one-time thing, right?

@Alystrasz
Copy link
Contributor Author

I agree!

The only downside I can see to this format is it prevents several authors from uploading a mod having the same name, but I don't think it's an issue, honestly...

@ASpoonPlaysGames
Copy link
Contributor

The only downside I can see to this format is it prevents several authors from uploading a mod having the same name, but I don't think it's an issue, honestly...

If you want your mod to be verified, don't have the same name as an already verified mod, simple. Tbh if a mod shares a name with another verified mod then it really should never be verified, as that would just cause confusion

@Alystrasz
Copy link
Contributor Author

If you want your mod to be verified, don't have the same name as an already verified mod, simple. Tbh if a mod shares a name with another verified mod then it really should never be verified, as that would just cause confusion

I also agree on this. I'll implement this format in this PR :)

@GeckoEidechse
Copy link
Member

Maybe we should just make DownloadLink an official key in mod.json and then propagate that to MasterServer. On the verified list we would basically just compare download link and version.

That would even allow us to stay independent from Thunderstore to some degree ^^

@Alystrasz
Copy link
Contributor Author

Maybe we should just make DownloadLink an official key in mod.json and then propagate that to MasterServer.

We can indeed enforce this, we can even make CI create the DownloadLink key during upload to Thunderstore.

But please, let's ALL agree on a verified mods list format, so I don't have to update MS and Launcher forks every 2 days 😄

@uniboi
Copy link

uniboi commented Sep 1, 2022

Maybe we should just make DownloadLink an official key in mod.json and then propagate that to MasterServer. On the verified list we would basically just compare download link and version.

That would even allow us to stay independent from Thunderstore to some degree ^^

What if I told you this already exists Northstar/NorthstarLauncher/pull/146
this does support receiving broadcasted downloadlinks from the ms which needs to be removed

DownloadLink is already used btw

@Alystrasz
Copy link
Contributor Author

DownloadLink is already used btw

How is this already used when it's not standard?

Those PRs are a bit different from yours, they intent to automatically download mods, without any action from users.

@uniboi
Copy link

uniboi commented Sep 2, 2022

DownloadLink is already used btw

How is this already used when it's not standard?

Those PRs are a bit different from yours, they intent to automatically download mods, without any action from users.

What do you mean standard? Download links from local mods are already supported by the launcher it's just that nobody uses them

@Alystrasz
Copy link
Contributor Author

What do you mean standard? Download links from local mods are already supported by the launcher it's just that nobody uses them

If you don't provide a DownloadLink in your mod, launcher will return an empty string; it's not enforced at all.

@Alystrasz
Copy link
Contributor Author

Maybe we should just make DownloadLink an official key in mod.json and then propagate that to MasterServer. On the verified list we would basically just compare download link and version.

That would even allow us to stay independent from Thunderstore to some degree ^^

@GeckoEidechse what do we do? Which mod format do we choose?

I would like this to get merged, for us to:

  • start verifying mods
  • continue working on the NorthstarLauncher mod downloading part :)

@GeckoEidechse
Copy link
Member

Maybe we should just make DownloadLink an official key in mod.json and then propagate that to MasterServer. On the verified list we would basically just compare download link and version.
That would even allow us to stay independent from Thunderstore to some degree ^^

@GeckoEidechse what do we do? Which mod format do we choose?

Uh, I would say we make DownloadLink something that's enforced for a mod to get verified. I'm not really a modder and I also have more important things on my plate rn, so I guess maybe get in contact with some bigger modders on Discord and get their opinion. We probably also draft up a spec for verified mods before start adding support to MS IMO.

@Alystrasz
Copy link
Contributor Author

Uh, I would say we make DownloadLink something that's enforced for a mod to get verified.

I can ping Emerald to automatically generate DownloadLink key while pushing mod to Thunderstore.
I pinged modders on Discord, we'll see if we have some feedback.

We probably also draft up a spec for verified mods before start adding support to MS IMO.

This is tracked there: R2Northstar/ModdingDocs#74

@EladNLG
Copy link
Member

EladNLG commented Sep 21, 2022

Hmmm.

I think it would be simpler to just limit the verified mods to thunderstore and make it an array.

Example:

[
    {
        "ModString": "EladNLG.ModSettings"
        "Versions": [ "1.1.2", "1.0.0" ]
    }
]

EDIT:

Object alternative:

{
   "EladNLG.ModSettings": {
        // Could add additional data here if needed.
        "Versions": [ "1.1.2", "1.0.0" ]
    }
}

@GeckoEidechse
Copy link
Member

"ModString": "EladNLG.ModSettings"

Would ModString be Thunderstore string or Northstar mod version. Cause if it's the latter, I could make a malicious mod with a matching Northstar mod string and it would count as "verified".

@EladNLG
Copy link
Member

EladNLG commented Sep 21, 2022

"ModString": "EladNLG.ModSettings"

Would ModString be Thunderstore string or Northstar mod version. Cause if it's the latter, I could make a malicious mod with a matching Northstar mod string and it would count as "verified".

Thunderstore string, omitting version.

@x3Karma

This comment was marked as off-topic.

@ASpoonPlaysGames
Copy link
Contributor

The download link must be stored or generated from the masterserver, the mod.json should have no say in the matter

@EladNLG
Copy link
Member

EladNLG commented Sep 21, 2022

Also, the verified mods list should be moved to a separate repo, with wider write access.

As of right now, it'll take way too long for a single mod to get verified. The verification process should not be done by a handful of people, there have to be more people able to verify mods.

@GeckoEidechse
Copy link
Member

The download link must be stored or generated from the masterserver, the mod.json should have no say in the matter

How would the masterserver generate it? There's no clear link between NS modname <-> Thunderstore modname.

Also, the verified mods list should be moved to a separate repo, with wider write access.

Separate repo has already been decided on, see #87 (comment)

Who gets write access would be decided once we reach that point.

@ASpoonPlaysGames
Copy link
Contributor

The download link must be stored or generated from the masterserver, the mod.json should have no say in the matter

How would the masterserver generate it? There's no clear link between NS modname <-> Thunderstore modname.

This sorta thing was discussed a bit in this PR's comments, a thunderstore link is fairly simple to generate, if needed

@Alystrasz
Copy link
Contributor Author

Closing this as NorthstarMasterServer is now deprecated.
I shall port this to the new Atlas backend.

@Alystrasz Alystrasz closed this Nov 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants