Skip to content

Commit 98b0fc1

Browse files
committed
Add content
1 parent afa9785 commit 98b0fc1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3292
-58
lines changed

content/explanations/community/federation-benefits.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,23 @@ title: Federation benefits
33
weight: 1
44
---
55

6-
# Federation Benefits
6+
# Open Terms Archive federation
7+
8+
Open Terms Archive is a decentralised system. It aims at enabling any entity set up their own collections and track terms on their own.
9+
10+
In order to maximise **discoverability**, **collaboration** and **political power**, public collections are federated within a single ecosystem. This makes their data mutually discoverable and enables mutualising effort.
11+
12+
## Benefits of joining the federation
13+
14+
A collection that joins the federation enjoys the following benefits:
15+
16+
1. Visibility on the Open Terms Archive website lists of collections and datasets.
17+
2. Access to the Open Terms Archive GitHub organisation, administered by the Open Terms Archive core team.
18+
3. Collection logo provided by the Open Terms Archive core team.
19+
4. Referencing in the official [collections list](https://opentermsarchive.org/collections.json), enabling off-the-shelf discovery in the [Federation API]({{< relref "/api/node" >}}).
20+
5. Referencing in the official [datasets list](https://opentermsarchive.org/datasets), providing visibility to analysts.
21+
6. Dedicated channel on the Open Terms Archive instant messaging system.
22+
7. API uptime tracking.
23+
8. Public announcement through all Open Terms Archive communication channels upon joining.
24+
25+
By joining the Open Terms Archive federation, your collection becomes part of a **dynamic network** that leverages **shared resources** and **collective visibility** to drive **greater impact**.
Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,57 @@
11
---
2-
title: Design principles
2+
title: "Design principles"
33
weight: 2
4+
aliases: /design-principles/
45
---
56

67
# Design principles
8+
9+
These overarching principles guide technical and governance decisions. They are fundamental and can only be changed through community consensus, based on a thorough impact assessment.
10+
11+
Each principle has a name, a rationale, and potential implementation examples or guidelines.
12+
13+
## 1. Never trust the services
14+
15+
A major goal of Open Terms Archive is to enable assessing the loyalty of services towards their end users. Since loyalty is not assumed, trust can not be warranted.
16+
17+
### Cases
18+
19+
Several services have been observed:
20+
21+
- blocking an IP or a user agent randomly;
22+
- pretending to encounter technical errors (`500`, `502`…) instead of being explicit about their intention (`robots.txt`, `403`…);
23+
- to not reflect actual updates in the “last update” date of their contractual documents;
24+
- changing the content of the same page based on user agent properties or source IP geolocation. When one accesses a supposedly already regionalized policy according to the URL, but gets a different content based on geolocation without any information nor ability to access other regional policies, we [consider](https://github.com/OpenTermsArchive/docs/pull/43#discussion_r1252232131) it misleading and disloyal.
25+
26+
### Examples of consequential choices
27+
28+
- Do not use “last update” date in documents or headers for metadata.
29+
30+
## 2. Do not require trust in maintainers
31+
32+
Open Terms Archive maintainers should not need to be trusted by users more than the services it enables assessing.
33+
34+
### Cases
35+
36+
- Collections can be unmaintained.
37+
- Maintainers can filter out content that could be relevant from the perspective of other maintainers.
38+
- A server can encounter technical problems and miss updates.
39+
40+
### Examples of consequential choices
41+
42+
- Always keep an untouched snapshot of the source documents.
43+
- Use cryptographic signatures to ensure the database can be authenticated.
44+
- Enable terms collection to be replicated by anyone.
45+
- Support duplication across collections as this increases the resilience of the network. It will be up to reusers to decide which source they prefer in case of divergence.
46+
47+
## 3. Obtain documents like a user would
48+
49+
In order to guarantee legal relevance, source documents should only be ones that end users of the service are themselves receiving. Following principle 1, technical workarounds to obtain some version of the source documents that are more easily handled by machines cannot be trusted to have the same content as the ones intended for end users.
50+
51+
### Cases
52+
53+
- Accessing the same URL from a differently geolocated IP address will change the contents in some services.
54+
55+
### Examples of consequential choices
56+
57+
- Scrape HTML even if one could obtain the contractual content from an API.

content/explanations/main-concepts.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,80 @@ title: Main concepts
33
weight: 1
44
---
55

6-
# Main concepts
6+
## Main concepts
7+
8+
Words in bold are [business domain names](https://en.wikipedia.org/wiki/Domain-driven_design).
9+
10+
**Services** have **terms** written in **documents**, contractual (Terms of Services, Privacy Policy…) or not (Community Guidelines, Deceased User Policy…), that can change over time. Open Terms Archive enables users rights advocates, regulatory bodies and interested citizens to follow the **changes** to these **terms**, to be notified whenever a new **version** is published, to explore their entire **history** and to collaborate in analysing them. This free and open-source engine is developed to support these goals.
11+
12+
### Collection
13+
14+
Open Terms Archive is a decentralised system. It aims at enabling any entity to **track** **terms** on its own. To that end, the Open Terms Archive **engine** can be run on any server, thus making it a dedicated **instance**. An **instance** **tracks** **terms** within a single **collection**.
15+
16+
A **collection** is characterised by a **scope** across **dimensions** that describe the **terms** it **tracks**, such as **language**, **jurisdiction** and **industry**.
17+
18+
#### Example scope
19+
20+
> The terms tracked in this collection are:
21+
22+
> - Of dating services used in Europe.
23+
> - In the European Union and Switzerland jurisdictions.
24+
> - In English, unless no English version exists, in which case the primary official language of the jurisdiction of incorporation of the service operator will be used.
25+
26+
### Federation
27+
28+
In order to maximise discoverability, collaboration and political power, public **collections** are **federated** within a single ecosystem. This makes their data mutually discoverable and enables mutualising effort.
29+
30+
### Terms types
31+
32+
To distinguish between the different **terms** of a **service**, each has a **type**, such as “Terms of Service”, “Privacy Policy”, “Developer Agreement”…
33+
34+
This **type** matches the topic, but not necessarily the title the **service** gives to it. Unifying the **types** enables comparing **terms** across **services**.
35+
36+
> More information on terms types can be found in the [dedicated repository](https://github.com/OpenTermsArchive/terms-types). They are published on NPM under [`@opentermsarchive/terms-types`](https://www.npmjs.com/package/@opentermsarchive/terms-types), enabling standardisation and interoperability beyond the Open Terms Archive engine.
37+
38+
### Declarations
39+
40+
The **terms** that constitute a **collection** are defined in simple JSON files called **declarations**.
41+
42+
A **declaration** also contains some metadata on the **service** on which the **terms** apply.
43+
44+
> Here is an example declaration tracking the Privacy Policy of Open Terms Archive:
45+
>
46+
> ```json
47+
> {
48+
> "name": "Open Terms Archive",
49+
> "terms": {
50+
> "Privacy Policy": {
51+
> "fetch": "https://opentermsarchive.org/en/privacy-policy",
52+
> "select": ".textcontent"
53+
> }
54+
> }
55+
> }
56+
> ```
57+
58+
- - -
59+
60+
## Add terms to a collection
61+
62+
Open Terms Archive **acquires** **terms** to deliver an explorable **history** of **changes**. This can be done in two ways:
63+
64+
1. For the present and future, by **tracking**.
65+
2. For the past, by **importing** from an existing **fonds** such as [ToSBack](https://tosback.org), the [Internet Archive](https://web.archive.org/), [Common Crawl](https://commoncrawl.org) or any other in-house format.
66+
67+
### Tracking terms
68+
69+
In order to **track** the **changes** of **terms**, the **engine** **records** a **snapshot** of **documents** that contain them by **fetching** their web **location** several times a day. The **engine** then **extracts** a **version** from this **snapshot** by:
70+
71+
1. **Selecting** the subset of the **document** (or **documents**) that contains the **terms** (instead of, e.g., navigation menus, footers, cookies banners…).
72+
2. **Removing insignificant content**, that is residual content in this subset that is not part of the **terms** (e.g. ads, illustrative pictures, internal navigation links…).
73+
3. **Filtering noise** that can emerge in the **terms** by preventing parts that change frequently from triggering false positives for **changes** (e.g. tracker identifiers in links, relative dates…). The **engine** can execute custom **filters** written in JavaScript to that end.
74+
75+
After these steps, if **changes** are spotted in the resulting **terms**, a new **version** is **recorded**.
76+
77+
Preserving **snapshots** enables recovering after the fact information potentially lost in the **extraction** step: if **declarations** were wrong, they can be **maintained** and corrected **versions** can be **extracted** from the original **snapshots**.
78+
79+
### Importing terms
80+
81+
Existing **fonds** can be prepared for easier analysis by unifying their format to the **Open Terms Archive dataset format**. This unique format enables building interoperable tools, fostering collaboration across reusers.
82+
Such a dataset can be generated from **versions** alone. If **snapshots** and **declarations** can be retrieved from the **fonds** too, then a full-fledged **collection** can be created.

content/explanations/terms-tracking/declarations-maintenance.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,87 @@ weight: 1
44
---
55

66
# Declarations maintenance
7+
8+
All parts of a **terms** **declaration** (web location, selection, noise removal, distribution across multiple documents…) can change over time. The process of updating these elements to enable continued **tracking** is called **maintenance**. Without it, **terms** can become:
9+
10+
- **unreachable**: no **snapshot** can be **recorded** at all, because the **location** changed or the **service** denies access;
11+
- **unextractable**: no **version** can be **extracted** from the **snapshot**, because the selection of content or some **filter** fails;
12+
- **noisy**: both **snapshots** and **versions** are **recorded** but the **changes** contain **noise** that should have been **filtered out**.
13+
14+
Open Terms Archive needs to keep track of this changes in order to regenerate versions history from snapshots history.
15+
16+
## Service history reference
17+
18+
To keep track of services declarations and filters changes, Open Terms Archive offers a versioning system. It is optional and should be added only when needed. It works by creating history files for terms declarations and filters, where each entry should be a previous valid declaration or filter function and should have an expiry date.
19+
20+
Both for terms and filters history, the expiration date is declared in a property `validUntil`. It should be the authored date and time of the last snapshot commit for which the declaration is still valid.
21+
22+
Terms declarations history files and filters history files can both evolve on their own. Having one does not imply to create the other.
23+
24+
The current (latest) valid declaration has no date and should not appear in the history object: it stays in its own file, just like if there was no history at all.
25+
26+
### Terms declaration history
27+
28+
Declarations history are stored in a history JSON file with the following name `declarations/$service_id.history.json`.
29+
30+
The terms history contains an object with terms types as properties. Each terms type property is an array of history entries. Each entry has the same format as a normal terms declaration, except there is the **mandatory** extra property `validUntil`.
31+
32+
```json
33+
{
34+
35+
"<terms type>": [
36+
{
37+
"fetch": "The URL where the document can be found",
38+
"executeClientScripts": "A boolean to execute client-side JavaScript loaded by the document before accessing the content, in case the DOM modifications are needed to access the content; defaults to false (fetch HTML only)",
39+
"filter": "An array of service specific filter function names",
40+
"remove": "A CSS selector, a range selector or an array of selectors that target the insignificant parts of the document that has to be removed. Useful to remove parts that are inside the selected parts",
41+
"select": "A CSS selector, a range selector or an array of selectors that target the meaningful parts of the document, excluding elements such as headers, footers and navigation",
42+
"validUntil": "The inclusive expiration date in ISO format"
43+
}
44+
]
45+
46+
}
47+
```
48+
49+
For example, to add a history entry for the `Terms of Service` of the service `ASKfm`, create the file `declarations/ASKfm.history.json` with the following contents:
50+
51+
```json
52+
{
53+
"Terms of Service": [
54+
{
55+
"fetch": "https://ask.fm/docs/terms_of_use/?lang=en",
56+
"select": "body",
57+
"filter": ["add"],
58+
"validUntil": "2020-10-29T21:30:00.000Z"
59+
}
60+
]
61+
}
62+
```
63+
64+
### Filters history
65+
66+
Filters history is declared in a filters history declaration JavaScript file with the following name: `declarations/$service_id.filters.history.js`.
67+
68+
For each filter, a variable named like the filter must be exported. This variable should contain an array of filter history entries. Each entry is an object with the expiration date, as `validUntil` property, and the valid function for this date, under the `filter` property. Both properties are **mandatory**.
69+
70+
```js
71+
export const <filterName> = [
72+
{
73+
validUntil: "The inclusive expiration date in ISO format",
74+
filter: function() { /* body valid until the expiration of the `validUntil` date */ }
75+
}
76+
];
77+
```
78+
79+
For example, to add a history entry for the `removeSharesButton` filter of the service `ASKfm`, create the file `declarations/ASKfm.filters.history.js` with the following content:
80+
81+
```js
82+
export const removeSharesButton = [
83+
{
84+
validUntil: '2020-08-22T11:30:21.000Z',
85+
filter: async (document) => {
86+
document.querySelectorAll('.shares').forEach((element) => element.remove());
87+
},
88+
},
89+
];
90+
```

content/explanations/terms-tracking/range-selectors.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,65 @@ title: Range selectors
33
weight: 2
44
---
55

6-
# Range selectors
6+
## Range selectors
7+
8+
When no unique wrapper element exists for the whole terms content, there is no easy way to select the content with only CSS selectors. Content between two elements in a document can be selected using a range selector, regardless of their DOM position. The concept is inspired by the DOM [Range API](https://developer.mozilla.org/en-US/docs/Web/API/Range), where content is defined by start and end points that may be included or excluded. The format is defined as a JSON object:
9+
10+
```json
11+
{
12+
"start[Before|After]": "CSS selector that marks where to begin capturing content",
13+
"end[Before|After]": "CSS selector that marks where to stop capturing content"
14+
}
15+
```
16+
17+
### Example
18+
19+
Let's take an example to see when range selectors can be useful. Given the following HTML:
20+
21+
```html
22+
<html>
23+
24+
<body>
25+
<main>
26+
<!-- Breadcrumb Navigation -->
27+
<ul>
28+
<li><a href="/">Home</a></li>
29+
<li>Terms and Conditions</li>
30+
</ul>
31+
32+
<!-- Main Content -->
33+
<h1 id="terms-title">Example Terms</h1>
34+
<p>Effective as of: January 1, 2024</p>
35+
36+
<h2>Authorized uses</h2>
37+
<p>You can use this service in the following cases:</p>
38+
39+
<ul>
40+
<li>At home</li>
41+
<li>In your office</li>
42+
<li>In a coffee shop</li>
43+
</ul>
44+
</main>
45+
<div>
46+
<ul id="footer-menu">
47+
<li><a href="/about">About</a></li>
48+
<li><a href="/contact">Contact</a></li>
49+
</ul>
50+
</div>
51+
</body>
52+
53+
</html>
54+
```
55+
56+
In this case, there is no unique wrapper element for the terms content which is represented by all elements after the main title in the `main` element. Here selecting the whole `main` would result in selecting elements that are not part of the terms content, like the breadcrumb and sub navigation. The range selector can be used to select the terms content by specifying the main title `#terms-title` as the start point and the footer `#footer-menu` as the end point. The selection starts *before* the main title, so it includes it, and ends *before* the footer, so it excludes it.
57+
58+
So the resulting range selector is:
59+
60+
```json
61+
{
62+
"startBefore": "#terms-title",
63+
"endBefore": "#footer-menu"
64+
}
65+
```
66+
67+
This range selector will select the terms content between the main title and the footer element.

content/explanations/terms-tracking/service-name-noise copy.md

Lines changed: 0 additions & 6 deletions
This file was deleted.

content/explanations/terms-tracking/service-name-noise.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,38 @@ title: Service naming
33
weight: 5
44
---
55

6-
# Service name usual noise
6+
## Service name
7+
8+
### Casing
9+
10+
- In order to find the service name casing, rely first on the page title (easily found in search results). Do not rely on the logo as it can be stylized differently. Example with Facebook:
11+
![facebook search](https://user-images.githubusercontent.com/222463/91416484-baaa3a00-e84f-11ea-94cf-8805d17aa711.png)
12+
- If it is still ambiguous, rely on Wikipedia as a source. However, make sure to differentiate the _service_ from the _provider_ company's name. Example with “DeviantArt”, a service (which used to be stylized deviantArt until 2014) by the limited liability company “deviantArt”:
13+
![deviantArt search](https://user-images.githubusercontent.com/222463/91416936-5b98f500-e850-11ea-80fe-a50be27356e3.png)
14+
15+
### Terms used by several services
16+
17+
- If you want to add terms which happen to be shared with another service from the same parent company, be specific in naming the exact service you want to track. For instance, you may find that a company like Github uses the same terms for its code hosting and its AI assistant. While this does not mean that the terms for GitHub (code hosting) are the only terms of GitHub Copilot (assistant), it does mean that these two services have terms that are represented in the same document. In tracking terms for one of these services, say Github Copilot, be specific in naming it as the service you want to track. This way, if GitHub was to introduce dedicated terms for each of these services in the future, their locations can be updated without having to create new terms since the service already existed before.
18+
19+
- - -
20+
21+
## Service ID
22+
23+
### Normalisation
24+
25+
1. For non-roman alphabets (Cyrillic, ideograms…), use the service-provided transliteration.
26+
2. For diacritics: normalise the string to its `NFD` normal UTF form, then remove the entire combining character class. [Details](https://stackoverflow.com/a/37511463/594053).
27+
3. As a last resort, use the domain name.
28+
29+
### Provider prefixing
30+
31+
- If you encounter terms you want to add to a service, yet find that it would override already-declared terms for this service such as Terms of Service or Privacy Policy, and that the only solution you see would be to create a new terms type that would contain the name of the feature, then it is likely you should declare a new service, potentially duplicating existing terms.
32+
33+
> Example: the Facebook Community Payments terms are Terms of Service. The only way to declare them in the Facebook service would be to add a “Community Payments Terms” terms type as they would otherwise conflict with Facebook's Terms of Service. It is better to declare a new service called “Facebook Payments” with its own Terms of Service. It turns out that this service also has a developer agreement, independent from the main Facebook service.
34+
35+
![Facebook Community Payments](https://user-images.githubusercontent.com/222463/91419033-3a85d380-e853-11ea-8468-42a536b7e87b.png)
36+
37+
- As a last resort, rely on the trademark.
38+
39+
Example: Apple's App Store uses only generic terms (“app” and “store”). However, it is of common use to mention “the App Store” as Apple's. To help us decide whether it should be prefixed or not, we can check that [Apple has trademarked “App Store”](https://www.apple.com/legal/intellectual-property/trademark/appletmlist.html). The service can thus be named “App Store”, without prefixing.
40+

0 commit comments

Comments
 (0)