三浦商店 施工事例検証システム 技術仕様書 v4

文書ID: miura-verification-spec-v4
公開予定場所: /verification/spec/v4/
想定公開日: 2026-03-29 JST
ステータス: v4 — 公開後は変更しない。改定時は v5 を新設する。
運営者: 有限会社三浦商店(宮城県黒川郡大和町)


0. 本文書の位置づけ

本文書は、三浦商店が公開する施工事例記事と /verification/ 配下の公開 artifact の対応関係を、第三者が検証できるように記述する公開技術仕様書である。

v3 からの最大の変更点は次の3つである。

  1. bundle_manifest.json における C2PA Phase 1 公開レーンを正式に記載する
  2. 記事 HTML における c2pa-proof/1 render-time injection を公開契約として追加する
  3. photo-proof/1manifest.json v2 の固定キー集合を維持したまま、C2PA 情報を additive に公開する

本文書は公開仕様であり、内部運用の全詳細や内部証拠束の構成は記述しない。


1. 目的と適用範囲

1.1 目的

本仕様書の目的は、施工事例記事に対応する写真・動画の公開 artifact、ハッシュ連鎖、OpenTimestamps(OTS)による時刻証明、ならびに C2PA 由来の provenance disclosure を、第三者が再現可能な形で示すことである。

1.2 適用範囲

本仕様書は以下に適用される。

1.3 本仕様書が記述しないもの

以下は本仕様書の範囲外とする。

1.4 規範語

本文書中の MUST / MUST NOT / SHOULD / SHOULD NOT / MAY は RFC 2119 的な規範語として用いる。


2. バージョン方針と不変原則

2.1 不変原則

2.2 v4 の設計原則


3. 用語定義

3.1 canonical artifact

一度公開したら変更しないファイル群。ハッシュ連鎖および OTS 整合の対象となる。

本仕様での canonical artifact:

3.2 auxiliary artifact

公開検証を補助するが canonical root ではない公開 artifact。

例:

3.3 JOB_ID

案件を識別する文字列。一般形は次のとおり。

{YYYY-MM-DD}_{description}_{suffix}

例: 2026-03-28_oil-waterheater_upload

3.4 WP_JOB_META_KEY

WordPress 側で JOB_ID を保持する post meta key。canonical は _miura_job_id

3.5 exact bytes

HTTP 取得またはローカル保存されたファイルの正確なバイト列。改行コード、インデント、空白、文字コード変換を含め、1 バイトでも変われば別物とみなす。

3.6 published subset

公開対象として残った写真集合。C2PA internal 検証結果全件ではなく、公開 artifact に載る集合を指す。

3.7 validation_status_public

C2PA 公開表示用の簡約 enum。

3.8 photo-proof/1

manifest.json v2 から render-time に組み立てる画像検証用 render object。Miura 独自の公開 JSON であり、canonical artifact ではない。

3.9 c2pa-proof/1

bundle_manifest.jsonc2pa_provenancebundle_core.source_assets[] から render-time に組み立てる公開 provenance disclosure object。Miura 独自の公開 JSON であり、標準 C2PA Manifest そのものではない

3.10 c2pa_provenance

bundle_manifest.json の top-level に置かれる C2PA job summary。bundle_core の外側にあり、bundle_chain_hash の計算対象外だが、bundle_manifest.json 全体に対する OTS stamp の対象には含まれる。


4. 公開アーキテクチャ概要

本システムの公開アーキテクチャは、写真系 canonical artifact、bundle root、OTS receipt、記事 HTML への render-time injection の 4 層から成る。

[施工事例記事 HTML]
  └─ render-time injection
      ├─ photo-proof/1
      ├─ c2pa-proof/1   (C2PA 対応案件のみ)
      ├─ BlogPosting JSON-LD
      └─ video-proof     (動画案件のみ)

[verification/jobs/{JOB_ID}/bundle_manifest.json]   ← canonical root
  ├─ bundle_core.photo.manifest_sha256
  ├─ bundle_core.source_assets[]                    ← C2PA public minimal lane
  ├─ bundle_chain_hash
  └─ c2pa_provenance                               ← C2PA job summary lane

[verification/jobs/{JOB_ID}/manifest.json]         ← canonical photo artifact
  └─ images[].sha256                               ← 公開画像ごとの SHA-256

[verification/ots/{JOB_ID}.bundle_manifest.json.ots]
  └─ bundle_manifest.json の exact bytes に対する時刻証明

5. ハッシュ連鎖と時刻証明

5.1 基本連鎖

[Bitcoin blockchain]
    ↑ OTS receipt が証明
[bundle_manifest.json]
    ├─ bundle_core.photo.manifest_sha256 = SHA-256(manifest.json の exact bytes)
    ├─ bundle_core.photo.chain_hash
    ├─ bundle_core.source_assets[]       = C2PA public minimal lane
    ├─ c2pa_provenance                   = C2PA job summary lane
    └─ bundle_chain_hash                 = SHA-256(normalize(bundle_core))
