[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6G25NNTAHH6K81FSYGX1HTG":3,"skill-same:01M6G25NNTAHH6K81FSYGX1HTG":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":42,"commitSha":43,"skillDirectory":44,"forksCount":45,"repositoryHtmlUrl":46,"repositoryHomepageUrl":6,"ownerHtmlUrl":47,"ownerBlogUrl":48,"ownerDescription":49,"updatedAt":50,"install":51,"resources":64},"01M6G25NNTAHH6K81FSYGX1HTG","django-security",null,"Django security best practices, authentication, authorization, CSRF protection, SQL injection prevention, XSS prevention, and secure deployment configurations.","oabdelmaksoud\u002FAgention","oabdelmaksoud","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F50699149?v=4","01M6D5CVVN778ZCDP1WHS816SP","Omar Abdelmaksoud","01M6D8A4TE76V3DCSH3D94VG1V",2,"MIT","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Fdjango-security\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"django security","django","security","xss","xss prevention","csrf protection","sql injection","protection","csrf","prevention","injection","authorization","security best practices","best practices","authentication","deployment","secure","sql","2026-11-10 10:12:30",false,"---\nname: django-security\ndescription: Django security best practices, authentication, authorization, CSRF protection, SQL injection prevention, XSS prevention, and secure deployment configurations.\n---\n\n# Django セキュリティベストプラクティス\n\n一般的な脆弱性から保護するためのDjangoアプリケーションの包括的なセキュリティガイドライン。\n\n## いつ有効化するか\n\n- Django認証と認可を設定するとき\n- ユーザー権限とロールを実装するとき\n- 本番セキュリティ設定を構成するとき\n- Djangoアプリケーションのセキュリティ問題をレビューするとき\n- Djangoアプリケーションを本番環境にデプロイするとき\n\n## 核となるセキュリティ設定\n\n### 本番設定の構成\n\n```python\n# settings\u002Fproduction.py\nimport os\n\nDEBUG = False  # 重要: 本番環境では絶対にTrueにしない\n\nALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')\n\n# セキュリティヘッダー\nSECURE_SSL_REDIRECT = True\nSESSION_COOKIE_SECURE = True\nCSRF_COOKIE_SECURE = True\nSECURE_HSTS_SECONDS = 31536000  # 1年\nSECURE_HSTS_INCLUDE_SUBDOMAINS = True\nSECURE_HSTS_PRELOAD = True\nSECURE_CONTENT_TYPE_NOSNIFF = True\nSECURE_BROWSER_XSS_FILTER = True\nX_FRAME_OPTIONS = 'DENY'\n\n# HTTPSとクッキー\nSESSION_COOKIE_HTTPONLY = True\nCSRF_COOKIE_HTTPONLY = True\nSESSION_COOKIE_SAMESITE = 'Lax'\nCSRF_COOKIE_SAMESITE = 'Lax'\n\n# シークレットキー（環境変数経由で設定する必要があります）\nSECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')\nif not SECRET_KEY:\n    raise ImproperlyConfigured('DJANGO_SECRET_KEY environment variable is required')\n\n# パスワード検証\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',\n        'OPTIONS': {\n            'min_length': 12,\n        }\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',\n    },\n]\n```\n\n## 認証\n\n### カスタムユーザーモデル\n\n```python\n# apps\u002Fusers\u002Fmodels.py\nfrom django.contrib.auth.models import AbstractUser\nfrom django.db import models\n\nclass User(AbstractUser):\n    \"\"\"より良いセキュリティのためのカスタムユーザーモデル。\"\"\"\n\n    email = models.EmailField(unique=True)\n    phone = models.CharField(max_length=20, blank=True)\n\n    USERNAME_FIELD = 'email'  # メールをユーザー名として使用\n    REQUIRED_FIELDS = ['username']\n\n    class Meta:\n        db_table = 'users'\n        verbose_name = 'User'\n        verbose_name_plural = 'Users'\n\n    def __str__(self):\n        return self.email\n\n# settings\u002Fbase.py\nAUTH_USER_MODEL = 'users.User'\n```\n\n### パスワードハッシング\n\n```python\n# デフォルトではDjangoはPBKDF2を使用。より強力なセキュリティのために:\nPASSWORD_HASHERS = [\n    'django.contrib.auth.hashers.Argon2PasswordHasher',\n    'django.contrib.auth.hashers.PBKDF2PasswordHasher',\n    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',\n    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',\n]\n```\n\n### セッション管理\n\n```python\n# セッション設定\nSESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # または 'db'\nSESSION_CACHE_ALIAS = 'default'\nSESSION_COOKIE_AGE = 3600 * 24 * 7  # 1週間\nSESSION_SAVE_EVERY_REQUEST = False\nSESSION_EXPIRE_AT_BROWSER_CLOSE = False  # より良いUXですが、セキュリティは低い\n```\n\n## 認可\n\n### パーミッション\n\n```python\n# models.py\nfrom django.db import models\nfrom django.contrib.auth.models import Permission\n\nclass Post(models.Model):\n    title = models.CharField(max_length=200)\n    content = models.TextField()\n    author = models.ForeignKey(User, on_delete=models.CASCADE)\n\n    class Meta:\n        permissions = [\n            ('can_publish', 'Can publish posts'),\n            ('can_edit_others', 'Can edit posts of others'),\n        ]\n\n    def user_can_edit(self, user):\n        \"\"\"ユーザーがこの投稿を編集できるかチェック。\"\"\"\n        return self.author == user or user.has_perm('app.can_edit_others')\n\n# views.py\nfrom django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin\nfrom django.views.generic import UpdateView\n\nclass PostUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):\n    model = Post\n    permission_required = 'app.can_edit_others'\n    raise_exception = True  # リダイレクトの代わりに403を返す\n\n    def get_queryset(self):\n        \"\"\"ユーザーが自分の投稿のみを編集できるようにする。\"\"\"\n        return Post.objects.filter(author=self.request.user)\n```\n\n### カスタムパーミッション\n\n```python\n# permissions.py\nfrom rest_framework import permissions\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n    \"\"\"所有者のみがオブジェクトを編集できるようにする。\"\"\"\n\n    def has_object_permission(self, request, view, obj):\n        # 読み取り権限は任意のリクエストに許可\n        if request.method in permissions.SAFE_METHODS:\n            return True\n\n        # 書き込み権限は所有者のみ\n        return obj.author == request.user\n\nclass IsAdminOrReadOnly(permissions.BasePermission):\n    \"\"\"管理者は何でもでき、他は読み取りのみ。\"\"\"\n\n    def has_permission(self, request, view):\n        if request.method in permissions.SAFE_METHODS:\n            return True\n        return request.user and request.user.is_staff\n\nclass IsVerifiedUser(permissions.BasePermission):\n    \"\"\"検証済みユーザーのみを許可。\"\"\"\n\n    def has_permission(self, request, view):\n        return request.user and request.user.is_authenticated and request.user.is_verified\n```\n\n### ロールベースアクセス制御(RBAC)\n\n```python\n# models.py\nfrom django.contrib.auth.models import AbstractUser, Group\n\nclass User(AbstractUser):\n    ROLE_CHOICES = [\n        ('admin', 'Administrator'),\n        ('moderator', 'Moderator'),\n        ('user', 'Regular User'),\n    ]\n    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')\n\n    def is_admin(self):\n        return self.role == 'admin' or self.is_superuser\n\n    def is_moderator(self):\n        return self.role in ['admin', 'moderator']\n\n# Mixin\nclass AdminRequiredMixin:\n    \"\"\"管理者ロールを要求するMixin。\"\"\"\n\n    def dispatch(self, request, *args, **kwargs):\n        if not request.user.is_authenticated or not request.user.is_admin():\n            from django.core.exceptions import PermissionDenied\n            raise PermissionDenied\n        return super().dispatch(request, *args, **kwargs)\n```\n\n## SQLインジェクション防止\n\n### Django ORM保護\n\n```python\n# GOOD: Django ORMは自動的にパラメータをエスケープ\ndef get_user(username):\n    return User.objects.get(username=username)  # 安全\n\n# GOOD: raw()でパラメータを使用\ndef search_users(query):\n    return User.objects.raw('SELECT * FROM users WHERE username = %s', [query])\n\n# BAD: ユーザー入力を直接補間しない\ndef get_user_bad(username):\n    return User.objects.raw(f'SELECT * FROM users WHERE username = {username}')  # 脆弱！\n\n# GOOD: 適切なエスケープでfilterを使用\ndef get_users_by_email(email):\n    return User.objects.filter(email__iexact=email)  # 安全\n\n# GOOD: 複雑なクエリにQオブジェクトを使用\nfrom django.db.models import Q\ndef search_users_complex(query):\n    return User.objects.filter(\n        Q(username__icontains=query) |\n        Q(email__icontains=query)\n    )  # 安全\n```\n\n### raw()での追加セキュリティ\n\n```python\n# 生のSQLを使用する必要がある場合は、常にパラメータを使用\nUser.objects.raw(\n    'SELECT * FROM users WHERE email = %s AND status = %s',\n    [user_input_email, status]\n)\n```\n\n## XSS防止\n\n### テンプレートエスケープ\n\n```django\n{# Djangoはデフォルトで変数を自動エスケープ - 安全 #}\n{{ user_input }}  {# エスケープされたHTML #}\n\n{# 信頼できるコンテンツのみを明示的に安全とマーク #}\n{{ trusted_html|safe }}  {# エスケープされない #}\n\n{# 安全なHTMLのためにテンプレートフィルタを使用 #}\n{{ user_input|escape }}  {# デフォルトと同じ #}\n{{ user_input|striptags }}  {# すべてのHTMLタグを削除 #}\n\n{# JavaScriptエスケープ #}\n\u003Cscript>\n    var username = {{ username|escapejs }};\n\u003C\u002Fscript>\n```\n\n### 安全な文字列処理\n\n```python\nfrom django.utils.safestring import mark_safe\nfrom django.utils.html import escape\n\n# BAD: エスケープせずにユーザー入力を安全とマークしない\ndef render_bad(user_input):\n    return mark_safe(user_input)  # 脆弱！\n\n# GOOD: 最初にエスケープ、次に安全とマーク\ndef render_good(user_input):\n    return mark_safe(escape(user_input))\n\n# GOOD: 変数を持つHTMLにformat_htmlを使用\nfrom django.utils.html import format_html\n\ndef greet_user(username):\n    return format_html('\u003Cspan class=\"user\">{}\u003C\u002Fspan>', escape(username))\n```\n\n### HTTPヘッダー\n\n```python\n# settings.py\nSECURE_CONTENT_TYPE_NOSNIFF = True  # MIMEスニッフィングを防止\nSECURE_BROWSER_XSS_FILTER = True  # XSSフィルタを有効化\nX_FRAME_OPTIONS = 'DENY'  # クリックジャッキングを防止\n\n# カスタムミドルウェア\nfrom django.conf import settings\n\nclass SecurityHeaderMiddleware:\n    def __init__(self, get_response):\n        self.get_response = get_response\n\n    def __call__(self, request):\n        response = self.get_response(request)\n        response['X-Content-Type-Options'] = 'nosniff'\n        response['X-Frame-Options'] = 'DENY'\n        response['X-XSS-Protection'] = '1; mode=block'\n        response['Content-Security-Policy'] = \"default-src 'self'\"\n        return response\n```\n\n## CSRF保護\n\n### デフォルトCSRF保護\n\n```python\n# settings.py - CSRFはデフォルトで有効\nCSRF_COOKIE_SECURE = True  # HTTPSでのみ送信\nCSRF_COOKIE_HTTPONLY = True  # JavaScriptアクセスを防止\nCSRF_COOKIE_SAMESITE = 'Lax'  # 一部のケースでCSRFを防止\nCSRF_TRUSTED_ORIGINS = ['https:\u002F\u002Fexample.com']  # 信頼されたドメイン\n\n# テンプレート使用\n\u003Cform method=\"post\">\n    {% csrf_token %}\n    {{ form.as_p }}\n    \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n\u003C\u002Fform>\n\n# AJAXリクエスト\nfunction getCookie(name) {\n    let cookieValue = null;\n    if (document.cookie && document.cookie !== '') {\n        const cookies = document.cookie.split(';');\n        for (let i = 0; i \u003C cookies.length; i++) {\n            const cookie = cookies[i].trim();\n            if (cookie.substring(0, name.length + 1) === (name + '=')) {\n                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n                break;\n            }\n        }\n    }\n    return cookieValue;\n}\n\nfetch('\u002Fapi\u002Fendpoint\u002F', {\n    method: 'POST',\n    headers: {\n        'X-CSRFToken': getCookie('csrftoken'),\n        'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify(data)\n});\n```\n\n### ビューの除外（慎重に使用）\n\n```python\nfrom django.views.decorators.csrf import csrf_exempt\n\n@csrf_exempt  # 絶対に必要な場合のみ使用！\ndef webhook_view(request):\n    # 外部サービスからのWebhook\n    pass\n```\n\n## ファイルアップロードセキュリティ\n\n### ファイル検証\n\n```python\nimport os\nfrom django.core.exceptions import ValidationError\n\ndef validate_file_extension(value):\n    \"\"\"ファイル拡張子を検証。\"\"\"\n    ext = os.path.splitext(value.name)[1]\n    valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf']\n    if not ext.lower() in valid_extensions:\n        raise ValidationError('Unsupported file extension.')\n\ndef validate_file_size(value):\n    \"\"\"ファイルサイズを検証（最大5MB）。\"\"\"\n    filesize = value.size\n    if filesize > 5 * 1024 * 1024:\n        raise ValidationError('File too large. Max size is 5MB.')\n\n# models.py\nclass Document(models.Model):\n    file = models.FileField(\n        upload_to='documents\u002F',\n        validators=[validate_file_extension, validate_file_size]\n    )\n```\n\n### 安全なファイルストレージ\n\n```python\n# settings.py\nMEDIA_ROOT = '\u002Fvar\u002Fwww\u002Fmedia\u002F'\nMEDIA_URL = '\u002Fmedia\u002F'\n\n# 本番環境でメディアに別のドメインを使用\nMEDIA_DOMAIN = 'https:\u002F\u002Fmedia.example.com'\n\n# ユーザーアップロードを直接提供しない\n# 静的ファイルにはwhitenoiseまたはCDNを使用\n# メディアファイルには別のサーバーまたはS3を使用\n```\n\n## APIセキュリティ\n\n### レート制限\n\n```python\n# settings.py\nREST_FRAMEWORK = {\n    'DEFAULT_THROTTLE_CLASSES': [\n        'rest_framework.throttling.AnonRateThrottle',\n        'rest_framework.throttling.UserRateThrottle'\n    ],\n    'DEFAULT_THROTTLE_RATES': {\n        'anon': '100\u002Fday',\n        'user': '1000\u002Fday',\n        'upload': '10\u002Fhour',\n    }\n}\n\n# カスタムスロットル\nfrom rest_framework.throttling import UserRateThrottle\n\nclass BurstRateThrottle(UserRateThrottle):\n    scope = 'burst'\n    rate = '60\u002Fmin'\n\nclass SustainedRateThrottle(UserRateThrottle):\n    scope = 'sustained'\n    rate = '1000\u002Fday'\n```\n\n### API用認証\n\n```python\n# settings.py\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication',\n        'rest_framework_simplejwt.authentication.JWTAuthentication',\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n}\n\n# views.py\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\n\n@api_view(['GET', 'POST'])\n@permission_classes([IsAuthenticated])\ndef protected_view(request):\n    return Response({'message': 'You are authenticated'})\n```\n\n## セキュリティヘッダー\n\n### Content Security Policy\n\n```python\n# settings.py\nCSP_DEFAULT_SRC = \"'self'\"\nCSP_SCRIPT_SRC = \"'self' https:\u002F\u002Fcdn.example.com\"\nCSP_STYLE_SRC = \"'self' 'unsafe-inline'\"\nCSP_IMG_SRC = \"'self' data: https:\"\nCSP_CONNECT_SRC = \"'self' https:\u002F\u002Fapi.example.com\"\n\n# Middleware\nclass CSPMiddleware:\n    def __init__(self, get_response):\n        self.get_response = get_response\n\n    def __call__(self, request):\n        response = self.get_response(request)\n        response['Content-Security-Policy'] = (\n            f\"default-src {CSP_DEFAULT_SRC}; \"\n            f\"script-src {CSP_SCRIPT_SRC}; \"\n            f\"style-src {CSP_STYLE_SRC}; \"\n            f\"img-src {CSP_IMG_SRC}; \"\n            f\"connect-src {CSP_CONNECT_SRC}\"\n        )\n        return response\n```\n\n## 環境変数\n\n### シークレットの管理\n\n```python\n# python-decoupleまたはdjango-environを使用\nimport environ\n\nenv = environ.Env(\n    # キャスティング、デフォルト値を設定\n    DEBUG=(bool, False)\n)\n\n# .envファイルを読み込む\nenviron.Env.read_env()\n\nSECRET_KEY = env('DJANGO_SECRET_KEY')\nDATABASE_URL = env('DATABASE_URL')\nALLOWED_HOSTS = env.list('ALLOWED_HOSTS')\n\n# .envファイル（これをコミットしない）\nDEBUG=False\nSECRET_KEY=your-secret-key-here\nDATABASE_URL=postgresql:\u002F\u002Fuser:password@localhost:5432\u002Fdbname\nALLOWED_HOSTS=example.com,www.example.com\n```\n\n## セキュリティイベントのログ記録\n\n```python\n# settings.py\nLOGGING = {\n    'version': 1,\n    'disable_existing_loggers': False,\n    'handlers': {\n        'file': {\n            'level': 'WARNING',\n            'class': 'logging.FileHandler',\n            'filename': '\u002Fvar\u002Flog\u002Fdjango\u002Fsecurity.log',\n        },\n        'console': {\n            'level': 'INFO',\n            'class': 'logging.StreamHandler',\n        },\n    },\n    'loggers': {\n        'django.security': {\n            'handlers': ['file', 'console'],\n            'level': 'WARNING',\n            'propagate': True,\n        },\n        'django.request': {\n            'handlers': ['file'],\n            'level': 'ERROR',\n            'propagate': False,\n        },\n    },\n}\n```\n\n## クイックセキュリティチェックリスト\n\n| チェック | 説明 |\n|-------|-------------|\n| `DEBUG = False` | 本番環境でDEBUGを決して実行しない |\n| HTTPSのみ | SSLを強制、セキュアクッキー |\n| 強力なシークレット | SECRET_KEYに環境変数を使用 |\n| パスワード検証 | すべてのパスワードバリデータを有効化 |\n| CSRF保護 | デフォルトで有効、無効にしない |\n| XSS防止 | Djangoは自動エスケープ、ユーザー入力で`|safe`を使用しない |\n| SQLインジェクション | ORMを使用、クエリで文字列を連結しない |\n| ファイルアップロード | ファイルタイプとサイズを検証 |\n| レート制限 | APIエンドポイントをスロットル |\n| セキュリティヘッダー | CSP、X-Frame-Options、HSTS |\n| ログ記録 | セキュリティイベントをログ |\n| 更新 | DjangoとDependenciesを最新に保つ |\n\n**覚えておいてください**: セキュリティは製品ではなく、プロセスです。定期的にセキュリティプラクティスをレビューし、更新してください。\n","# Django セキュリティベストプラクティス\n\n一般的な脆弱性から保護するためのDjangoアプリケーションの包括的なセキュリティガイドライン。\n\n## いつ有効化するか\n\n- Django認証と認可を設定するとき\n- ユーザー権限とロールを実装するとき\n- 本番セキュリティ設定を構成するとき\n- Djangoアプリケーションのセキュリティ問題をレビューするとき\n- Djangoアプリケーションを本番環境にデプロイするとき\n\n## 核となるセキュリティ設定\n\n### 本番設定の構成\n\n```python\n# settings\u002Fproduction.py\nimport os\n\nDEBUG = False  # 重要: 本番環境では絶対にTrueにしない\n\nALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')\n\n# セキュリティヘッダー\nSECURE_SSL_REDIRECT = True\nSESSION_COOKIE_SECURE = True\nCSRF_COOKIE_SECURE = True\nSECURE_HSTS_SECONDS = 31536000  # 1年\nSECURE_HSTS_INCLUDE_SUBDOMAINS = True\nSECURE_HSTS_PRELOAD = True\nSECURE_CONTENT_TYPE_NOSNIFF = True\nSECURE_BROWSER_XSS_FILTER = True\nX_FRAME_OPTIONS = 'DENY'\n\n# HTTPSとクッキー\nSESSION_COOKIE_HTTPONLY = True\nCSRF_COOKIE_HTTPONLY = True\nSESSION_COOKIE_SAMESITE = 'Lax'\nCSRF_COOKIE_SAMESITE = 'Lax'\n\n# シークレットキー（環境変数経由で設定する必要があります）\nSECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')\nif not SECRET_KEY:\n    raise ImproperlyConfigured('DJANGO_SECRET_KEY environment variable is required')\n\n# パスワード検証\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',\n        'OPTIONS': {\n            'min_length': 12,\n        }\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',\n    },\n    {\n        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',\n    },\n]\n```\n\n## 認証\n\n### カスタムユーザーモデル\n\n```python\n# apps\u002Fusers\u002Fmodels.py\nfrom django.contrib.auth.models import AbstractUser\nfrom django.db import models\n\nclass User(AbstractUser):\n    \"\"\"より良いセキュリティのためのカスタムユーザーモデル。\"\"\"\n\n    email = models.EmailField(unique=True)\n    phone = models.CharField(max_length=20, blank=True)\n\n    USERNAME_FIELD = 'email'  # メールをユーザー名として使用\n    REQUIRED_FIELDS = ['username']\n\n    class Meta:\n        db_table = 'users'\n        verbose_name = 'User'\n        verbose_name_plural = 'Users'\n\n    def __str__(self):\n        return self.email\n\n# settings\u002Fbase.py\nAUTH_USER_MODEL = 'users.User'\n```\n\n### パスワードハッシング\n\n```python\n# デフォルトではDjangoはPBKDF2を使用。より強力なセキュリティのために:\nPASSWORD_HASHERS = [\n    'django.contrib.auth.hashers.Argon2PasswordHasher',\n    'django.contrib.auth.hashers.PBKDF2PasswordHasher',\n    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',\n    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',\n]\n```\n\n### セッション管理\n\n```python\n# セッション設定\nSESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # または 'db'\nSESSION_CACHE_ALIAS = 'default'\nSESSION_COOKIE_AGE = 3600 * 24 * 7  # 1週間\nSESSION_SAVE_EVERY_REQUEST = False\nSESSION_EXPIRE_AT_BROWSER_CLOSE = False  # より良いUXですが、セキュリティは低い\n```\n\n## 認可\n\n### パーミッション\n\n```python\n# models.py\nfrom django.db import models\nfrom django.contrib.auth.models import Permission\n\nclass Post(models.Model):\n    title = models.CharField(max_length=200)\n    content = models.TextField()\n    author = models.ForeignKey(User, on_delete=models.CASCADE)\n\n    class Meta:\n        permissions = [\n            ('can_publish', 'Can publish posts'),\n            ('can_edit_others', 'Can edit posts of others'),\n        ]\n\n    def user_can_edit(self, user):\n        \"\"\"ユーザーがこの投稿を編集できるかチェック。\"\"\"\n        return self.author == user or user.has_perm('app.can_edit_others')\n\n# views.py\nfrom django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin\nfrom django.views.generic import UpdateView\n\nclass PostUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):\n    model = Post\n    permission_required = 'app.can_edit_others'\n    raise_exception = True  # リダイレクトの代わりに403を返す\n\n    def get_queryset(self):\n        \"\"\"ユーザーが自分の投稿のみを編集できるようにする。\"\"\"\n        return Post.objects.filter(author=self.request.user)\n```\n\n### カスタムパーミッション\n\n```python\n# permissions.py\nfrom rest_framework import permissions\n\nclass IsOwnerOrReadOnly(permissions.BasePermission):\n    \"\"\"所有者のみがオブジェクトを編集できるようにする。\"\"\"\n\n    def has_object_permission(self, request, view, obj):\n        # 読み取り権限は任意のリクエストに許可\n        if request.method in permissions.SAFE_METHODS:\n            return True\n\n        # 書き込み権限は所有者のみ\n        return obj.author == request.user\n\nclass IsAdminOrReadOnly(permissions.BasePermission):\n    \"\"\"管理者は何でもでき、他は読み取りのみ。\"\"\"\n\n    def has_permission(self, request, view):\n        if request.method in permissions.SAFE_METHODS:\n            return True\n        return request.user and request.user.is_staff\n\nclass IsVerifiedUser(permissions.BasePermission):\n    \"\"\"検証済みユーザーのみを許可。\"\"\"\n\n    def has_permission(self, request, view):\n        return request.user and request.user.is_authenticated and request.user.is_verified\n```\n\n### ロールベースアクセス制御(RBAC)\n\n```python\n# models.py\nfrom django.contrib.auth.models import AbstractUser, Group\n\nclass User(AbstractUser):\n    ROLE_CHOICES = [\n        ('admin', 'Administrator'),\n        ('moderator', 'Moderator'),\n        ('user', 'Regular User'),\n    ]\n    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user')\n\n    def is_admin(self):\n        return self.role == 'admin' or self.is_superuser\n\n    def is_moderator(self):\n        return self.role in ['admin', 'moderator']\n\n# Mixin\nclass AdminRequiredMixin:\n    \"\"\"管理者ロールを要求するMixin。\"\"\"\n\n    def dispatch(self, request, *args, **kwargs):\n        if not request.user.is_authenticated or not request.user.is_admin():\n            from django.core.exceptions import PermissionDenied\n            raise PermissionDenied\n        return super().dispatch(request, *args, **kwargs)\n```\n\n## SQLインジェクション防止\n\n### Django ORM保護\n\n```python\n# GOOD: Django ORMは自動的にパラメータをエスケープ\ndef get_user(username):\n    return User.objects.get(username=username)  # 安全\n\n# GOOD: raw()でパラメータを使用\ndef search_users(query):\n    return User.objects.raw('SELECT * FROM users WHERE username = %s', [query])\n\n# BAD: ユーザー入力を直接補間しない\ndef get_user_bad(username):\n    return User.objects.raw(f'SELECT * FROM users WHERE username = {username}')  # 脆弱！\n\n# GOOD: 適切なエスケープでfilterを使用\ndef get_users_by_email(email):\n    return User.objects.filter(email__iexact=email)  # 安全\n\n# GOOD: 複雑なクエリにQオブジェクトを使用\nfrom django.db.models import Q\ndef search_users_complex(query):\n    return User.objects.filter(\n        Q(username__icontains=query) |\n        Q(email__icontains=query)\n    )  # 安全\n```\n\n### raw()での追加セキュリティ\n\n```python\n# 生のSQLを使用する必要がある場合は、常にパラメータを使用\nUser.objects.raw(\n    'SELECT * FROM users WHERE email = %s AND status = %s',\n    [user_input_email, status]\n)\n```\n\n## XSS防止\n\n### テンプレートエスケープ\n\n```django\n{# Djangoはデフォルトで変数を自動エスケープ - 安全 #}\n{{ user_input }}  {# エスケープされたHTML #}\n\n{# 信頼できるコンテンツのみを明示的に安全とマーク #}\n{{ trusted_html|safe }}  {# エスケープされない #}\n\n{# 安全なHTMLのためにテンプレートフィルタを使用 #}\n{{ user_input|escape }}  {# デフォルトと同じ #}\n{{ user_input|striptags }}  {# すべてのHTMLタグを削除 #}\n\n{# JavaScriptエスケープ #}\n\u003Cscript>\n    var username = {{ username|escapejs }};\n\u003C\u002Fscript>\n```\n\n### 安全な文字列処理\n\n```python\nfrom django.utils.safestring import mark_safe\nfrom django.utils.html import escape\n\n# BAD: エスケープせずにユーザー入力を安全とマークしない\ndef render_bad(user_input):\n    return mark_safe(user_input)  # 脆弱！\n\n# GOOD: 最初にエスケープ、次に安全とマーク\ndef render_good(user_input):\n    return mark_safe(escape(user_input))\n\n# GOOD: 変数を持つHTMLにformat_htmlを使用\nfrom django.utils.html import format_html\n\ndef greet_user(username):\n    return format_html('\u003Cspan class=\"user\">{}\u003C\u002Fspan>', escape(username))\n```\n\n### HTTPヘッダー\n\n```python\n# settings.py\nSECURE_CONTENT_TYPE_NOSNIFF = True  # MIMEスニッフィングを防止\nSECURE_BROWSER_XSS_FILTER = True  # XSSフィルタを有効化\nX_FRAME_OPTIONS = 'DENY'  # クリックジャッキングを防止\n\n# カスタムミドルウェア\nfrom django.conf import settings\n\nclass SecurityHeaderMiddleware:\n    def __init__(self, get_response):\n        self.get_response = get_response\n\n    def __call__(self, request):\n        response = self.get_response(request)\n        response['X-Content-Type-Options'] = 'nosniff'\n        response['X-Frame-Options'] = 'DENY'\n        response['X-XSS-Protection'] = '1; mode=block'\n        response['Content-Security-Policy'] = \"default-src 'self'\"\n        return response\n```\n\n## CSRF保護\n\n### デフォルトCSRF保護\n\n```python\n# settings.py - CSRFはデフォルトで有効\nCSRF_COOKIE_SECURE = True  # HTTPSでのみ送信\nCSRF_COOKIE_HTTPONLY = True  # JavaScriptアクセスを防止\nCSRF_COOKIE_SAMESITE = 'Lax'  # 一部のケースでCSRFを防止\nCSRF_TRUSTED_ORIGINS = ['https:\u002F\u002Fexample.com']  # 信頼されたドメイン\n\n# テンプレート使用\n\u003Cform method=\"post\">\n    {% csrf_token %}\n    {{ form.as_p }}\n    \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n\u003C\u002Fform>\n\n# AJAXリクエスト\nfunction getCookie(name) {\n    let cookieValue = null;\n    if (document.cookie && document.cookie !== '') {\n        const cookies = document.cookie.split(';');\n        for (let i = 0; i \u003C cookies.length; i++) {\n            const cookie = cookies[i].trim();\n            if (cookie.substring(0, name.length + 1) === (name + '=')) {\n                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n                break;\n            }\n        }\n    }\n    return cookieValue;\n}\n\nfetch('\u002Fapi\u002Fendpoint\u002F', {\n    method: 'POST',\n    headers: {\n        'X-CSRFToken': getCookie('csrftoken'),\n        'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify(data)\n});\n```\n\n### ビューの除外（慎重に使用）\n\n```python\nfrom django.views.decorators.csrf import csrf_exempt\n\n@csrf_exempt  # 絶対に必要な場合のみ使用！\ndef webhook_view(request):\n    # 外部サービスからのWebhook\n    pass\n```\n\n## ファイルアップロードセキュリティ\n\n### ファイル検証\n\n```python\nimport os\nfrom django.core.exceptions import ValidationError\n\ndef validate_file_extension(value):\n    \"\"\"ファイル拡張子を検証。\"\"\"\n    ext = os.path.splitext(value.name)[1]\n    valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf']\n    if not ext.lower() in valid_extensions:\n        raise ValidationError('Unsupported file extension.')\n\ndef validate_file_size(value):\n    \"\"\"ファイルサイズを検証（最大5MB）。\"\"\"\n    filesize = value.size\n    if filesize > 5 * 1024 * 1024:\n        raise ValidationError('File too large. Max size is 5MB.')\n\n# models.py\nclass Document(models.Model):\n    file = models.FileField(\n        upload_to='documents\u002F',\n        validators=[validate_file_extension, validate_file_size]\n    )\n```\n\n### 安全なファイルストレージ\n\n```python\n# settings.py\nMEDIA_ROOT = '\u002Fvar\u002Fwww\u002Fmedia\u002F'\nMEDIA_URL = '\u002Fmedia\u002F'\n\n# 本番環境でメディアに別のドメインを使用\nMEDIA_DOMAIN = 'https:\u002F\u002Fmedia.example.com'\n\n# ユーザーアップロードを直接提供しない\n# 静的ファイルにはwhitenoiseまたはCDNを使用\n# メディアファイルには別のサーバーまたはS3を使用\n```\n\n## APIセキュリティ\n\n### レート制限\n\n```python\n# settings.py\nREST_FRAMEWORK = {\n    'DEFAULT_THROTTLE_CLASSES': [\n        'rest_framework.throttling.AnonRateThrottle',\n        'rest_framework.throttling.UserRateThrottle'\n    ],\n    'DEFAULT_THROTTLE_RATES': {\n        'anon': '100\u002Fday',\n        'user': '1000\u002Fday',\n        'upload': '10\u002Fhour',\n    }\n}\n\n# カスタムスロットル\nfrom rest_framework.throttling import UserRateThrottle\n\nclass BurstRateThrottle(UserRateThrottle):\n    scope = 'burst'\n    rate = '60\u002Fmin'\n\nclass SustainedRateThrottle(UserRateThrottle):\n    scope = 'sustained'\n    rate = '1000\u002Fday'\n```\n\n### API用認証\n\n```python\n# settings.py\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': [\n        'rest_framework.authentication.TokenAuthentication',\n        'rest_framework.authentication.SessionAuthentication',\n        'rest_framework_simplejwt.authentication.JWTAuthentication',\n    ],\n    'DEFAULT_PERMISSION_CLASSES': [\n        'rest_framework.permissions.IsAuthenticated',\n    ],\n}\n\n# views.py\nfrom rest_framework.decorators import api_view, permission_classes\nfrom rest_framework.permissions import IsAuthenticated\n\n@api_view(['GET', 'POST'])\n@permission_classes([IsAuthenticated])\ndef protected_view(request):\n    return Response({'message': 'You are authenticated'})\n```\n\n## セキュリティヘッダー\n\n### Content Security Policy\n\n```python\n# settings.py\nCSP_DEFAULT_SRC = \"'self'\"\nCSP_SCRIPT_SRC = \"'self' https:\u002F\u002Fcdn.example.com\"\nCSP_STYLE_SRC = \"'self' 'unsafe-inline'\"\nCSP_IMG_SRC = \"'self' data: https:\"\nCSP_CONNECT_SRC = \"'self' https:\u002F\u002Fapi.example.com\"\n\n# Middleware\nclass CSPMiddleware:\n    def __init__(self, get_response):\n        self.get_response = get_response\n\n    def __call__(self, request):\n        response = self.get_response(request)\n        response['Content-Security-Policy'] = (\n            f\"default-src {CSP_DEFAULT_SRC}; \"\n            f\"script-src {CSP_SCRIPT_SRC}; \"\n            f\"style-src {CSP_STYLE_SRC}; \"\n            f\"img-src {CSP_IMG_SRC}; \"\n            f\"connect-src {CSP_CONNECT_SRC}\"\n        )\n        return response\n```\n\n## 環境変数\n\n### シークレットの管理\n\n```python\n# python-decoupleまたはdjango-environを使用\nimport environ\n\nenv = environ.Env(\n    # キャスティング、デフォルト値を設定\n    DEBUG=(bool, False)\n)\n\n# .envファイルを読み込む\nenviron.Env.read_env()\n\nSECRET_KEY = env('DJANGO_SECRET_KEY')\nDATABASE_URL = env('DATABASE_URL')\nALLOWED_HOSTS = env.list('ALLOWED_HOSTS')\n\n# .envファイル（これをコミットしない）\nDEBUG=False\nSECRET_KEY=your-secret-key-here\nDATABASE_URL=postgresql:\u002F\u002Fuser:password@localhost:5432\u002Fdbname\nALLOWED_HOSTS=example.com,www.example.com\n```\n\n## セキュリティイベントのログ記録\n\n```python\n# settings.py\nLOGGING = {\n    'version': 1,\n    'disable_existing_loggers': False,\n    'handlers': {\n        'file': {\n            'level': 'WARNING',\n            'class': 'logging.FileHandler',\n            'filename': '\u002Fvar\u002Flog\u002Fdjango\u002Fsecurity.log',\n        },\n        'console': {\n            'level': 'INFO',\n            'class': 'logging.StreamHandler',\n        },\n    },\n    'loggers': {\n        'django.security': {\n            'handlers': ['file', 'console'],\n            'level': 'WARNING',\n            'propagate': True,\n        },\n        'django.request': {\n            'handlers': ['file'],\n            'level': 'ERROR',\n            'propagate': False,\n        },\n    },\n}\n```\n\n## クイックセキュリティチェックリスト\n\n| チェック | 説明 |\n|-------|-------------|\n| `DEBUG = False` | 本番環境でDEBUGを決して実行しない |\n| HTTPSのみ | SSLを強制、セキュアクッキー |\n| 強力なシークレット | SECRET_KEYに環境変数を使用 |\n| パスワード検証 | すべてのパスワードバリデータを有効化 |\n| CSRF保護 | デフォルトで有効、無効にしない |\n| XSS防止 | Djangoは自動エスケープ、ユーザー入力で`|safe`を使用しない |\n| SQLインジェクション | ORMを使用、クエリで文字列を連結しない |\n| ファイルアップロード | ファイルタイプとサイズを検証 |\n| レート制限 | APIエンドポイントをスロットル |\n| セキュリティヘッダー | CSP、X-Frame-Options、HSTS |\n| ログ記録 | セキュリティイベントをログ |\n| 更新 | DjangoとDependenciesを最新に保つ |\n\n**覚えておいてください**: セキュリティは製品ではなく、プロセスです。定期的にセキュリティプラクティスをレビューし、更新してください。\n",{"name":5,"description":7},"main","a318f48de3c5718e8ea2e9f6fae7790e8a759e85","upstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Fdjango-security",0,"https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fo-abdelmaksoud\u002F","Full-Stack Engineer | AI Systems Architect | Building autonomous multi-agent systems","2026-03-08 21:23:03",{"source":8,"skillName":5,"commands":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add oabdelmaksoud\u002FAgention --skill django-security",{"tool":57,"command":58},"bunx","bunx skills add oabdelmaksoud\u002FAgention --skill django-security",{"tool":60,"command":61},"pnpm","pnpm dlx skills add oabdelmaksoud\u002FAgention --skill django-security","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fdocs\u002Fja-JP\u002Fskills\u002Fdjango-security\u002FSKILL.md",true,[],[66,90,104,137,162,181],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":77,"publishedAt":37},"01M6G2QFCBNBYAJF2KTK85G9A6","visa-doc-translate","Translate visa application documents (images) to English and create a bilingual PDF with original and translation","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fvisa-doc-translate\u002FSKILL.md",[72],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",[78,79,80,81,82,83,84,85,86,87,88,89],"translate","doc","visa doc translate","bilingual","with","english","application","PDF","translation","documents","create","images",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":37},"01M6G2QB09TSK6BY4ME5X20EVQ","verification-loop","A comprehensive verification system for Claude Code sessions.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fverification-loop\u002FSKILL.md",[],[97,98,99,100,101,102,103],"verification","loop","verification loop","sessions","code","claude code sessions","system",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":121,"publishedAt":37},"01M6G2Q6V2F7G03VAAF27FXPJR","tdd-workflow","Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Ftdd-workflow\u002FSKILL.md",[110,113,116],{"categoryNo":111,"categoryName":112,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":114,"categoryName":115,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":117,"categoryName":118,"taxonomyType":119,"taxonomyTypeDesc":120},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[122,123,124,125,126,127,128,129,130,101,131,132,133,134,82,135,136],"workflow","tdd","tdd workflow","use","unit","coverage","refactoring","e2e","integration","development","e2e tests","tests","driven","test","writing",{"skillNo":138,"name":139,"nameZh":6,"description":140,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":141,"categories":142,"keywords":143,"publishedAt":37},"01M6G2Q359YJRWAR2PFCEQAXF3","swiftui-patterns","SwiftUI architecture patterns, state management with @Observable, view composition, navigation, performance optimization, and modern iOS\u002FmacOS UI best practices.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswiftui-patterns\u002FSKILL.md",[],[144,145,146,147,148,149,150,32,151,152,153,154,155,156,157,158,159,160,161,82],"patterns","swiftui","swiftui patterns","architecture","macos","performance","state management","state","ui","Optimization","ios","architecture patterns","Composition","performance optimization","view","management","swiftui architecture","navigation",{"skillNo":163,"name":164,"nameZh":6,"description":165,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":166,"categories":167,"keywords":169,"publishedAt":37},"01M6G2PY8B2FWZTWPZ84H83Y7C","swift-protocol-di-testing","Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-protocol-di-testing\u002FSKILL.md",[168],{"categoryNo":111,"categoryName":112,"taxonomyType":75,"taxonomyTypeDesc":76},[170,171,172,173,101,174,175,176,29,103,177,178,179,180],"swift protocol di testing","protocol","swift","testing","protocols","file","network","dependency","swift testing","dependency injection","mock",{"skillNo":182,"name":183,"nameZh":6,"description":184,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":185,"categories":186,"keywords":187,"publishedAt":37},"01M6G2PSCN2GXV9FFZDRRRWVB6","swift-concurrency-6-2","Swift 6.2 Approachable Concurrency — single-threaded by default, @concurrent for explicit background offloading, isolated conformances for main actor types.","https:\u002F\u002Fgithub.com\u002Foabdelmaksoud\u002FAgention\u002Fblob\u002Fmain\u002Fupstream-sync\u002Fwork\u002Fecc\u002Fskills\u002Fswift-concurrency-6-2\u002FSKILL.md",[],[188,189,190,172,191,42,192],"concurrency","swift concurrency","swift concurrency 6 2","default","types"]