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

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


本文書は検証可能性のために公開している。


1. 目的と適用範囲

1.1 目的

本仕様書は、三浦商店が公開する施工事例記事に付随する「写真・動画の検証情報」の公開構造を記述する。

本仕様書の目的は、公開時点の施工写真・施工動画と公開 artifact の対応関係、および公開後に canonical artifact が差し替えられていないことを、第三者が検証可能な形で示すことである。

1.2 適用範囲

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

2025年12月26日より前に公開された記事は、本仕様書の適用対象外とする。

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

以下は本仕様書の範囲外である。


2. 用語定義

canonical artifact

一度公開したら変更しないファイル群。ハッシュ連鎖の対象であり、変更すると OTS による時刻証明との整合が失われる。以下の3種類が該当する。

receipt lane

OpenTimestamps (OTS) が生成する時刻証明ファイル。canonical artifact のうち bundle_manifest.json の正確なバイト列に対して発行される。

non-canonical artifact

検証の補助情報として公開しているが、ハッシュ連鎖の root ではないファイル。canonical artifact と同列には扱わない。

legacy artifact

現行の canonical 構造に移行する前の旧形式ファイル。/verification/ots/ に混在している場合がある。

sidecar

canonical artifact とは別に配置される補助ファイルの総称。canonical artifact を変更せず、補正情報や検証サマリを提供する。

JOB_ID

各施工案件を識別する文字列。命名規則は以下のとおり。

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

実例: 2026-03-08_toilet-reform_upload

SHA-256

NIST FIPS 180-4 で規定されるハッシュ関数。本システムでは全てのハッシュ値に SHA-256 を使用する。表記は小文字16進数64桁。

OTS (OpenTimestamps)

Bitcoin ブロックチェーンを利用した分散型タイムスタンプ・プロトコル。任意のデータのハッシュ値を Bitcoin トランザクションに埋め込むことで、そのデータがその時点で存在していたことを証明する。

VCL (Verified Construction Log)

三浦商店が施工写真・動画の公開記録と検証情報の対応関係を管理するために用いる記録方式の名称。施工事例記事の HTML には、対応する公開 artifact への参照情報を含む VCL 用の構造化データが埋め込まれている。

JCS (JSON Canonicalization Scheme)

RFC 8785 で規定される JSON の正規化方式。本システムでは bundle_chain_hash の計算に使用する。

正確なバイト列(exact bytes)

HTTP 取得またはローカル保存されたファイルのバイト列そのものをいう。改行コード、空白、文字コード変換を含め、1バイトでも変われば別物として扱う。


3. ハッシュ連鎖の構造

本システムの中核は、以下のハッシュ連鎖である。

[Bitcoin blockchain]
    ↑ OTS receipt (.ots) が証明
[bundle_manifest.json]
    ├─ bundle_core.photo.manifest_sha256 = SHA-256(manifest.json の正確なバイト列)
    ├─ bundle_core.photo.chain_hash      = 写真系 chain 値
    ├─ bundle_core.video.proof_sha256    = SHA-256(video_proof_public.json の正確なバイト列)  ※動画案件のみ
    └─ bundle_chain_hash                 = SHA-256(JCS(bundle_core))
[manifest.json]
    └─ images[].sha256 = 各公開画像ファイルの SHA-256
[video_proof_public.json]  (動画案件のみ)
    └─ bundle_core.video.* から参照

3.1 連鎖の意味

bundle_manifest.json を OTS が stamp しており、その内部フィールド bundle_core.photo.manifest_sha256manifest.json の SHA-256 を保持している。

したがって、以下が成立する。

この連鎖により、OTS の時刻証明が manifest.json の各画像 SHA-256 まで間接的に及ぶ。

3.2 適用範囲

bundle_chain_hash は、top-level JSON 全体ではなく bundle_core オブジェクトに対して JCS を適用した結果から計算する。

3.3 正確なバイト列の原則

以下の SHA-256 はすべて正確なバイト列に対して算出する。

3.4 chain_hash

chain_hashbundle_manifest.jsonbundle_core.photo.chain_hash および動画案件の bundle_core.video.chain_hash に記録される値である。詳細生成手順は本仕様書の範囲外とする。


4. 公開データ層の生成概要

本章は、公開 artifact 間の生成関係だけを記述する。内部証拠束の生成手順や内部運用は含めない。

4.1 入力

公開データ層における入力は次のとおりである。

4.2 処理概要

公開データ層における bundle_manifest.json 生成の概略は次のとおりである。

1. manifest_sha256 = SHA-256(manifest.json の正確なバイト列)

2. bundle_core.photo を構成する
   - chain_algo
   - chain_hash
   - manifest_sha256
   - url_or_rel

3. 動画案件では proof_sha256 = SHA-256(video_proof_public.json の正確なバイト列)

4. 動画案件では bundle_core.video を構成する
   - chain_algo
   - chain_hash
   - proof_sha256
   - url_or_rel

5. bundle_chain_hash = SHA-256(JCS(bundle_core))

6. bundle_manifest.json を生成する

7. bundle_manifest.json の正確なバイト列に対して OTS receipt を取得する

