provin
← トップへ戻る

IMPLEMENTATION SPECIFICATIONS

実装から読む、provin の技術仕様

このページは構想ではなく、provin OSS のコード、依存関係、既定設定を読み解いた実装スナップショットです。何を採用したかだけでなく、その選択が実行時に何を保証し、どこまでを保証しないかを明記します。

main @ 793c27923f57 · 2026-07-17 · 0.x / PoC source ↗

SYSTEM SHAPE

2つの面と、持ち出せる証跡

standalone ノードは、登録・調整を行う制御面と、イベントを処理するデータ面を一つの設定から組み立てます。両方を横断して残る証跡は、稼働中のノードから切り離して検証できます。※ standalone 構成はこのスナップショット時点のもの — その後退役し、現行 main は cmd/network + cmd/pipeline の 2 バイナリ構成(CHANGELOG 参照)。

01

Control plane

DID、鍵、スキーマ、チェーン関係、監査を ConnectRPC サービスとして公開します。状態は YAML とファイルに置き、レジストリ専用ノードとしても起動できます。

source ↗

02

Data plane

Source / Chained / Sink / Custom のプロセスが NATS 上でイベントを受け渡し、検証・変換・署名を繰り返します。各プロセスは同じ契約に従う対等な構成要素です。

source ↗

03

Evidence path

credential、監査 verdict、transparency log、receipt を追記型で保持し、bundle として export / offline verify できます。通信相手を信頼することと、データの来歴を検証することを分離します。

source ↗

SELECTION CATALOG

責務ごとの技術選定

バージョンはこのスナップショットの go.mod と生成設定に基づきます。選定理由は、コードから確認できる役割と挙動に限定しています。

領域選定実装上の意味現在の境界
Runtime Go 1.25.5 standalone ノードと provin 運用 CLI を同じ module から静的に組み立てます。並行処理、標準 TLS、組み込みテストを共通基盤にします。

配布物は dist/standalone と dist/provin(スナップショット時点 — standalone はその後退役し、cmd/network + cmd/pipeline へ再編)。データベースや別言語ランタイムを必須にしません。

source ↗
Service API Protobuf + Buf v2 + ConnectRPC サービス契約を dplaax.*.v1 の protobuf として定義し、Go 型と Connect ハンドラを生成します。Buf lint は STANDARD、breaking 判定は FILE 単位です。

HTTP listener は一つ。公開 API の互換性は proto の v1 package と breaking check で管理します。

source ↗
Event transport Core NATS · server 2.12.6 / Go client 1.50.0 疎結合な subject ベースの pub/sub と、operator / account JWT による組織間 subject grant を使います。publish 後に FlushTimeout で broker 受領を確認します。

JetStream ではありません。永続キュー、再配信、exactly-once はなく、残余の配送保証は at-most-once です。

source ↗
Transformation JSONata 1.5.4 + JSON Schema 2020-12 filter と converter を設定からコンパイルし、入力・出力境界を schema で検証します。JSONata 式は起動時に事前コンパイルされます。

Chained は一入力一出力の stateless 処理。状態を持つ集約は Source / aggregate 側の責務です。

source ↗
Credential proof W3C VC Data Integrity + Ed25519 payload 本体ではなく content hash、process、時刻、直前 credential を署名付き credential に記録します。既定 suite は eddsa-jcs-2022 です。

署名鍵は Ed25519 のみ。P-256 / P-384 は現行 PoC の対象外です。

source ↗
Canonicalization RFC 8785 JCS + URDNA2015 JSON の同値な表現を同じ署名入力にします。JCS を既定とし、RDFC suite では埋め込み JSON-LD context と URDNA2015 を使います。

JSON-LD context はネットワーク取得しません。RDFC の @json で 2^53 を超える整数は文字列で表す必要があります。

source ↗
Identity & keys did:dplaax + delegation credentials Owner → Pipeline → Process の階層で、発行者・認証鍵・委譲権限を解決します。process signing key は registry custody に置きます。

現在は file / YAML keystore。Vault、HSM、cloud KMS は interface の差し替え先であり、同梱済み連携ではありません。

