開発者コンソール

台帳

App の記録のハッシュを積み、ある時点にその値が確定していたことを後から示す範囲です。

台帳に載るのは App が作ったハッシュ(c)だけです。記録の本文、利用者の識別子、日時は送りません。本文と salt は App か Vault に残します。

開発者コンソール

  1. 1. Org を開きます。無ければ Org を作成します。

  2. 2. Org のプラン面で台帳を購入します。

  3. 3. App を登録し、ホストを確認します(クイックスタート)。

  4. 4. App 詳細の用途に台帳を入れて保存します。

認証

App のサーバが operate 鍵で、要求ごとに JWT を署名します。session JWT は使いません。

JWT claims

{
  "iss": "app:<app_id>",
  "aud": "clavis-ledger",
  "app_id": "<app_id>",
  "htm": "POST",
  "htu": "/archive/ledger/v1/entries",
  "body_sha256": "<本文の SHA-256(hex)。本文が無いときは付けない>",
  "iat": 1790000000,
  "exp": 1790000060,
  "jti": "<一度だけ使う値>"
}
  • htu
    パスとクエリです。/archive から書きます。
  • exp − iat
    300 秒までです。
  • jti
    同じ値は二度通りません。

コミットメント

App のサーバで計算
salt = 32 バイトの乱数(記録ごとに新しく作る)
c    = SHA-256( "clavis.commit.v1" ‖ salt ‖ canonical_json(record) )
slot = HMAC-SHA256( App の秘密鍵, "asset:<asset_id>:v<version>" )   // 任意
  • salt
    記録ごとに乱数で作ります。使い回すと、本文の推測を防げません。
  • canonical_json
    キーを昇順に並べた JSON です。
  • slot
    同じ資産の同じ版に、二つ目の記録を確定させないための枠です。App の秘密鍵を Clavis に渡す必要はありません。

opening(App か Vault に残す)

{
  "salt": "<base64url 32 バイト>",
  "record": { "kind": "transfer", "asset": "a-1", "from": "u1", "to": "u2" }
}

手順

  1. 1. record と salt から c を作ります。所有権の移転なら slot も作ります。

  2. 2. 葉を送ります。応答の receipt を記録と一緒に残します。

    Request
    POST https://api.clavis.nexus/archive/ledger/v1/entries
    Authorization: ClavisApp <JWT>
    Content-Type: application/json
    
    {
      "leaf": { "v": 1, "c": "<64 hex>", "slot": "<64 hex(任意)>" }
    }

    201 Response

    {
      "log_id": "<Org の UUID>",
      "status": "created",
      "index": 41,
      "leaf_hash": "<64 hex>",
      "receipt": "clavis.ledger.receipt/v1\nclavis.nexus/ledger/<Org の UUID>\n41\n<base64>\n\n— clavis-ledger-log <base64>\n"
    }
  3. 3. 約 1 分後、チェックポイントに入った包含証明を取ります。入る前は 202 です。

    Request
    GET https://api.clavis.nexus/archive/ledger/v1/proof?index=41
    Authorization: ClavisApp <JWT>

    200 Response

    {
      "log_id": "<Org の UUID>",
      "index": 41,
      "size": 42,
      "checkpoint": "clavis.nexus/ledger/<Org の UUID>\n42\n<base64 root>\ntime 1790000060\n\n— clavis-ledger-log <base64>\n",
      "inclusion": ["<base64>", "<base64>"]
    }
  4. 4. 相手に渡すときは証拠束を取り、opening を足します。外部の時刻証明(anchor)は 1 時間ほどで付きます。

    Request
    GET https://api.clavis.nexus/archive/ledger/v1/bundle?index=41
    Authorization: ClavisApp <JWT>

    200 Response

    {
      "anchor_status": "stamped",
      "bundle": {
        "version": 3,
        "log_id": "<Org の UUID>",
        "leaf": { "v": 1, "c": "<64 hex>" },
        "index": 41,
        "receipt": "<signed note>",
        "checkpoint": "<signed note>",
        "inclusion": ["<base64>"],
        "anchor": {
          "index": 7,
          "checkpoint": "<signed note>",
          "inclusion": ["<base64>"],
          "tsa": [{ "url": "<TSA>", "response": "<RFC 3161 応答(base64)>" }]
        },
        "jwks": { "keys": [], "master": {} }
      }
    }