4.3 出力

この処理の出力は次のとおりである。

4.4 不変条件

以下は公開データ層における不変条件である。


5. sidecar の位置付け

canonical artifact は immutable であるため、補正や追加情報は sidecar で提供する。本仕様書では次の2種を区別する。

5.1 sidecar の2種類

ファイル 目的 現在の状態
bundle_manifest.json.verify.json OTS receipt の検証サマリ optional(未配備の案件あり)
photo-proof-sidecar-v1.json timezone 等の補正情報 未実装

5.2 重要な区別

この2種類の sidecar は目的が異なる。

いずれも canonical artifact を変更するものではなく、canonical artifact と並置する補助ファイルである。

5.3 本仕様書での扱い

photo-proof-sidecar-v1.json は本仕様書の公開時点で未実装であるため、スキーマの詳細は記載しない。

bundle_manifest.json.verify.json は全案件に配備されているわけではない。配備済み案件では、OTS の検証状態を確認する補助として参照できる。


6. 公開 artifact の構成

6.1 ディレクトリ構造

https://miurast.com/verification/
├── (検証方針ページ / WordPress 固定ページ)
├── spec/
│   ├── v1/
│   ├── v2/
│   └── v3/                            ← 本仕様書(immutable permalink)
├── jobs/
│   └── {JOB_ID}/
│       ├── bundle_manifest.json       ← canonical
│       ├── manifest.json              ← canonical
│       └── video_proof_public.json    ← canonical(動画案件のみ)
└── ots/
    ├── {JOB_ID}.bundle_manifest.json.ots                    ← receipt (current)
    ├── {JOB_ID}.bundle_manifest.json.onchain_hinted.json    ← non-canonical
    └── {JOB_ID}.manifest.json.ots                           ← legacy receipt(一部案件)

6.2 各 artifact の役割

bundle_manifest.json

案件全体の証明情報を束ねるルートファイル。OTS receipt の対象である。

URL: /verification/jobs/{JOB_ID}/bundle_manifest.json

主要フィールド:

フィールド 内容
bundle_core.photo.manifest_sha256 manifest.json の正確なバイト列の SHA-256
bundle_core.photo.chain_hash bundle_manifest.json に記録される写真系 chain 値
bundle_core.video.proof_sha256 video_proof_public.json の正確なバイト列の SHA-256
bundle_chain_hash SHA-256(JCS(bundle_core))
bundle_chain_algo ハッシュ連鎖のアルゴリズム識別子

manifest.json

各公開画像の SHA-256 一覧を保持するファイル。bundle_manifest.json から manifest_sha256 で参照される。

URL: /verification/jobs/{JOB_ID}/manifest.json

主要フィールド:

フィールド 内容
images[] 公開画像の配列
images[].seq 画像の順序番号(安定キー)
images[].sha256 画像ファイルの SHA-256
images[].shot_at 撮影日時
images[].url_or_rel 公開ファイルの URL または相対パス

video_proof_public.json

動画案件の証明情報。動画案件にのみ存在する。画像のみの案件には存在しない(HTTP 404 を返す)。

URL: /verification/jobs/{JOB_ID}/video_proof_public.json

{JOB_ID}.bundle_manifest.json.ots

OpenTimestamps が bundle_manifest.json の正確なバイト列に対して発行した receipt。バイナリ形式。

URL: /verification/ots/{JOB_ID}.bundle_manifest.json.ots

Content-Type: application/octet-stream

{JOB_ID}.bundle_manifest.json.onchain_hinted.json

OTS の Bitcoin アンカー情報を人間可読な JSON に変換したもの。non-canonical であり、ハッシュ連鎖の root ではない。

URL: /verification/ots/{JOB_ID}.bundle_manifest.json.onchain_hinted.json

6.3 VCL参照情報

各施工事例記事の HTML には、VCL に対応する構造化データが埋め込まれている。この構造化データは対応する /verification/jobs/{JOB_ID}/ 配下の artifact への参照情報を含み、記事ページから検証情報への導線を提供する。

第三者が検証を行う場合、記事ページ内の VCL 参照情報から JOB_ID を取得し、第7章の手順に進む。

6.4 /verification/ots/ の mixed legacy 状態

/verification/ots/ には次の3種類のファイルが混在しうる。

パターン 分類 説明
{JOB_ID}.bundle_manifest.json.ots current 現行の canonical receipt
{JOB_ID}.bundle_manifest.json.onchain_hinted.json non-canonical Bitcoin アンカー情報(互換用)
{JOB_ID}.manifest.json.ots legacy 旧形式 receipt

legacy receipt は、現行のハッシュ連鎖構造に移行する前に発行されたものであり、新規案件には生成されない。


7. 第三者による検証手順

検証の入口は、施工事例記事内の VCL 参照情報から JOB_ID を取得するか、/verification/ ページから対象の JOB_ID を特定することである。

7.1 基本検証(ハッシュ連鎖の確認)

  1. /verification/jobs/{JOB_ID}/bundle_manifest.json を取得する
  2. /verification/jobs/{JOB_ID}/manifest.json を取得する
  3. manifest.json の正確なバイト列の SHA-256 を計算する
  4. bundle_manifest.json 内の bundle_core.photo.manifest_sha256 と比較する
  5. 一致すれば、manifest.jsonbundle_manifest.json が参照する内容と同一である

