規制コンプライアンス:GDPR と SOC2
準拠したエージェントのために、データ最小化、同意の追跡、アクセス制御を実装します。
「規制コンプライアンス:GDPR と SOC2」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。
AIエージェントに規制が適用される理由
AIエージェントはユーザーデータを処理し、判断を下し、アクションを実行します。そのため、データ保護規制(GDPR)やセキュリティフレームワーク(SOC 2)の適用対象に直接含まれます。
コンプライアンスは任意ではありません。GDPR違反には、全世界の年間売上高の最大4%に相当する罰金が科される可能性があります。
GDPR: データ最小化
GDPRのデータ最小化の原則では、明示した目的に厳密に必要な個人データだけを収集することが求められます。分析に必要なのが結果(解決済み・未解決)だけであれば、エージェントは会話の完全な記録を保存すべきではありません。
def minimized_log_entry(conversation: list[dict], user_id: str) -> dict:
'''Store only what is needed — not the full transcript.'''
return {
'user_id': user_id,
'timestamp': conversation[-1].get('timestamp'),
'turns': len(conversation),
'resolved': conversation[-1].get('resolved', False),
'intent': conversation[-1].get('intent'),
'satisfaction': conversation[-1].get('csat_score'),
# NOT stored: full message text, PII mentioned in conversation
}
# WRONG — stores raw messages which may contain PII
# {'messages': conversation, 'user_id': user_id}
if __name__ == '__main__':
conversation = [
{'timestamp': 1717000000, 'resolved': True, 'intent': 'reset_password', 'csat_score': 5}
]
print('Minimized log entry:', minimized_log_entry(conversation, user_id='u42'))
GDPR: 同意の追跡
エージェントが個人データを処理する前に、通常はユーザーの同意など、法的根拠を得ておく必要があります。同意を取得した時期と対象範囲を記録し、撤回にも対応してください。
from datetime import datetime, timezone
consent_store: dict[str, dict] = {} # user_id -> consent record
def record_consent(user_id: str, purpose: str, version: str = '1.0'):
if user_id not in consent_store:
consent_store[user_id] = {'purposes': {}}
consent_store[user_id]['purposes'][purpose] = {
'granted': True,
'timestamp': datetime.now(timezone.utc).isoformat(),
'version': version
}
def withdraw_consent(user_id: str, purpose: str):
if user_id in consent_store:
consent_store[user_id]['purposes'].pop(purpose, None)
def has_consent(user_id: str, purpose: str) -> bool:
return bool(
consent_store.get(user_id, {}).get('purposes', {}).get(purpose, {}).get('granted')
)
if __name__ == '__main__':
record_consent('u42', 'marketing_emails')
print('Has consent:', has_consent('u42', 'marketing_emails'))
withdraw_consent('u42', 'marketing_emails')
print('Has consent after withdrawal:', has_consent('u42', 'marketing_emails'))
GDPR: 消去権(忘れられる権利)
ユーザーから削除を要求された場合、エージェントはそのユーザーに関連するすべての個人データを消去する必要があります。これには、エージェントログ、会話履歴、キャッシュされたプロファイルが含まれます。消去は要求から30日以内に実行する必要があります。
import os
def erase_user_data(user_id: str, conn) -> dict:
'''Delete all personal data for a user across all storage systems.'''
deleted = {}
# 1. Delete from audit log (if not using WORM storage)
with conn.cursor() as cur:
cur.execute('DELETE FROM agent_audit_log WHERE user_id = %s', (user_id,))
deleted['audit_log_rows'] = cur.rowcount
# 2. Delete conversation history
with conn.cursor() as cur:
cur.execute('DELETE FROM conversation_history WHERE user_id = %s', (user_id,))
deleted['conversations'] = cur.rowcount
# 3. Remove consent record
consent_store.pop(user_id, None)
deleted['consent_record'] = 1
# 4. Clear cached profile
profile_cache = {} # reference to your cache
profile_cache.pop(user_id, None)
deleted['profile_cache'] = 1
conn.commit()
return {'user_id': user_id, 'erased': deleted}GDPR: データポータビリティ
ユーザーには、機械可読形式(例: JSONまたはCSV)で自分のデータを受け取る権利があります。エージェントの各システムに保存されているユーザーに関するすべてのデータを収集するエクスポート機能を構築してください。
import json
def export_user_data(user_id: str, conn) -> str:
export = {'user_id': user_id, 'data': {}}
with conn.cursor() as cur:
cur.execute(
'SELECT timestamp, action_type, result FROM agent_audit_log '
'WHERE user_id = %s ORDER BY timestamp',
(user_id,)
)
rows = cur.fetchall()
export['data']['audit_log'] = [
{'timestamp': r[0], 'action': r[1], 'result': r[2]}
for r in rows
]
export['data']['consent'] = consent_store.get(user_id, {})
return json.dumps(export, indent=2)SOC 2: アクセス制御
SOC 2 Type IIでは、システムとデータへのアクセスが認可された個人に限定されていることを証明する必要があります。エージェントの場合、これはエージェントツールへのロールベースアクセス、管理者アクセスへのMFA、定期的なアクセスレビューを意味します。
ROLE_PERMISSIONS = {
'agent_basic': {'web_search', 'read_file', 'query_database'},
'agent_email': {'web_search', 'read_file', 'query_database', 'send_email'},
'agent_admin': {'web_search', 'read_file', 'write_file', 'query_database',
'send_email', 'create_ticket', 'execute_python_sandbox'},
'human_admin': {'*'} # all permissions
}
def get_permitted_actions(role: str) -> set:
perms = ROLE_PERMISSIONS.get(role, set())
if '*' in perms:
return ALLOWED_ACTIONS # reference to full allowlist
return perms
def check_role_permission(role: str, action: str) -> bool:
return action in get_permitted_actions(role)SOC 2:保存時および転送中の暗号化
SOC 2では、保存時(データベースの暗号化、暗号化ディスク)および転送中(TLS 1.2以降)の機密データを暗号化する必要があります。エージェントの場合、暗号化された会話の保存、すべてのAPI呼び出しでのTLSの使用、ログへの平文のシークレットの記録禁止を意味します。
from cryptography.fernet import Fernet
import os
# Key stored in environment variable, never in code
ENCRYPTION_KEY = os.environ.get('LOG_ENCRYPTION_KEY', Fernet.generate_key())
cipher = Fernet(ENCRYPTION_KEY)
def encrypt_sensitive_field(value: str) -> str:
return cipher.encrypt(value.encode()).decode()
def decrypt_sensitive_field(encrypted: str) -> str:
return cipher.decrypt(encrypted.encode()).decode()
# Usage: encrypt PII before storing in audit log
encrypted_email = encrypt_sensitive_field('user@example.com')
print(encrypted_email[:30], '...') # starts with gAAAA...SOC 2:セキュリティイベントの監査ログ
SOC 2の監査人は、ログイン試行、機密データへのアクセス、設定変更、ポリシー違反などのセキュリティイベントのログを確認します。これらは安全に保存し、少なくとも1年間保持する必要があります。
import logging, json, time
security_logger = logging.getLogger('agent.security')
SECURITY_EVENTS = {
'auth_success', 'auth_failure', 'policy_violation',
'data_access_pii', 'admin_action', 'config_change'
}
def log_security_event(event_type: str, agent_id: str,
user_id: str, details: dict):
assert event_type in SECURITY_EVENTS, f'Unknown security event: {event_type}'
entry = {
'timestamp': time.time(),
'event_type': event_type,
'agent_id': agent_id,
'user_id': user_id,
'details': details
}
security_logger.warning(json.dumps(entry))
if __name__ == '__main__':
import sys
security_logger.addHandler(logging.StreamHandler(sys.stdout))
log_security_event('auth_failure', 'agent-1', 'user-42', {'reason': 'bad_token'})
エージェントの出力に含まれるPIIの追跡
エージェントは、ログに記録したり、サードパーティサービス(分析、モニタリング)に送信したりする出力にPIIを含めないようにする必要があります。送信前に、送信内容をスキャンしてPIIのパターンを検出してください。
import re
PII_PATTERNS = [
(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', 'email'),
(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', 'phone'),
(r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b', 'credit_card'),
(r'\b\d{3}-\d{2}-\d{4}\b', 'ssn')
]
def redact_pii(text: str) -> tuple[str, list[str]]:
redacted = text
found_types = []
for pattern, pii_type in PII_PATTERNS:
if re.search(pattern, redacted):
found_types.append(pii_type)
redacted = re.sub(pattern, f'[{pii_type.upper()}_REDACTED]', redacted)
return redacted, found_types
text, types = redact_pii('Contact john@example.com or call 555-867-5309')
print(text)
print('PII found:', types)コンプライアンスチェックリストの作成
個人データを扱うエージェントをデプロイする前に、次の管理策が整備されていることを確認してください。
COMPLIANCE_CHECKLIST = [
('GDPR', 'Consent captured before processing personal data'),
('GDPR', 'Data minimization: only necessary data is collected'),
('GDPR', 'Right-to-erasure endpoint implemented and tested'),
('GDPR', 'Data portability export available'),
('GDPR', 'Data retention policy enforced (auto-delete after N days)'),
('SOC2', 'Role-based access control implemented for all agent tools'),
('SOC2', 'All data encrypted at rest and in transit (TLS 1.2+)'),
('SOC2', 'Security events logged and retained for 12+ months'),
('SOC2', 'Access reviews scheduled quarterly'),
('SOC2', 'Incident response plan documented'),
('BOTH', 'PII redaction applied to logs and analytics exports'),
('BOTH', 'Vendor DPAs signed for all third-party APIs used'),
]
for framework, control in COMPLIANCE_CHECKLIST:
print(f'[ ] [{framework}] {control}')データ保持の自動化
GDPRでは、元の目的に必要なくなったデータを削除することが求められます。設定可能な保持期間に基づいて古いレコードを削除する保持ポリシージョブを使い、これを自動化してください。
from datetime import datetime, timedelta, timezone
RETENTION_POLICIES = {
'conversation_history': 90, # days
'agent_audit_log': 365,
'cached_profiles': 1,
'session_data': 30
}
def purge_expired_data(conn):
purged = {}
for table, retention_days in RETENTION_POLICIES.items():
cutoff = datetime.now(timezone.utc) - timedelta(days=retention_days)
try:
with conn.cursor() as cur:
cur.execute(
f'DELETE FROM {table} WHERE timestamp < %s',
(cutoff.timestamp(),)
)
purged[table] = cur.rowcount
except Exception as e:
purged[table] = f'Error: {e}'
conn.commit()
return purged
if __name__ == '__main__':
class FakeCursor:
def __enter__(self):
return self
def __exit__(self, *exc):
return False
def execute(self, sql, params):
self.rowcount = 3
class FakeConn:
def cursor(self):
return FakeCursor()
def commit(self):
pass
result = purge_expired_data(FakeConn())
print('Rows purged per table:')
for table, count in result.items():
print(f' {table}: {count}')
GDPRのデータ最小化原則とは
データ最小化はGDPRの中核原則の一つであり、エージェントシステムを最初からどのように設計すべきかに直接影響します。
GDPRとSOC 2のコンプライアンス総括
GDPRへの準拠には、同意の追跡、データ最小化、消去権の実装、データポータビリティ用エクスポート、ログ内のPIIのマスキングが必要です。
SOC 2では、ロールベースアクセス制御、保存時および転送中の暗号化、セキュリティイベントのログ記録、アクセスレビューが必要です。保持ポリシーを自動化して、期限切れのデータを削除してください。
よくある質問
「規制コンプライアンス:GDPR と SOC2」レッスンは無料ですか?
はい。「規制コンプライアンス:GDPR と SOC2」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。
「規制コンプライアンス:GDPR と SOC2」で何を学びますか?
準拠したエージェントのために、データ最小化、同意の追跡、アクセス制御を実装します。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Agentsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「規制コンプライアンス:GDPR と SOC2」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Agentsレッスンでコードを書いて実行できますか?
はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- エージェントの改ざん不能なアクションログ
- エージェントアクションへのポリシー適用
- 規制コンプライアンス:GDPR と SOC2
- Human-in-the-Loop 承認ゲート