読み取り

最新のチェックポイント
GET https://api.clavis.nexus/archive/ledger/v1/checkpoint
Authorization: ClavisApp <JWT>
二つのチェックポイントの整合性証明
GET https://api.clavis.nexus/archive/ledger/v1/consistency?first=<size>&second=<size>
Authorization: ClavisApp <JWT>
チェックポイントの時刻証明
GET https://api.clavis.nexus/archive/ledger/v1/anchor-proof?size=<size>
Authorization: ClavisApp <JWT>
index の葉
GET https://api.clavis.nexus/archive/ledger/v1/entries/<index>
Authorization: ClavisApp <JWT>
c から index
GET https://api.clavis.nexus/archive/ledger/v1/entries?c=<64 hex>
Authorization: ClavisApp <JWT>
  • 読めるのは、その App が属する Org のログだけです。
  • 解約後も読み取りと証拠束の取得はできます。

Vault

opening を失わないための保管庫です。App 側で暗号化してから置きます。台帳とは独立して消せます。

置く
PUT https://api.clavis.nexus/archive/vault/v1/objects/<object_id>?subject_tag=<64 hex>&expires_at=<unix>
Authorization: ClavisApp <JWT>
Content-Type: application/octet-stream

<暗号文>
取る
GET https://api.clavis.nexus/archive/vault/v1/objects/<object_id>
Authorization: ClavisApp <JWT>
消す
DELETE https://api.clavis.nexus/archive/vault/v1/objects/<object_id>
Authorization: ClavisApp <JWT>
本人単位で消す
DELETE https://api.clavis.nexus/archive/vault/v1/subjects/<subject_tag>
Authorization: ClavisApp <JWT>
  • object_id
    英数字・ハイフン・下線で 16〜128 文字です。上書きはできません。
  • subject_tag
    任意です。App の利用者 ID から作った HMAC など、Clavis が人を特定できない値にします。
  • expires_at
    任意です。過ぎたものは毎日消します。

検証

  • 証拠束は Clavis が止まっていても検証できます。必要なのは証拠束と集約 JWKS の Master 公開鍵です。
  • 受領証とチェックポイントは C2SP signed note(Ed25519)、包含・整合性証明は RFC 9162、時刻証明は RFC 3161 です。
  • opening があれば c を計算し直し、記録の中身まで確かめられます。
  • ブラウザで確かめるときは archive.clavis.nexus/verify に証拠束を貼ります。証拠束は送信されません。

上限

  • 新しい葉 1 件を台帳の 1 回と数えます。同じ c の再送と読み取りは数えません。
  • 葉の追記と Vault への保存には、台帳の購入と当月の残りが要ります。
  • App ごとに毎分 600 要求までです。
  • Vault は 1 件 256 KiB、Org 合計 1 GiB までです。

エラー

共通形は error、message、requestId、trace_id です。

  • 401 APP_AUTH_FAILED
    JWT を検証できません。message の値(signature、claims、expired、body_mismatch など)を直してください。
  • 409 DUPLICATE_JTI
    その jti は使われています。要求ごとに新しい JWT を作ってください。
  • 409 APP_NOT_ACTIVE
    App のホストが未確認です。
  • 402 CARD_CLOSED
    message が declaration のときは用途に台帳がありません。それ以外は購入か当月の残りです。
  • 400 INVALID_LEAF
    leaf は v、c、slot(任意)だけです。c と slot は小文字の 64 hex です。
  • 409 SLOT_TAKEN
    その slot には別の c が確定しています。版を進めてから送ってください。
  • 202 pending
    まだチェックポイントか時刻証明に入っていません。時間をおいて取り直してください。
  • 409 OBJECT_EXISTS
    同じ object_id があります。消してから置き直してください。
  • 413 OBJECT_TOO_LARGE / 507 VAULT_QUOTA_EXCEEDED
    Vault の上限を超えています。
  • 429 RATE_LIMITED
    毎分の上限を超えました。

参照