source ↗
Configuration & state HOCON + YAML / files reference.conf、application.conf、環境 overlay の順で設定を合成します。control state と evidence の reference store は YAML / files で、storage と PDP は interface 境界を持ちます。

provin node は database なしでも動作します。database-backed registry は同梱しておらず、選択する auth provider、PDP、adapter は独自の database を必要とする場合があります。

source ↗
Observability OpenTelemetry 1.44 + Prometheus emit、verification、audit verdict などの counter を OTel で計装し、Prometheus 形式の /metrics から公開できます。

metrics endpoint は既定で無効。trace backend や dashboard を製品依存として組み込みません。

source ↗

PIPELINE RUNTIME

Chained process の一回の処理

入力を受けてから次へ発行するまでの順序は、来歴の連続性と payload の同一性を崩さないための実行契約です。途中で検証不能になった入力は次の credential を生成しません。

  1. 01

    隣接 credential を検証

    直前区間の Data Integrity、署名者、chain consistency を評価します。

  2. 02

    受信 credential を保存

    後からの検証に必要な ingress credential を同期的に保持し、保存できなければ失敗します。

  3. 03

    payload を解決

    inline または by-reference の payload を取り出します。

  4. 04

    hash binding を照合

    payload の SHA-256 と credential が宣言した content hash を比較します。

  5. 05

    入力 schema を検証

    設定されている場合に、変換前の構造を検証します。

  6. 06

    filter を評価

    JSONata filter を順に評価し、不一致は意図的な drop として記録します。

  7. 07

    converter を実行

    JSONata converter で一つの入力を一つの出力へ変換します。

  8. 08

    出力 schema を検証

    設定されている場合に、変換後の構造を検証します。

  9. 09

    strict decode

    duplicate key と trailing data を拒否し、数値を json.Number のまま扱います。

  10. 10

    入出力 hash を計算

    処理前後をそれぞれ content-addressed な値に固定します。

  11. 11

    新しい credential に署名

    previousCredential を一つだけ引き継ぎ、線形な chain を伸ばします。

  12. 12

    通知して publish

    observer を呼び出してから primary subject へ発行し、成功後に emission log を追記します。

処理順序をコードと README で確認 ↗ sequence と配送境界をコードで確認 ↗

判定と配送の意味

Verified only

producing process が次へ進めるのは ConfidenceVerified だけです。failed と indeterminate はエラーとして閉じます。

At-most-once

core NATS への publish と flush は broker 受領までを確認しますが、consumer 再配信や永続化は行いません。

Known crash window

publish 後、log 追記前の停止は「配送済み・未記録」の gap を残します。file log は事前に durable intent を記録するため番号を再利用しませんが、broker 受領後の flush timeout は「失敗」と見えて番号が再利用される余地があります。

CONCRETE SAMPLE

1件の入力が、credential と verdict になる

E2E は構成全体が動くことを確認する手順です。この sample は、実行せずに wire shape と検証結果を読める固定例です。hash と proofValue は表示用に省略しています。

01 / INPUT

POST /ingest/src/push
{"sensor":"temp-01","celsius":21.5}

02 / FIRSTDROP CREDENTIAL — EXCERPT

{
  "issuer": "did:dplaax:…:pipeline:readings:process:s1",
  "credentialSubject": {
    "pipelineId": "readings",
    "processId": "s1",
    "transformationClaim": "provin:convert",
    "inputHash": "sha256:3b8…",
    "outputHash": "sha256:3b8…"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "proofValue": "z…"
  }
}

03 / VERIFICATION RESULT — EXCERPT

{
  "confidence": "CONFIDENCE_VERIFIED",
  "axes": {
    "dataIntegrity": "CONFIDENCE_VERIFIED",
    "signerAuthenticity": "CONFIDENCE_VERIFIED",
    "chainConsistency": "CONFIDENCE_VERIFIED"
  }
}

Source Process が発行する FirstDrop には previousCredential がありません。次の Chained Process は previousCredential を追加し、outputHash[n] == inputHash[n+1] を満たす線を伸ばします。

transformationClaim の意味 — 文法は dPLaaX、意味は provin profile

