{
  "feature": "gdpr-data-export",
  "version": "1.0.0",
  "description": "Complete workspace data export for GDPR right-to-portability, compliance archival, and migration purposes, producing a JSONL stream with optional ZIP packaging of all messages, files, users,...",
  "category": "data",
  "tags": [
    "gdpr",
    "data-portability",
    "export",
    "bulk-export",
    "compliance",
    "migration",
    "jsonl"
  ],
  "actors": [
    {
      "id": "system_admin",
      "name": "System Administrator",
      "type": "human",
      "description": "Initiates and monitors export jobs; downloads completed archives"
    },
    {
      "id": "export_job",
      "name": "Export Job",
      "type": "system",
      "description": "Background worker that streams JSONL records and packages attachments"
    }
  ],
  "fields": [
    {
      "name": "include_attachments",
      "type": "boolean",
      "required": true,
      "label": "Whether file attachments referenced in messages are bundled into the export"
    },
    {
      "name": "include_profile_pictures",
      "type": "boolean",
      "required": true,
      "label": "Whether user and bot profile images are included in the export"
    },
    {
      "name": "include_archived_channels",
      "type": "boolean",
      "required": true,
      "label": "Whether archived channels and their message history are exported"
    },
    {
      "name": "include_roles_and_schemes",
      "type": "boolean",
      "required": true,
      "label": "Whether permission role definitions and scheme assignments are exported"
    },
    {
      "name": "create_archive",
      "type": "boolean",
      "required": true,
      "label": "When true the output is a ZIP archive; when false raw JSONL is streamed"
    },
    {
      "name": "output_path",
      "type": "text",
      "required": true,
      "label": "Filesystem path where the export file or directory is written"
    }
  ],
  "states": {
    "field": "export_status",
    "values": [
      {
        "name": "pending",
        "description": "Export job created but not yet started",
        "initial": true
      },
      {
        "name": "running",
        "description": "Export actively writing records",
        "terminal": false
      },
      {
        "name": "completed",
        "description": "All records written; archive available for download",
        "terminal": true
      },
      {
        "name": "failed",
        "description": "Export encountered an unrecoverable error",
        "terminal": true
      }
    ],
    "transitions": [
      {
        "from": "pending",
        "to": "running",
        "actor": "export_job",
        "description": "Job worker picks up the export task"
      },
      {
        "from": "running",
        "to": "completed",
        "actor": "export_job",
        "description": "All entity types processed and written"
      },
      {
        "from": "running",
        "to": "failed",
        "actor": "export_job",
        "description": "Unrecoverable error during export"
      }
    ]
  },
  "rules": {
    "rule_01": "Records are written in JSONL format (one JSON object per line) for streaming and incremental processing.",
    "rule_02": "Export processes entity types sequentially — version metadata, roles/schemes, teams, channels, users, bots, posts, emoji, direct channels, direct posts — to maintain referential integrity.",
    "rule_03": "Posts include their reactions, thread relationships (via root_id/parent_id), and file attachment references.",
    "rule_04": "Soft-deleted records (users, posts, channels) are included in the export with their deletion timestamps.",
    "rule_05": "File attachments and profile pictures are copied into a data/ subdirectory within the export archive.",
    "rule_06": "If a file cannot be copied, the error is logged in a warnings.txt file in the archive root, but the export continues; individual file failures do not abort the job.",
    "rule_07": "When ZIP output is requested, JSONL data, attachments, profile pictures, and warnings are packaged into a single archive.",
    "rule_08": "Custom emoji SVG files are exported to an exported_emoji/ directory.",
    "rule_09": "All exported user records include notification preferences, display settings, and privacy-relevant profile fields.",
    "rule_10": "Progress is tracked per entity type and reported in job metadata for monitoring."
  },
  "outcomes": {
    "export_started": {
      "priority": 10,
      "given": [
        "actor is system administrator",
        "output_path is writable"
      ],
      "then": [
        {
          "action": "create_record",
          "target": "export_job",
          "description": "Job record created; background worker begins processing",
          "type": "export"
        },
        {
          "action": "emit_event",
          "event": "export.started",
          "payload": [
            "job_id",
            "actor_id",
            "options",
            "timestamp"
          ]
        }
      ],
      "result": "Export job running; administrator can monitor progress"
    },
    "export_completed": {
      "priority": 10,
      "given": [
        "export job processes all entity types successfully"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "job.status",
          "value": "completed"
        },
        {
          "action": "emit_event",
          "event": "export.completed",
          "payload": [
            "job_id",
            "output_path",
            "warning_count",
            "timestamp"
          ]
        }
      ],
      "result": "Complete export archive available at output_path"
    },
    "export_with_warnings": {
      "priority": 8,
      "given": [
        "export completes but one or more files could not be copied"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "job.status",
          "value": "completed"
        },
        {
          "action": "create_record",
          "target": "warnings_file",
          "description": "warnings.txt written to archive root listing each failed file and reason",
          "type": "warnings"
        },
        {
          "action": "emit_event",
          "event": "export.completed_with_warnings",
          "payload": [
            "job_id",
            "warning_count",
            "output_path",
            "timestamp"
          ]
        }
      ],
      "result": "Export complete; administrator should review warnings.txt for missing files"
    },
    "export_failed": {
      "priority": 5,
      "error": "EXPORT_FAILED",
      "given": [
        "export encounters an unrecoverable error (e.g., disk full, database error)"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "job.status",
          "value": "failed"
        },
        {
          "action": "emit_event",
          "event": "export.failed",
          "payload": [
            "job_id",
            "error_reason",
            "timestamp"
          ]
        }
      ],
      "result": "Export aborted; partial output may exist at output_path"
    }
  },
  "errors": [
    {
      "code": "EXPORT_FAILED",
      "message": "The data export encountered an error. Please check server logs and try again.",
      "status": 500
    },
    {
      "code": "EXPORT_PERMISSION_DENIED",
      "message": "Only system administrators can run data exports.",
      "status": 403
    },
    {
      "code": "EXPORT_OUTPUT_PATH_UNAVAILABLE",
      "message": "The export output path is not writable.",
      "status": 503
    }
  ],
  "events": [
    {
      "name": "export.started",
      "description": "Data export job initiated",
      "payload": [
        "job_id",
        "actor_id",
        "include_attachments",
        "include_archived",
        "timestamp"
      ]
    },
    {
      "name": "export.completed",
      "description": "Export archive successfully produced",
      "payload": [
        "job_id",
        "output_path",
        "file_size_bytes",
        "warning_count",
        "timestamp"
      ]
    },
    {
      "name": "export.completed_with_warnings",
      "description": "Export completed but some files could not be included",
      "payload": [
        "job_id",
        "warning_count",
        "output_path",
        "timestamp"
      ]
    },
    {
      "name": "export.failed",
      "description": "Export job failed before completion",
      "payload": [
        "job_id",
        "error_reason",
        "timestamp"
      ]
    },
    {
      "name": "export.progress",
      "description": "Export job progress update (entity type completed)",
      "payload": [
        "job_id",
        "entity_type",
        "records_written",
        "timestamp"
      ]
    }
  ],
  "related": [
    {
      "feature": "user-deactivation-archiving",
      "type": "recommended",
      "reason": "GDPR export should be run before permanent user deletion to satisfy portability requests"
    },
    {
      "feature": "data-retention-policies",
      "type": "recommended",
      "reason": "Retention deletion removes content from future exports; export before retention window closes"
    },
    {
      "feature": "compliance-exports",
      "type": "optional",
      "reason": "Compliance export targets specific message ranges; full data export covers the entire workspace"
    },
    {
      "feature": "audit-logging",
      "type": "required",
      "reason": "Export initiation and completion are recorded in the audit trail"
    }
  ],
  "agi": {
    "goals": [
      {
        "id": "reliable_gdpr_data_export",
        "description": "Complete workspace data export for GDPR right-to-portability, compliance archival, and migration purposes, producing a JSONL stream with optional ZIP packaging of all messages, files, users,...",
        "success_metrics": [
          {
            "metric": "data_accuracy",
            "target": "100%",
            "measurement": "Records matching source of truth"
          },
          {
            "metric": "duplicate_rate",
            "target": "0%",
            "measurement": "Duplicate records detected post-creation"
          }
        ],
        "constraints": [
          {
            "type": "performance",
            "description": "Data consistency must be maintained across concurrent operations",
            "negotiable": false
          }
        ]
      }
    ],
    "autonomy": {
      "level": "supervised",
      "human_checkpoints": [
        "before transitioning to a terminal state"
      ],
      "escalation_triggers": [
        "error_rate > 5"
      ]
    },
    "safety": {
      "action_permissions": [
        {
          "action": "export_started",
          "permission": "autonomous"
        },
        {
          "action": "export_completed",
          "permission": "autonomous"
        },
        {
          "action": "export_with_warnings",
          "permission": "autonomous"
        },
        {
          "action": "export_failed",
          "permission": "autonomous"
        }
      ]
    },
    "tradeoffs": [
      {
        "prefer": "data_integrity",
        "over": "performance",
        "reason": "data consistency must be maintained across all operations"
      }
    ],
    "coordination": {
      "protocol": "orchestrated",
      "consumes": [
        {
          "capability": "audit_logging",
          "from": "audit-logging",
          "fallback": "degrade"
        }
      ]
    }
  },
  "extensions": {
    "source": {
      "repo": "https://github.com/mattermost/mattermost",
      "project": "Mattermost",
      "tech_stack": "Go (server), React + TypeScript (webapp)",
      "files_traced": 5,
      "entry_points": [
        "server/public/model/bulk_export.go",
        "server/channels/app/bulk_export.go"
      ]
    }
  }
}