quest'n'click 4.5.0 · r1

Built for quest'n'click 4.5.0, revision r1. Whether it is published, and which one is current, is recorded at publication.json.

Open Badges connector

Français · Type: how-to + reference · Audience: admin · Context: Reality Bridge · Status: ready · Applies from: 4.3.0

The connectors (email, Telnet, SSH, Open Badges) · contract: experimental · verified by CI (support matrix of 4.4.0, 2026-10-23): Node 22 on Ubuntu (Telnet and SSH not on Windows) · automated checks: jobs connectors, connector-archive-e2e; CI plan reality; 3 test files · people's passes: connectors-real-security not run (#79) · known limits: bridge-badge-code-once

The Open Badges connector serves a small form: a player posts a badge (an Open Badges 2.0 assertion or a 3.0 credential) with the pairing code their game shows, the connector verifies the badge, and the verdict (valid, invalid, expired, revoked, indeterminate) proposes the signal the game declares for it. The game never receives the badge. It is experimental, like every connector (Connectors overview).

What you get

A quest-n-click-connector open-badge process answering POST /v1/badges, fetching the badge's documents under a strict network policy, and proposing one signal per badge and verdict.

Context and versions

Prerequisites

Where to run the commands

grant where the Bridge's folder is; the connector behind your HTTPS proxy, in a folder holding its configuration and token. npm run connector -- open-badge … in the engine repository, npx quest-n-click-connector open-badge … with the package.

Steps

  1. Grant the connector its token, for the badge signals only, with pairing:

    # in the engine repository (the Bridge's folder is .cache/bridge)
    npm run bridge -- grant --connector=garden-badges --source=badge --signals=badge.valid,badge.refused --pair > badge.token
    
  1. Write its configuration, badge.json; hosts defaults to the hosts of the game's https: issuers:

    {
      "bridge": { "url": "http://127.0.0.1:8787/", "tokenFile": "badge.token" },
      "gameId": "signals",
      "health": { "port": 9304 },
      "open-badge": { "port": 8790, "hosts": ["badges.example.org"] }
    }
    
  1. Start it:

    # in the engine repository
    npm run connector -- open-badge --config badge.json
    

    It refuses to start when the game declares no reality.connectors['open-badge'].

  1. A player posts, with a code the game has just shown:

    # from the player's side (your form does this)
    curl -s -X POST http://127.0.0.1:8790/v1/badges -H 'Content-Type: application/json' \
      -d '{"code":"ABCD2345","badge":"https://badges.example.org/assertions/42","email":"player@example.org"}'
    

    badge is a URL, a compact JWS, or the credential itself; email (or recipient) is what a hashed recipient is checked against. The answer is 202 {"status":"valid","signal":"accepted"}, or 200 {"status":"…","signal":"none"} when the game declares no signal for that verdict.

Expected result, and how to check it

Common errors

AnswerCauseFix
422 {"error":"pairing-pairing"}The code is unknown, expired or used already: a code serves onceA new code from the game
400 {"error":"shape"}Not JSON, or no codePost { code, badge, email? }
202 with "status":"indeterminate"A proof suite it cannot check (eddsa-rdfc-2022…), or a document it could not fetch under its policyAsk the issuer for a supported format; check hosts
202 with "status":"invalid"Another issuer than the game's, a recipient that does not match, a bad or weak signature—
413, or 429 {"error":"rate"}A body over 64 KB; over 30 posts a minute from one address—

Files or data changed

None on disk. Revocation and status lists are cached in memory for at most a day.

Recovery or going back

Stop the process (SIGTERM). Revoke its token on the Bridge if it leaked, and grant a new one.

Limit · bridge-badge-code-once A pairing code serves once. Each post needs a code the game has just shown, and confirming it links the game to a new pseudonymous player, as any pairing does.

Reference: what is verified

Reference: the network policy

Every document is fetched under one policy: https: only; hosts from hosts (by default the hosts of the issuers); the name resolved once, and no private, loopback, link-local, multicast or unspecified address (IPv4, IPv6 and IPv4-mapped IPv6); two redirects at most, each checked again; 64 KB; 10 seconds; JSON nested at most 8 deep; @context never fetched.

Guarantee · bridge-badge-network-policy · referenced · executed on aff6caab7514 · scope self-checked by the author (AI), not reviewed A fetch without https:, to a host off the list, with credentials in its URL, or whose name resolves to a private address is refused, and a name is resolved once (no rebinding).

The open-badge section:

FieldDefaultMeaning
port, host—, 127.0.0.1Where POST /v1/badges listens
hoststhe hosts of the game's https: issuersWhere documents may be fetched from
perMinutePerIp30Posts a minute per address
maxBytes65 536A post's body

What it keeps

The badge and the documents it points to are fetched, checked and dropped; only a verdict leaves the connector, as a signal, with a hash of the badge's id and issuer as evidenceHash. The email a player gives to match a hashed recipient is hashed with the badge's salt for the comparison, then dropped: never stored, logged or sent. Revocation and status lists (an issuer's, not a person's) are cached for at most a day. The addresses that post to the form are counted in memory for a minute (the rate limit), then forgotten.

References


Edit the source of this page · Report an error