この sample の "provin:convert" のようなクレームの文法(1 トークン)は dPLaaX が定め、その意味 — 発行者が何を保証するか — は provin wire profile が規範として定めます。中核は閉世界性: closed なクレームは「宣言した入力がこの出力の情報源のすべて」を保証し、排除推論(このロットはこの出力に含まれ得ない)を成立させます。

provin:filter closed — 宣言した入力が情報源のすべて
provin:convert closed
provin:filter-convert closed
provin:aggregate closed fold — 宣言した入力集合の畳み込み
provin:enrich conformant-closed — 排除推論は適合フローに限る
provin:generate open — 宣言した入力の外に情報源を認める
provin:sink-receipt identity — 変換ではなく受領

PROOF & CANONICALIZATION

署名対象を、再現可能な byte 列にする

credential body を唯一の正として正規化し、proof configuration と document を別々に hash して連結します。未知の signed-scope field も map に保持されるため、再エンコードで署名範囲から落ちません。

Data Integrity signing input

hashData = SHA-256(canon(proofConfig)) ‖ SHA-256(canon(document))
proofValue = base58btc(Ed25519.sign(hashData))
source ↗

eddsa-jcs-2022

実装済み · 既定

RFC 8785 JCS で JSON を canonicalize し、Ed25519 で署名します。Phase 1 の必須 suite です。

eddsa-rdfc-2022

実装済み · 任意

埋め込み context と URDNA2015 を用いる RDFC suite。runtime の外部 context fetch は禁止されています。

Strict JSON decoder

全 signed path

duplicate key、trailing data、暗黙な float64 化を避けます。lint が signed JSON の decode path を一つに制限します。

Linear credential chain

実装済み

previousCredential は常に単数です。payload は埋め込まず、input / output hash により内容を結びます。

verification confidence

data integrity、signer authenticity、chain consistency の3軸を評価し、failed < indeterminate < verified の最弱値を全体判定にします。

TRUST BOUNDARIES

通信の認可と、来歴の検証を分ける

リクエストを受け付けてよいか、peer が正当か、受け取ったデータの来歴が正しいかは別の問題です。provin はこの3層を異なる証拠と失敗条件で扱います。

守る境界方式失敗時
L1 · Service authorization 管理・登録 API Bearer token → PDP。protobuf の method policy annotation と PEP interceptor で適用します。既定 backend は JWT を検証する o3co です。 設定欠落は起動失敗。static backend の空 allow-list は deny-all です。
L2 · Peer wire proof ChainPeer / Payload service signerDID、operation、nonce、issuedAt、fields の JCS view を Ed25519 署名し、DID から認証鍵を解決します。 時刻窓、nonce 単回使用、restart epoch を検査します。auth-off mode はありません。
L3 · Provenance evidence データそのもの credential chain、content hash、transparency log、audit verdict を組み合わせ、transport の信頼とは独立に検証します。 3軸の一つでも failed、または確定不能なら producing path を閉じます。

PDP backend の意味は同一ではない

o3co は JWT を検証します。OPA は policy 自身が認証を担う構成、Cedar は raw bearer principal を受ける構成、static は token の存在または allow-list を見るだけです。backend 名だけで同じ認証強度を仮定しません。

source ↗

threat model の現在地

検出する対象

署名後の record 改変、payload と content hash の不一致、申告された chain の不連続、許可されていない signer / request を、それぞれの境界で fail-closed に扱います。

依存する信頼

issuer の鍵管理、DID registry と resolver、検証者の trust policy、transport confidentiality、時刻と nonce の運用が保証の一部を支えます。

保証の外と未完了

正当に署名された誤データ、記録されなかった処理、侵害済みの正規鍵、低 entropy payload hash の推測は chain だけでは防げません。repository-wide threat model は初回公開後の課題です。

Security policy と trust boundary ↗

CONFIGURATION & EVIDENCE

file-backed を既定に、状態と証跡を分ける

provin node は YAML / files だけでも動作し、storage / PDP は interface で差し替えられます。設定、制御状態、証跡、短命状態を分け、選択する auth provider、PDP、adapter の外部依存を個別に組み合わせます。

