# 監査ログが書き換えを見つける仕組み：追記専用の記録・ハッシュの連鎖・検査では分からないこと

> OpenStock Japan の監査ログの仕組みを説明します。記録は追記専用で、1 件ごとに直前の記録のハッシュを含めた SHA-256 のハッシュを持ち、途中の書き換え・抜き取りを検査で見つけます。検査では分からないことと、運用で補う方法も書きました。

- 種類: ガイド
- 公開日: 2026年11月11日
- 対象: 管理者・監査を行う方・開発者
- タグ: 監査ログ、セキュリティ、システム監査、内部統制、仕組み
- URL: https://o-stock.org/guides/audit-log

株主名簿には、氏名・住所・持株数が入ります。だれが見て、だれが変えたのかを、あとから確かめられなければ、台帳として信用できません。OpenStock Japan は、すべての変更を監査ログに残し、その記録が書き換えられていないことを検査できるようにしています。この記事では、その仕組みと、仕組みだけでは防げないことを説明します。

## この記事の要点

- 監査ログは追記専用です。更新と削除は、データベースが拒否します
- 記録は 1 件ごとに、直前の記録のハッシュを含めて計算した SHA-256 のハッシュを持ちます。途中の書き換え・抜き取りは、検査で見つかります
- 末尾の記録を消された場合は、検査だけでは分かりません。最新の連番とハッシュを、システムの外に控えておきます
- データベースの管理者は、仕組みそのものを外せます。それを防ぐのは、データベースへのアクセスの管理です

## 何が残るか

監査ログには、3 つの経路で記録が入ります。データの変更は、データベースのトリガーが、変更と同じトランザクションの中で残します。アプリのコードの書き忘れで、記録が抜けることがありません。

表: 監査ログに記録が入る 3 つの経路

| 記録元 | 残るもの | 残し方 |
| --- | --- | --- |
| データの変更 | すべての業務・設定のテーブルの、行の追加・更新・削除。変更前と変更後の値つき | データベースのトリガー |
| 認証 | ログイン（接続元の IP アドレスとブラウザつき）、ログアウト、パスワードの再設定の要求、二要素認証の登録・解除など | 認証サービス（Supabase Auth）のテーブルに付けたトリガー |
| アプリの操作 | ログインの失敗、権限の無い操作の試み、文書のダウンロード、Excel への出力、監査ログの閲覧・出力・検査、AI への送信など | サーバが記録 |

