Open Site Pass

Uno standard aperto di codice QR per registrarsi nei luoghi di lavoro. Qualsiasi app può mostrare un pass e qualsiasi chiosco può leggerlo.

Versione 1, novembre 2026. Uso gratuito con licenza CC BY 4.0.

Gli appaltatori si registrano ogni settimana in una sede diversa, e ognuna chiede gli stessi dati: nome, azienda, cellulare, veicolo, tessera Site Safe. Open Site Pass consente di tenere questi dati in un'app e consegnarli mostrando un codice QR. Qualsiasi app può mostrare un pass e qualsiasi chiosco di registrazione può leggerlo, chiunque li abbia creati.

Prima di scrivere questo abbiamo cercato uno standard esistente. I prodotti di registrazione visitatori con pass QR hanno ciascuno un proprio formato che funziona solo al loro interno. Gli standard generali di identità (W3C Verifiable Credentials, OpenID for Verifiable Presentations, patenti mobili ISO 18013-5) richiedono un'app portafoglio e uno scambio in più passaggi, più di quanto serva a un tablet all'ingresso di una sede. Per questo è un formato piccolo che qualsiasi linguaggio può leggere e verificare con la crittografia integrata.

1. Cosa contiene il codice QR

Il codice QR contiene testo semplice in tre parti unite da punti:

OSP1.<pass>.<signature>
  • OSP1 indica che è un Open Site Pass, versione 1.
  • <pass> è il pass in JSON, UTF-8, poi base64url senza riempimento.
  • <signature> è una firma ECDSA P-256 con SHA-256 sul testo ASCII di <pass> (esattamente come appare nel codice QR), nella forma r ‖ s da 64 byte, poi base64url senza riempimento. È la forma prodotta da crypto.subtle.sign di Web Crypto.

2. Il pass

{
  "version": 1,
  "issuer": "https://timeclock.kiwi",
  "keyId": "2026-11-3fa9c1",
  "holderId": "b7f3c2e1a94d0c55e1f3b2a8",
  "issuedAt": "2026-11-01T09:42:00.000Z",
  "expiresAt": "2026-11-01T09:43:00.000Z",
  "firstName": "Sam",
  "lastName": "Taylor",
  "company": "Harbour Electrical Ltd",
  "phone": "+64215550142",
  "vehicleRegistration": "QKT482",
  "documents": [
    { "type": "site-safe-passport", "number": "SS-482913", "expiresOn": "2027-03-31" }
  ]
}
versionSempre 1 per questa versione.
issuerL'origine HTTPS di chi ha firmato il pass, es. https://timeclock.kiwi. Le sue chiavi si trovano da qui.
keyIdQuale chiave dell'emittente l'ha firmato.
holderIdUguale per una persona con un emittente, e diverso con ogni altro emittente. Consente a una sede di riconoscere un visitatore che ritorna. Non deve essere un numero di dipendente, un'email o altro che lo identifichi altrove.
issuedAt, expiresAtOrari ISO 8601. Un pass dovrebbe durare circa un minuto e non più di 15 minuti, così una sua foto diventa presto inutile.
firstName, lastNameIl nome.
companyPer chi lavora, se ha scelto di condividerlo.
phoneNumero di cellulare, preferibilmente in formato internazionale.
emailIndirizzo email.
vehicleRegistrationTarga del veicolo con cui è arrivato.
documentsTessere e certificati: ognuno ha type (dall'elenco sotto) e, facoltativamente, number, issuer ed expiresOn (AAAA-MM-GG).

Obbligatori: version, issuer, keyId, holderId, issuedAt, expiresAt, firstName. Tutto il resto è facoltativo e scelto dal titolare ogni volta.

Tipi di documento

site-safe-passportSite Safe passport
public-liability-insuranceAssicurazione di responsabilità civile
electrical-registrationRegistrazione da elettricista
plumbing-gasfitting-registrationRegistrazione idraulica, gas o fognature
forklift-licencePatentino per carrelli elevatori (F endorsement)
first-aid-certificateCertificato di primo soccorso
working-at-heightsLavoro in quota
confined-spacesSpazi confinati
construction-induction-cardTessera di formazione edile (White Card)
cscs-cardCSCS card

Per proporre un altro tipo, contattaci qui sotto. I chioschi conservano i documenti di tipi sconosciuti, ma non li abbinano a nulla.

3. Chiavi dell'emittente

Gli emittenti pubblicano le chiavi pubbliche in <issuer>/.well-known/open-site-pass/keys.json:

{
  "keys": [
    {
      "keyId": "2026-11-3fa9c1",
      "publicKey": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" }
    }
  ]
}

Ogni publicKey è un JWK, che Web Crypto può caricare direttamente. Continua a pubblicare una chiave per almeno un giorno dopo aver smesso di firmare con essa. Le chiavi di Timeclock.Kiwi sono in https://timeclock.kiwi/.well-known/open-site-pass/keys.json.

4. Regole per i chioschi

  1. Controlla la firma con la chiave dell'emittente e che il pass non sia scaduto. Concedi fino a 2 minuti di margine per le differenze di orologio.
  2. Scarica le chiavi solo dall'origine HTTPS dell'emittente e memorizzale nella cache per controllare un pass offline.
  3. Mostra i dati e il dominio dell'emittente, e lascia confermare il visitatore prima di salvare qualsiasi cosa.
  4. Considera i dati dei documenti come inseriti dal titolare, non verificati. Se la tua sede deve verificarli, fai controllare la tessera reale a una persona.
  5. Puoi accettare solo pass di emittenti fidati, oppure qualsiasi emittente HTTPS mostrando "Verified by <domain>".
  6. Non chiedere mai all'app del titolare più di quanto contenga il pass. Il titolare sceglie cosa condividere.

5. Regole per le app

  1. Crea un nuovo pass almeno ogni minuto mentre è sullo schermo.
  2. Lascia scegliere al titolare quali dati facoltativi inserire, ogni volta o come scelta salvata modificabile.
  3. Non inserire mai nulla che il titolare non abbia scelto, inclusi datore di lavoro, posizione o ID interni.

6. Controllare un pass in JavaScript

È tutto ciò che serve a un chiosco, usando solo la crittografia integrata del browser:

async function readPass(text, fetchKeys) {
  const [prefix, body, signature] = text.split('.');
  if (prefix !== 'OSP1') throw new Error('Not a site pass');

  const pass = JSON.parse(atob(body.replace(/-/g, '+').replace(/_/g, '/')));
  const keys = await fetchKeys(pass.issuer); // GET <issuer>/.well-known/open-site-pass/keys.json
  const jwk = keys.find(k => k.keyId === pass.keyId)?.publicKey;

  const key = await crypto.subtle.importKey('jwk', jwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['verify']);
  const fromB64 = s => Uint8Array.from(atob(s.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0));
  const ok = await crypto.subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, key, fromB64(signature), new TextEncoder().encode(body));

  const now = Date.now(), slack = 2 * 60 * 1000;
  if (!ok || Date.parse(pass.expiresAt) + slack < now) throw new Error('Not valid');
  return pass;
}

Uso con Timeclock.Kiwi

Chiunque abbia effettuato l'accesso all'app Timeclock.Kiwi può mostrare un pass da Il mio pass di sede, e ogni chiosco di registrazione Timeclock.Kiwi li legge, inclusi i pass di altre app che seguono questo formato.

Siamo sempre felici di aiutarti.
Contattaci e faremo del nostro meglio perché il nostro sistema di rilevazione presenze funzioni per te.