[manifest.json]
    └─ images[].sha256                   = 各公開画像ファイルの SHA-256

5.2 bundle_chain_hash

bundle_chain_hashbundle_core に JSON 正規化(sort_keys + compact separators による決定論的シリアライズ。RFC 8785 を参考にした方式)を適用した結果の SHA-256 である。
したがって bundle_core.source_assets[]bundle_chain_hash の計算対象に 含まれる

5.3 c2pa_provenance の位置づけ

c2pa_provenancebundle_core外側にあるため、bundle_chain_hash の計算対象には 含まれない
ただし bundle_manifest.json 全体の exact bytes に対して OTS receipt が発行されるため、c2pa_provenance の値は OTS の時刻証明対象に 含まれる

5.4 exact bytes 原則

次の整合確認は、すべて exact bytes に対して行う。


6. 公開ディレクトリ構造

https://miurast.com/verification/
├── spec/
│   ├── v1/
│   ├── v2/
│   ├── v3/
│   └── v4/                          ← 本仕様書
├── spec/workflow-v2/                ← 公開ワークフローノート v2
├── jobs/
│   └── {JOB_ID}/
│       ├── bundle_manifest.json     ← canonical
│       ├── manifest.json            ← canonical
│       ├── video_proof_public.json  ← canonical(動画案件のみ)
│       └── google_ca.pem            ← trust anchor disclosure 用 PEM
└── ots/
    ├── {JOB_ID}.bundle_manifest.json.ots
    └── {JOB_ID}.bundle_manifest.json.onchain_hinted.json   ← 任意

7. canonical artifact 仕様

7.1 manifest.json(画像-only 正本)

schema は miura-photo-manifest-public/2schema_version=2 とする。

top-level 必須キー

images[] 必須キー

重要契約

7.2 bundle_manifest.json

bundle_manifest.json は案件全体の canonical root であり、OTS receipt の対象とする。

最低限の論理構造

7.3 video_proof_public.json

動画案件に限り存在する canonical artifact。動画の詳細スキーマは本仕様書では簡略記載に留める。


8. C2PA Phase 1 公開統合

8.1 基本方針

v4 では C2PA 公開統合を Phase 1 まで正式化する。
Phase 1 の公開面は次の 3 点で構成される。

  1. bundle_core.source_assets[]
  2. top-level c2pa_provenance
  3. 記事 HTML への c2pa-proof/1 render-time injection

8.2 bundle_core.source_assets[]

bundle_core.source_assets[] は C2PA の公開最小版 provenance 接続である。

1 entry の必須キー

契約

8.3 top-level c2pa_provenance

c2pa_provenance は公開 bundle 単体で trust anchor の所在と job summary を self-describing にする。

必須キー

job_provenance_summary 必須キー

trust_anchors 必須キー

契約

8.4 validation_status_public の意味

8.5 job_mode

公開案件では、invalid は通常 published subset に乗らない。
したがって public 側で job_mode="mixed" を確認したい場合は、通常 valid + missing の組み合わせになる。

8.6 historical jobs

過去 job の canonical artifact は書き換えない。
pre-C2PA job や C2PA 非対応 job は、photo-proof/1BlogPosting JSON-LD を出し続けてもよいが、c2pa-proof/1 は出さない。


9. render-time injection 契約

9.1 基本方針

編集・生成の対象は本文 HTML(body)であり、verification JSON や BlogPosting JSON-LD を毎回手書きしない。
最終レンダリング HTML では WordPress / function が _miura_job_id を起点に公開検証 artifacts を読み、必要な render object を注入する。

9.2 必須 render object

写真がある案件では、最終レンダリング HTML に少なくとも次が存在しなければならない。

C2PA 対応案件では追加で次が存在しなければならない。

動画案件では必要に応じて次を追加してよい。

9.3 verification artifact block

最終レンダリング HTML では、verification 系 script tag を論理的にひとまとまりとして出力してよい。
ただし 相対順序自体は semantic contract としない。意味上重要なのは、各 object が 1 回ずつ存在し、内容が canonical artifact と整合することである。

9.4 photo-proof/1

photo-proof/1manifest.json v2 から render-time に組み立てる。

top-level 必須キー

images[] 必須キー

9.5 c2pa-proof/1

c2pa-proof/1bundle_manifest.json から render-time に組み立てる Miura 独自の public disclosure object とする。

出力条件

次の両方を満たすときのみ出力する。

どちらかが欠ける場合、c2pa-proof/1 は出力しない。

HTML 形

<script type="application/json"
        class="c2pa-proof"
        data-miura-managed="1"
        data-actor="c2pa-proof"
        data-version="c2pa-proof/1">
{ ... }
</script>

top-level 必須キー

artifacts 必須キー

images[] 必須キー

images[] optional キー

9.6 c2pa-proof/1 の意味

c2pa-proof/1標準 C2PA manifest の代替物ではない
これは、Miura の公開 bundle に記録された C2PA Phase 1 情報を、記事 HTML から機械可読に参照できるようにする disclosure object である。

9.7 script 安全性