設定の合成順序

  1. 01

    reference.conf

    配布物に埋め込む完全な既定値。Go コード側に隠れた default を置きません。

  2. 02

    config/application.conf

    ノード固有の任意設定。存在すると既定値を上書きします。

  3. 03

    environment overlay

    指定された環境 overlay を最後に合成し、最終値を typed config へ decode します。

source ↗

状態の置き場所

YAML control state

DID、pipeline / process、schema、chain 設定などの registry 状態。

File-backed evidence

credential variant、resolution pool、audit queue / verdict、receipt、sink reject。credential は content-addressed かつ append-only です。

In-memory PoC state

wire-auth nonce など。restart epoch barrier で再起動をまたぐ replay を閉じますが、複数ノードで共有する nonce store ではありません。

offline verification

provin bundle export が credential と依存証拠をまとめ、provin bundle verify がネットワークアクセスなしで検証します。JSON-LD context も binary に埋め込まれています。evidence は削除・変更せず、cold archive への rotate を行います。

source ↗

transparency log の現在地

現在は hash-chained file log を replay して改変を検出します。Merkle inclusion proof / consistency proof を備える CT 型 log は段階導入であり、現行実装の保証には含めません。

source ↗

OPERATIONS

既定値と運用面

安全側の既定を持ちつつ、PoC でまだ運用者が補う箇所を数値と挙動で示します。

項目既定 / 実装運用上の意味
Listen address 127.0.0.1:8443 既定は loopback。外部公開を暗黙に行いません。
HTTP mode cleartext h2c on loopback 非 loopback は node-native TLS、または明示的な allow-cleartext と隔離された TLS terminator が必要です。
TLS minimum 1.2 Go 標準 library の secure cipher defaults。証明書の hot reload はなく、rotation は再起動です。
Health /healthz · /readyz liveness と readiness を分離します。
Metrics /metrics · default off OpenTelemetry counter を Prometheus exposition で公開します。
Data-plane dependency Core NATS process event transport。JetStream の durable queue / redelivery は使いません。
Authorization dependency external PDP または static o3co / OPA / Cedar は外部 PDP。static は in-process allow-list で、authentication ではありません。auth provider の storage 要件は選択した実装に従います。
Durable state YAML / files · unbounded by default data dir の backup と disk monitoring が必要です。relationship evidence は停止後に cold archive へ rotate できます。
Resource sizing not published 最小 CPU / memory / disk、throughput、latency の推奨値は未公表です。小さい container limit での起動・E2E確認は下限探索、benchmark は定常性能の測定として別に必要です。
Credential / push limit 1 MiB / 1 MiB credential と受信 body の上限を設定し、無制限な入力を受けません。
Resolver worker 30s · batch 64 · retry 5 · depth 1024 未解決 chain を batch で再評価し、深さと再試行を制限します。
Audit runner 30s · batch 64 · attempts 10 監査 queue を bounded batch で処理します。

operator CLI

owner init、pipeline / process create、schema register、chain relationship 管理、organization verify / diagnose、bundle export / verify、evidence rotate を提供します。秘密鍵生成時は RFC 8037 OKP JWK を mode 0600 で保存します。

IMPLEMENTATION BOUNDARY

固定スナップショット時点であるものと、まだ前提にしないもの

0.x / PoC で確認できる実装だけを「実装済み」に置きます。段階導入は設計上の方向であり、利用可能性の約束ではありません。

実装済み

  • Source / Chained / Sink / Custom の process contract と NATS runtime
  • ConnectRPC の registry、chain、payload、schema、signer、tlog、audit、resolver services
  • Ed25519 Data Integrity、JCS、RDFC、strict signed-JSON decode
  • 3層の trust boundary と fail-closed な configuration validation
  • file-backed evidence、bundle export / offline verify、evidence rotation
  • health / readiness、任意の Prometheus metrics、standalone / operator binaries
  • DID login の既定は LEGACY_DID_LOGIN@1 — relationship-blind(DID Document の authentication / assertionMethod を検証せず、controller 一致の鍵で通す)。OWNER 契約(関係検証・三者 kid 一致・audience 必須)は main で配線済み — 現行リリース v0.2.1 には未収載で、次リリースに乗る

