{
  "name": "Member",
  "label": "Member",
  "description": "Association table for team members and their roles",
  "tags": ["team", "user", "association", "membership", "roles"],
  "table": {
    "name": "member",
    "comment": "Association table for team members and their roles"
  },
  "columns": [
    // ============================================================================
    // Basic Fields
    // ============================================================================
    {
      "name": "id",
      "type": "ID",
      "label": "ID",
      "comment": "Primary key identifier",
      "primary": true
    },
    {
      "name": "member_id",
      "type": "string",
      "label": "Member ID",
      "comment": "Global unique member identifier",
      "length": 255,
      "unique": true,
      "index": true
    },
    {
      "name": "team_id",
      "type": "string",
      "label": "Team ID",
      "comment": "Team identifier (references team.team_id)",
      "length": 255,
      "nullable": false,
      "index": true
    },
    {
      "name": "user_id",
      "type": "string",
      "label": "User ID",
      "comment": "User identifier (references user.user_id) - null for robot members",
      "length": 255,
      "nullable": true,
      "index": true
    },

    // ============================================================================
    // Member Type & Configuration
    // ============================================================================
    {
      "name": "member_type",
      "type": "enum",
      "label": "Member Type",
      "comment": "Type of member: user (human) or robot (automated)",
      "option": [
        "user", // Human user member
        "robot" // Automated robot member
      ],
      "default": "user",
      "index": true,
      "nullable": false
    },

    // ============================================================================
    // Member Profile Fields (Team-specific identity)
    // Shared by both user and robot members
    // ============================================================================
    {
      "name": "display_name",
      "type": "string",
      "label": "Display Name",
      "comment": "Display name for this member within the team (can differ from user.name for users, robot name for robots)",
      "length": 200,
      "nullable": true,
      "index": true
    },
    {
      "name": "bio",
      "type": "text",
      "label": "Bio",
      "comment": "Personal bio/description for this member within the team (robot description for robots)",
      "nullable": true
    },
    {
      "name": "avatar",
      "type": "string",
      "label": "Avatar",
      "comment": "Avatar/icon URL for this member (shared by both users and robots)",
      "length": 500,
      "nullable": true
    },
    {
      "name": "email",
      "type": "string",
      "label": "Email",
      "comment": "Email for this member within the team (can differ from user.email, used for communication including robots)",
      "length": 255,
      "nullable": true,
      "index": true
    },

    // ============================================================================
    // Role & Permission Fields
    // ============================================================================
    {
      "name": "role_id",
      "type": "string",
      "label": "Role ID",
      "comment": "User role within the team (references role.role_id)",
      "length": 50,
      "nullable": false,
      "index": true
    },
    {
      "name": "is_owner",
      "type": "boolean",
      "label": "Is Owner",
      "comment": "Whether this member is the team owner (redundant field for query performance and UI display)",
      "default": false,
      "index": true,
      "nullable": false
    },
    {
      "name": "status",
      "type": "enum",
      "label": "Status",
      "comment": "Membership status",
      "option": [
        "pending", // Invitation sent, not accepted yet
        "active", // Active member
        "inactive", // Temporarily inactive
        "suspended" // Suspended by admin
      ],
      "default": "pending",
      "index": true,
      "nullable": false
    },

    // ============================================================================
    // Robot Identity & Role Fields (only for robot members)
    // ============================================================================
    {
      "name": "system_prompt",
      "type": "text",
      "label": "System Prompt",
      "comment": "Identity & role prompt/instructions for robot member (defines robot personality and behavior)",
      "nullable": true
    },
    {
      "name": "manager_id",
      "type": "string",
      "label": "Direct Manager",
      "comment": "User ID of the direct manager/supervisor for this robot member",
      "length": 255,
      "nullable": true,
      "index": true
    },

    // ============================================================================
    // Robot Configuration Fields (only for robot members)
    // ============================================================================
    {
      "name": "robot_email",
      "type": "string",
      "label": "Robot Email",
      "comment": "Globally unique email address for the robot to receive and send emails",
      "length": 255,
      "nullable": true,
      "unique": true,
      "index": true
    },
    {
      "name": "authorized_senders",
      "type": "json",
      "label": "Authorized Senders",
      "comment": "Whitelist of email addresses authorized to send instructions to this robot. Robot will respond to and execute commands from these senders only (JSON array)",
      "nullable": true
    },
    {
      "name": "email_filter_rules",
      "type": "json",
      "label": "Email Filter Rules",
      "comment": "Email filtering rules (supports regex patterns) to determine which emails to receive and process. Can include domain patterns, address patterns, etc. (JSON array)",
      "nullable": true
    },
    {
      "name": "robot_config",
      "type": "json",
      "label": "Robot Configuration",
      "comment": "Robot-specific configuration including behavior settings, scheduling, activity patterns, and capabilities",
      "nullable": true
    },
    {
      "name": "agents",
      "type": "json",
      "label": "Accessible Agents",
      "comment": "List of accessible AI agents (public service NPCs) that robot can interact with",
      "nullable": true
    },
    {
      "name": "mcp_servers",
      "type": "json",
      "label": "MCP Servers",
      "comment": "List of accessible MCP servers (system integrated command servers)",
      "nullable": true
    },
    {
      "name": "language_model",
      "type": "string",
      "label": "Language Model",
      "comment": "Language model used by the robot (e.g., gpt-4, claude-3-opus)",
      "length": 100,
      "nullable": true
    },
    {
      "name": "workspace",
      "type": "string",
      "label": "Workspace",
      "comment": "Workspace ID bound to this robot member (nullable = not bound)",
      "length": 255,
      "nullable": true,
      "index": true
    },
    {
      "name": "cost_limit",
      "type": "decimal",
      "label": "Cost Limit (USD/month)",
      "comment": "Monthly cost limit in USD for robot operations",
      "precision": 10,
      "scale": 2,
      "nullable": true
    },
    {
      "name": "autonomous_mode",
      "type": "boolean",
      "label": "Autonomous Mode",
      "comment": "Whether robot can operate autonomously and perform automated tasks",
      "default": false,
      "index": true
    },

    // ============================================================================
    // Robot Activity & Status Tracking
    // ============================================================================
    {
      "name": "last_robot_activity",
      "type": "timestamp",
      "label": "Last Robot Activity",
      "comment": "When the robot last performed an automated activity",
      "nullable": true,
      "index": true
    },
    {
      "name": "robot_status",
      "type": "enum",
      "label": "Robot Status",
      "comment": "Current operational status of robot member",
      "option": [
        "idle", // Robot is idle, waiting for tasks
        "working", // Robot is currently executing tasks
        "paused", // Robot is temporarily paused
        "error", // Robot encountered an error
        "maintenance" // Robot is under maintenance
      ],
      "default": "idle",
      "index": true,
      "nullable": true
    },

    // ============================================================================
    // Invitation & Join Information
    // ============================================================================
    {
      "name": "invitation_id",
      "type": "string",
      "label": "Invitation ID",
      "comment": "Unique invitation identifier for pending invitations (business ID for invitations)",
      "length": 100,
      "nullable": true,
      "unique": true,
      "index": true
    },
    {
      "name": "invited_by",
      "type": "string",
      "label": "Invited By",
      "comment": "User ID who sent the invitation",
      "length": 255,
      "nullable": true
    },
    {
      "name": "invited_at",
      "type": "timestamp",
      "label": "Invited At",
      "comment": "When the invitation was sent",
      "nullable": true,
      "index": true
    },
    {
      "name": "joined_at",
      "type": "timestamp",
      "label": "Joined At",
      "comment": "When the user accepted and joined the team",
      "nullable": true,
      "index": true
    },
    {
      "name": "invitation_token",
      "type": "string",
      "label": "Invitation Token",
      "comment": "Unique token for invitation acceptance",
      "length": 100,
      "nullable": true,
      "unique": true,
      "index": true
    },
    {
      "name": "invitation_expires_at",
      "type": "timestamp",
      "label": "Invitation Expires At",
      "comment": "When the invitation expires",
      "nullable": true
    },

    // ============================================================================
    // Activity Tracking
    // ============================================================================
    {
      "name": "last_active_at",
      "type": "timestamp",
      "label": "Last Active At",
      "comment": "When the user was last active in this team",
      "nullable": true,
      "index": true
    },
    {
      "name": "login_count",
      "type": "integer",
      "label": "Login Count",
      "comment": "Number of times user has accessed this team",
      "default": 0,
      "nullable": true
    },

    // ============================================================================
    // Metadata
    // ============================================================================
    {
      "name": "notes",
      "type": "text",
      "label": "Notes",
      "comment": "Internal notes about this membership",
      "nullable": true
    },
    {
      "name": "metadata",
      "type": "json",
      "label": "Metadata",
      "comment": "Additional metadata for this membership",
      "nullable": true
    }
  ],
  "indexes": [
    {
      "name": "idx_team_user_unique",
      "columns": ["team_id", "user_id"],
      "type": "unique",
      "comment": "Unique constraint: one user can have only one membership per team"
    },
    {
      "name": "idx_team_invitation_unique",
      "columns": ["team_id", "invitation_id"],
      "type": "unique",
      "comment": "Unique constraint: one invitation_id per team (for pending invitations)"
    },
    {
      "name": "idx_team_email",
      "columns": ["team_id", "email"],
      "type": "index",
      "comment": "Index for querying members by email within team (email is for display only)"
    },
    {
      "name": "idx_team_member_type_role",
      "columns": ["team_id", "member_type", "role_id", "status"],
      "type": "index",
      "comment": "Index for finding members by type, role and status within team"
    },
    {
      "name": "idx_team_owner",
      "columns": ["team_id", "is_owner"],
      "type": "index",
      "comment": "Index for quickly finding team owner"
    },
    {
      "name": "idx_user_teams",
      "columns": ["user_id", "member_type", "status", "role_id"],
      "type": "index",
      "comment": "Index for finding all teams for a user by member type"
    },
    {
      "name": "idx_robot_members",
      "columns": ["member_type", "autonomous_mode", "robot_status"],
      "type": "index",
      "comment": "Index for finding active robot members"
    },
    {
      "name": "idx_robot_activity",
      "columns": ["member_type", "last_robot_activity", "autonomous_mode"],
      "type": "index",
      "comment": "Index for robot activity scheduling"
    },
    {
      "name": "idx_robot_type_status",
      "columns": ["member_type", "robot_status", "autonomous_mode"],
      "type": "index",
      "comment": "Index for finding robot members by status"
    },
    {
      "name": "idx_robot_display_name",
      "columns": ["member_type", "display_name"],
      "type": "index",
      "comment": "Index for finding robot members by display name"
    },
    {
      "name": "idx_robot_manager",
      "columns": ["manager_id", "member_type"],
      "type": "index",
      "comment": "Index for finding robots by manager"
    },
    {
      "name": "idx_team_invitations",
      "columns": ["team_id", "status", "invited_at"],
      "type": "index",
      "comment": "Index for managing invitations"
    },
    {
      "name": "idx_invitation_id",
      "columns": ["invitation_id", "status", "invitation_expires_at"],
      "type": "index",
      "comment": "Index for invitation ID lookup and status"
    },
    {
      "name": "idx_invitation_token",
      "columns": ["invitation_token", "invitation_expires_at"],
      "type": "index",
      "comment": "Index for invitation token lookup and expiration"
    },
    {
      "name": "idx_team_activity",
      "columns": ["team_id", "last_active_at"],
      "type": "index",
      "comment": "Index for team activity tracking"
    },
    {
      "name": "idx_team_display_name",
      "columns": ["team_id", "display_name"],
      "type": "index",
      "comment": "Index for searching members by display name within team"
    }
  ],
  "relations": {
    "team": {
      "type": "hasOne",
      "model": "__yao.team",
      "key": "team_id",
      "foreign": "team_id"
    },
    "user": {
      "type": "hasOne",
      "model": "__yao.user",
      "key": "user_id",
      "foreign": "user_id"
    },
    "inviter": {
      "type": "hasOne",
      "model": "__yao.user",
      "key": "invited_by",
      "foreign": "user_id"
    },
    "role": {
      "type": "hasOne",
      "model": "__yao.role",
      "key": "role_id",
      "foreign": "role_id"
    }
  },
  "values": [],
  "option": { "timestamps": true, "soft_deletes": true, "permission": true }
}
