Proposal for an open, decentralized social credit system for publishing and consuming reputation, boycott, and recommendation data about organizations, political groups, companies, and products.

Anyone can publish a static reputation file; anyone can build a client.

Users choose which sources they trust, with no central server, no mandatory account, and no enforced ideology.


There is already boycott apps and voting recommendation website, in addition to even more centralised or state wide concept of a 'social credit system' but they are often closed source and are fixed to a specific ideology.

Unlike these previous approach, this proposed system has:

  • no central authority
  • no mandatory participation
  • no unified score
  • no enforcement mechanism

What we should create is a standard for interchange of reputation, so that apps or web browser extension for voting recommendations and boycotting can be done as part of a federated social credit ecosystem.

If possible I would like to see an open standard defined for publishing boycott and reputation data as simple static files, and an open-source Android app or web browser extension that reads them. NGOs, researchers, unions, or individuals can host their own lists. Users choose who to trust and compare sources side-by-side.

Data format for interchange

So for this feed if I'm making a first stab, I'll like to see:

  • Feed metadata (id, name, license, maintainer)
  • Entities:
    • Products (identified by barcode)
    • Companies (identified by name and optional IDs)
  • Reputation assertions:
    • Scope (product or company)
    • Status or score
    • Optional tags, reasons, and source links

Where in json it might look like:

{
  "feed": {
    "id": "example.mixed.feed",
    "name": "Example Mixed Reputation Feed",
    "license": "CC-BY-4.0",
    "updated_at": "2026-01-01"
  },
  "entities": [
    {
      "entity_id": "company_example_corp",
      "type": "company",
      "name": "Example Corporation"
    },
    {
      "entity_id": "party_example_green",
      "type": "political_party",
      "name": "Example Green Party",
      "country": "DE"
    }
  ],
  "products": [
    {
      "barcode": "4006381333931",
      "name": "Example Chocolate Bar",
      "entity_id": "company_example_corp"
    }
  ],
  "claims": [
    {
      "entity_id": "company_example_corp",
      "type": "company",
      "status": "boycott",
      "score": -80,
      "reason": "Labor violations",
      "source_url": "https://example.org/report"
    },
    {
      "entity_id": "party_example_green",
      "type": "political_party",
      "status": "recommended",
      "score": 75,
      "reason": "Strong environmental platform",
      "source_url": "https://example.org/platform"
    }
  ]
}

In recfiles it might look like below (more friendly for git diffs):

# Feed metadata
%rec: feed

id: example.mixed.feed
name: Example Mixed Reputation Feed
license: CC-BY-4.0
updated_at: 2026-01-01


# Entities
%rec: entity

entity_id: company_example_corp
type: company
name: Example Corporation

entity_id: party_example_green
type: political_party
name: Example Green Party
country: DE


# Products
%rec: product

barcode: 4006381333931
name: Example Chocolate Bar
entity_id: company_example_corp


# Claims
%rec: claim

entity_id: company_example_corp
status: boycott
score: -80
reason: Labor violations

entity_id: party_example_green
status: recommended
score: 75
reason: Environmental platform

Above was ran though a recfix rep.recfile command to double check that it is valid.

In SQLlite maybe it will look internally like below. Where the idea is that it's a faster way to partially look up a database without having to download the whole feed (e.g. via http range select) e.g. sqlite3vfshttp:

CREATE TABLE entities (
  entity_id TEXT PRIMARY KEY,
  type TEXT,
  name TEXT,
  country TEXT
);

CREATE TABLE products (
  barcode TEXT PRIMARY KEY,
  name TEXT,
  entity_id TEXT REFERENCES entities(entity_id)
);

CREATE TABLE claims (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  entity_id TEXT REFERENCES entities(entity_id),
  status TEXT,
  score INTEGER,
  reason TEXT,
  source_url TEXT
);

Anyway I hope this sketch will provide enough detail for building a federated style reputation sharing mechanism of social credits.

Ideally we will get to the point where even individuals can their their scoring list with other friends directly to bypass the issue of organizations getting compromised as well (e.g. legal bans on boycott or reputation scoring organisation)


Additional consideration 2026-01-13

Some extra considerations

  • The claim section would ideally include Markdown or HTML with a paragraph or two explaining the issue, as well as hyperlinks to news articles and date of the claim.
    • If it's a full paragraph, a chatbot could read it and say for instance "Markus doesn't care about this topic, so we will avoid adding this recommendation to his blacklist".
    • There will be those skeptical of the claims and it would be responsible to provide hyperlinks and references.
    • Date of claim will also be important as different people would also have different time horizons for when a sin can be forgiven.
  • May want to make this an extension of this standard from schema org
  • Instead of a seperate product feed, we may want to consider it as an entity but where it's canonical ID is the product barcode?

How would we avoid accidentally blacklisting an entitity?

We would include trusted entities as well which has no positive/negative claims against it, which would help disambiguate potential website or products.

How to find the canonical ID of an entity?

We got an entity ID, but how do we canonically identify them in a global manner? It's possible for multiple people to identify the same organisation/company/etc... entity ID is essentially just a local key.

This identifier would also be useful in example of a browser extension which may use "domain" id to detect that "example.com" url is associated with this entry.

"entities": [
  {
    "identity": [
      {
        "scheme": "lei",
        "value": "549300JGZ5X0Y1Q1JX75",
        "confidence": 1.0
      },
      {
        "scheme": "company_number",
        "country": "SE",
        "value": "556703-7485",
        "confidence": 0.95
      },
      {
        "scheme": "wikidata",
        "value": "Q306656",
        "confidence": 0.7
      },
      {
        "scheme": "domain",
        "value": "example.com",
        "confidence": 0.6,
        "evidence": [
          "https://example.com/legal",
          "https://whois.example.com"
        ]
      }
    ],
    "entity_id": "company_example_corp",
    "type": "company",
    "name": "Example Corporation"
  }
]

Note that it is an array so that we can assign levels of priority when matching IDs.

One person also recommended that the standard should also encode a URI for the schema being used to define the canonicity of the entity as it would be a big concern to have misidentified entities. Unsure how that can be done, but I presume that would be via putting a correctly formatted URI into the "scheme" field.

How would we rank feeds from most trusted to least trusted?

This should be decided by the user's software on their end.

"trusted_feeds": [
  { "feed_id": "labor.union.se", "weight": 1.0 },
  { "feed_id": "random.github.user", "weight": 0.3 }
]

Time horizon for forgiveness

"effective_from": "2024-01-01",
"review_after": "2026-01-01",
"last_reviewed": "2025-06-01"

Using these timestamps clients on their side can:

  • Fade out old claims
  • Prompt users to re-evaluate
  • Let users say “I don’t care about this issue”

How to discover other feeds?

This is similar to OPML which is a list of feed of other feeds, but for our use case of a distributed federated trust system rather than federated news feeds.

{
  "feed": {
    "id": "example.feed_index.labor",
    "type": "feed_index",
    "maintainer": "Example Labor NGO"
  },
  "feeds": [
    {
      "feed_id": "labor.eu.textiles",
      "url": "https://example.org/textiles.json",
      "topics": ["labor", "manufacturing"],
      "trust_hint": 0.9
    }
  ]
}

This will be useful for clients to interchange feeds when moving between devices... or for feeds to share other feeds.