第10巻 内部設計書(2) ― I/F契約とデータ辞書
目次
- 第12章 I/F契約・データ辞書 <a id="appendix-a-if"></a>
- 12.1 cmd/event一覧(正本)
- 12.2 共通ヘッダ(全cmd/event:固定)
- 12.3 データ辞書(最小十分:揉めどころ固定)
- 12.4 idempotency_key のスコープ(規範)
- 12.5 command_seq / event_seq の粒度(規範)
- 12.6 署名対象(signed_fields)と正規化(canonicalization)(規範)
- 12.7 パラメータ統制(公開版)
- 12.8 対象カテゴリ(例)
- 12.9 PR-* パラメータ台帳 <a id="pr-params"></a>
第10巻 内部設計書(2) ― I/F契約とデータ辞書
本巻は
docs/specs/30_internal_design.mdの第12章(I/F契約・データ辞書)を収める。前巻→第9巻の続き、続きは→第11巻。
第12章 I/F契約・データ辞書
本章以降(第12〜16章)は、実装・検証のための静的参照(スキーマ、型、制約、コード表、レーン詳細)である。
本章は規範(Normative) であり、実装・運用・監査・契約の前提として固定される。
ここに無いものは「実装しても良いが、制度・接続の共通基盤として保証しない」。
採番について(旧付録記号の廃止):かつて独立していた付録A〜Iは本章以下の章番号ベースの節番号(
12.1,13.1, …)へ移行済みである。旧記号は本書群では使用しない。対応は次のとおり。
旧記号 現節 内容 付録A(A.0〜A.2) §12.1〜§12.3 I/F契約:cmd/event一覧・共通ヘッダ・データ辞書 (新設) §12.4〜§12.6 冪等キーのスコープ・seq の粒度・署名対象と正規化 付録D(D.0〜D.2) §12.7〜§12.9 パラメータ統制・対象カテゴリ・PR-* 台帳 付録E §13.1〜§13.6 主要メッセージのボディ定義 付録F §14.1〜§14.3 LSM(Bulk向け流動性節約)詳細 付録G §15.1〜§15.6 HTLC(hashlock+timelock)詳細 付録H §16.1〜§16.3 Raft運用(合意ログ)詳細 付録I 20_method_design.md§10.10CASE(例外収束)運用テンプレ 付録B・付録C 廃止 用語は 10_requirements.md序章「Zenith 独自用語ミニディクショナリー」を参照
12.1 cmd/event一覧(正本)
本表は ZC ⇄ 参加行のあいだで交換する cmd/event 名の正本である。他文書のシーケンス図・本文が
名指すメッセージは、すべて本表に存在しなければならない。
FinalityLog の
event_typeとは別の語彙である。 本表は「線の上を流れる電文」の名前を固定する。FinalityLog に追記される監査イベントの語彙はこれより広く(ZC 内部のライフサイクル事実を含む)、
その正本は
src/types/api/messaging.ts#FinalityEventTypeである。両者の関係は §12.1.6 に示す。
12.1.1 取引ライフサイクル(TX / GTID / RTP / PSPR / CASE)
| name | type | producer → consumer | aggregate | 再送条件(例) | 配送 | 順序制約 |
|---|---|---|---|---|---|---|
| TxReceived | EVENT | ZC → Banks | TX:{txid} | 再送可 | at-least-once | txid内でevent_seq単調 |
| PaymentInitiated | EVENT | PayerBank → ZC | TX:{txid} | ACK未達/timeout | 同上 | txid内でevent_seq単調 |
| NameCheckRequested | COMMAND | ZC → PayeeBank | TX:{txid} | timeout/DLQ復旧 | 同上 | txid内でcommand_seq単調 |
| NameChecked | EVENT | PayeeBank → ZC | TX:{txid} | 同上 | 同上 | txid内でevent_seq単調 |
| AuthorityCheckRequested | COMMAND | ZC → Authority | TX:{txid} | timeout/DLQ復旧 | 同上 | txid内でcommand_seq単調 |
| AuthorityCleared | EVENT | Authority → ZC | TX:{txid} | 同上 | 同上 | txid内でevent_seq単調 |
| TransferAuthorize | COMMAND | PayerBank → ZC | TX:{txid} | ACK未達/timeout | 同上 | txid内でcommand_seq単調 |
| HReservationPlaced | EVENT | ZC → Banks | TX:{txid} | 再送可(冪等) | 同上 | txid内で単調 |
| PayerExecRequested | COMMAND | ZC → PayerBank | TX:{txid} | timeout/DLQ復旧 | 同上 | txid内でcommand_seq単調 |
| PayerExecConfirmed | EVENT | PayerBank → ZC | TX:{txid} | ACK未達/timeout | 同上 | txid内でevent_seq単調 |
| DecideToSettle | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | Finality Log順序 |
| DecidedCancel | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | Finality Log順序 |
| PayeeExecRequested | COMMAND | ZC → PayeeBank | TX:{txid} | timeout/DLQ復旧 | 同上 | txid内でcommand_seq単調 |
| PayeeExecConfirmed | EVENT | PayeeBank → ZC | TX:{txid} | ACK未達/timeout | 同上 | txid内でevent_seq単調 |
| NoDebitRecordedProofSubmitted | EVENT | PayerBank → ZC | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| CreditFailedProofSubmitted | EVENT | PayeeBank → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
| HUnlockAuthorized | EVENT | ZC/Ops → Banks | TX:{txid} | 再送可 | 同上 | Finality Log順序 |
| MisrecordCorrected | EVENT | ZC/Ops → Banks | TX:{txid} | 再送可 | 同上 | Finality Log順序 |
| ReversalInitiated | EVENT | Bank → ZC | TX:{reversal_txid} | 再送可 | 同上 | txid内で単調 |
| CaseOpened | EVENT | ZC/Banks → ZC/Banks | CASE:{case_id} | 再送可 | 同上 | case内で単調 |
| CaseUpdated | EVENT | ZC/Banks → ZC/Banks | CASE:{case_id} | 再送可 | 同上 | case内で単調 |
| ExpressCapabilityChanged | EVENT | ZC → Banks | BANK:{bank_id} | 再送可 | 同上 | bank_id内で単調 |
| PspRegisterRequested | COMMAND | ZC → PayeeBank | PSPR:{pspr_ref} | timeout/DLQ復旧 | 同上 | pspr_ref内でcommand_seq単調 |
| PspRegistered | EVENT | PayeeBank → ZC | PSPR:{pspr_ref} | 再送可 | 同上 | pspr_ref内でevent_seq単調 |
| RtpRequested | EVENT | PayeeBank → ZC | RTP:{rtp_id} | 再送可 | 同上 | rtp_id内で単調 |
| RequestToAttempt | COMMAND | ZC → PayerBank | RTP:{rtp_id}:{attempt_id} | timeout/DLQ復旧 | 同上 | attempt内で単調 |
| AttemptResult | EVENT | PayerBank → ZC | RTP:{rtp_id}:{attempt_id} | 再送可 | 同上 | attempt内で単調 |
| GtLegRegistered | EVENT | Initiator → ZC | GT:{gtid} | 再送可 | 同上 | gtid内で単調 |
| GtDecideToSettle | EVENT | ZC → Banks | GT:{gtid} | 再送可 | 同上 | gtid内で単調 |
| GtDecidedCancel | EVENT | ZC → Banks | GT:{gtid} | 再送可 | 同上 | gtid内で単調 |
| LegPayeeExecConfirmed | EVENT | PayeeBank → ZC | LEG:{gtid}:{leg_id} | 再送可 | 同上 | leg内で単調 |
| LsmRunCommitted | EVENT | ZC → Banks | WINDOW:{window_id} | 再送可 | 同上 | window内で単調 |
| LsmRunFallback | EVENT | ZC → Banks | WINDOW:{window_id} | 再送可 | 同上 | window内で単調 |
| GtLegReadyRequested | COMMAND | ZC → Banks | LEG:{gtid}:{leg_id} | timeout/DLQ復旧 | 同上 | leg内でcommand_seq単調 |
| GtLegReadyAcked | EVENT | Banks → ZC | LEG:{gtid}:{leg_id} | ACK未達/timeout | 同上 | leg内でevent_seq単調 |
| RtpNotified | COMMAND | ZC → PayerBank | RTP:{rtp_id} | timeout/DLQ復旧 | 同上 | rtp_id内でcommand_seq単調 |
| RtpExecuteNowRequested | COMMAND | PayerBank → ZC | RTP:{rtp_id} | ACK未達/timeout | 同上 | rtp_id内でcommand_seq単調 |
| RtpDeferred | EVENT | PayerBank → ZC | RTP:{rtp_id} | 再送可 | 同上 | rtp_id内でevent_seq単調 |
| TransferStarted | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| InternalCancelAccepted | EVENT | PayerBank → ZC | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| CustomerCancelRequested | EVENT | PayerBank → ZC | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
12.1.2 HTLC・クロスチェーン・条件付き決済
| name | type | producer → consumer | aggregate | 再送条件(例) | 配送 | 順序制約 |
|---|---|---|---|---|---|---|
| HtlcLocked | EVENT | ZC → Banks | TX:{txid} | 再送可 | at-least-once | txid内でevent_seq単調 |
| HtlcClaimRejected | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| HtlcConditionsEvaluated | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| CrossChainLocked | EVENT | Watcher → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
| OnchainProofObserved | EVENT | Watcher → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
| OnchainFinalityClassified | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| BenefitAttested | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
12.1.3 外部清算(IGS/DNS/中央銀行レール)
| name | type | producer → consumer | aggregate | 再送条件(例) | 配送 | 順序制約 |
|---|---|---|---|---|---|---|
| DnsHoldRequested | EVENT | ZC → Banks | DNS:{business_date} | 再送可 | at-least-once | 日次内で単調 |
| DnsHoldActivated | EVENT | ZC → Banks | DNS:{business_date} | 再送可 | 同上 | 日次内で単調 |
| DnsResumed | EVENT | ZC → Banks | DNS:{business_date} | 再送可 | 同上 | 日次内で単調 |
| DnsIntradayCutoff | EVENT | ZC → Banks | DNS:{business_date} | 再送可 | 同上 | 日次内で単調 |
| ExtInstructionSent | EVENT | ZC → (記録) | TX:{txid} | 再送可(ext_instruction_id で冪等) |
同上 | txid内でevent_seq単調 |
| ExtResultObserved | EVENT | ESA → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
| ExtResultReconciled | EVENT | ZC → Banks | TX:{txid} | 再送可 | 同上 | txid内でevent_seq単調 |
| CbSettled | EVENT | ESA → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
| CbPending | EVENT | ESA → ZC | TX:{txid} | 再送可(冪等) | 同上 | txid内でevent_seq単調 |
12.1.4 所有権・システム運用
| name | type | producer → consumer | aggregate | 再送条件(例) | 配送 | 順序制約 |
|---|---|---|---|---|---|---|
| OwnershipTransferred | EVENT | ZC → (記録) | TX:{txid} | 再送不可(CAS で1回) | at-least-once | txid内でevent_seq単調 |
| OwnershipReclaimed | EVENT | ZC → (記録) | TX:{txid} | 再送不可(CAS で1回) | 同上 | txid内でevent_seq単調 |
| SystemQuorumLossActivated | EVENT | ZC → Banks | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
| SystemQuorumLossCleared | EVENT | ZC → Banks | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
| SystemBcpActivated | EVENT | ZC/Ops → Banks | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
| SystemBcpDeactivated | EVENT | ZC/Ops → Banks | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
| DataAccessViolationDetected | EVENT | ZC → Ops/監査 | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
| ClosedDomainAccessGranted | EVENT | ZC → Ops/監査 | GLOBAL | 再送可 | 同上 | GLOBALチェーン内で単調 |
12.1.5 図中略記と正式名の対応(規範)
20_method_design.md 第2章のシーケンス図は、可読性のため UPPER_SNAKE の略記とCMD/EVT 接頭辞を用いる。正式名は本節(§12.1)であり、図中表記は略記に過ぎない。
両者の対応は次のとおり固定する(図に新しいメッセージを描く場合は、本表と §12.1.1〜§12.1.4
への追加を同じ変更で行う)。
| 図中の略記 | 正式名 |
|---|---|
PSPR_REGISTER |
PspRegisterRequested |
TransferAccept / GroupAccept / HTLC_ACCEPT |
PaymentInitiated |
NAMECHECK_REQUEST / NAMECHECK_RESULT / NAMECHECK_PRESENT |
NameCheckRequested / NameChecked |
AUTHORITY_CHECK / AUTHORITY_RESULT / AUTHORITY_PRESENT / AUTHORITY_RECHECK_IF_NEEDED |
AuthorityCheckRequested / AuthorityCleared |
PAYER_EXEC_REQUEST / PAYER_EXEC_CONFIRMED |
PayerExecRequested / PayerExecConfirmed |
PAYEE_EXEC_REQUEST / PAYEE_EXEC_CONFIRMED |
PayeeExecRequested / PayeeExecConfirmed |
LEG_READY_REQUEST / LEG_READY_ACK |
GtLegReadyRequested / GtLegReadyAcked |
RTP_REQUESTED |
RtpRequested |
REQUEST_TO_ATTEMPT / ATTEMPT_RESULT |
RequestToAttempt / AttemptResult |
RTP_NOTIFY / RTP_EXECUTE_NOW / RTP_DEFERRED |
RtpNotified / RtpExecuteNowRequested / RtpDeferred |
START_TRANSFER / STARTED |
TransferStarted |
BOJ_SETTLE_REQUEST |
ExtInstructionSent |
CB_SETTLED / EVT_CB_SETTLED / IGS_RESULT / BOJ_SETTLED |
CbSettled |
BOJ_PENDING |
CbPending |
INTERNAL_CANCEL_ACCEPTED |
InternalCancelAccepted |
EXT_INSTRUCTION_SENT / EXT_RESULT_OBSERVED / EXT_RESULT_RECONCILED |
ExtInstructionSent / ExtResultObserved / ExtResultReconciled |
DNS_HOLD_REQUESTED / DNS_HOLD_ACTIVE / DNS_RESUMED |
DnsHoldRequested / DnsHoldActivated / DnsResumed |
READ_ONLY_ENTERED / READ_ONLY_EXITED |
縮退の種別ごとに SystemQuorumLossActivated / SystemQuorumLossCleared(原則10の自動縮退)または SystemBcpActivated / SystemBcpDeactivated(運用者宣言) |
12.1.6 FinalityLog の event_type との関係(規範)
§12.1 の cmd/event(I/F 語彙)と、FinalityLog に追記される event_type(監査語彙)は
別の集合であり、部分的にしか重ならない。混同すると「この電文名で監査ログを引けるはずだ」
という誤った期待を生むため、関係を明示する。
§12.1 cmd/event(I/F 語彙) FinalityEventType(監査語彙)
┌──────────────────┐
│ NameCheckRequested │ ZC 内部のライフサイクル事実
│ PayerExecRequested │ (PreCheckPassed / HReserved /
│ GtLegReadyRequested … │ Suspended / Settled / DnsKicked …)
│ ┌──────────┼──────────────────┐
│ │ 同名で FinalityLog にも記録される(下記 1.) │
│ └──────────┼──────────────────┘
└──────────────────┘
1. 同名で FinalityLog にも記録されるもの(30 件)
集合の正は下記の列挙であり、CI が実装の列挙型と機械照合する。
PaymentInitiated / PayerExecConfirmed / PayeeExecConfirmed / DecidedCancel /NoDebitRecordedProofSubmitted / CreditFailedProofSubmitted / HUnlockAuthorized /MisrecordCorrected / RtpRequested /LsmRunCommitted / LsmRunFallback / HtlcLocked / HtlcClaimRejected /HtlcConditionsEvaluated / CrossChainLocked / OnchainProofObserved /OnchainFinalityClassified / BenefitAttested / DnsHoldRequested / DnsHoldActivated / DnsResumed /DnsIntradayCutoff / OwnershipTransferred / OwnershipReclaimed /SystemQuorumLossActivated / SystemQuorumLossCleared / SystemBcpActivated /SystemBcpDeactivated / DataAccessViolationDetected / ClosedDomainAccessGranted
2. I/F 語彙のみ(FinalityLog には別名で、または個別には記録されない)
:NameCheckRequested / PayerExecRequested / GtLegReadyRequested 等の要求・応答電文。
これらの結果は状態遷移イベント(PreCheckPassed・HReserved・DecidedToSettle 等)として
記録される。
3. 監査語彙のみ(線の上を流れない ZC 内部事実)
:PreCheckPassed / PreCheckFailed / HReserved / DecidedToSettle / Suspended /Settled / Cancelled / FailedExecution / GtidRegistered / GtidDecided / GtidSettled /DnsKicked / DnsSettled / DnsHoldActivated / DnsRingfencePromoted / IgsDeferred /HtlcCreated / HtlcFulfillRequested / HtlcAuthRequested / FinalityCosigned /WatcherEquivocationDetected 等。
規範
- FinalityLog の
event_type列の値域はsrc/types/api/messaging.ts#FinalityEventTypeを正とする
(31_schema.md § FinalityLog)。本書 §12.1 はこの列の値域ではない。 - 上記 1. の集合は「§12.1 の名前 ∩
FinalityEventType」と一致しなければならない
(test/invariants/spec_refs.test.tsが機械照合する)。§12.1 に新しい EVENT を足し、
それを同名で FinalityLog にも記録するなら、1. のリストとFinalityEventTypeの両方を
同じ変更で更新すること。
12.2 共通ヘッダ(全cmd/event:固定)
{
"schema_version": "1.0",
"message_type": "COMMAND|EVENT",
"name": "PaymentInitiated|PayerExecRequested|...",
"message_id": "uuid",
"occurred_at": "RFC3339",
"idempotency_key": "string",
"command_seq": 123,
"event_seq": 456,
"correlation_id": "uuid",
"causation_id": "uuid",
"producer": { "org_id": "string", "system_id": "string" },
"signature": {
"alg": "POLICY_DEFINED",
"canonicalization": "FIXED",
"signed_fields": ["..."],
"value": "base64"
}
}
規範(固定)
command_seq/event_seqは 永続・単調増加(巻戻り不可) 。欠番は許容するが再利用不可。- **COMMANDは
command_seq必須 /event_seqはnullまたは省略。EVENTはevent_seq必須 /command_seqはnullまたは省略。 ** (両方を同時必須にしない) - 粒度: 送信者×aggregate(§12.5)。
correlation_idは業務トレース単位で継承。causation_idは直前因果。- 署名は 対象範囲と正規化を固定(§12.6)。
12.3 データ辞書(最小十分:揉めどころ固定)
12.3.1 識別子
| field | required | type | maxLen | null | constraint |
|---|---|---|---|---|---|
| txid | 条件 | string | 64 | 可 | 一意 |
| gtid | 条件 | string | 64 | 可 | 一意 |
| leg_id | 条件 | string | 64 | 可 | gtid内一意 |
| rtp_id | 条件 | string | 64 | 可 | 一意 |
| attempt_id | 条件 | int | - | 可 | 1..PR-RTP-ATTEMPT-MAX(§12.9) |
| case_id | 条件 | string | 64 | 可 | 一意 |
12.3.2 金額
| field | required | type | constraint |
|---|---|---|---|
| amount.value | 必須 | int | >0 |
| amount.currency | 必須 | string | ISO通貨(運用でJPY固定可) |
| amount_components[] | 条件 | array | 内訳列挙 |
| calculation_version | 必須 | string | 版管理 |
| trace_digest | 必須 | string | 改ざん検知 |
12.3.3 Proof参照(bank_proof_ref:固定)
b証憑(PAYEE_EXEC_PROOF)は、単なるACKではなく、銀行内部の台帳記録を指し示すものでなければならない。
{
"bank_proof_ref": {
"issuer_bank_id": "B001",
"proof_type": "PAYEE_EXEC_PROOF",
"proof_id": "core_journal_id_12345",
"recorded_at": "RFC3339",
"retrieval_hint": "...",
"custody_detail": {
"is_custody": true,
"reason_code": "ACCOUNT_CLOSED",
"custody_account_ref": "segregated_custody_acct_001"
}
}
}
- 規範 :
proof_idは後日の監査において、銀行の勘定系元帳(GL)と突合可能でなければならない。 custody_detailは Custody 発生時のみ付与し、Custodyでない場合は省略してよい。
proof_type の値域(規範)
proof_type は自由文字列ではなく、次の閉じた集合とする。追加は本表の更新を伴う。
現行の値域(実装の正: src/types/primitives.ts#ProofType: PAYER_EXEC_PROOF | PAYER_HV_ISOLATION_PROOF | PAYEE_EXEC_PROOF | NO_DEBIT_RECORDED_PROOF | ONCHAIN_ESCROW_LOCK_PROOF | ONCHAIN_RELEASE_PROOF | CREDIT_FAILED_PROOF | EXT_REFUND_PROOF)
| proof_type | 発行主体 | 意味 | 参照 |
|---|---|---|---|
PAYER_EXEC_PROOF |
PayerBank | a(支払人側実施完了)の証憑 | 20_method_design.md §6.3.1 |
PAYER_HV_ISOLATION_PROOF |
PayerBank | a_HV:顧客口座→清算専用中継勘定への資金隔離完了。ZC はこの proof_type を受領した場合にのみ中銀決済(IGS)を起動する | 10_requirements.md §1.2.3、20_method_design.md §1.5.1 |
PAYEE_EXEC_PROOF |
PayeeBank | b(受取人側利用可能化=弁済完了)の証憑 | 20_method_design.md §6.3.1 |
NO_DEBIT_RECORDED_PROOF |
PayerBank | 未実行証明。H_locked の自動解放根拠 | 20_method_design.md §6.4.1 |
ONCHAIN_ESCROW_LOCK_PROOF |
外部レール(Watcher 観測) | 同一 hashlock 下のオンチェーンエスクローがロックされた事実 |
本書 §15.6、20_method_design.md §7.7 |
ONCHAIN_RELEASE_PROOF |
外部レール(Watcher 観測) | hashlock に一致する preimage でオンチェーンエスクローが解放された事実 |
本書 §15.6、20_method_design.md §7.7 |
CREDIT_FAILED_PROOF |
PayeeBank | 物理的に資金移動が不能であることの証明。Reversal を許容する唯一の原因事由。受理は POST /api/transfers/:txid/credit-failed-proof(32_api_contracts.md)で、b 成立後・PayeeBank 発行・口座都合でないことを検査する |
10_requirements.md §4.3.0、20_method_design.md §6.3.2 |
EXT_REFUND_PROOF |
PayerBank | 中銀決済が不成立(FAILED/HOLD)となった際の、隔離資金の内部復元証跡。銀行間 Reversal の前提にしない——資金は支払銀行から出ていないので、行間で巻き戻すものが無い | 10_requirements.md §1.2.3 |
規範(
proof_typeとvenueは直交する別軸) :SettlementProofRefは
BankProofRefの別名であってproof_typeの値ではない。「どの決済場で確定したか」は
venue列(BANK_LEDGER/IGS_BOJ/ONCHAIN/ATTESTATION/CB_TOKEN、実装の正:
src/types/primitives.ts#ProofVenue)が担い、proof_typeは「その証憑が何を証明しているか」を担う。両者を同じ列挙に混ぜてはならない
(契約は
32_api_contracts.md § SettlementProofRef)。
規範(HV の起動条件) :高額即時レーンにおいて、
PayerExecConfirmedの
bank_proof_ref.proof_typeがPAYER_HV_ISOLATION_PROOFでない場合、ZC は
ExtInstructionSent(中銀決済依頼)を発行してはならない。外形上の状態は
PAYER_EXEC_CONFIRMED(a)と同一であるため、区別は proof_type だけが担う。
12.4 idempotency_key のスコープ(規範)
冪等キーは「どの論理コマンドの再送か」を一意に決める。スコープを取り違えると
txid / gtid / leg / attempt が混線し、別々の指図が同一要求として吸収される——
本節はその混線を構造的に防ぐためにキー空間を固定する。
書式(固定)
TX:{txid}:{name}:{issuer}
GT:{gtid}:{name}:{issuer}
LEG:{gtid}:{leg_id}:{name}:{issuer}
RTP:{rtp_id}:{attempt_id}:{name}:{issuer}
CASE:{case_id}:{name}:{issuer}
| 要素 | 意味 | 制約 |
|---|---|---|
| 先頭トークン | aggregate 種別(TX/GT/LEG/RTP/CASE) |
閉じた集合。新設は本節の更新を伴う |
| 識別子部 | 当該 aggregate の主キー。LEG は gtid と leg_id の両方、RTP は rtp_id と attempt_id の両方を含む |
省略不可 |
{name} |
§12.1 の正式名 | §12.1 に存在する名前のみ |
{issuer} |
発行主体の org_id(producer.org_id と一致) |
省略不可 |
規範
- 同一キー=同一要求 :同一
idempotency_keyの再送に対し、受信側は副作用を
1 回だけ発生させ、保存済みの応答を返す(32_api_contracts.md § 冪等性)。 - 識別子部の省略禁止 :
LEGからleg_idを、RTPからattempt_idを落として
はならない。落とすと同一 gtid の別 leg、同一 rtp_id の別 attempt が同一要求として
吸収され、片方の指図が黙って消える。 {issuer}の省略禁止 :発行主体が異なれば別のキーである。省略すると、ZC 発行の
コマンドと参加行発行のイベントが衝突し得る。- キーの再利用禁止 :ボディが異なる同一キーの再使用は
409 IDEMPOTENCY_KEY_CONFLICT
(ボディ同一性はリクエスト全体の SHA-256 で判定。src/shared/idempotency.ts)。 - 単発キーの例外 :署名リプレイ防止用の
sig:{key_id}:{nonce}はボディ比較の対象外
(ハッシュ未保存・常に非衝突)。
実装: src/shared/idempotency.ts(acquireIdempotency / completeIdempotency /resolveIdempotency)、テーブルは 31_schema.md § IdempotencyKeys。
12.5 command_seq / event_seq の粒度(規範)
seq は「どの範囲で単調であることを契約するか」を決める。全体順序は要求しない
(20_method_design.md §5.1)。
- 粒度=送信者 × aggregate 。すなわち
(producer.org_id, aggregate)の組ごとに
独立したカウンタを持つ。aggregate の表記は §12.4 の先頭トークン+識別子部と同一
(TX:{txid}/GT:{gtid}/LEG:{gtid}:{leg_id}/RTP:{rtp_id}:{attempt_id}/CASE:{case_id}/BANK:{bank_id}/PSPR:{pspr_ref}/WINDOW:{window_id}/DNS:{business_date}/GLOBAL)。 - 永続・単調増加・巻戻り不可 。プロセス再起動をまたいでも巻き戻らないこと。
- 欠番は許容、再利用は禁止 。欠番は配送欠落・破棄として説明できるが、再利用は
「同じ seq で別の内容」を生み監査が破綻する。 - COMMAND は
command_seq必須/event_seqは null または省略。EVENT はevent_seq
必須/command_seqは null または省略(両方を同時必須にしない。§12.2)。 - 受信側の検証義務 :Kafka 等のキー順序に依存する場合でも、アプリ層で seq を検証する
(20_method_design.md§5.5)。ギャップは許容、巻戻りは拒否。
ZC 内部の event_seq との関係 :上記は参加行との I/F 契約上の粒度である。
ZC が FinalityLog へ書く
event_seqは、これとは別にFinalitySeq単一行の
UPDATE ... RETURNINGで大域単調に採番される(§4 不変条件、§7.2)。両者を混同しないこと。
12.6 署名対象(signed_fields)と正規化(canonicalization)(規範)
署名は「アルゴリズム」より先に「何を署名するか」と「どうバイト列に落とすか」を
固定する。ここが揺れると、後日の監査・訴訟で「その署名は何を保証していたのか」が
争点になる。
12.6.1 署名対象(signed_fields)
最小必須集合(すべての cmd/event で署名対象に含める)
| フィールド | 理由 |
|---|---|
schema_version |
世代の取り違えによる再解釈を防ぐ(32_api_contracts.md § スキーマ進化) |
message_type / name |
COMMAND と EVENT、別名メッセージの取り違えを防ぐ |
message_id |
メッセージ同一性 |
occurred_at |
時刻の後付け改変を防ぐ(TIMESTAMP_SKEW 検査の対象) |
idempotency_key |
§12.4 のスコープごと署名対象に含める |
command_seq / event_seq |
順序の改変を防ぐ(該当する方のみ) |
correlation_id / causation_id |
因果リンクの改変を防ぐ |
producer.org_id / producer.system_id |
発行主体のなりすまし防止 |
| ボディ側の金額・識別子・時刻・相関ID・証憑参照 | 20_method_design.md §7.3 の最低限 |
規範
signature.signed_fieldsには、実際に署名対象としたフィールドの完全な列挙を
JSON Pointer 形式(/amount/value等)で昇順に記載する。- 署名対象外のフィールドを増やしてはならない。 新フィールドを加法的に追加する場合
(32_api_contracts.md § スキーマ進化の「加法的・任意」)も、そのフィールドが業務上の
意味を持つなら署名対象へ入れる。「任意フィールドだから署名しない」は禁止する——
署名されない業務フィールドは、経路上で書き換えても検出できない。 signed_fieldsに列挙されていないフィールドは、受信側が業務判断に用いてはならない。
12.6.2 正規化(canonicalization)
signature.canonicalization の値は FIXED とし、次の手順を指す。
signed_fieldsの各 JSON Pointer が指す値を、列挙順に取り出す。- 各値を次のとおり文字列化する。
- 文字列: そのまま(Unicode 正規化は NFC)
- 整数: 十進表記、先行ゼロなし、負号は
- - 真偽:
true/false - null / 不在: 空文字列
- 配列・オブジェクト: 本手順を再帰適用し、要素を
,で連結
- 得られた文字列を
|(U+007C)で連結する(FinalityLog のentry_hashと同じ区切り。20_method_design.md§8.2.1)。 - UTF-8 でエンコードしたバイト列を署名対象とする。
規範
- 浮動小数点は署名対象に含めない(金額は整数、レートは整数固定小数。
20_method_design.md§17.3.1)。 - JSON のキー順・空白・エスケープ表現は正規化の入力にしない(値だけを順序どおり連結する)。
これにより JSON シリアライザの実装差が署名の可否を左右しない。 - 本手順は破壊的変更の対象としない。 変更が必要な場合は
canonicalizationに
新しい値(FIXED_V2等)を導入し、32_api_contracts.md § スキーマ進化の n / n-1
併存受理に従って移行する。
12.6.3 検証側の義務
- 署名検証はメッセージ単位で行う(
20_method_design.md§7.1 ゼロトラスト)。 - 鍵は
KeyRegistry(31_schema.md § KeyRegistry)で解決し、revoked_atは非遡及
(occurred_at < revoked_atの署名は有効。10_requirements.md§3.3.4)。 - 失敗時の
reason_codeは32_api_contracts.md § エラーカタログのEXTERNAL_SIGNATURE_INVALID/KEY_NOT_FOUND/KEY_REVOKED/KEY_EXPIRED/SIGNATURE_REPLAYED/TIMESTAMP_SKEWに写す。
実装: src/shared/external_signature.ts(外部主体の検証)、src/shared/zc_signature.ts
(ZC egress の非対称署名)、src/shared/hmac.ts(旧方式の後方互換パス)。
12.6.4 共有 HMAC のローテーション重複窓(規範)
ZC_HMAC_SECRET は全参加者が同じ値を持つ対称鍵であり、非対称鍵(§12.6.3)と違ってkey_id 単位の差し替えができない。重複窓が無ければ交換は全か無かの切替になり、ZC が新しい
値で検証を始めた瞬間に旧値で署名している相手が全て 401 になる——結果として運用上は決して
ローテーションされないという、共有鍵にとって最悪の定常状態に落ち着く。したがって次を規範と
する。
- 署名は常に現行値のみ。旧値で署名してはならない(対外的な切替は瞬時に完了する)。
- 検証は旧値も受理する。ただし期限まで。旧値は
ZC_HMAC_SECRET_PREVIOUS、期限はZC_HMAC_SECRET_PREVIOUS_UNTIL(RFC3339)で与える。期限到来後は再デプロイなしに
受理をやめる(窓は時計が閉じるのであって、人が変数を消し忘れないことに依存しない)。 - 期限の無い旧値は無効とする(fail-closed)。期限の無い 2 本目は重複窓ではなく
「生きた鍵が 2 本ある」状態であり、本項が防ごうとしているものそのものである。解釈不能な
期限も同じく無効として扱い、いずれの場合も警告を残す。 - 同じ扱いは bearer / API キーとしての比較(
X-Api-Key・Authorization)にも適用する。
比較は定数時間で行い、どの値に一致したかを応答時間から区別できないようにする
(窓の開いている間、捕獲した鍵が現行か退役中かを attacker に教えないため)。
実装: src/shared/secret_rotation.ts。
12.6.5 /api/* の外周認証(規範)
ZC Core API に到達した呼び出し元を認証するのは 資格情報だけである。リクエストヘッダは
呼び出し元が自由に設定できる以上、ヘッダから「これは自分のダッシュボードだ」と推論しては
ならない。特に Origin の不在を同一オリジンの証拠として扱ってはならない——Origin は
ブラウザのヘッダであり、curl・スクリプト・サーバ間呼び出しは既定で付けない。不在を許可条件に
すると、排除したかった呼び出し元だけが通るという反転が起きる(Sec-Fetch-Site も同様。
ページには設定できないがクライアントには設定できるので、非ブラウザの攻撃者には何も証明しない)。
鍵無しの経路は推論ではなく運用上の明示的な選択としてのみ残す:同梱のデモ用ダッシュボードの
ために ZC_ALLOW_UNAUTHENTICATED_UI="true" を設定したときに限り、同一オリジンの無資格
呼び出しを通す。既定は off——何も書かなかったデプロイは閉じている。有効時は 1 リクエスト
ごとに警告ログ(http.unauthenticated_ui_access)を残し、この設定を入れた配備は API を
公開したのだと読むこと。同一オリジン判定はブラウザ向けの礼儀であって、第二の要素ではない。
このフラグが、UI から鍵なしで取引する(/api/* の POST を含む)ための公式かつ唯一の経路
である。参照リファレンスとしては UI から手で動かせることに価値があるが、その手段は
隠れた迂回路(バックドア)ではなく、明示・opt-in・可視のフラグでなければならない——
規範として理由を固定する:リファレンスはコピーされるため、認証を迂回する隠れた経路を
コードに置くと、複製した配備がその迂回路ごと本番に出る(本章が塞いだ Origin 欠落の穴と
同型)。ゆえに鍵無し経路を追加する場合も、常にこの 3 条件——既定 off・明示的な env による
opt-in・1 リクエストごとの記録——を満たすこと。ハードコードされた常時許可、未文書の
マジックヘッダ、常に通る秘密値の類は置いてはならない。
なお /internal/* は X-Cron-Secret の定数時間比較で fail-closed(src/router/internal.ts)、/bank/* の ZC→Bank ingress は署名検証(§12.6.3)で、それぞれ別の資格情報に依っている。
実装: src/shared/api_auth.ts(判定)、src/index.ts(適用)。
12.7 パラメータ統制(公開版)
- パラメータはカテゴリ単位で管理し、変更時は 変更証跡(evidence_ref) と周知期間を必須とする。
- 変更は「変更管理(合意・証跡)」「監督説明」「参加者運用」のいずれに属するかを明確化し、責任主体を固定する。
12.8 対象カテゴリ(例)
- Express:PSPR有効期限、同期受付の目標遅延
- Standard:名義確認/Authority Checkのタイムアウト、保留→CASEへの収束期限
- Decision:受理→DECIDED_* の最大待ち、取消/保留境界
- RTP:Attempt回数(
PR-RTP-ATTEMPT-MAX)・推奨時刻(PR-RTP-ATTEMPT-SCHEDULE)(当日収束のための自動再挑戦) - gtid:legs固定後の変更不可、収束タイムアウト、総額上限
- Vault:保持上限、削除トリガ、退避(Evict)運用
- Consensus/Delivery:過半数合意を満たすノード構成、配送モデル(at-least-once)、冪等(seq巻戻り禁止)
- Crisis:DNS_HOLD/IGS制御(
igs_mode)、dns_recovery_reserve算定の信頼度閾値(reserve_confidence)、公平性スロットリング(igs_throttle_budget)
設計規範(Vault保持と情報喪失リスクの排除)
Vaultは短期保持を基本としつつ、Decisionに必要な情報が保持上限超過で失われないよう、上限到達時は退避(Evict)して参照を残す。
退避時は参照IDを発行し、参加主体側またはWORM複製へ自動移送する。
これにより「Decisionに必要な情報が消える」事故を規範として禁止する。
12.9 PR-* パラメータ台帳
本文(10_requirements.md・20_method_design.md)中に PR-* として登場する規程パラメータの索引。値そのものは制度(規程)で確定し、公開版では非公開のものがある。「所定時間」「所定水準」等の伏せ字も本台帳のカテゴリに属する。
| パラメータ名 | 意味 | 単位 | 確定主体 | 公開可否 | 本文での参照箇所 |
|---|---|---|---|---|---|
PR-GTID-TTL |
GTID の一部 leg 未成立を GT_SUSPENDED に収束させるまでの許容時間 |
時間 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.4-5 |
PR-LIQ-COVER2_FACTOR |
cover-2 算定で加算する第2位ネット債務者の割合 | 比率 | 制度(規程) | 非公開 | 10_requirements.md §3.2.5.3 |
PR-DATA-VIOLATION_NOTIFY_TTL |
重大データアクセス違反の当局・本会・監査への通知期限 | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.3.2.2.1.1-4 |
PR-SOFT-LIMIT |
Express の条件付き Soft Reservation を許容する1取引上限(例: 5万円) | 金額 | 制度(規程) | 公開(例示値) | 20_method_design.md §13.7.2 |
PR-HV-THRESHOLD |
EXPRESS/STANDARD を HIGH_VALUE へ自動エスカレーションする金額閾値。変更は所定の承認権者(4眼)のみ(技術既定=最終フォールバックは 1 億円、src/shared/constants.ts#DEFAULT_HV_THRESHOLD)。参加行個別の上書きは Participants.hv_threshold、システム共通の上書きは環境変数 ZC_HV_THRESHOLD |
金額 | 制度(規程) | 公開(例示値) | 10_requirements.md §3.2.7 |
PR-RTP-ATTEMPT-MAX |
RTP の当日 Attempt 回数上限(attempt_id の上限値) |
回 | 制度(規程) | 非公開(Public版) | 10_requirements.md §1.2.1、20_method_design.md §2.2.3・§10.4、本書 §12.3.1 |
PR-RTP-ATTEMPT-SCHEDULE |
RTP の各 Attempt の推奨実行時刻 | 時刻列 | 制度(規程) | 非公開(Public版) | 20_method_design.md §2.2.3 |
PR-DD-PERIOD-AHEAD-MAX |
継続収納(PERIODIC 費目)で受理する将来期間の上限。これを超える先の期間を費目に指定した予告は受理しない |
期間 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.8.3-4 |
PR-DD-AMEND-FREEZE |
収納予告の変更受付を凍結する時刻(振替日から遡る相対値)。凍結後は不利益変更のみを止め、減額・取下げは受け付ける | 時間 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.8.5-2 |
PR-DD-LADDER-MAX |
事前登録ラダーの段数上限(制度上限。契約はこれ以下の値を宣言する) | 段 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.8.5-9 |
PR-DD-LATEFEE-RATE-MAX |
継続収納の遅延損害金の率上限(年率)。契約はこれ以下の値を宣言する。適法性の判断は各参加主体の責任であり ZC は行わない | 比率 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.8.5-11 |
PR-DD-LATEFEE-CAP |
継続収納の遅延損害金の絶対額上限 | 金額 | 制度(規程) | 非公開(Public版) | 10_requirements.md §3.2.8.5-11 |
PR-SLO-STANDARD-P99 |
Standard の end-to-end latency SLO(20_method_design.md §10.9.1 の X) |
秒 | 制度(規程) | 非公開 | 20_method_design.md §10.9.1・§16.2 |
PR-SLO-RTP-P99 |
RTP の acceptance-to-b latency SLO(同 Y) | 秒 | 制度(規程) | 非公開 | 20_method_design.md §10.9.1・§16.2 |
PR-SLO-BULK-COMPLETION |
Bulk の期限内完了率 SLO(同 Z) | 比率 | 制度(規程) | 非公開 | 20_method_design.md §10.9.1・§16.2 |
PR-SLO-DNS-CYCLE-CLOSE |
DNS サイクル閉鎖時間 SLO(同 T) | 時間 | 制度(規程) | 非公開 | 20_method_design.md §10.9.1・§16.2 |
PR-FRESHNESS-RED |
照会応答の freshness_level が RED になる Read Model 遅延(GREEN=10秒 / YELLOW=60秒 は公開既定値。実装既定は 60 秒) |
秒 | 制度(規程) | 非公開 | 本書 §13.6 |
PR-CASE-SLA |
CASE が OPEN / IN_PROGRESS のまま滞留してよい上限。超過で ESCALATED へ昇格する(技術既定は 24 時間) |
時間 | 制度(規程) | 非公開 | 20_method_design.md §10.7.4・§10.10.2 |
PR-CASE-SECONDARY-COUNT |
ESCALATED の CASE に束ねた取引の件数がこれを超えたら、状態を変えずに再通知する(二次エスカレーション。技術既定は 100 件) |
件数 | 運用 | 非公開 | 20_method_design.md §10.7.2.2 |
PR-RETRY-MAX |
非同期 cmd/event の再送上限回数。到達で DLQ へ落とし CASE へ接続する(20_method_design.md §5.4)。技術既定は 3(IGS 再送。実装の正: src/zc/settlement/igs.ts#retryFailedIgs) |
回 | 制度(規程) | 公開(例示値) | 10_requirements.md 序章(DLQ 用語)、20_method_design.md §5.4 |
PR-DNS-HOLD-NOTIFY-TTL |
DNS_HOLD 宣言後の当局・当事者への閉域通知期限(「所定時間内」) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.3.1-1 |
PR-DNS-HOLD-DISCLOSE-TTL |
DNS_HOLD の第1報公表期限(「所定期間内」) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.3.1-3 |
PR-BREAKGLASS-REVIEW-TTL |
ブレークグラス付与の事後レビュー期限(「所定時間以内」) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.3.2.2.2 |
PR-BREAKGLASS-GRANT-MAX |
一時権限の最長付与期間(「最長所定時間」) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.3.2.2.3 |
PR-STRESS-PASS-RATE |
ストレステスト合格基準:当日解消率(「所定水準」) | 比率 | 制度(規程) | 非公開 | 10_requirements.md §3.2.5.3 |
PR-STRESS-MAX-RESOLVE |
ストレステスト合格基準:最大解消時間(「所定時間」) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §3.2.5.3 |
PR-DNS-ROLLOVER-MAX |
DNS_HOLD の翌日繰越を許容する時間・回数(「所定の時間・回数」) | 時間/回 | 制度(規程) | 非公開 | 10_requirements.md §3.2.5.4 |
PR-NFR-AVAILABILITY-DECISION |
受付・Decision 系 API の年間可用性目標(要件 A-1) | 比率 | 制度(規程) | 非公開 | 10_requirements.md §8.2.1 |
PR-NFR-AVAILABILITY-QUERY |
照会系 API の年間可用性目標(要件 A-2。A-1 より高い水準) | 比率 | 制度(規程) | 非公開 | 10_requirements.md §8.2.1 |
PR-NFR-RTO |
復旧目標時間(要件 A-6) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §8.2.2 |
PR-NFR-READMODEL-REBUILD |
Finality Log からの Read Model 全再構築の目標時間(要件 A-7) | 時間 | 制度(規程) | 非公開 | 10_requirements.md §8.2.2 |
PR-NFR-EXPRESS-P99 |
Express の同期 Decision 応答時間 SLO(要件 P-2。店舗導線で成立する水準) | ミリ秒 | 制度(規程) | 非公開 | 10_requirements.md §8.3.1 |
PR-NFR-PEAK-TPS |
設計ピーク受付レート(レーン別。要件 P-4) | 件/秒 | 制度(規程) | 非公開 | 10_requirements.md §8.3.2 |
PR-NFR-PEAK-FACTOR |
ピーク係数=平常時比の設計余裕(要件 P-5) | 倍率 | 制度(規程) | 非公開 | 10_requirements.md §8.3.2 |
PR-NFR-DEGRADED-CAPACITY |
1 地域喪失時に維持すべき処理能力(要件 P-7) | 比率 | 制度(規程) | 非公開 | 10_requirements.md §8.3.2 |
PR-NFR-RETENTION-ONLINE |
オンラインで即時照会可能とする期間(これ以降は WORM 退避可。要件 B-6) | 年 | 制度(規程) | 非公開 | 10_requirements.md §8.4 |
12.9.1 伏せ字の基準(規範)
公開版で値を伏せるか具体値を書くかは、担当者の裁量にせず次の基準で決める。
| 区分 | 扱い | 例 |
|---|---|---|
| 技術的な既定値(実装が持ち、値が漏れても制度リスクにならない) | 具体値を書く | PSPR 短寿命 60〜180 秒、HTLC preimage TTL capture_expires_at + 60 分、Attestation 鮮度 60 分、RATE_SCALE=1e8、MAX_AMOUNT_VALUE=1兆、freshness GREEN 10 秒 / YELLOW 60 秒 |
| 制度が確定するパラメータ(値の公開が濫用・裁定・風評を招き得る) | PR-* 名で参照し、値は本台帳で非公開 |
上表の全項目 |
| 法令・監督指針に由来する既定値(公表が前提のもの) | 具体値を書き、根拠法令を併記 | 保存年限(10_requirements.md §3.3.5.1) |
HV 閾値の位置づけ(規範):HIGH_VALUE 自動エスカレーション閾値の最終フォールバック
(1 億円)は法令由来の値ではなく、ZC 運営が 4 眼承認で確定する制度パラメータである
(
10_requirements.md§3.2.7)。したがって上表の中段(制度が確定するパラメータ)に属し、
PR-HV-THRESHOLDとして本台帳に登録する。PR-SOFT-LIMITと同じ「公開(例示値)」の扱い——値そのものは公開する(顧客説明・接続認定で必要なため)が、変更は制度行為である。
規範 :本文に「所定時間」「所定期間」「所定水準」等の伏せ字を書く場合は、必ず対応する
PR-*を本台帳に登録し、本文からはその名前で参照する。名前の無い伏せ字を残してはならない(どのパラメータの話かが特定できず、変更管理の対象にならないため)。
値の変更は §12.7 のパラメータ統制(
evidence_ref+周知期間)に従う。新規のPR-*を本文へ追加する場合は本台帳にも同時登録する。