プレミアリーグU-11 アプリ / データ蓄積基盤

規約の判定と、蓄積のためのデータモデル

現行の利用規約(2026年4月1日施行)とプライバシーポリシーを読んだうえでの、コンディション機能の実装可否判定と、縦断データを貯めるためのスキーマ設計です。

判定:全面改定は不要。追記で足ります。

利用目的に「競技成長管理」「データ分析」「研究・教育」「スポンサー連携」が既にあり、取得項目にも身体情報(身長・体重・怪我・睡眠・体調)が明記されています。スポンサーへの提供も「原則として匿名加工情報または統計情報のみ」と先回りして書かれている。基礎はできています。 ただし口腔・歯科まわりに4つの穴があり、うち2つは着手前に必ず塞ぐ必要があります。

Part 1 / 現行規約の棚卸し

すでに書かれていて、そのまま使えるもの

追加の同意取得なしに実装できる範囲です。プロトタイプで言えば 01 ホーム・04 マウスガード・05 学ぶ・07 指導者ビューはここに収まります。

使える

身長・体重・睡眠・体調の取得

PP 第4条3項 / 規約 第5条
身体情報 身長、体重、怪我情報、睡眠、体調等(任意入力)」
選手成長記録機能(身体計測記録、サッカーノート、ライフログ)」

成長記録はそのまま実装可能です。任意入力と明記されている点も適切。マウスガードの交換判定は身長データから導出するので、04 マウスガード管理も現行規約の範囲で作れます

使える

研究・教育、データ分析、スポンサー連携という利用目的

PP 第6条

9つの利用目的のうち「データ分析」「研究・教育」「スポンサー連携」が既に入っています。これは大きい。全国集計レポート(プロトタイプ08)を出す根拠が最初から用意されている状態です。

多くのサービスがここで詰まって規約を作り直します。先回りして書かれています。

使える

スポンサーへの提供は匿名加工・統計のみ

PP 第8条
「スポンサー企業には(略)原則として匿名加工情報または統計情報のみ提供します」
「ただし以下は提供しません:健康情報、AIチャット内容、コンディション情報

個票を出さない線引きが明文化済み。SCOとの交渉でも「規約でこう約束しています」と言えるので、むしろ守りの材料になります

使える

16歳未満は保護者同意、保護者→子アカウント構造

PP 第13条 / 規約 第3条2項・第8条4項

同意の主体が保護者であること、保護者が閲覧・修正・削除を請求できることが明記済み。データモデルの guardiansconsents はこの構造をそのまま実装します。

使える

退会後も匿名データは継続利用できる

PP 第17条 / 規約 第16条2項
「匿名化された統計データは引き続き利用されることがあります」

縦断データの土台になります。卒業後もアカウントが使える設定になっているとのことなので、個票の継続保有と匿名統計の永続利用が両方成立します。ここは想定より条件が良い。

使える

越境移転・事業承継・AI利用

PP 第7条・第14条・第19条

クラウドや分析サービスが海外にある前提が書かれています。分析基盤の選定で詰まりません。

Part 2 / 穴

塞がないと着手できないもの

4件。上2件は必須、下2件は口腔内写真や歯科ブースを扱う段階までに必要です。

必須

取得項目に口腔・歯科が入っていない

PP 第4条3項

身体情報は「身長、体重、怪我情報、睡眠、体調」。口腔セルフチェックの回答、歯の生え替わり記録、歯科の受診歴、口腔内写真を「体調等」に読み込ませるのは無理があります。利用目的の特定は具体的でなければならないので、「等」で押し切ると後で全部が使えなくなる。

ここが最大の穴です。1文の追記で塞げます。

PP 第4条3項 追記案

3 身体情報
- 身長、体重、怪我情報、睡眠、体調等(任意入力)
+ 身長、体重、怪我情報、睡眠、体調、口腔に関する情報
+ (セルフチェックの回答、歯の生え替わりの記録、歯科受診の有無、
+ マウスガードの使用状況、口腔内の写真を含みます)等(任意入力)
必須

要配慮個人情報の取扱いが定義だけで終わっている

PP 第3条(定義のみ)

第3条で用語定義はしていますが、取得する旨・同意の取り方・利用範囲の条項がありません。ここで線引きが要ります。

データ要配慮個人情報か必要な同意
保護者のセルフチェック回答
(口が開いている、喉が渇く 等)
該当しない可能性が高い。医師の診療結果でも健康診断結果でもなく、保護者の観察の自己申告取得項目への追記で足りる
歯科の受診歴グレー。病歴に近づく安全側に倒して個別同意
大会の歯科ブースでの検診結果明確に該当。医師等による診療・健診の結果個別の明示同意が必須。オプトアウト不可