HTML に注入する JSON script は、</script> を安全にエスケープしなければならない。


10. third-party verification procedure

第三者は以下の手順で検証できる。

10.1 記事 HTML の取得

  1. 施工事例ページ HTML を取得する
  2. photo-proof/1BlogPosting JSON-LD、必要時 c2pa-proof/1 を抽出する
  3. c2pa-proof/1 がある場合は job_idartifacts を読む

10.2 canonical artifact の取得

  1. bundle_manifest.json
  2. manifest.json
  3. {JOB_ID}.bundle_manifest.json.ots
  4. 必要に応じて google_ca.pem
  5. 動画案件では video_proof_public.json

10.3 photo chain の確認

  1. manifest.json の exact bytes の SHA-256 を計算する
  2. bundle_core.photo.manifest_sha256 と一致することを確認する
  3. 公開画像ファイルの SHA-256 を再計算し、manifest.json.images[].sha256 と照合する(SHOULD — 完全な検証にはこの手順を含めるべきである)

10.4 bundle chain の確認

  1. bundle_core に JSON 正規化(§5.2 と同じ方式)を適用する
  2. SHA-256 を計算し、bundle_chain_hash と照合する

10.5 OTS の確認

  1. bundle_manifest.json の exact bytes と .ots receipt を用意する
  2. OTS client で verify する
  3. ローカル Bitcoin node を使う verify が最も強い検証になる

10.6 C2PA disclosure の確認

c2pa-proof/1 がある場合:

  1. c2pa-proof/1.job_provenance_summarybundle_manifest.json.c2pa_provenance.job_provenance_summary が整合すること
  2. c2pa-proof/1.images[]bundle_core.source_assets[]seq 集合が整合すること
  3. trust_anchors.pem_url_or_rel で指された PEM の SHA-256 が、公開された trust_anchors_sha256 と一致すること
  4. published_asset_sha256 がある場合、photo-proof/1.images[] の同一 seqsha256 と一致すること(MAY — 撮影原本から公開画像への対応を cross-check する補助手段)

10.7 検証結果の意味

これらを合わせることで、公開後の差し替え困難性と source provenance disclosure の両方を第三者が確認できる。

C2PA disclosure の検証限界について: c2pa-proof/1 は、Miura が内部で実施した C2PA 検証の結果を公開する disclosure object である。撮影原本 JPEG はプライバシー保護のため非公開であるため、第三者が原本 JPEG を入手して C2PA 署名検証を独立に再現することはできない。 ただし、disclosure の内容は bundle_manifest.json に記録され、その exact bytes は OTS で Bitcoin にアンカーされている。したがって、disclosure の内容を事後的に改変することは困難である。 将来、Phase 2 で AVIF に対する C2PA sidecar を公開配置した場合、第三者は公開 AVIF と sidecar を使って AVIF レベルでの C2PA 検証を独立に実行できるようになる。


11. backward compatibility と fail-closed

11.1 pre-C2PA / non-C2PA 案件

11.2 C2PA 対応案件

11.3 public fail-closed

次のようなケースでは c2pa-proof/1 を public 非出力に落としてよい。

ただし、PEM 不在や hash 契約違反のような公開直前の致命条件は、生成工程側では hard fail とするのが望ましい。

field-level degradation: published_asset_sha256 は optional helper field であり、manifest.json の hash 照合(bundle_core.photo.manifest_sha256 との一致)、schema 検証、job_id 一致、image_count 一致、duplicate seq 拒否のいずれかに失敗した場合は null に落とす。この場合も bundle_manifest.json 側の C2PA public lane(source_assets[] + c2pa_provenance)が健全であれば、c2pa-proof/1 自体は継続出力してよい。


12. セキュリティ・プライバシー・表現上の注意

12.1 公開禁止情報

public artifact および render object に次を含めてはならない。

12.2 C2PA の表現

C2PA 情報を表示または公開する際は、「真正であると断定する UI」ではなく、「Content Credentials / provenance 情報があることを示し、利用者が判断できる材料を出す UI」を採るべきである。

12.3 BlogPosting JSON-LD

BlogPosting は SEO / structured data のための object であり、photo-proof や c2pa-proof と意味が異なる。
identifier 系の連携は整合必須だが、BlogPosting は canonical artifact ではない。


13. out of scope / future extension

13.1 Phase 2A derivative provenance

Phase 2A の c2pa_derivative_provenance、AVIF / MP4 sidecar、durable discovery は v4 の範囲外とする。
将来版では別レーンとして追加し得るが、v4 では public contract に固定しない。

13.2 visible badge / detail table

画像横の C2PA バッジ、一覧表、モーダル UI、tooltip は v4 の範囲外である。
v4 では machine-readable JSON の公開までを固定する。

13.3 photo-proof/1 / manifest.json v2 の C2PA 拡張

v4 では行わない。
C2PA 公開 disclosure は c2pa-proof/1bundle_manifest.json 側で扱う。


14. 公開適合チェックリスト

14.1 記事側

14.2 bundle / manifest 側

14.3 C2PA 側


15. informative references