要約

  • RFC 3601 の phone-string は DTMF、pause、tonewait、視覚上の separator を組み合わせる。local-phone には外線番号、carrier access、service password、接続後の menu 入力まで含み得る。
  • 出所、型、local context、実行許可、device action、signaling、connection、service outcome は独立した receipt で管理すべきであり、前段の成功を後段の証明にしてはならない。

電話機が音を検出し、待機を解除した。その瞬間に monitoring 画面を緑にするのは簡単だ。しかし何の音だったのか、誰が応答したのか、session が本当に確立したのかは別問題である。RFC 3601 の tonewait は、この小さな断絶を仕様の表面に出している。

RFC 3601 は 2003 年 9 月に Standards Track として公開され、Dial Sequence と dial 可能な GSTN/E.164 address の共通 text notation を定義した。Dial Sequence は DTMF element と、人または device が行う action の列である。phone-string は数字、#、*、A-D、pause の p、tonewait の w、さらに と . の written separator を許す。

同じ文字列に存在しても役割は違う。separator は人間の読みやすさだけのためにあり、action を起こしてはならない。実装は挿入も削除もできる。一方 p と w は制御である。hyphen を無視する比較は意味を保てるが、すべての非数字を削る cleanup は、待機や pause を消して program を変更する。

しかも action の実時間は一つではない。仕様は一つの pause を一秒と解釈することを推奨し、tonewait は dial tone または後続文字を処理できる別の indication まで待つことを推奨する。off-hook indication を使うこともできる。ただし正確な意味は device と implementation に依存する。文字列が同じでも、実行機器が変われば time line が変わる。

ここで parse と execution を分ける必要がある。ABNF に合うことは文字と順序の証拠にすぎない。DTMF が出た、pause が何秒だった、どの observation で wait が解除された、といった事実は executor の receipt からしか得られない。tonewait complete は local detector の判断であり、remote identity や call answer の証明ではない。

address と sequence の境界も重要だ。RFC 3601 の gstn-phone には global と local がある。global-phone は + で始まり、dial 可能な E.164 numeric address を表す。だが完全な abstract E.164 address には dial できない要素があり、この notation に完全変換できないと仕様は述べる。plus は namespace の標識であって、抽象 address の全情報を動作列に変える魔法ではない。

local-phone は context をさらに強く要求する。exit-code と dial-number を持つことができ、exit-code には外線取得、long-distance carrier access、service password などが入る。同じ bytes を別の PBX や拠点へ移しても、その場所の dial plan、carrier policy、roaming state がなければ同じ意味にはならない。

後続の RFC 3966 は tel URI を identifier、つまり name と位置付けた。そこには特定番号へ到達する steps も dialing semantics も含まれず、どこからでも reachable だという保証もない。dial string、pause、post-dial は範囲外にされた。local number の phone-context は有効範囲を識別するもので、前置すれば E.164 が作れる prefix ではない。

RFC 4967 は後に SIP/SIPS の user=dialstring を導入した。dial string は必ず context の中にあり、同じ文字を持つ user part と識別可能でなければならない。RFC 6116 も ENUM に dialed digits を渡さず、先頭 + を持つ fully qualified E.164 を使う。同じ E.164 へ向かう local dial sequence は場所ごとに異なり得る。

この区別は migration の設計を変える。旧来の phone field を一括で tel URI にする前に、identifier、global-phone、local-phone、Dial Sequence、subaddress、post-dial のどれかを判定する必要がある。action を表現できない schema に action を押し込むことも、黙って削除することも、安全な format conversion ではない。

post-dial は前提を伴う。RFC 3601 では destination device との connection が確立した後、automated menu などへ DTMF を送る列である。database に post-dial が存在しても、接続済みとは限らない。answer/session receipt を先に結び、その後に送信した digits と application response を記録しなければならない。

秘密も混じる。RFC の例は voice mailbox の user ID と PIN を Dial Sequence に含める。security section は、protocol や application がその文字列を保護せず運ぶと private code が漏れ得ると警告する。phone number として検索・複製された値が、そのまま credential である可能性がある。

漏えい経路は通信部分だけではない。CRM export、search index、analytics、debug log、support screenshot は、field label を信じて全列をコピーする。全桁 masking では forensic linkage が失われ、平文保存では秘密が広がる。public address、action plan、protected secret reference を別々に持ち、log には hash、構造、event を残す設計が必要だ。

証拠 chain は source から始まる。供給者、元 field type、raw hash、時刻を保存する。次に classification と parser version。site、PBX、numbering plan、carrier rule、configuration epoch を context receipt にする。文字変換を明記し、実行前に authorization を得る。実行時は各 DTMF、pause duration、wait release observation を記録する。route、connection、post-dial、business outcome はさらに別の receipt である。

この分離により、便利だが誤った status 圧縮を防げる。imported は classified ではない。valid は authorized ではない。dialed は connected ではない。answered は intended party の証明ではない。digits sent は menu acceptance ではない。各層は観測した範囲だけを語るべきである。