前回「健康情報=要配慮個人情報」とまとめて書きましたが、正確にはこの3段階です。セルフチェックだけなら軽く、歯科医が関わった瞬間に重くなります。実装順序に直結するので、ここを分けて設計します。

写真を扱う前に

スポンサーへの写真利用許諾が広すぎる

PP 第12条2項 / 規約 第9条3項
「当社は、選手の容貌が判別できる写真または動画を、広報活動目的で、スポンサーに利用させることができるものとします」

広報用の試合写真を想定した条項ですが、文言上口腔内写真がここに読み込まれかねません。歯の記録(プロトタイプ03)を実装するなら、除外を明記してください。

PP 第12条 追記案(新3項)

+ 3 前項にかかわらず、口腔内の写真その他健康状態の記録を目的として
+ 取得した画像は、広報活動およびスポンサーへの提供の対象外とします。

なお規約 第9条3項は「いつでも同意を撤回できる」と書かれていて、この点は適切です。

07を実装する前に

指導者の閲覧範囲が広い

PP 第10条
「所属チームの指導者またはリーグ運営者が、選手の競技記録・試合データ・成長記録等を閲覧できる場合があります」

プロトタイプ07は「指導者には実施率だけ、個人の回答は見せない」設計にしました。現行条文は成長記録まで閲覧可能と読めるので、仕様と規約が食い違います

子どもの健康情報がチーム内の起用判断に流れないようにするのは仕様の根幹なので、規約側を仕様に合わせてください。

PP 第10条 追記案

+ ただし、口腔に関する情報その他健康状態に関する情報については、
+ 指導者は個々の選手の内容を閲覧できないものとし、
+ チーム単位の実施状況のみを閲覧できるものとします。

ついでに足しておくと後が楽になるもの

  • 保存期間の明記 — PPに記載がありません。卒業後も追跡するなら「登録抹消後◯年」を書いておく。縦断データの根拠が強くなります
  • 匿名加工情報の作成と公表 — 第3条で定義していますが、作成する旨と法定の公表義務の履行方法が未記載
  • 共同利用 — SCOと共同利用の枠組みを取るなら、項目・範囲・管理責任者を事前に公表する必要があります。後付けはできません。ただし匿名加工情報での提供で足りるなら、この枠組みは不要です

条文の当てはめは弁護士確認を

上記は公開されている規約・ポリシーを読んだうえでの整理です。特にセルフチェック回答が要配慮個人情報にあたらないという判断は、設問の書きぶり次第で変わり得ます。スキーマを固める前に1回レビューを入れてください。設計に入ってからの手戻りより、はるかに安く済みます。

Part 3 / データモデル

縦断データを貯めるためのスキーマ

卒業後もアカウントが使える前提で設計しています。設計上の争点は5つ。

選手と所属を分ける

players は永続、enrollments が年度・カテゴリ・チームを持ちます。これで小5を卒業してもIDが生き、U-10 → U-11 → その先が1本の線としてつながります。

選手テーブルにチームIDを持たせてはいけません。 持たせた瞬間に縦断データが作れなくなります。

同意は追記のみ。UPDATEしない

consents は付与も撤回も新しい行として積みます。「今の同意状態」はビューで導出。

過去のある時点の同意状態を再現できないと、そのとき集めたデータの適法性を証明できません。 上書きした瞬間に証明手段が消えます。

同意した規約の版を特定できるようにする

policy_documents に本文ハッシュと施行日を持ち、consents から参照します。規約は必ず改定されるので、「この人が同意したのはどの文面か」が後から言えることが要ります。

設問にバージョンを振る

セルフチェックの設問は必ず変わります。oral_check_questions を版管理し、回答は版を参照。文言が変わっても過去と比較できます。

要配慮は別テーブルに隔離する

歯科医による検診結果は clinical_screenings に分離。暗号化・アクセスログ・保存期間・権限がすべて他と違うので、同じテーブルに混ぜると全体が重くなります。

匿名加工は片方向

anon_factsplayer_id を持ちません。個票へ戻れないことが匿名加工情報の要件です。生成時のk値を anon_batches に記録します。

