modrinth / code

The Modrinth monorepo containing all code which powers Modrinth!
https://modrinth.com
Other
904 stars 167 forks source link

Implement geographic restrictions #2507

Open brawaru opened 2 days ago

brawaru commented 2 days ago

Please confirm the following.

What parts of Modrinth is your feature request related too?

API, Website, App

Is your suggested feature related to a problem? Please describe.

We're living in a difficult world where governments consider calls for basic human rights extremist movements. For example, just about a month ago Georgia has adopted an anti-LGBTQ+ law against “LGBTQ+ propaganda”, just a few days ago Discord has been banned in Russia and Türkiye for hosting “illegal content”. And just a day ago 7TV has been banned in Russia for “gay propaganda” after hosting an emote of two kissing men.

In this reality Modrinth is faced with a tough choice. Because it hosts a lot of LGBTQ+ related content, and creators on the platform are free to put political messages in their project descriptions, it is only a question of time until authorities of a country with such laws reach out to Modrinth to take down illegal content.

We can stay to our principles and do not comply with such requests, getting our platform blocked in those countries, but by doing so we make it inaccessible to many users. One can argue that users from these countries can use censorship circumvention measures, such as VPNs, but it has been proven countless times that a hindrance like this will cause a major downfall of traffic. Not every user is equipped with knowledge to install a simple VPN, let alone set up VPNs or proxies with circumvention measures.

Describe the solution you'd like

I believe by staying our ground we will be doing a disservice to our users from the affected regions. Therefore, I think it would be in best interest for Modrinth to prioritise accessibility of the service, and to implement geographic restrictions functionality, where certain projects can be made inaccessible for specific region upon receiving a request from authorities or manually.

If such functionality is to be implemented, it should be as transparent as possible. This means communicating to the creator why their project has been made inaccessible in a region, and to user why the project cannot be accessed. We may also give creators ability to create geographic restrictions on their own. For example, creators of AI projects from US or relying on US technologies (OpenAI, etc) may use geographic restrictions to comply with sanctions.

Since the same functionality can be used to provide age checks for projects that feature content that should not be shown to minors in certain regions (e.g., smoking or alcohol), creators and moderators should be able to create ‘gate’ restrictions. The gate name comes from requiring an action to see the project. This means that upon accessing the project the user will be presented with a warning, or be required to provide their birth date (to calculate their age) for age gates.

Determining user location

Because Modrinth uses Cloudflare, we can use IP Geolocation or Managed Transforms to add visitor location headers. Alternatively, Geolite2 database can be utilised to determine the location using IP address.

User location from the IP address can be stored in user profiles and session cookies for performance, especially for database lookups.

Data changes

Geographical restrictions for projects will be stored in database, each restriction entry containing:

Considerations: affected version for restrictions that apply to specific versions (unlikely needed and way too precise for implementing).

API changes

Search endpoint

The /search endpoint will automatically remove all geographically blocked hits by default. For developers a new parameter will be introduced called geo_hiding that can be set to all to hide all hits restricted in any way (default), unavailable to hide all non-gated hits, none to show all hits. The none option is authorized (see below).

All hits will include information about restrictions applying to requester's location to allow for hiding or redacting of project information (e.g., hiding mature-only projects for underage users, or blurring project icon for gated content).

Project endpoint

The /project/{id|slug} endpoint will return 451 Unavailable For Legal Reasons for blocked content, except if requested project is managed by the current user or restriction bypassing is authorized. Otherwise, the returned project information will include all restrictions applying to requester's location (likely gates).

New project geographical restrictions endpoints

The /project/{id|slug}/geo will return restrictions that apply to the project for the requester's location. region and type parameters can be used to filter the results. region can be set to XX to request restrictions in all locations. type can be set to all (default), gate, block.

PUT request to /project/{id|slug}/geo allows for creation of new restrictions. The restriction data is returned back together with its ID.

GET request to /project/{id|slug}/geo/{restriction_id} returns the restriction data.

PATCH request to /project/{id|slug}/geo/{restriction_id} allows to modify the restriction.

DELETE request to /project/{id|slug}/geo/{restriction_id} deletes the restriction.

Project-associated endpoints

The following endpoints will return 451 Unavailable For Legal Reasons for blocked content unless the associated project is managed by the current user or bypassing is authorized.

Considerations: include restrictions that apply to requester's location to avoid needing additional request to /project/{id|slug}/geo endpoint.

The following endpoints will hide results for blocked and gated content. geo_hiding parameter can be provided accepting the same values as /search endpoint (requiring bypass authorization for none).

451 Unavailable For Legal Reasons response

When an endpoint cannot return a response due to geographical restrictions, 451 HTTP error is returned. The data will contain the ID, display message key, restriction data, and current region. E.g.

{
  "id": "dEaDB3Ef",
  "message": "illegal",
  "region": "RU"
}

Geographical restrictions bypassing

Geographical restrictions can be bypassed, but this would require Modrinth-Geo-Bypass header to be supplied containing a special token issued by Modrinth. The token is only issued for authorized use, e.g. public data analytics. Failure to authorize will result in a 403 Forbidden error response.

User location override

When making requests to API, the location can be overridden with Modrinth-Geo-Override header containing an override looking like {REGION};token={TOKEN}, where {REGION} is a region for which the request is made and {TOKEN} is a token only issued for internal use. E.g., FR;token=JNNxsDdZ1m8RMhZL2iMGZrwj0kWD-SPZ8C7UDi8JziU.

Considerations: can we technically merge bypassing into override, e.g. by allowing overriding region to XX?

Frontend changes

Requests to API

Frontend will determine user location on the server side either through Cloudflare or by querying internal API. On the server all API requests will use user location override. On client no override is used and location is determined from requests to API. If the same method is used, it is unlikely this will result in a mismatch.

451 status code is handled to display proper error messages about project not being available to the end user.

Because frontend will support all of the gates, requests that support geo_hiding parameter will be made with it set to unavailable. Resulting age from age gates will be stored in cookies, this way server can properly generate responses—the cookie won't be used any other way. Gated projects will have their icon blurred in search.

Project settings

A new section introduced in settings called geo-restrictions. There users can view all the geographical restrictions that were set for their project by moderators and why they were set, as well as create a custom restriction.

Describe alternatives you've considered

No response

Additional context

This is a draft proposal and may be revised later with additions, changes and corrections, but you are already welcome to share your thoughts on it.

Felix14-v2 commented 4 hours ago

Despite I really dislike this suggestion, I understand that (as you said) this was just a matter of time. Modrinth is growing, and sooner or later, we will have to implement geographical restrictions to avoid issues with censorship systems.

We need to choose the lesser of two evils.