7.2 画像の検証

  1. manifest.jsonimages[] から対象画像の sha256url_or_rel を取得する
  2. url_or_rel で示される公開画像ファイルをダウンロードする
  3. ダウンロードした画像の SHA-256 を計算する
  4. manifest.json に記載された sha256 と比較する
  5. 一致すれば、その画像は manifest.json に記録された内容から変更されていない

7.3 動画案件の公開証明ファイルの検証

  1. 動画案件では /verification/jobs/{JOB_ID}/video_proof_public.json を取得する
  2. video_proof_public.json の正確なバイト列の SHA-256 を計算する
  3. bundle_manifest.json 内の bundle_core.video.proof_sha256 と比較する
  4. 一致すれば、その video_proof_public.jsonbundle_manifest.json が参照する内容と同一である

7.4 OTS による時刻証明の検証

  1. /verification/ots/{JOB_ID}.bundle_manifest.json.ots を取得する
  2. OpenTimestamps のクライアント(ots verify コマンド等)で検証する
  3. OTS が bundle_manifest.json に対する有効な時刻証明を返せば、その bundle_manifest.json はその時点で存在していたことが証明される
  4. 7.1 および 7.3 の連鎖により、manifest.jsonvideo_proof_public.json(動画案件のみ)も間接的にその時点での存在が証明される

8. 検証の限界

本システムが証明するのは以下である。

本システムが証明しないのは以下である。


9. 既知の制約

9.1 /verification/ ページの curl 403

2026-03-18 時点で、https://miurast.com/verification/curl によるアクセスに対して HTTP 403 を返した。通常の User-Agent および browser-like User-Agent のいずれでも 403 であった。

ブラウザからの通常アクセスでは正常に表示された。

/verification/jobs/ および /verification/ots/ 配下の artifact ファイルは curl で正常に取得できた(HTTP 200)。

9.2 OTS のアンカー状態

全ての案件の OTS receipt が Bitcoin ブロックチェーンへのアンカーを完了しているとは限らない。発行直後の receipt は pending 状態である場合がある。

onchain_hinted.json は non-canonical であり、この情報の有無や状態は canonical な証拠連鎖の有効性に影響しない。

9.3 shot_at のタイムゾーン表記

一部の案件で、manifest.jsonimages[].shot_at にタイムゾーンオフセット(+09:00 等)が付与されていない場合がある。これは EXIF 由来のデータがオフセットを含まないことに起因する。

canonical artifact の immutable 原則により、この値は manifest.json 内で変更しない。補正が必要な場合は sidecar で対応する。

9.4 /verification/ots/ の mixed legacy 状態

旧形式 receipt と current receipt が混在している場合がある。これは移行過程の状態であり、新規案件では current 形式のみを生成する。


10. 公開記録

10.1 仕様書 URL の固定

本仕様書は /verification/spec/v3/ に固定 URL で公開する。

10.2 公開日時の記録

本仕様書の公開日時は、公開ページ本体、freeze、または付随する記録ファイルで保持する。

10.3 仕様書ファイルのハッシュ

必要に応じて、仕様書本体または関連公開ファイルの SHA-256 を別ファイルで記録する。


11. 代表案件の簡易実例

以下は、2026-03-18 に取得・検証した代表案件の簡易確認例である。

11.1 動画案件: 2026-03-08_toilet-reform_upload

対応公開ページ:
https://miurast.com/jutaku/toilet-replace-drain-trouble-taiwa-20260216/

artifact の取得可否例:

URL HTTP status 分類
/verification/jobs/2026-03-08_toilet-reform_upload/bundle_manifest.json 200 canonical
/verification/jobs/2026-03-08_toilet-reform_upload/manifest.json 200 canonical
/verification/jobs/2026-03-08_toilet-reform_upload/video_proof_public.json 200 canonical(動画)
/verification/ots/2026-03-08_toilet-reform_upload.bundle_manifest.json.ots 200 receipt
/verification/ots/2026-03-08_toilet-reform_upload.bundle_manifest.json.onchain_hinted.json 200 non-canonical

簡易確認値:

項目
bundle_core.photo.manifest_sha256 298425cda18f810603dced1ff7f7b02c7d5b6cc739f3eac633ca99a0524977d9
manifest.json 実ファイルの SHA-256 298425cda18f810603dced1ff7f7b02c7d5b6cc739f3eac633ca99a0524977d9
bundle_chain_hash f24ff1f86967be1737ba80779110907ca5a468d22feef9ccd948ce4690214bed
判定 一致

bundle_chain_hash は、対応する bundle_manifest.json を取得すれば確認できる。


12. 変更履歴

日付 内容
v1 2026-03-18 初版
v2 2026-03-18 文言整理。現行公開物に整合
v3 2026-03-20 公開データ層の生成概要、正確なバイト列の原則、動画案件の公開証明ファイル検証、chain_hash の範囲外明記、公開記録を追記。JSON 全文ダンプを簡略化