【実装】ファイル配布サイト
概要
本記事は、安全にファイルを共有するための配布サイトを Cloudflare 上に実装した記録です。Workers / D1 / R2 を使い、実装作業は Codex のみで進めました。1
実装背景
- ファイルを安全に共有するためのサイトを作る
- 実装は Codex のみで進める
- Cloudflare を活用し、公開経路、データ保存、認証まわりの基盤をまとめる
実装メモ
以下は、Codex の実装メモ report.txt をそのまま掲載したものです。
+----------------------------------------------------------------------------------+
| 実装過程 第三者向け報告書 |
| resource.area11.org / resource-portal |
| 作成日: 2026-03-21 (JST) |
+----------------------------------------------------------------------------------+
[文書の位置づけ]
-------------------------------------------------------------------------------
本書は、当該リポジトリに対して実施した実装作業の経緯、判断、成果物、発生した
問題、修正内容、現在の到達点を、第三者が後から追跡できるように整理した報告書
である。
本書は説明用成果物であり、ユーザー要請によりコミット対象には含めていない。
+----------------------------------------------------------------------------------+
| 1. 対象システムの概要 |
+----------------------------------------------------------------------------------+
システム種別:
- 一時認証型ダウンロードポータル Web アプリ
想定利用形態:
- 管理者が配布案件を登録
- 利用者が ID / Pass / Pass2 で認証
- 認証通過後に一時配布ファイルをダウンロード
公開ドメイン:
- resource.area11.org
実行基盤:
- Cloudflare Workers
- Cloudflare D1
- Cloudflare R2
リポジトリ管理:
- GitHub
- Repository: https://github.com/UOToneg/resource
+----------------------------------------------------------------------------------+
| 2. 初期条件 |
+----------------------------------------------------------------------------------+
実装開始時の前提:
- リポジトリには仕様書のみが存在
- GitHub リポジトリは未作成
- Cloudflare アカウントは既存
- 独自ドメインは取得済み
- サブドメインとして resource.area11.org を利用予定
初期状態の制約:
- 実装コードなし
- 運用手順なし
- 自動テストなし
- CI なし
- Cloudflare 実リソース未反映
+----------------------------------------------------------------------------------+
| 3. 進行方針 |
+----------------------------------------------------------------------------------+
実装全体で採用した方針:
1) 仕様書と実装済みドキュメントを分離する
2) ファーストコミット可能な最小構成を先に作る
3) Cloudflare 実リソースに接続しながら、運用用 CLI まで含めて整備する
4) ローカル手作業に依存しないよう、案件登録と公開停止を CLI 化する
5) 実装済み範囲に対応する文書を都度更新する
6) 問題発生時は再現、原因特定、修正、再検証までを一体で行う
ドキュメントの整理方針:
- docs/planning
仕様、計画、設計など未実装要素
- docs/implemented
実装済みの運用情報、構成情報、マニュアル
+----------------------------------------------------------------------------------+
| 4. 実装フェーズの全体像 |
+----------------------------------------------------------------------------------+
Phase 1:
- リポジトリ初期整備
- 仕様書 / 計画書 / 実装済み文書の分離
- Workers プロジェクト骨格作成
Phase 2:
- Worker 本体実装
- D1 schema 実装
- R2 ダウンロード経路実装
Phase 3:
- GitHub リポジトリ作成と push
- Cloudflare 認証、リソース作成、カスタムドメイン反映
Phase 4:
- 管理 CLI 初版実装
- create-case / open-site / close-site / maintenance-site / status
Phase 5:
- 対話中断対策
- pending 復旧
- 実ファイルを使った本番相当テスト
- 不具合修正
Phase 6:
- 認証失敗ロック
- IP 単位 rate limit
- CLI 拡張
- 自動テスト
- GitHub Actions CI
+----------------------------------------------------------------------------------+
| 5. フェーズ別の詳細実施内容 |
+----------------------------------------------------------------------------------+
[5.1 リポジトリ初期整備]
-------------------------------------------------------------------------------
- Git 初期化を実施
- Workers 用の package.json, tsconfig.json, wrangler.toml を追加
- docs/planning と docs/implemented のディレクトリ構成を整理
- 仕様書と計画書を planning 配下へ移動
- 実装済み範囲を記録する implemented 文書を追加
[5.2 Worker 本体実装]
-------------------------------------------------------------------------------
実装した主機能:
- SITE_MODE による早期返却
- 入口画面
- 認証画面
- ダウンロード画面
- ID / Pass / Pass2 認証
- 短命セッション Cookie
- D1 による案件管理
- R2 による非公開ファイル配布
- ダウンロード時のみ回数減算
- 監査ログ記録
実装したルート:
- GET /
- POST /auth
- POST /verify
- GET /download
- POST /download
[5.3 D1 / R2 / Cloudflare 実環境反映]
-------------------------------------------------------------------------------
作成または反映した実リソース:
- Worker: resource-portal
- D1: resource-portal-db
- R2: resource-portal-files
- R2 Preview: resource-portal-files-preview
- Custom Domain: resource.area11.org
実施事項:
- wrangler 認証
- Worker secret 登録
- D1 migration 適用
- Worker deploy
- Custom Domain 応答確認
[5.4 管理 CLI 初版]
-------------------------------------------------------------------------------
実装した初期コマンド:
- create-case
- open-site
- close-site
- maintenance-site
- status
create-case の責務:
- 配布元ファイルまたはディレクトリ指定
- tar 化
- OpenSSL 暗号化
- SHA-256 算出
- D1 仮登録
- R2 upload
- D1 有効化
- 管理者向けログ生成
- 受領者向け復号メモ生成
[5.5 対話中断対策と運用補強]
-------------------------------------------------------------------------------
採用した考え方:
- 途中中断時に危険な公開状態を残さない
- 復旧または cleanup できる情報だけを残す
実装した対策:
- ops/pending に途中状態を保存
- D1 仮登録は is_enabled=0
- temp file は中断時 cleanup
- 平文 Pass / Pass2 / 復号 passphrase は永続化しない
追加したコマンド:
- resume-case
- cleanup-pending
[5.6 本番相当テストの実施]
-------------------------------------------------------------------------------
実施内容:
- 実ファイルとして README.md を使用
- テスト案件 CASE20260321A1 を作成
- site_mode を on に切替
- ブラウザから認証、ダウンロード、復号、展開、README 内容確認を実施
検証結果:
- 認証は成功
- 初回のダウンロードは失敗
- 原因調査を実施
- 修正後、ダウンロード成功
- 復号と展開成功
- テスト案件は cleanup 済み
[5.7 追加の運用 CLI 拡張]
-------------------------------------------------------------------------------
後続で追加したコマンド:
- disable-case
- delete-file
- verify-case
- list-cases
- show-case
- show-audit
追加した改善:
- ops/summaries へ .txt と .md の両方を出力
- verify-case で D1 / R2 整合確認
- show-audit で監査ログ確認を容易化
[5.8 認証ガードの追加]
-------------------------------------------------------------------------------
Worker 側へ追加した防御:
- 同一 IP の認証試行数に基づく rate limit
- 同一 IP / 同一 public_id の連続失敗に基づく一時ロック
現在の閾値:
- 10 分で 20 回以上の認証試行 -> 429
- 15 分で 5 回以上の invalid_credentials -> 423
補足:
- 判定には download_audit の client_ip_hash を利用
- 判定用 index を追加 migration で適用
[5.9 テストと CI の追加]
-------------------------------------------------------------------------------
自動テスト:
- Node 標準 test runner を採用
- item-state
- auth-service
- download-service
- request-guard-service
CI:
- GitHub Actions を追加
- npm ci
- npm run check
- npm test
+----------------------------------------------------------------------------------+
| 6. 実装中に発生した主要な問題と対処 |
+----------------------------------------------------------------------------------+
[問題 1]
-------------------------------------------------------------------------------
事象:
- open-site 実行時の deploy で
"The entry-point file at src/index.ts was not found" が発生
原因:
- 一時生成した wrangler 設定ファイルを temp directory に置いていた
- wrangler が config 基準で相対 path を解決するため main = src/index.ts が壊れた
対処:
- 一時設定ファイルを repo 直下へ生成する方式へ変更
対応コミット:
- 4823717 Fix wrangler temp config path handling
[問題 2]
-------------------------------------------------------------------------------
事象:
- 認証成功後の POST /download で
"現在ファイルを取得できません。管理者へ確認してください。" が表示
原因:
- 管理 CLI の R2 操作が local resource を向いていた
- D1 は production、R2 は local という不整合が発生
- Worker から見る production R2 に object が存在しなかった
調査方法:
- download_audit で missing_object を確認
- D1 row の存在確認
- wrangler r2 object get --remote で production 側 object 不在を確認
対処:
- R2 put / delete / get を remote 指定に統一
- production R2 へ object を再投入
- curl により HTTP 200 と hash 一致を確認
対応コミット:
- bfa0b2c Use remote R2 operations in admin CLI
[問題 3]
-------------------------------------------------------------------------------
事象:
- ops/cases/*.json をブラウザで直接開くと日本語が文字化けするケースがあった
原因:
- JSON ファイル自体には charset 指定を持てない
- file:// 表示時のエンコーディング推定に依存していた
対処:
- JSON を UTF-8 BOM 付きで保存
- 読込側は BOM を除去して処理
対応コミット:
- 90efc23 Harden ops file encoding and site mode config
[問題 4]
-------------------------------------------------------------------------------
事象:
- close-site 実行時に
"wrangler.toml から SITE_MODE を置換できませんでした。" が発生
原因:
- 元の wrangler.toml が既に SITE_MODE=off のため
置換後文字列が差分なしとなり、異常扱いしていた
対処:
- 置換前にキー存在だけ確認し、値が同じでも一時 config を生成するよう修正
対応コミット:
- 90efc23 Harden ops file encoding and site mode config
+----------------------------------------------------------------------------------+
| 7. 実施した検証 |
+----------------------------------------------------------------------------------+
[静的確認]
-------------------------------------------------------------------------------
- node --check scripts/admin.mjs
- npm run check
[自動テスト]
-------------------------------------------------------------------------------
- npm test
- 結果: 11 件 pass / 0 fail
[Cloudflare / CLI 確認]
-------------------------------------------------------------------------------
- npm run admin -- status
- npm run admin -- create-case --dry-run
- npm run admin -- open-site --dry-run
- npm run admin -- resume-case --dry-run
- npm run admin -- list-cases
- npm run admin -- verify-case
[本番相当動作確認]
-------------------------------------------------------------------------------
- 実案件作成
- site_mode on への切替
- ブラウザ認証
- ダウンロード
- 復号
- 展開
- テスト案件 cleanup
- site_mode off への復帰
+----------------------------------------------------------------------------------+
| 8. コミット履歴 |
+----------------------------------------------------------------------------------+
85f0074
- Initial commit
b125ed7
- Add admin CLI and deployment docs
- 管理 CLI 初版と Cloudflare 構築関連ドキュメントの追加
4823717
- Fix wrangler temp config path handling
- 一時 wrangler 設定ファイルの配置不備修正
bfa0b2c
- Use remote R2 operations in admin CLI
- R2 local/remote 不整合の修正
90efc23
- Harden ops file encoding and site mode config
- ops JSON の BOM 対応
- SITE_MODE 同値時の temp config 生成修正
2597940
- Add auth guards, admin tools, and CI
- 認証ガード、CLI 拡張、自動テスト、CI、関連文書更新
+----------------------------------------------------------------------------------+
| 9. 現在の成果物 |
+----------------------------------------------------------------------------------+
ソースコード:
- Worker 本体
- D1 migration
- 管理 CLI
- ハッシュ、暗号化、Cloudflare 操作用補助モジュール
ドキュメント:
- README
- 実装済み範囲
- 管理 CLI 文書
- Cloudflare 構築状況
- 管理者向け運用マニュアル
- 仕様書
- 実装計画書
- 対話型スクリプト設計書
テスト / CI:
- Node 標準テスト
- GitHub Actions CI
+----------------------------------------------------------------------------------+
| 10. 現在のシステム状態 |
+----------------------------------------------------------------------------------+
Git 状態:
- branch: main
- local / origin: 同期済み
- worktree: clean
Cloudflare 状態:
- Worker deploy: 済み
- D1 migration: 0001, 0002 適用済み
- Custom Domain: 設定済み
- site_mode(local): off
- site_mode(live): off
- pending(local): 0
セキュリティ関連状態:
- PEPPER 設定済み
- TOKEN_SECRET 設定済み
- 認証失敗ロック有効
- 認証 rate limit 有効
テスト案件:
- 作成、実験、cleanup 済み
- 本番環境に当該テスト案件の D1 row / audit / R2 object は残していない
+----------------------------------------------------------------------------------+
| 11. 現時点で未実装の項目 |
+----------------------------------------------------------------------------------+
現在の未実装事項:
- ダウンロード系の IP rate limit
- ブラウザ E2E テスト
- ops/cases と remote D1 の双方向同期
補足:
- いずれも MVP 運用を阻害するものではない
- ただし継続運用上は次段階の改善対象となる
+----------------------------------------------------------------------------------+
| 12. 第三者への引継ぎ観点 |
+----------------------------------------------------------------------------------+
引継ぎ時に重要な理解ポイント:
1) 本システムは「常時公開」ではなく「必要時のみ公開」が前提
2) 管理操作の主入口は scripts/admin.mjs である
3) create-case 後に verify-case を実行する運用が推奨である
4) 公開前に open-site、終了後に close-site を実行する
5) 障害時は show-audit, disable-case, delete-file の順で切り分け可能
引継ぎ後にまず確認すべき資料:
- README.md
- docs/implemented/manual.txt
- docs/implemented/管理CLI.md
- docs/implemented/Cloudflare構築状況.md
- docs/implemented/実装済み範囲.md
+----------------------------------------------------------------------------------+
| 13. 総括 |
+----------------------------------------------------------------------------------+
当初は仕様書のみの状態から開始し、以下を一体で整備した。
- Worker 実装
- Cloudflare 実環境反映
- GitHub リポジトリ運用
- 管理 CLI
- 運用文書
- 実案件による本番相当検証
- 問題発生時の原因調査と修正
- 自動テスト
- CI
現在の段階では、MVP としての公開運用に必要な機能と運用導線は揃っている。
一方で、長期運用の観点では、E2E テストやダウンロード系 rate limit など、
次段階で着手すべき改善余地も残っている。
総合評価:
- 初期要件に対して、実装、運用、検証、文書化までを含めて完了済み
- 実運用開始可能な水準
- 改善余地は残るが、現時点の構成は十分に引継ぎ可能
+----------------------------------------------------------------------------------+
| End of Report |
+----------------------------------------------------------------------------------+