段階導入・対象外

  • JetStream、durable queue、retry / dead-letter、exactly-once delivery
  • ambiguous publish を排除するより強い配送契約と distributed nonce store
  • P-256 / P-384 signing、HSM / Vault / cloud KMS backend
  • Merkle inclusion / consistency proof を持つ production transparency log
  • database-backed registry や複数ノードでの control-state replication
  • 外部製品・規制フレームワーク向け adapter / connector
  • OWNER パスでの複数鍵 DID Document — controller 一致の verificationMethod を複数持つ document は ambiguous として fail-closed で拒否(鍵ローテーション中に遭遇し得る — follow-up)
  • HTTP push の ingest handle から生成された credential head への対応付け(既知の欠落 — 公開 E2E findings E2E-F-030)

release・互換性・運営の現在地

領域現在の状態判断時の扱い
Public release provin OSS v0.3.0 と公開 E2E v0.2.0 を公開済み。本ページの技術詳細は 2026-07-17 の固定スナップショットに基づく(その後 node は cmd/network + cmd/pipeline の 2 バイナリ構成へ再編 — CHANGELOG 参照)。 0.x / PoC のため、公開 artifact と E2E を対象環境で再検証して判断します。
Compatibility credential Data Integrity wire は固定。Go API、config、その他の signed view は 0.x 変更対象。凍結の範囲と強制方法は下記「wire freeze」節。 同じ「0.x」でも wire と API の安定性を分けて評価します。
Security maintenance 公開後は最新 minor line のみ assessment / fix 対象。SLA と bug bounty はありません。 production support 契約や backport を前提にしません。
Governance maintainer-led(1o1 Co. Ltd.)。GOVERNANCE.md が wire 変更(next-MAJOR)の手続きと maintainer 拡大の方針を定める。 複数組織の maintainer 体制は未達。手続きは GOVERNANCE.md を参照し、継続性は引き続き評価が必要です。
Operational evidence conformance vector、W3C vector、KAT、E2E test はあり、production soak と公開 benchmark はありません。 対象 topology と workload で再現試験を行います。

wire freeze — 凍結の範囲と強制方法

v0 credential Data Integrity wire — 署名に参加するすべてのバイト — は凍結済みです。凍結を担保するのは宣言やプロセスではなく、リポジトリ内のテスト(W3C 公式 vc-di-eddsa ベクタ、KAT、context の sha256 ピン)です。

凍結されているもの

  • credential の @context セット — W3C 規範 sha256 にピンした credentials/v2、埋め込み済みの dplaax.dev/vc/v1 と provin.dev/vc/v1
  • Data Integrity proof アルゴリズム — SHA-256(canon(proofConfig)) ‖ SHA-256(canon(document)) と base58btc の proofValue
  • 両 cryptosuite と canonicalization — eddsa-jcs-2022(RFC 8785)と eddsa-rdfc-2022(URDNA2015)。W3C 公式ベクタにアンカーし、URDNA2015 は KAT でも固定
  • source-commitment form — JCS 正規化した source credential 上の RFC 6962 Merkle tree hash と source_root エンコーディング
  • DID verification-method の読み取り契約 — OKP/Ed25519 JWK と Multikey

上記のいずれを変更しても発行済み credential との証明互換性が壊れるため、next-MAJOR 変更です。手続きは GOVERNANCE.md に定めます。

凍結の対象外(別契約で管理)

  • tlog checkpoint の SignedView
  • chain-manager / payload-resolver の wire-auth view
  • lifecycle log に記録する DID-document の JCS hash

それぞれ独自の golden test でピンされ、互換性に関わる変更は CHANGELOG に明記されます。何を凍結していないかまで明示できることが、凍結範囲の信頼性を支えます。

「元のシステムがなくなったあとも検証できる」という本サイトの主張は、この凍結がテストで固定されていることに立ちます。将来の検証可能性は実演できません — 根拠は、凍結範囲と強制方法が公開されていることです。

この境界は「拡張できる」と「今使える」を混同しないためのものです。導入判断では、固定コミットと対象環境での検証を行ってください。

固定コミットを GitHub で開く