機能の全体像/ A bird's-eye view
松葉 / Matsuba は、利用者向けの機能 28 種と、管理者向けの機能 5 群、そして裏方で動く自動メンテナンスの 18 種で構成されます。それぞれの機能には設計書上の機能 ID(FE-*)が振られており、要件 ID(F-*)と双方向にトレースできます。
利用者向け機能For users
社内ユーザ・社外ユーザの双方が日常的に使う機能群です。アカウント、Box、ファイル、共有リンク、通知の 5 カテゴリ・全 28 機能で構成しています。
アカウントと認証Account & Auth
認証
社内は Google SSO(hd=example.com 強制 + サーバ側ドメイン再検証)、社外はメール+パスワード or Google を選択可。自己サインアップは禁止し、招待制で運用します。
MFA(多要素認証)
社外ユーザ全員に毎ログイン 6 桁のメール OTP を要求します。信頼デバイスは 30 日、バックアップコードは 10 桁 × 10 個。OTP を続けて誤ると 15 分ロック。
プロフィール
表示名 / 企業名 / 企業タグ(複数)/ 所属 / 電話番号を本人が編集します。個人情報カラムは将来 pgsodium で透過暗号化する雛形を持ちます。
アカウントライフサイクル
退職時は無効化(履歴は保全)、未アサインユーザ管理、5 年経過後に system_admin の承認で完全消去。Google Workspace と日次で同期します。
Box(共有箱)Box
Box の作成・編集・無効化・削除
Better Auth の organizations テーブルを単一管理場所として使用します。論理削除 → 30 日後物理削除。
メンバーとロール
Viewer / Uploader / Editor / Owner の 4 ロール。Box アサイン時にメール招待を送付、Owner 譲渡も可能です。参加申請の承認・却下もここで処理します。
Box 一覧・検索
社内ユーザは internal_searchable / internal_open の Box を非メンバーでも発見できます。pg_trgm(部分一致拡張)で trigram 検索。
Drive 同期・保持・アーカイブ設定
Drive 同期 ON/OFF、同期先フォルダ ID、Box 単位の保持期間(30 / 90 / 180 / 365 / 無制限)、世代数を設定します。
Box 可視性(3 段階)
members(既定)/ internal_searchable / internal_open。社外ユーザに対しては可視性問わずメンバーのみ。RLS で 4 テーブル群を制御します。
参加申請
社内非メンバーが internal_searchable / internal_open Box へ参加申請を送信。Owner が承認 / 却下、一定期間の経過で自動取り下げ。
ホーム「最近のファイル」
直近 30 日にアクセスした上位 10 ファイルをウィジェットで表示。データソースは user_file_reads.last_read_at。
Box アクティビティ
Box メンバー向けの read-only 履歴タブ。audit_logs を SECURITY DEFINER ヘルパで正規化し、IP / User-Agent などの内部情報を除外して提示します。
ファイルとフォルダFiles & Folders
アップロードと世代管理
V4 Signed URL + tus-js-client で 未検査バケットへ Resumable 直送。差し替えは世代追加(最新 + 10 世代)。最大 200 MB。
フォルダ・ゴミ箱
サブフォルダ CRUD、論理削除 30 日 → 物理削除 → Drive ゴミ箱送り。trash-cleanup-daily ジョブが日次で実行。
バッジ表示
未読 / 差し替え済み / コメントあり / Drive 消失 / 保持期限残日数(30 / 7 / 1 日でグレー・黄・赤) / Hold 設定済み。
ロール別操作可否
アプリ層(Hono ミドルウェア) + DB 層(RLS)の二重防御。Uploader は「自分がアップロードしたファイルのみ」削除可。
コメント
Box メンバー間でコメントを共有。投稿時にアプリ内通知(メール送付は任意)。
プレビュー
PDF(@react-pdf-viewer/core)/ 動画・音声(react-player)/ 画像(next/image)/ Office(Drive Viewer の iframe)。短時間だけ有効な署名 URL 経由。
ウイルススキャン
クライアントとサーバ両方で拡張子・MIME・マジックバイトを検証し、その後 ClamAV 1.4 が未検査 → 検査済み / 隔離バケットへ rewrite します。マクロ Office と旧 Office 形式は拡張子レベルで拒否。
保持関連 UI
残日数バッジ、Editor / Owner による個別 Hold(理由必須)、アクセスで last_accessed_at 更新 → 期限延長(ローリングウィンドウ)、UL 直後 30 日凍結期間。
Box 内検索
pg_trgm の trigram + ILIKE による部分一致検索。対象はファイル名・フォルダ名・タグ・説明文・アップローダ名。タグナビ(?tag=...)は nuqs 経由。
一括ダウンロード
複数選択 ZIP DL とフォルダ ZIP DL。共有リンクと同じしきい値(合計 200 MB または 10 ファイル超)。folder-zip-builder Job が共有 ZIP バケット(一定期間で自動削除)に配置します。
アーカイブ
ファイル / フォルダの disabled 状態(UI 表示のみ)。GCS Lifecycle 実体移行はリリース後拡張で雛形のみ用意します。
共有リンクShare Link
共有リンク(Box 外への一時共有)
32 桁ランダムトークン、最長 14 日、パスワード(任意) / DL 回数制限 / 受取人メール OTP(6 桁) / 即時無効化に対応します。CDN キャッシュ無効化 + レート制限。発行と同時に Resend で受取人にメール送付(カスタムメッセージ最大 1000 文字)。パスワード保護時は「別チャネルで連絡」の注意書きを必ず本文に含めます。
通知Notifications
メール通知
Resend + react-email + Handlebars テンプレ。配信モードは immediate(即時) / digest(30 分単位の時刻指定) / off から選択。Box ごとの上書き設定にも対応。
アプリ内通知バッジ
通知センター、未読件数、NEW / UPDATED / COMMENT バッジ。user_file_reads で既読管理し、「すべて既読」アクションも提供します。
削除関連通知
自動削除当日(Owner + UL者 + 最終アクセス者、immediate 強制) / Owner 向け週次「今週削除予定」 / 全社デフォルト変更時の Box Owner 全員通知 / 招待 3 回連続バウンスでの警告。
管理者向け機能For administrators
system_admin(システム管理者)が日々の運用を行う /admin 配下の 17 ページ群です。ヘルスサマリ・ストレージ・ユーザ・Box・保持・スキャン・隔離・同期・共有リンク・監査・通知・アラート・各種設定がアプリ内に集約され、Google Cloud コンソールに毎回入る必要はありません。
| URL | 画面 | 主な役割 |
|---|---|---|
/admin | ダッシュボード | ヘルスインジケータ 6 観点(信号機方式)+ 主要 KPI 6 種 + 未対応アラート件数 |
/admin/storage | ストレージ管理 | バケット別 / Box 別 / ユーザ別の使用量、12 ヶ月推移、増加率予測、大ファイル一覧 |
/admin/users | ユーザ管理 | 無効化 / 再有効化 / MFA リセット / 全セッション失効 / 退職者一括 CSV 取り込み |
/admin/boxes | Box 管理 | 死蔵 Box(90 日無操作)/ 大容量 Box / Drive 設定異常 / Hold 合計バッジ表示 |
/admin/retention | 保持期間運用 | 削除予定キュー / Hold 一覧 / 全社・Box デフォルト編集 / 影響シミュレーション |
/admin/scan-queue | スキャン状態 | 5 分以上 scanning 滞留 / failed 一覧 / シグネチャ DB バージョン / 手動再スキャン |
/admin/quarantine | 隔離ファイル | ClamAV 感染検出ファイルの参照 / 専用 SA で取り出し / 恒久削除 |
/admin/sync | Drive 同期管理 | 同期ジョブ状態 / DLQ 個別・一括再投入 / Drive クォータ / 失敗集計 |
/admin/drive-orphans | Drive 管轄外検知 | Drive 上「アプリ管轄外」一覧 / Box 担当者通知導線 |
/admin/share-links | 共有リンク全社一覧 | 全社の共有リンク / ブルートフォース検知 / 即時無効化 / 期限切れ間近のハイライト |
/admin/audit | 監査ログ | 閲覧 / 絞り込み / CSV エクスポート(オンライン + GCS 退避の二段構え) |
/admin/notifications | 通知状況 | 配信失敗 / Resend クォータ / テンプレ使用状況 / ゼロベース通知履歴 |
/admin/alerts | アプリ層アラート | 感染検出 / DLQ / Drive 同期失敗継続 / 共有リンクブルートフォース / Resend バウンス / ストレージ / Billing の 7 種 |
/admin/settings/templates | 通知テンプレ編集 | テンプレ CRUD / プレビュー / 変数挿入 / グローバル + Box 別テンプレ |
/admin/settings/extensions | 許可拡張子管理 | 許可 / 拒否拡張子の編集、system_settings 保存で実行時上書き |
/admin/settings/retention-defaults | 全社デフォルト保持期間 | 180 日初期値の編集 + 影響シミュレーション + Box Owner 全員への通知 |
/admin/settings/maintenance | メンテナンスモード | ON/OFF 切替で全リクエストを 503 化、告知バナー編集 |
重大操作の二重チェック: 隔離ファイル取り出し / ユーザ無効化 / MFA リセット / 全セッション失効 / 保持期間変更 / メンテナンスモードといった重大操作は、理由テキストの入力が必須で、実行と同時に system_admin 全員にメールで通知され、監査ログに actor_type='system_admin' で残ります。
自動メンテナンス(裏方)Background jobs
ユーザの目には触れませんが、20 年運用を支える 18 種類の定期バッチを単一の Cloud Run Jobs サービス docshare-batch に統合しています。実行間隔は Cloud Scheduler から指示し、--args でジョブ種別を振り分けます。
| ジョブ | 頻度 | 役割 |
|---|---|---|
outbox-dispatcher | 1 分 | Outbox テーブルの未送信イベントを Pub/Sub に publish |
dlq-monitor | 5 分 | Dead Letter Queue の件数監視、しきい値超で critical アラート |
digest-worker | 30 分 | 該当時刻のユーザの digest 通知をまとめて送信 |
retention-deletion-daily | 日次 | 保持期限切れファイルの論理削除と当日メール通知 |
trash-cleanup-daily | 日次 | 論理削除 30 日経過分の物理削除と Drive ゴミ箱送り |
drive-repair | 日次 | Box 単位の並列処理で Drive 側の差分補修・orphan 検知・削除検知 |
admin-metrics-aggregator | 日次 | storage / user_activity / box_activity を集計し materialized view 更新 |
retention-warning-aggregator | 日次 | 「今週削除予定」を Box Owner 向け週次サマリ生成 |
expired-invitations-cleanup | 日次 | 一定期間を過ぎた招待 / 参加申請を自動失効 |
workspace-directory-sync | 日次 | Google Workspace Directory を読んで在籍状態をユーザに反映 |
version-cleanup-weekly | 週次 | Box 設定の世代数を超えた旧バージョンを GCS から削除 |
drive-archive-sync | 週次 | Drive アーカイブの exists_in_drive を週次で更新 |
audit-log-partition-rotator | 月次 | 25 ヶ月超のパーティションを GCS archive class へ退避し DROP |
notifications-cleanup-monthly | 月次 | 1 年経過の通知履歴を単純 DELETE |
clamav-eicar-test | 月次 | EICAR テストファイルを自動 UL → 検出確認の E2E |
disabled-user-cleanup-5y | 月次 | 5 年経過の無効化ユーザを system_admin 承認のうえ完全消去 |
jwks-rotator | 年次 | Better Auth の JWT 鍵を年次ローテ、旧鍵を一定期間並行公開して無停止切替 |
share-link-cleanup | 5 分 | 失効期日を過ぎた共有リンクを revoked 化 |
特筆すべき機能特性Notable characteristics
上に挙げた個々の機能のうち、本サービスを「これまでの社内アプリ」と分ける 4 つの特性です。詳細は構成・運用 ページで取り上げます。
社外ユーザ全員にメール OTP MFA を必須化
外部ユーザを社内アプリのように扱う前提で、SMS は採用せず、全員にメール OTP の二要素認証を必須としました。信頼デバイス 30 日で日常的な負担も最小化します。
5 バケット経由のウイルス検査を通過してから利用可能
ファイルアップロード直後は 未検査バケットに置かれ、ClamAV のスキャンを経て 検査済みバケットに rewrite されたタイミングで初めてユーザに開示されます。感染が検出されると 隔離バケットに隔離されます。
監査ログを「追記専用」RLS で UPDATE/DELETE 拒否
監査ログテーブルは PostgreSQL の RLS(行レベルセキュリティ)で UPDATE と DELETE を拒否しています。Supabase 自動バックアップ + 25 ヶ月超のパーティション GCS 退避と合わせて、20 年運用に耐える完整性を確保します。
Drive 直接アップロード・Drive 側削除も日次バッチで検知
Drive 側でアプリ管轄外のファイルが追加されたり、アプリ管轄ファイルが削除されたりした場合、日次バッチが appProperties.docshare_* を使って検出し、UI に「⚠️ Drive から消えています」を表示します。