erDiagram
  players ||--o{ enrollments : "年度ごとの所属"
  players ||--o{ measurements : "身長体重"
  players ||--o{ oral_check_sessions : "月次チェック"
  players ||--o{ dentition_records : "歯式"
  players ||--o{ mouthguards : "用具"
  players ||--o{ clinical_screenings : "歯科検診"
  players ||--o{ media_assets : "画像"
  guardians ||--o{ guardian_links : ""
  players ||--o{ guardian_links : ""
  guardians ||--o{ consents : "同意の主体"
  players ||--o{ consents : "対象"
  consent_purposes ||--o{ consents : "目的"
  policy_documents ||--o{ consents : "同意時の版"
  oral_check_sessions ||--o{ oral_check_answers : ""
  oral_check_questions ||--o{ oral_check_answers : "設問の版"
  anon_batches ||--o{ anon_facts : "生成バッチ"

  players {
    uuid id PK
    date birth_date
    char sex
    text status
    date graduated_on
  }
  enrollments {
    uuid id PK
    uuid player_id FK
    int season
    text category
    uuid team_id
  }
  consents {
    uuid id PK
    uuid guardian_id FK
    uuid player_id FK
    text purpose_code FK
    uuid policy_id FK
    text action
    timestamptz acted_at
  }
  measurements {
    uuid id PK
    uuid player_id FK
    text metric
    numeric value
    date observed_on
    uuid superseded_by
  }
  clinical_screenings {
    uuid id PK
    uuid player_id FK
    date screened_on
    text provider
    jsonb findings
  }
  anon_facts {
    uuid id PK
    uuid batch_id FK
    text cohort_key
    text metric
    numeric value
    int n
  }
      

主要テーブルの役割

テーブル役割設計上の注意
players選手の永続マスタチーム・学年を持たせない。 卒業後も行を消さず status で表現
enrollments年度×カテゴリ×チームの所属履歴1選手に複数行。移籍もここで表現
guardians / guardian_links保護者と紐付け両親の2アカウント、兄弟の複数子に対応
policy_documents規約・PPの版管理本文ハッシュを持つ。改定のたびに新行
consent_purposes同意目的のマスタ成長記録/口腔チェック/統計利用/広告受信/歯科検診 を個別に
consents同意ログ(追記型)UPDATE・DELETE禁止。 撤回も新行
measurements身長・体重など時系列上書きしない。訂正は新行+superseded_by
oral_check_questions設問の版管理codeversion。文言変更でも比較可能に
oral_check_sessions / _answers月次チェックの実施と回答算出した「サイン件数」は保存せず、都度導出
dentition_records歯式(歯の位置ごとの状態)FDI歯式番号で持つ。観察日つきの追記型
mouthguards使用開始・終了・交換理由交換判定はmeasurementsと結合して導出
clinical_screenings要配慮個人情報別スキーマ/別権限/列暗号化/アクセスログ必須
media_assets口腔内写真等既定は端末内。アップロードは同意時のみ、広報利用フラグは常にfalse
sensitive_access_logs閲覧記録要配慮に触れた操作は全件記録
anon_batches / anon_facts匿名加工の集計系統player_idを持たない。 k値と加工方法を記録

Part 4 / DDL

PostgreSQL

新設分のみ。既存の teams 等は参照だけしています。

01_identity.sql — 選手の永続化

-- 選手は永続。卒業しても行は消さない。所属は enrollments が持つ。
CREATE TABLE players (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  birth_date    date        NOT NULL,
  sex           char(1),
  status        text        NOT NULL DEFAULT 'active'
                CHECK (status IN ('active','graduated','withdrawn','deleted')),
  graduated_on  date,
  created_at    timestamptz NOT NULL DEFAULT now()
);

-- 年度ごとの所属。移籍・カテゴリ変更もここで表現する。
CREATE TABLE enrollments (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id   uuid NOT NULL REFERENCES players(id),
  season      int  NOT NULL,
  category    text NOT NULL,   -- 'U-10' | 'U-11' | ...
  team_id     uuid NOT NULL,
  prefecture  text NOT NULL,
  jersey_no   int,
  UNIQUE (player_id, season, category)
);

CREATE TABLE guardians (
  id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  email      citext NOT NULL UNIQUE,
  created_at timestamptz NOT NULL DEFAULT now()
);

-- 両親2アカウント、兄弟の複数子に対応するため多対多。
CREATE TABLE guardian_links (
  guardian_id uuid NOT NULL REFERENCES guardians(id),
  player_id   uuid NOT NULL REFERENCES players(id),
  relation    text,
  PRIMARY KEY (guardian_id, player_id)
);

02_consent.sql — 同意(追記型・改変禁止)

-- 同意した時点の規約文面を特定できるようにする。
CREATE TABLE policy_documents (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  kind          text NOT NULL CHECK (kind IN ('terms','privacy')),
  version       text NOT NULL,
  body_sha256   text NOT NULL,
  effective_on  date NOT NULL,
  UNIQUE (kind, version)
);

-- 目的は必ず個別に。まとめて1つにしないこと。
CREATE TABLE consent_purposes (
  code            text PRIMARY KEY,
  label           text NOT NULL,
  is_sensitive    boolean NOT NULL DEFAULT false,
  default_granted boolean NOT NULL DEFAULT false
);
INSERT INTO consent_purposes VALUES
  ('growth_record',   '成長の記録',               false, true ),
  ('oral_selfcheck',  '口腔セルフチェック',       false, false),
  ('clinical_screen', '歯科検診の結果',          true,  false),
  ('anon_stats',      '匿名統計としての利用',     false, false),
  ('ad_optin',        '歯科医院の案内の受信',     false, false);

-- 付与も撤回も追記。UPDATE / DELETE は行わない。
-- 「現在の状態」は下のビューで導出する。
CREATE TABLE consents (
  id           uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  guardian_id  uuid NOT NULL REFERENCES guardians(id),
  player_id    uuid NOT NULL REFERENCES players(id),
  purpose_code text NOT NULL REFERENCES consent_purposes(code),
  policy_id    uuid NOT NULL REFERENCES policy_documents(id),
  action       text NOT NULL CHECK (action IN ('grant','withdraw')),
  acted_at     timestamptz NOT NULL DEFAULT now(),
  ip_hash      text,
  ui_surface   text
);
CREATE INDEX ON consents (player_id, purpose_code, acted_at DESC);

-- 現在の同意状態。過去の任意時点も acted_at で絞れば再現できる。
CREATE VIEW v_consent_now AS
SELECT DISTINCT ON (player_id, purpose_code)
       player_id, purpose_code, action, acted_at
FROM consents
ORDER BY player_id, purpose_code, acted_at DESC;

03_records.sql — 記録(時系列・追記型)

-- 上書きしない。訂正は新しい行を入れて旧行に superseded_by を張る。
CREATE TABLE measurements (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id     uuid NOT NULL REFERENCES players(id),
  metric        text NOT NULL CHECK (metric IN ('height_cm','weight_kg')),
  value         numeric(5,1) NOT NULL,
  observed_on   date NOT NULL,
  recorded_by   uuid REFERENCES guardians(id),
  superseded_by uuid REFERENCES measurements(id),
  created_at    timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX ON measurements (player_id, metric, observed_on);

-- 設問は版管理する。文言を変えても過去と比較できるように。
CREATE TABLE oral_check_questions (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  code        text NOT NULL,      -- 'mouth_breathing' 等
  version     int  NOT NULL,
  body        text NOT NULL,
  flag_answer text NOT NULL,      -- サインとして数える回答
  retired_at  timestamptz,
  UNIQUE (code, version)
);

CREATE TABLE oral_check_sessions (
  id           uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id    uuid NOT NULL REFERENCES players(id),
  answered_by  uuid NOT NULL REFERENCES guardians(id),
  period_ym    date NOT NULL,      -- 月初日で保持
  completed_at timestamptz,
  UNIQUE (player_id, period_ym)
);

-- 「サイン◯件」は保存しない。設問版と結合して都度導出する。
-- 判定ロジックを変えたとき、過去分も新ロジックで見直せる。
CREATE TABLE oral_check_answers (
  session_id  uuid NOT NULL REFERENCES oral_check_sessions(id),
  question_id uuid NOT NULL REFERENCES oral_check_questions(id),
  answer      text NOT NULL CHECK (answer IN ('yes','no','unknown')),
  PRIMARY KEY (session_id, question_id)
);

-- FDI歯式番号(11-48)。観察日つきの追記型。
CREATE TABLE dentition_records (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id   uuid NOT NULL REFERENCES players(id),
  tooth_fdi   int  NOT NULL,
  state       text NOT NULL CHECK (state IN ('primary','erupting','permanent','missing')),
  observed_on date NOT NULL
);
CREATE INDEX ON dentition_records (player_id, observed_on DESC);

-- 交換目安は measurements と結合して導出する(保存しない)。
CREATE TABLE mouthguards (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id     uuid NOT NULL REFERENCES players(id),
  started_on    date NOT NULL,
  ended_on      date,
  end_reason    text,
  height_at_fit numeric(5,1)
);

04_sensitive.sql — 要配慮個人情報(隔離)

-- 別スキーマに置き、アプリの通常ロールからは触れないようにする。
CREATE SCHEMA sensitive;
REVOKE ALL ON SCHEMA sensitive FROM app_readwrite;

-- 歯科医による検診結果。取得には個別の明示同意が必須。
CREATE TABLE sensitive.clinical_screenings (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id   uuid NOT NULL,
  screened_on date NOT NULL,
  event_id    uuid,                    -- 大会ブース等
  provider    text NOT NULL,           -- 実施した歯科医院
  findings    bytea NOT NULL,          -- 列暗号化して格納
  consent_id  uuid NOT NULL,           -- 根拠となる同意レコード
  retain_until date NOT NULL
);

-- 口腔内写真。既定は端末内保存。アップロードは同意時のみ。
CREATE TABLE sensitive.media_assets (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  player_id     uuid NOT NULL,
  kind          text NOT NULL CHECK (kind IN ('intraoral','other')),
  storage_key   text NOT NULL,
  captured_on   date NOT NULL,
  consent_id    uuid NOT NULL,
  -- PP第12条の広報利用の対象外であることをスキーマで固定する
  promo_allowed boolean NOT NULL DEFAULT false
                CHECK (promo_allowed = false)
);

-- 要配慮に触れた操作は全件記録する。
CREATE TABLE sensitive.access_logs (
  id         bigserial PRIMARY KEY,
  actor_id   uuid NOT NULL,
  actor_role text NOT NULL,
  player_id  uuid NOT NULL,
  resource   text NOT NULL,
  action     text NOT NULL,
  at         timestamptz NOT NULL DEFAULT now()
);

05_anonymized.sql — 匿名加工(片方向)

-- 生成のたびに1バッチ。加工方法とk値を必ず残す。
CREATE TABLE anon_batches (
  id          uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  generated_on date NOT NULL,
  method      text NOT NULL,
  k_anonymity int  NOT NULL CHECK (k_anonymity >= 10),
  source_note text NOT NULL,
  published_at timestamptz          -- 法定の公表を行った日時
);

-- player_id を持たない。個票へ戻れないことが匿名加工情報の要件。
-- cohort_key は 都道府県 x 学年 x 性別 のように粒度を固定する。
CREATE TABLE anon_facts (
  id         uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  batch_id   uuid NOT NULL REFERENCES anon_batches(id),
  cohort_key text NOT NULL,
  metric     text NOT NULL,
  value      numeric NOT NULL,
  n          int NOT NULL CHECK (n >= 10)   -- 小さすぎる母数は出さない
);

実装で必ず守ること

  • consentsUPDATE / DELETE の権限を与えない。DBロールのレベルで塞ぐ
  • 記録の書き込み前に v_consent_now を必ず確認する。同意がない状態で書けてしまう経路を作らない
  • anon_facts を生成するジョブから、個票への参照を残さない
  • 削除請求が来たら、個票は消し、anon_facts は残す(規約 第16条2項の建て付けどおり)

Part 5

着手順序

  1. PP 第4条3項に口腔情報を追記するこれだけで 01 ホーム・02 セルフチェック・03 歯の記録・04 マウスガードの取得根拠が揃います。1文です。
  2. PP 第10条・第12条に除外条項を足す指導者の閲覧範囲と、口腔内写真の広報利用除外。仕様と規約を一致させます。
  3. 弁護士レビューセルフチェック回答の要配慮該当性を確定させる。ここでスキーマが変わる可能性があるので、実装前に。
  4. 同意基盤を先に作るpolicy_documents / consent_purposes / consents。記録テーブルより先です。逆にすると同意なしデータが生まれます。
  5. Phase 1(学ぶ)を出すデータを1件も集めずにSCOへの最初の実績になります。ここは規約改定を待たずに走れます。
  6. 記録系を実装するmeasurements から。成長記録が動けばマウスガードの交換判定が導出できます。
  7. 匿名加工は最後母数が貯まってから。1年目は個票を貯めることに集中して問題ありません。

1シーズン目で決まること

縦断データは後から遡って作れません。2026年度に enrollments を分離せず選手テーブルにチームを持たせてしまうと、その学年は永久に追跡できなくなります。同意ログを上書き型で作った場合も同じで、その年に集めたデータの適法性を後から証明できません。

逆に言えば、この2つさえ最初に正しく作れば、他は後から直せます