Open Site Pass
作業現場の受付のためのオープンな QR コード標準です。どのアプリでもパスを表示でき、どのキオスクでも読み取れます。
バージョン 1、2026 年 11 月。CC BY 4.0 のもとで無料で使用できます。
業者は毎週違う現場で受付し、どこでも同じ情報を求められます。名前、会社、携帯電話、車両、Site Safe カードです。Open Site Pass を使えば、これらをアプリに入れておき、QR コードを見せるだけで渡せます。作った会社を問わず、どのアプリでもパスを表示でき、どの受付キオスクでも読み取れます。
これを書く前に既存の標準を探しました。QR パスを使う訪問者受付製品はそれぞれ独自の形式で、その製品の中でしか機能しません。一般的な ID 標準(W3C Verifiable Credentials、OpenID for Verifiable Presentations、ISO 18013-5 モバイル運転免許証)はウォレットアプリと複数段階のやり取りが必要で、現場の入口のタブレットには過剰です。そこで、どの言語でも内蔵の暗号機能で読み取りと検証ができる小さな形式にしました。
1. QR コードの中身
QR コードにはドットでつないだ 3 つの部分のプレーンテキストが入っています。
OSP1.<pass>.<signature> OSP1は Open Site Pass のバージョン 1 であることを示します。<pass>は JSON のパスで、UTF-8 にしてからパディングなしの base64url にしたものです。<signature>は<pass>の ASCII テキスト(QR コードの表記のまま)に対する SHA-256 の ECDSA P-256 署名で、64 バイトの r ‖ s 形式にし、パディングなしの base64url にしたものです。Web Crypto のcrypto.subtle.signが生成する形式です。
2. パス
{
"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" }
]
} | version | このバージョンでは常に 1 です。 |
|---|---|
| issuer | パスに署名した者の HTTPS オリジン。例:https://timeclock.kiwi。ここから鍵を見つけます。 |
| keyId | 発行者のどの鍵で署名したか。 |
| holderId | 同じ発行者なら同じ人で同じ値、他の発行者では異なる値です。現場が再訪問者を認識できます。従業員番号、メール、他で本人を特定できるものにしてはいけません。 |
| issuedAt, expiresAt | ISO 8601 の時刻。パスの有効期間は約 1 分とし、15 分を超えてはならないため、写真はすぐに無効になります。 |
| firstName, lastName | 名前。 |
| company | 勤務先(共有を選んだ場合)。 |
| phone | 携帯電話番号。できれば国際形式で。 |
| メールアドレス。 | |
| vehicleRegistration | 来場した車両のナンバープレート。 |
| documents | カードと証明書:それぞれ type(下の一覧から)と、任意で number、issuer、expiresOn(YYYY-MM-DD)を持ちます。 |
必須:version, issuer, keyId, holderId, issuedAt, expiresAt, firstName。それ以外は任意で、毎回保有者が選びます。
書類の種類
site-safe-passport | Site Safe passport |
|---|---|
public-liability-insurance | 賠償責任保険 |
electrical-registration | 電気工事士の登録 |
plumbing-gasfitting-registration | 配管、ガス工事、排水工事の登録 |
forklift-licence | フォークリフト免許(F endorsement) |
first-aid-certificate | 応急手当の証明書 |
working-at-heights | 高所作業 |
confined-spaces | 閉所 |
construction-induction-card | 建設導入カード(White Card) |
cscs-card | CSCS card |
他の種類を提案するには、下からご連絡ください。キオスクは知らない種類の書類も保持しますが、何にも照合しません。
3. 発行者の鍵
発行者は公開鍵を <issuer>/.well-known/open-site-pass/keys.json で公開します。
{
"keys": [
{
"keyId": "2026-11-3fa9c1",
"publicKey": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" }
}
]
} 各 publicKey は JWK で、Web Crypto で直接読み込めます。署名に使わなくなった鍵も少なくとも 1 日は公開を続けてください。Timeclock.Kiwi の鍵は https://timeclock.kiwi/.well-known/open-site-pass/keys.json にあります。
4. キオスクのルール
- 発行者の鍵で署名を確認し、パスが期限切れでないことを確認します。時計のずれとして前後 2 分まで許容します。
- 鍵は発行者自身の HTTPS オリジンからのみ取得し、オフラインでパスを確認できるようキャッシュします。
- 詳細と発行者のドメインを表示し、保存する前に訪問者に確認してもらいます。
- 書類の詳細は保有者が入力したものとして扱い、確認済みとはみなしません。確認が必要な現場では、人が実物のカードを確認してください。
- 信頼する発行者のパスのみ受け入れるか、任意の HTTPS 発行者を受け入れて「Verified by <domain>」と表示できます。
- パスの内容以上のものを保有者のアプリに求めないでください。何を共有するかは保有者が選びます。
5. アプリのルール
- 画面に表示している間は、少なくとも 1 分ごとに新しいパスを作成します。
- 任意の情報を入れるかは、毎回または変更可能な保存済みの選択として、保有者が選べるようにします。
- 保有者が選んでいないものは、雇用主、位置情報、内部 ID を含めて入れないでください。
6. JavaScript でパスを確認する
キオスクに必要なのはこれだけで、ブラウザ内蔵の暗号機能のみを使います。
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;
} Timeclock.Kiwi で使う
Timeclock.Kiwi アプリにログインしている人は誰でも「マイサイトパス」からパスを表示でき、すべての Timeclock.Kiwi 現場受付キオスクが読み取ります。この形式に従う他のアプリのパスも読み取れます。