Slack MCP Agent — データモデル設計¶
v1.8 / 2026-05-08
既存プロトタイプの DDL (Schema Version 1) を基盤に、MVP 追加要件を反映した完全なデータモデルを定義する。
docs/architecture.mdSection 7、docs/mvp-spec.mdSection 11 と整合。
1. ER 図¶
erDiagram
tenants ||--o{ tasks : "1:N"
tenants ||--|| settings : "1:1"
tenants ||--o{ integrations : "1:N"
tenants ||--o{ hr_employees : "1:N"
tenants ||--o{ hr_snapshots : "1:N"
tenants ||--o{ hr_flags : "1:N"
tenants ||--o{ routing_decisions : "1:N"
tenants ||--o{ monthly_reports : "1:N"
hr_snapshots ||--o{ hr_flags : "1:N"
tenants ||--o{ tool_permissions : "1:N"
tenants ||--o{ audit_logs : "1:N"
tasks ||--o{ prompts : "1:N (versioned)"
tasks ||--o{ processes : "1:N (versioned)"
tasks ||--o{ executions : "1:N"
tasks ||--o{ slack_messages : "1:N"
prompts ||--|| processes : "1:1"
processes ||--o{ executions : "1:N"
tenants {
TEXT id PK "ULID"
TEXT name
TEXT slug UK
TEXT agent_id "将来用"
TEXT vault_id "将来用"
}
tasks {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT title
TEXT status "TaskStatus enum"
TEXT source "channel / agent_container"
TEXT routing_tier "A / B / C"
TEXT slack_channel
TEXT slack_thread_ts
}
prompts {
TEXT id PK "ULID"
TEXT task_id FK
INTEGER version
TEXT content
TEXT status "PromptStatus enum"
TEXT rejection_reason
}
processes {
TEXT id PK "ULID"
TEXT task_id FK
TEXT prompt_id FK
INTEGER version
TEXT steps "JSON"
TEXT status "ProcessStatus enum"
TEXT rejection_reason
}
executions {
TEXT id PK "ULID"
TEXT task_id FK
TEXT process_id FK
TEXT session_id
TEXT status "ExecutionStatus enum"
TEXT results "JSON"
TEXT cancelled_by
}
slack_messages {
TEXT id PK "ULID"
TEXT task_id FK
TEXT card_type
TEXT message_ts
}
audit_logs {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT timestamp
TEXT action
TEXT details "JSON"
}
settings {
TEXT id PK "ULID"
TEXT tenant_id FK "UNIQUE"
TEXT config "JSON"
}
integrations {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT provider
TEXT status
TEXT credentials "JSON encrypted"
}
hr_employees {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT freee_employee_id
TEXT login_email
TEXT slack_user_id "NULL allowed"
TEXT status
}
hr_snapshots {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT target_date
TEXT snapshot_kind
TEXT payload_json "JSON"
}
hr_flags {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT snapshot_id FK
TEXT target_date
TEXT flag_kind
TEXT severity
TEXT resolved_at
}
routing_decisions {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT target_kind
TEXT target_id
TEXT decision "A / B / C"
TEXT decision_source
TEXT reason_json "JSON"
TEXT decided_at
}
monthly_reports {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT report_month
TEXT title
TEXT metrics_json "JSON"
TEXT status "draft / delivered"
}
tool_permissions {
TEXT id PK "ULID"
TEXT tenant_id FK
TEXT tool_name
INTEGER allowed
}
リレーション一覧¶
| 親 | 子 | 関係 | FK |
|---|---|---|---|
| tenants | tasks | 1:N | tasks.tenant_id → tenants.id |
| tenants | settings | 1:1 | settings.tenant_id → tenants.id (UNIQUE) |
| tenants | integrations | 1:N | integrations.tenant_id → tenants.id |
| tenants | hr_employees | 1:N | hr_employees.tenant_id → tenants.id |
| tenants | hr_snapshots | 1:N | hr_snapshots.tenant_id → tenants.id |
| tenants | hr_flags | 1:N | hr_flags.tenant_id → tenants.id |
| tenants | routing_decisions | 1:N | routing_decisions.tenant_id → tenants.id |
| tenants | monthly_reports | 1:N | monthly_reports.tenant_id → tenants.id |
| hr_snapshots | hr_flags | 1:N | hr_flags.snapshot_id → hr_snapshots.id |
| tenants | tool_permissions | 1:N | tool_permissions.tenant_id → tenants.id |
| tenants | audit_logs | 1:N | audit_logs.tenant_id → tenants.id |
| tasks | prompts | 1:N | prompts.task_id → tasks.id |
| tasks | processes | 1:N | processes.task_id → tasks.id |
| tasks | executions | 1:N | executions.task_id → tasks.id |
| tasks | slack_messages | 1:N | slack_messages.task_id → tasks.id |
| prompts | processes | 1:1 | processes.prompt_id → prompts.id |
| processes | executions | 1:N | executions.process_id → processes.id |
2. テーブル定義¶
2.1 tenants¶
テナント管理。MVP はシングルテナント (default)。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | テナント ID |
name |
TEXT | NOT NULL | 表示名 |
slug |
TEXT | NOT NULL, UNIQUE | URL スラッグ |
agent_id |
TEXT | Managed Agent 定義 ID (将来用) | |
vault_id |
TEXT | Vault ID (将来用) | |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 (ISO 8601) |
updated_at |
TEXT | NOT NULL, DEFAULT now | 更新日時 |
2.2 tasks¶
L1 出力のタスク。パイプラインのルートエンティティ。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | タスク ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | 所属テナント |
title |
TEXT | NOT NULL | L1 が抽出したタイトル |
description |
TEXT | NOT NULL, DEFAULT '' | L1 が抽出した説明 |
priority |
TEXT | NOT NULL, DEFAULT 'medium' | low / medium / high / urgent |
task_type |
TEXT | NOT NULL, DEFAULT 'standard' | standard / urgent / faq |
status |
TEXT | NOT NULL, DEFAULT 'extracted' | TaskStatus enum |
source |
TEXT | NOT NULL, DEFAULT 'channel' | channel / agent_container (MVP は channel のみ書き込み、agent_container は Post-MVP) |
routing_tier |
TEXT | NOT NULL, DEFAULT 'B' | 最新の処理区分。A = AI 自動、B = AI 補助 + 人レビュー、C = 人対応必須 |
slack_channel |
TEXT | NOT NULL | Slack channel ID |
slack_thread_ts |
TEXT | NOT NULL | Slack thread timestamp |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
updated_at |
TEXT | NOT NULL, DEFAULT now | 更新日時 |
インデックス:
- idx_tasks_tenant ON (tenant_id)
- idx_tasks_status ON (status)
- idx_tasks_created_at ON (created_at DESC) -- 一覧ソート用
2.3 prompts¶
L2 出力の実行方針。タスクごとにバージョン管理。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | プロンプト ID |
task_id |
TEXT | NOT NULL, FK → tasks | 親タスク |
version |
INTEGER | NOT NULL, DEFAULT 1 | バージョン番号 |
content |
TEXT | NOT NULL, DEFAULT '' | 実行方針テキスト |
status |
TEXT | NOT NULL, DEFAULT 'generating' | PromptStatus enum |
approved_by |
TEXT | 承認者 (Slack user ID) | |
approved_at |
TEXT | 承認日時 | |
rejection_reason |
TEXT | 却下理由 | |
rejected_by |
TEXT | 却下者 (Slack user ID) | |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
制約:
- UNIQUE (task_id, version) -- タスク内で版番号は一意
インデックス:
- idx_prompts_task ON (task_id)
2.4 processes¶
L3 出力のステップ計画。タスクごとにバージョン管理。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | プロセス ID |
task_id |
TEXT | NOT NULL, FK → tasks | 親タスク |
prompt_id |
TEXT | NOT NULL, FK → prompts | 基にしたプロンプト |
version |
INTEGER | NOT NULL, DEFAULT 1 | バージョン番号 |
steps |
TEXT | NOT NULL, DEFAULT '[]' | JSON: ステップ配列 |
status |
TEXT | NOT NULL, DEFAULT 'generating' | ProcessStatus enum |
approved_by |
TEXT | 承認者 | |
approved_at |
TEXT | 承認日時 | |
rejection_reason |
TEXT | 却下理由 | |
rejected_by |
TEXT | 却下者 | |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
steps JSON 構造:
[
{
"stepId": "step-1",
"order": 1,
"tool": "list_employees",
"toolInput": { "department": null, "status": "active" },
"description": "従業員一覧を取得する",
"expectedOutput": "従業員のリスト"
}
]
制約:
- UNIQUE (task_id, version)
インデックス:
- idx_processes_task ON (task_id)
2.5 executions¶
L4 の実行記録。1 プロセスに対して複数回実行可能 (再実行)。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | 実行 ID |
task_id |
TEXT | NOT NULL, FK → tasks | 親タスク |
process_id |
TEXT | NOT NULL, FK → processes | 実行したプロセス |
session_id |
TEXT | Managed Agent Session ID | |
status |
TEXT | NOT NULL, DEFAULT 'pending' | ExecutionStatus enum |
current_step |
INTEGER | NOT NULL, DEFAULT 0 | 現在のステップ番号 |
results |
TEXT | NOT NULL, DEFAULT '[]' | JSON: ステップ実行結果 |
error |
TEXT | エラーメッセージ | |
cancelled_by |
TEXT | 中止者 (Slack user ID) | |
cancelled_at |
TEXT | 中止日時 | |
started_at |
TEXT | 実行開始日時 | |
completed_at |
TEXT | 実行完了日時 |
results JSON 構造:
[
{
"stepId": "step-1",
"tool": "list_employees",
"status": "completed",
"result": { "count": 42 },
"duration_ms": 800,
"started_at": "2026-04-18T14:35:00Z",
"completed_at": "2026-04-18T14:35:00.800Z"
}
]
インデックス:
- idx_executions_task ON (task_id)
- idx_executions_process ON (process_id)
2.6 slack_messages¶
Slack カードの message_ts と DB エンティティのマッピング。chat.update で書き換える際に使用。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
task_id |
TEXT | NOT NULL, FK → tasks | 親タスク |
card_type |
TEXT | NOT NULL | task_card / prompt_card / process_card / execution_card / faq_card |
channel |
TEXT | NOT NULL | Slack channel ID |
message_ts |
TEXT | NOT NULL | Slack message timestamp |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
インデックス:
- idx_slack_messages_task ON (task_id)
2.7 audit_logs (MVP 新規)¶
全操作の監査ログ。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | ログ ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
timestamp |
TEXT | NOT NULL | イベント発生日時 |
actor_type |
TEXT | NOT NULL | user / system / agent |
actor_id |
TEXT | Slack user ID or 空 | |
action |
TEXT | NOT NULL | アクション種別 (下記参照) |
resource_type |
TEXT | NOT NULL | task / prompt / process / execution / settings / integration |
resource_id |
TEXT | 対象リソースの ID | |
details |
TEXT | DEFAULT '{}' | JSON: 補足情報 |
アクション種別:
| action | actor_type | トリガー |
|---|---|---|
task.created |
system | L1 完了 |
prompt.approved |
user | Slack [承認] |
prompt.rejected |
user | Slack [却下] |
process.approved |
user | Slack [承認] |
process.rejected |
user | Slack [却下] |
execution.started |
system | L4 開始 |
execution.completed |
system | L4 正常完了 |
execution.failed |
system | L4 異常終了 |
execution.cancelled |
user | [中止] |
faq.escalated_to_hr |
user | FAQ カードの HR に確認する |
settings.updated |
user | Web 設定保存 |
integration.connected |
user | OAuth 接続完了 |
integration.disconnected |
user | [切断] |
インデックス:
- idx_audit_logs_tenant_ts ON (tenant_id, timestamp DESC) -- 一覧フィルタ用
- idx_audit_logs_action ON (action)
2.8 settings (MVP 新規)¶
テナント設定。1 テナント 1 レコード。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants, UNIQUE | テナント (1:1) |
config |
TEXT | NOT NULL, DEFAULT '{}' | JSON: 設定値 |
updated_at |
TEXT | NOT NULL, DEFAULT now | 最終更新日時 |
updated_by |
TEXT | 更新者 |
config JSON 構造:
{
"name": "HR AI Agent",
"slug": "default",
"prompt_approval_required": true,
"process_approval_required": true,
"model": "claude-sonnet-4-6",
"l4_timeout_seconds": 360,
"auto_approve_tools": true,
"faq_knowledge_text": "# リモートワーク規程\n前営業日18時までに申請する。"
}
faq_knowledge_text は社内ハウスルール FAQ 一次回答に使う Markdown ナレッジ。Web settings は settings.config を merge 更新し、未編集キーを保持する。
2.9 integrations (MVP 新規)¶
外部サービス接続情報。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
provider |
TEXT | NOT NULL | freee / google / slack |
status |
TEXT | NOT NULL, DEFAULT 'disconnected' | connected / disconnected / error |
credentials |
TEXT | DEFAULT '{}' | JSON (暗号化): OAuth トークン等 |
metadata |
TEXT | DEFAULT '{}' | JSON: プロバイダー固有情報 |
connected_at |
TEXT | 接続日時 | |
updated_at |
TEXT | NOT NULL, DEFAULT now | 更新日時 |
制約:
- UNIQUE (tenant_id, provider) -- テナント内でプロバイダーは一意
2.10 hr_employees (MVP 新規)¶
freee 従業員 ID と Slack UserID を対応付ける人物マスタ。後続の個別通知(リマインド、エスカレーション等)は、freee 従業員 ID または Slack UserID からこのテーブルを経由して通知先を解決する。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
freee_employee_id |
TEXT | NOT NULL | freee 従業員 ID |
login_email |
TEXT | NOT NULL | freee employee_group_memberships.login_email |
slack_user_id |
TEXT | NULL | Slack users.lookupByEmail で解決した UserID。未登録・メール不一致時は NULL |
display_name |
TEXT | NOT NULL, DEFAULT '' | freee 側表示名 |
department |
TEXT | NOT NULL, DEFAULT '' | freee 部署名または employee group 名 |
status |
TEXT | NOT NULL, DEFAULT 'active' | active / retired / on_leave |
synced_at |
TEXT | NOT NULL | 最終同期日時 |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
updated_at |
TEXT | NOT NULL, DEFAULT now | 更新日時 |
制約:
- UNIQUE (tenant_id, freee_employee_id) -- freee 従業員はテナント内で一意
インデックス:
- idx_hr_employees_tenant ON (tenant_id)
- idx_hr_employees_login_email ON (tenant_id, login_email)
- idx_hr_employees_slack_user ON (tenant_id, slack_user_id)
運用ルール:
- 初期 MVP は sync_hr_employees の手動実行で初回構築・差分更新を行う。将来のスケジューラ基盤は同じ job 関数を呼び出す。
- 入社時は freee 側登録後に同期し、Slack 未登録やメール不一致があれば手動で補正する。
- 退社済みは同期時に status='retired' として保持し、削除は手動運用で行う。
- 休職中は status='on_leave' または最も近い正規化値として保持する。
- 複数 Slack アカウントが疑われる場合でも、exact email に対する users.lookupByEmail の結果を正とし、曖昧なケースは手動修正に回す。
2.11 hr_snapshots (MVP 新規)¶
日次 HR パイプラインの取得結果を保存するスナップショット。取得元 API のレスポンスをそのまま固定化するのではなく、後続ジョブが参照できる最小正規化 JSON として payload_json に保持する。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
target_date |
TEXT | NOT NULL | 対象日 (YYYY-MM-DD) |
snapshot_kind |
TEXT | NOT NULL | attendance / employee 等の種別 |
payload_json |
TEXT | NOT NULL, DEFAULT {"schema_version":1,"records":[]} |
JSON: { "schema_version": 1, "records": [] } |
source |
TEXT | NOT NULL, DEFAULT 'scheduler' | 作成元 |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
制約:
- UNIQUE (tenant_id, target_date, snapshot_kind) -- 同一日・同一種別のスナップショットは 1 件
インデックス:
- idx_hr_snapshots_tenant_date ON (tenant_id, target_date DESC)
- idx_hr_snapshots_unique_kind ON (tenant_id, target_date, snapshot_kind)
2.12 hr_flags (MVP 新規)¶
日次 HR パイプラインの差分検出や異常検知結果を保存するフラグ。resolved_at が NULL のものを未解決として扱う。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
snapshot_id |
TEXT | FK → hr_snapshots, NULL allowed | 根拠スナップショット |
target_date |
TEXT | NOT NULL | 対象日 (YYYY-MM-DD) |
flag_kind |
TEXT | NOT NULL | missing_clockin / leave_expiring 等の種別 |
severity |
TEXT | NOT NULL, DEFAULT 'info' | info / warning / critical |
payload_json |
TEXT | NOT NULL, DEFAULT '{}' | JSON: 判定根拠や対象従業員 ID |
resolved_at |
TEXT | NULL | 解決日時。NULL は未解決 |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
インデックス:
- idx_hr_flags_tenant_date ON (tenant_id, target_date DESC)
- idx_hr_flags_unresolved ON (tenant_id, resolved_at)
Lane B payload contract:
hr_snapshots.snapshot_kind='attendance_daily' は日次勤怠レコードを保持し、打刻エラー検出で参照する。
hr_snapshots.snapshot_kind='attendance_monthly' は月次勤怠サマリを保持し、前月差異と36協定チェックで参照する。
通常運用では Lane B scheduler jobs が freee 勤怠を取得してこれらのスナップショットを作成する。
月次レコードは employee_id, month, total_minutes, overtime_minutes,
holiday_work_minutes, paid_leave_days を最小項目とする。検出結果は
hr_flags.flag_kind に missing_clock_in, missing_clock_out, zero_minute_work,
over_24h_work, holiday_work, monthly_overtime_spike, agreement_36_* を保存する。
36協定では単月、年次、2〜6ヶ月平均、45時間超過月数を決定的ロジックで判定し、違反は severity='critical' とする。
Lane C payload contract:
hr_snapshots.snapshot_kind='payroll_proration_draft' は日割り計算ドラフトを保持する。
hr_snapshots.snapshot_kind='payroll_monthly' は月次給与明細(前月/当月比較の入力)を保持する。
hr_snapshots.snapshot_kind='payroll_diff_explanation' は差異説明ドラフトを保持する。
hr_snapshots.snapshot_kind='payroll_violation_risk' は法令リスク候補を保持する。
hr_flags.flag_kind には payroll_large_difference, minimum_wage_risk,
overtime_limit_risk, social_insurance_risk, insufficient_data_risk を保存する。
Lane Cの hr_flags は全件 routing_tier='C' を前提に作成し、最終判断は人間が行う。
Lane A payload contract:
Lane A 通知の重複送信防止では hr_flags を marker として利用する。
代表例:
lane_a_attendance_closing_notifiedlane_a_missing_clockin_notifiedlane_a_missing_clockin_escalatedlane_a_paid_leave_notified_60d/30d/10d/7dleave_expiring_7d_escalation
2.13 routing_decisions (MVP 新規)¶
A/B/C ルーティングの判定履歴。tasks.routing_tier は最新値のみを保持し、このテーブルは適用ルール名と根拠 JSON を監査・Phase 2 の AI ルーティング昇格で参照する。
AI 判定は decision_source='ai' として追加保存し、低リスク側への降格は反映しない。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
target_kind |
TEXT | NOT NULL | task / hr_flag 等の対象種別 |
target_id |
TEXT | NOT NULL | 対象レコード ID |
decision |
TEXT | NOT NULL | A / B / C |
decision_source |
TEXT | NOT NULL, DEFAULT 'rules' | rules / 将来の ai |
reason_json |
TEXT | NOT NULL, DEFAULT '{}' | JSON: applied_rule, task_type, flag_kind, severity 等 |
decided_at |
TEXT | NOT NULL | 判定日時 |
インデックス:
- idx_routing_decisions_target ON (tenant_id, target_kind, target_id, decided_at)
- idx_routing_decisions_decision ON (tenant_id, decision)
2.14 monthly_reports¶
月次 HR 業務完了レポート。Lane A/B の通知・検知・スナップショット・タスク状態を月単位で集計し、HR レビュー用 draft として保存する。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レポート ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | 所属テナント |
report_month |
TEXT | NOT NULL | 対象月 YYYY-MM |
title |
TEXT | NOT NULL | 表示タイトル |
body |
TEXT | NOT NULL, DEFAULT '' | Slack/Web 表示本文 |
metrics_json |
TEXT | NOT NULL, DEFAULT '{}' | 集計指標 JSON |
status |
TEXT | NOT NULL, DEFAULT 'draft' | draft / delivered |
slack_channel |
TEXT | 投稿先チャンネル | |
slack_message_ts |
TEXT | レビューカードの Slack timestamp | |
delivered_by |
TEXT | 配信済みにした Slack user ID | |
delivered_at |
TEXT | 配信済み日時 | |
created_at |
TEXT | NOT NULL | 作成日時 |
updated_at |
TEXT | NOT NULL | 更新日時 |
制約・インデックス:
- UNIQUE (tenant_id, report_month) -- 同一月の再生成は上書き
- idx_monthly_reports_tenant_month ON (tenant_id, report_month DESC)
- idx_monthly_reports_status ON (tenant_id, status)
2.15 tool_permissions¶
ツール実行権限 (Post-MVP で活用)。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id |
TEXT | PK (ULID) | レコード ID |
tenant_id |
TEXT | NOT NULL, FK → tenants | テナント |
tool_name |
TEXT | NOT NULL | ツール名 |
allowed |
INTEGER | NOT NULL, DEFAULT 1 | 1=許可, 0=禁止 |
constraints |
TEXT | NOT NULL, DEFAULT '{}' | JSON: 制約条件 |
created_at |
TEXT | NOT NULL, DEFAULT now | 作成日時 |
updated_at |
TEXT | NOT NULL, DEFAULT now | 更新日時 |
制約:
- UNIQUE (tenant_id, tool_name)
3. 状態遷移図¶
3.1 TaskStatus¶
stateDiagram-v2
[*] --> extracted
extracted --> running : L4 実行開始
extracted --> cancelled : タスク取消
running --> completed : L4 正常完了
running --> failed : L4 異常終了
running --> cancelled : 中止ボタン
failed --> running : 再実行ボタン
completed --> [*]
failed --> [*]
cancelled --> [*]
| 遷移元 | 遷移先 | トリガー |
|---|---|---|
| extracted | running | L4 実行開始 |
| extracted | cancelled | 承認前にタスク取消 |
| running | completed | L4 正常完了 |
| running | failed | L4 異常終了 |
| running | cancelled | [中止] ボタン |
| failed | running | [再実行] ボタン |
3.2 PromptStatus¶
stateDiagram-v2
[*] --> generating
generating --> pending_approval : L2 完了
pending_approval --> approved : 承認ボタン
pending_approval --> rejected : 却下ボタン
rejected --> [*] : 新 version を generating で作成
approved --> [*]
| 遷移元 | 遷移先 | トリガー |
|---|---|---|
| generating | pending_approval | L2 完了、content 書込 |
| pending_approval | approved | [承認] ボタン |
| pending_approval | rejected | [却下] ボタン |
3.3 ProcessStatus¶
PromptStatus と同一パターン。
| 遷移元 | 遷移先 | トリガー |
|---|---|---|
| generating | pending_approval | L3 完了、steps 書込 |
| pending_approval | approved | [承認] ボタン |
| pending_approval | rejected | [却下] ボタン |
3.4 ExecutionStatus¶
stateDiagram-v2
[*] --> pending
pending --> running : Session 作成完了
running --> completed : Session idle + summary
running --> failed : Session error / timeout
running --> cancelled : 中止ボタン
completed --> [*]
failed --> [*]
cancelled --> [*]
| 遷移元 | 遷移先 | トリガー |
|---|---|---|
| pending | running | Session 作成完了 |
| running | completed | Session idle + summary |
| running | failed | Session error / timeout |
| running | cancelled | [中止] ボタン |
4. マイグレーション戦略¶
4.1 現状 (Schema Version 1)¶
プロトタイプの DDL。tenants, tasks, prompts, processes, executions, slack_messages, tool_permissions の 7 テーブル + インデックス。
4.2 MVP (Schema Version 2)¶
Version 1 からの差分:
-- Schema Version 2: MVP additions
-- tasks: source カラム追加
ALTER TABLE tasks ADD COLUMN source TEXT NOT NULL DEFAULT 'channel';
-- prompts: 却下理由カラム追加
ALTER TABLE prompts ADD COLUMN rejection_reason TEXT;
ALTER TABLE prompts ADD COLUMN rejected_by TEXT;
-- processes: 却下理由カラム追加
ALTER TABLE processes ADD COLUMN rejection_reason TEXT;
ALTER TABLE processes ADD COLUMN rejected_by TEXT;
-- executions: 中止カラム・ステータス追加
ALTER TABLE executions ADD COLUMN cancelled_by TEXT;
ALTER TABLE executions ADD COLUMN cancelled_at TEXT;
-- audit_logs (新規)
CREATE TABLE IF NOT EXISTS audit_logs (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
timestamp TEXT NOT NULL,
actor_type TEXT NOT NULL,
actor_id TEXT,
action TEXT NOT NULL,
resource_type TEXT NOT NULL,
resource_id TEXT,
details TEXT NOT NULL DEFAULT '{}'
);
CREATE INDEX IF NOT EXISTS idx_audit_logs_tenant_ts
ON audit_logs(tenant_id, timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_audit_logs_action
ON audit_logs(action);
-- settings (新規)
CREATE TABLE IF NOT EXISTS settings (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
config TEXT NOT NULL DEFAULT '{}',
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now')),
updated_by TEXT
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_settings_tenant
ON settings(tenant_id);
-- integrations (新規)
CREATE TABLE IF NOT EXISTS integrations (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
provider TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'disconnected',
credentials TEXT NOT NULL DEFAULT '{}',
metadata TEXT NOT NULL DEFAULT '{}',
connected_at TEXT,
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now'))
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_integrations_tenant_provider
ON integrations(tenant_id, provider);
-- tasks: 作成日時降順インデックス追加
CREATE INDEX IF NOT EXISTS idx_tasks_created_at
ON tasks(created_at DESC);
-- executions: process_id インデックス追加
CREATE INDEX IF NOT EXISTS idx_executions_process
ON executions(process_id);
4.3 Phase 0 人物マスタ (Schema Version 3)¶
Version 2 からの差分:
-- Schema Version 3: HR employee master
CREATE TABLE IF NOT EXISTS hr_employees (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
freee_employee_id TEXT NOT NULL,
login_email TEXT NOT NULL,
slack_user_id TEXT,
display_name TEXT NOT NULL DEFAULT '',
department TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'active',
synced_at TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now')),
UNIQUE (tenant_id, freee_employee_id)
);
CREATE INDEX IF NOT EXISTS idx_hr_employees_tenant
ON hr_employees(tenant_id);
CREATE INDEX IF NOT EXISTS idx_hr_employees_login_email
ON hr_employees(tenant_id, login_email);
CREATE INDEX IF NOT EXISTS idx_hr_employees_slack_user
ON hr_employees(tenant_id, slack_user_id);
4.4 Phase 0 スケジューラ基盤 (Schema Version 4)¶
Version 3 からの差分:
-- Schema Version 4: scheduler snapshots and flags
CREATE TABLE IF NOT EXISTS hr_snapshots (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
target_date TEXT NOT NULL,
snapshot_kind TEXT NOT NULL,
payload_json TEXT NOT NULL DEFAULT '{"schema_version":1,"records":[]}',
source TEXT NOT NULL DEFAULT 'scheduler',
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now'))
);
CREATE INDEX IF NOT EXISTS idx_hr_snapshots_tenant_date
ON hr_snapshots(tenant_id, target_date DESC);
CREATE UNIQUE INDEX IF NOT EXISTS idx_hr_snapshots_unique_kind
ON hr_snapshots(tenant_id, target_date, snapshot_kind);
CREATE TABLE IF NOT EXISTS hr_flags (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
snapshot_id TEXT REFERENCES hr_snapshots(id),
target_date TEXT NOT NULL,
flag_kind TEXT NOT NULL,
severity TEXT NOT NULL DEFAULT 'info',
payload_json TEXT NOT NULL DEFAULT '{}',
resolved_at TEXT,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%f+00:00', 'now'))
);
CREATE INDEX IF NOT EXISTS idx_hr_flags_tenant_date
ON hr_flags(tenant_id, target_date DESC);
CREATE INDEX IF NOT EXISTS idx_hr_flags_unresolved
ON hr_flags(tenant_id, resolved_at);
payload_json の最小 contract:
4.5 Phase 1 A/B/C ルーティング (Schema Version 5)¶
Version 4 からの差分:
-- Schema Version 5: rule-based routing decisions
ALTER TABLE tasks ADD COLUMN routing_tier TEXT NOT NULL DEFAULT 'B';
CREATE TABLE IF NOT EXISTS routing_decisions (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
target_kind TEXT NOT NULL,
target_id TEXT NOT NULL,
decision TEXT NOT NULL,
decision_source TEXT NOT NULL DEFAULT 'rules',
reason_json TEXT NOT NULL DEFAULT '{}',
decided_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_routing_decisions_target
ON routing_decisions(tenant_id, target_kind, target_id, decided_at);
CREATE INDEX IF NOT EXISTS idx_routing_decisions_decision
ON routing_decisions(tenant_id, decision);
reason_json の例:
4.6 マイグレーション実行¶
既存の _MIGRATIONS dict にバージョンを追加し、migrate() で自動適用:
SCHEMA_VERSION = 5
_MIGRATIONS: dict[int, str] = {
1: "...(既存)...",
2: "...(MVP additions)...",
3: "...(HR employee master)...",
4: "...(scheduler snapshots and flags)...",
5: "...(routing decisions)...",
}
5. データフロー¶
5.1 パイプライン実行時の書込順序¶
1. tasks INSERT (status: extracted, routing_tier: A/B/C)
2. routing_decisions INSERT (target_kind: task, decision_source: rules)
3. audit_logs INSERT (action: routing.decided)
4. slack_messages INSERT (card_type: task)
5. prompts INSERT (status: generating)
6. slack_messages INSERT (card_type: prompt)
7. prompts UPDATE (content, status: pending_approval)
8. audit_logs INSERT (action: task.created)
--- 承認後 ---
9. prompts UPDATE (status: approved, approved_by, approved_at)
10. audit_logs INSERT (action: prompt.approved)
11. processes INSERT (status: generating)
12. slack_messages INSERT (card_type: process)
13. processes UPDATE (steps, status: pending_approval)
--- 承認後 ---
14. processes UPDATE (status: approved)
15. audit_logs INSERT (action: process.approved)
16. tasks UPDATE (status: running)
17. executions INSERT (status: pending)
18. slack_messages INSERT (card_type: execution)
19. executions UPDATE (status: running, started_at)
20. audit_logs INSERT (action: execution.started)
--- 完了 ---
21. executions UPDATE (status: completed, results, completed_at)
22. tasks UPDATE (status: completed)
23. audit_logs INSERT (action: execution.completed)
5.2 人物マスタ同期時の書込順序¶
1. freee employees SELECT via API
2. freee employee_group_memberships SELECT via API
3. Slack users.lookupByEmail login_email ごとに解決
4. hr_employees INSERT/UPDATE by (tenant_id, freee_employee_id)
Slack 未登録・メール不一致の場合は slack_user_id = NULL で保存し、warning log を出す。Lane A 個別通知系処理は hr_employees.slack_user_id が NULL の場合、運用チャンネルへのフォールバック通知で補う。
変更履歴¶
| 日付 | バージョン | 変更内容 |
|---|---|---|
| 2026-04-18 | v1.0 | 初版作成 |
| 2026-04-20 | v1.1 | tasks.source の利用範囲(MVP は channel のみ)を注記。実装の SCHEMA_VERSION=2 に整合済みであることを確認 |
| 2026-04-29 | v1.2 | hr_employees 人物マスタ、Schema Version 3、freee login_email と Slack UserID の同期運用を追加 |
| 2026-04-29 | v1.3 | hr_snapshots / hr_flags、Schema Version 4、スケジューラ基盤の保存先を追加 |
| 2026-04-29 | v1.4 | tasks.routing_tier / routing_decisions、Schema Version 5、A/B/C ルーティング履歴を追加 |
| 2026-05-05 | v1.5 | Lane B の勤怠異常、月次差異、36協定、AIルーティング昇格で使う snapshot / flag payload contract を追加 |
| 2026-05-06 | v1.6 | Lane C の給与日割り・差異・説明・法令リスクで使う snapshot / flag payload contract を追加 |
| 2026-05-06 | v1.7 | Lane A の通知 marker (hr_flags) と未紐付け時フォールバック運用を追加 |
| 2026-05-08 | v1.8 | monthly_reports、faq task type、FAQ/レポート用 settings key を追加 |