![監査ログの画面。操作した人で絞り込んだ一覧に、ログインや監査ログの閲覧の記録が、連番・メールアドレス・ロール・結果・接続元つきで並んでいる](https://o-stock.org/screens/audit-log.webp)

*画面: 監査ログの画面。見られるのは、管理者と監査人だけです。*

1 件の記録には、次のものが入ります。

- **連番**: 組織ごとに 1 から、データベースが振ります。
- **日時**: データベースのサーバーの時刻です。呼び出し側が渡した時刻は使いません。
- **操作した人**: アカウントの id と、その時点のメールアドレス・ロール。あとでアカウントが消えても、だれだったかが残ります。
- **変更前・変更後の値**: 追加は行の全体、削除は消えた行の全体、更新は変わった項目だけ。
- **結果と接続元**: 成功・失敗・拒否と、IP アドレス・ブラウザ・リクエストの番号。
- **ハッシュ**: この記録と、直前の記録のハッシュから計算した値。

> **補足: 残さないもの**
> パスワード、二要素認証の秘密の値、招待・共有リンクのトークン、AI の API キーは残しません（「（秘匿）」に置き換えます）。AI に送った内容と AI の出力も残しません。

## 書き換えも削除もできないようにする

- 監査ログの更新・削除・全消去は、データベースのトリガーが拒否します。
- アプリが使う権限（`service_role`）からも、更新・削除の権限を外しています。
- ブラウザからは、読むことも書くこともできません。
- 操作した人は、サーバがセッションを確かめて決めます。ブラウザが送ってきた値は使いません。

本番に入れたら、実際に書き換えを試して、拒否されることを確かめておきます。

書き換えが拒否されることを確かめる（SQL）:

```sql
set role service_role;
update system_audit_logs set detail = 'x' where seq = 1;  -- permission denied になること
reset role;
```

## 記録をハッシュでつなぐ

追記専用にしても、データベースに直接つなげる人なら、記録を書き換えられるかもしれません。そこで、書き換えられたことを、あとから見つけられるようにします。記録のたびに、「直前の記録のハッシュ + この記録の内容」から SHA-256 のハッシュを計算して、一緒に残します。

> **図: 上は、正しくつながった記録。下は、途中の 1 件を書き換えたとき。そこから先の計算が合わなくなります（ハッシュの値は例です）。**
> 監査ログの記録が、連番とハッシュで鎖のようにつながっている図。それぞれの記録は、直前の記録のハッシュを含めて自分のハッシュを計算する。連番 543 の記録の内容を書き換えると、543 のハッシュが変わり、それを含めて計算している 544 以降のハッシュも、残っている値と合わなくなる。

ハッシュは、内容が 1 文字でも変わると、まったく違う値になります。途中の 1 件を書き換えたり抜いたりすると、その記録から先のハッシュが、計算し直した値と合わなくなります。

## 検査する

1. **「改ざんの検査」を開く** — サイドバーの「監査ログ」を開き、「改ざんの検査」のタブを選びます。
2. **「検査する」を押す** — 最初の記録から順に計算し直して、連番の飛びと、ハッシュの食い違いが無いかを確かめます。記録が多いと、時間がかかることがあります。
3. **結果を控える** — 検査のあとに表示される「最新の連番」と「最新のハッシュ」を、月次の記録など、このシステムの外に控えます。

![改ざんの検査の結果。「書き換え・抜き取りは見つかりませんでした」の見出しの下に、確かめた件数、最新の連番、最新のハッシュ（64 文字）と「連番とハッシュをコピー」のボタン、検査した日時が表示されている](https://o-stock.org/screens/audit-result.webp)

*画面: 検査の結果。最新の連番とハッシュは、ボタンでコピーできます。*

計算が合わないときは、最初に合わなくなった連番と、その理由（連番の飛び・前の記録とのつながり・記録の内容）が分かります。検査をしたことと、その結果も、監査ログに残ります。

## 検査では分からないこと

この仕組みには、限界があります。監査の説明では、正直に伝える必要がある点です。

- **末尾の記録を消された場合。** 連鎖が見つけるのは、途中の変更です。いちばん新しい側が消えても、残った記録どうしの計算は合ったままです。
- **データベースの管理者は、何でもできます。** データベースに管理者としてつなげる人は、トリガーを外して、すべてを作り直せます。ツールが防げるのは、アプリ経由の書き換えまでです。
- **画面で見たことは、記録しません。** 記録するのは、変更・ダウンロード・出力・ログインです。「だれがどの株主の画面を開いたか」までは残りません。
- **承認の流れはありません。** 登録した人と別の人が承認する仕組みは無いので、重要な登録は、あとから監査ログで確かめる運用になります。

> **注意: 最新の連番とハッシュを外に控えてください**
> 末尾の削除と、作り直しを見つける方法は、控えとの照合です。次に検査するとき、控えておいた連番とハッシュを「控えと照合する」の欄に入れると、その連番の記録がいまも残っていて、ハッシュが同じかどうかを確かめられます。同じであれば、そこまでの記録は変わっていません。

ほかの限界（ログインのロック、接続元の IP アドレス、Cookie の扱いなど）は、文書「[システム監査への対応](https://github.com/japan-gx-group/open-stock-japan/blob/main/docs/system-audit.md)」の「このツールだけでは担保できないこと」に、すべて書いています。

## 定期的に行うこと

仕組みは、使って初めて役に立ちます。運用する会社が行うことを、間隔ごとにまとめます。

表: 監査ログまわりで、定期的に行うこと

| 間隔 | 行うこと |
| --- | --- |
| 毎月 | 改ざんの検査をし（前回の控えと照合する）、最新の連番とハッシュを別の場所に控える |
| 毎月 | 権限エラーとログインの失敗が増えていないかを、監査ログで見る |
| 四半期ごと | アカウントの棚卸し（退職・異動した人のアカウント、ロールの範囲、二要素認証の有無） |
| 人の出入りのつど | 退職・異動した人のアカウントを消す、ロールを変える |
| 年 1 回 | バックアップからの復元を試す |

手元で試すには、ガイド「[デモの会社を、手元で動かす](https://o-stock.org/guides/local-demo)」の手順でデモの環境を用意し、監査人のアカウント（`audit@example.com`）で入ってください。

---

画面は、架空の会社のデモデータで撮影したものです。画面に出る期限・要件の判定は実務の目安であり、法的な助言・税務の助言ではありません。
