01
Control plane
DID、鍵、スキーマ、チェーン関係、監査を ConnectRPC サービスとして公開します。状態は YAML とファイルに置き、レジストリ専用ノードとしても起動できます。
source ↗SYSTEM SHAPE
standalone ノードは、登録・調整を行う制御面と、イベントを処理するデータ面を一つの設定から組み立てます。両方を横断して残る証跡は、稼働中のノードから切り離して検証できます。※ standalone 構成はこのスナップショット時点のもの — その後退役し、現行 main は cmd/network + cmd/pipeline の 2 バイナリ構成(CHANGELOG 参照)。
01
DID、鍵、スキーマ、チェーン関係、監査を ConnectRPC サービスとして公開します。状態は YAML とファイルに置き、レジストリ専用ノードとしても起動できます。
source ↗02
Source / Chained / Sink / Custom のプロセスが NATS 上でイベントを受け渡し、検証・変換・署名を繰り返します。各プロセスは同じ契約に従う対等な構成要素です。
source ↗03
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
入力を受けてから次へ発行するまでの順序は、来歴の連続性と payload の同一性を崩さないための実行契約です。途中で検証不能になった入力は次の credential を生成しません。
直前区間の Data Integrity、署名者、chain consistency を評価します。
後からの検証に必要な ingress credential を同期的に保持し、保存できなければ失敗します。
inline または by-reference の payload を取り出します。
payload の SHA-256 と credential が宣言した content hash を比較します。
設定されている場合に、変換前の構造を検証します。
JSONata filter を順に評価し、不一致は意図的な drop として記録します。
JSONata converter で一つの入力を一つの出力へ変換します。
設定されている場合に、変換後の構造を検証します。
duplicate key と trailing data を拒否し、数値を json.Number のまま扱います。
処理前後をそれぞれ content-addressed な値に固定します。
previousCredential を一つだけ引き継ぎ、線形な chain を伸ばします。
observer を呼び出してから primary subject へ発行し、成功後に emission log を追記します。
producing process が次へ進めるのは ConfidenceVerified だけです。failed と indeterminate はエラーとして閉じます。
core NATS への publish と flush は broker 受領までを確認しますが、consumer 再配信や永続化は行いません。
publish 後、log 追記前の停止は「配送済み・未記録」の gap を残します。file log は事前に durable intent を記録するため番号を再利用しませんが、broker 受領後の flush timeout は「失敗」と見えて番号が再利用される余地があります。
CONCRETE SAMPLE
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] を満たす線を伸ばします。
この 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
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 ↗ RFC 8785 JCS で JSON を canonicalize し、Ed25519 で署名します。Phase 1 の必須 suite です。
埋め込み context と URDNA2015 を用いる RDFC suite。runtime の外部 context fetch は禁止されています。
duplicate key、trailing data、暗黙な float64 化を避けます。lint が signed JSON の decode path を一つに制限します。
previousCredential は常に単数です。payload は埋め込まず、input / output hash により内容を結びます。
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 を閉じます。 |
o3co は JWT を検証します。OPA は policy 自身が認証を担う構成、Cedar は raw bearer principal を受ける構成、static は token の存在または allow-list を見るだけです。backend 名だけで同じ認証強度を仮定しません。
署名後の 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 は初回公開後の課題です。
CONFIGURATION & EVIDENCE
provin node は YAML / files だけでも動作し、storage / PDP は interface で差し替えられます。設定、制御状態、証跡、短命状態を分け、選択する auth provider、PDP、adapter の外部依存を個別に組み合わせます。
配布物に埋め込む完全な既定値。Go コード側に隠れた default を置きません。
ノード固有の任意設定。存在すると既定値を上書きします。
指定された環境 overlay を最後に合成し、最終値を typed config へ decode します。
DID、pipeline / process、schema、chain 設定などの registry 状態。
credential variant、resolution pool、audit queue / verdict、receipt、sink reject。credential は content-addressed かつ append-only です。
wire-auth nonce など。restart epoch barrier で再起動をまたぐ replay を閉じますが、複数ノードで共有する nonce store ではありません。
provin bundle export が credential と依存証拠をまとめ、provin bundle verify がネットワークアクセスなしで検証します。JSON-LD context も binary に埋め込まれています。evidence は削除・変更せず、cold archive への rotate を行います。
source ↗現在は 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 で処理します。 |
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 で確認できる実装だけを「実装済み」に置きます。段階導入は設計上の方向であり、利用可能性の約束ではありません。
| 領域 | 現在の状態 | 判断時の扱い |
|---|---|---|
| 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 で再現試験を行います。 |
v0 credential Data Integrity wire — 署名に参加するすべてのバイト — は凍結済みです。凍結を担保するのは宣言やプロセスではなく、リポジトリ内のテスト(W3C 公式 vc-di-eddsa ベクタ、KAT、context の sha256 ピン)です。
上記のいずれを変更しても発行済み credential との証明互換性が壊れるため、next-MAJOR 変更です。手続きは GOVERNANCE.md に定めます。
それぞれ独自の golden test でピンされ、互換性に関わる変更は CHANGELOG に明記されます。何を凍結していないかまで明示できることが、凍結範囲の信頼性を支えます。
「元のシステムがなくなったあとも検証できる」という本サイトの主張は、この凍結がテストで固定されていることに立ちます。将来の検証可能性は実演できません — 根拠は、凍結範囲と強制方法が公開されていることです。
この境界は「拡張できる」と「今使える」を混同しないためのものです。導入判断では、固定コミットと対象環境での検証を行ってください。
固定コミットを GitHub で開く