fix: tighten edge cases across services (#3158)

This commit is contained in:
Hampus
2026-10-03 13:04:29 +02:00
committed by GitHub
parent a9f7a23c0d
commit 4e6b837ccc
170 changed files with 2028 additions and 421 deletions
+285 -21
View File
@@ -13912,7 +13912,7 @@
"responses": {
"200": {
"description": "Success",
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserPrivateResponse"}}}
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserUpdateResponse"}}}
},
"400": {
"description": "Bad Request - The request was malformed or contained invalid data",
@@ -13953,7 +13953,7 @@
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
}
},
"description": "Updates the authenticated user's profile information such as username, avatar, and bio. Requires sudo mode verification for security-sensitive changes. Only default users can modify their own profile.",
"description": "Updates the authenticated user's profile information such as username, avatar, and bio. Requires sudo mode verification for security-sensitive changes. Only default users can modify their own profile. A password change invalidates all existing sessions and returns the replacement session token.",
"security": [{"sessionToken": []}],
"requestBody": {
"required": false,
@@ -21543,7 +21543,7 @@
]
},
"referenced_message": {
"description": "The reply target. Present and populated when the target resolved, present and null when the target is gone, absent when this message carries no default reference. Clients must tell null apart from absent by key presence.",
"description": "The reply target. Present and populated when the target resolved, present and null when the target is gone, absent when this message has no default reference. Clients must tell null apart from absent by key presence.",
"anyOf": [
{
"type": "object",
@@ -25300,6 +25300,250 @@
"webauthn_challenge": {"description": "WebAuthn challenge string", "type": "string"}
}
},
"UserUpdateResponse": {
"type": "object",
"properties": {
"id": {
"description": "The unique identifier (snowflake) for this user",
"$ref": "#/components/schemas/SnowflakeStringType"
},
"username": {"type": "string", "description": "The username of the user, not unique across the platform"},
"discriminator": {"type": "string", "description": "The four-digit discriminator tag of the user"},
"global_name": {"description": "The display name of the user, if set", "type": ["string", "null"]},
"avatar": {"description": "The hash of the user avatar image", "type": ["string", "null"]},
"avatar_color": {
"anyOf": [{"$ref": "#/components/schemas/Int32Type"}, {"type": "null"}],
"description": "The dominant avatar color of the user as an integer"
},
"bot": {"description": "Whether the user is a bot account", "type": "boolean"},
"system": {"description": "Whether the user is an official system user", "type": "boolean"},
"flags": {"$ref": "#/components/schemas/PublicUserFlags"},
"mention_flags": {
"description": "The user's account-wide reply mention preference. Omitted when the user has no preference set (treated as NO_PREFERENCE).",
"$ref": "#/components/schemas/MentionReplyPreferences"
},
"is_staff": {"type": "boolean", "description": "Whether the user has staff permissions"},
"acls": {
"type": "array",
"items": {"type": "string"},
"description": "Access control list entries for the user"
},
"traits": {
"type": "array",
"items": {"type": "string"},
"description": "Special traits assigned to the user account"
},
"email": {"description": "The email address associated with the account", "type": ["string", "null"]},
"email_bounced": {
"description": "Whether the current email address is marked as bounced by the mail provider",
"type": "boolean"
},
"has_verified_phone": {"type": "boolean", "description": "Deprecated. Always false."},
"bio": {"description": "The user biography text", "type": ["string", "null"]},
"pronouns": {"description": "The preferred pronouns of the user", "type": ["string", "null"]},
"accent_color": {
"anyOf": [{"$ref": "#/components/schemas/Int32Type"}, {"type": "null"}],
"description": "The user-selected accent color as an integer"
},
"timezone": {"description": "The IANA timezone identifier saved by the user", "type": ["string", "null"]},
"timezone_privacy_flags": {"$ref": "#/components/schemas/ProfileFieldPrivacyFlags"},
"banner": {"description": "The hash of the user profile banner image", "type": ["string", "null"]},
"banner_color": {
"anyOf": [{"$ref": "#/components/schemas/Int32Type"}, {"type": "null"}],
"description": "The default banner color if no custom banner is set"
},
"mfa_enabled": {"type": "boolean", "description": "Whether multi-factor authentication is enabled"},
"authenticator_types": {
"description": "The types of authenticators configured for MFA",
"type": "array",
"items": {"$ref": "#/components/schemas/UserAuthenticatorTypes"}
},
"verified": {"type": "boolean", "description": "Whether the email address has been verified"},
"account_limited": {"description": "Whether the account is limited", "type": "boolean"},
"premium_type": {
"anyOf": [
{"$ref": "#/components/schemas/UserPremiumTypes", "description": "The type of premium subscription"},
{"type": "null"}
]
},
"premium_since": {
"description": "ISO8601 timestamp of when premium was first activated",
"type": ["string", "null"]
},
"premium_until": {
"description": "ISO8601 timestamp of when premium access ends, including stacked gift time",
"type": ["string", "null"]
},
"premium_will_cancel": {
"type": "boolean",
"description": "Whether premium is set to cancel at the end of the billing period"
},
"premium_billing_cycle": {
"description": "The billing cycle for the premium subscription",
"type": ["string", "null"]
},
"premium_lifetime_sequence": {
"anyOf": [{"$ref": "#/components/schemas/Int32Type"}, {"type": "null"}],
"description": "The sequence number for lifetime premium subscribers"
},
"premium_grace_ends_at": {
"description": "ISO8601 timestamp at which grace access ends after premium_until passes: after a failed renewal payment (7 days from the renewal for monthly plans, 14 for yearly), after a subscription ends (3 days), or during an App Store or Google Play grace period. Perks stay active and the original premium_since is kept on resubscribe until this timestamp passes. Null when no grace is recorded, in which case access lasts 3 days after premium_until.",
"type": ["string", "null"]
},
"premium_discriminator": {
"type": "boolean",
"description": "Whether the user selected a premium-only discriminator that will be rerolled when non-lifetime premium access ends"
},
"premium_badge_hidden": {
"type": "boolean",
"description": "Whether the premium badge is hidden on the profile"
},
"premium_badge_masked": {
"type": "boolean",
"description": "Whether the premium badge shows a masked appearance"
},
"premium_badge_timestamp_hidden": {
"type": "boolean",
"description": "Whether the premium start timestamp is hidden"
},
"premium_badge_sequence_hidden": {
"type": "boolean",
"description": "Whether the lifetime sequence number is hidden"
},
"premium_purchase_disabled": {
"type": "boolean",
"description": "Whether premium purchases are disabled for this account"
},
"premium_enabled_override": {
"type": "boolean",
"description": "Whether premium features are enabled via override"
},
"premium_perks_disabled": {
"type": "boolean",
"description": "Whether premium perks are temporarily disabled for this account"
},
"password_last_changed_at": {
"description": "ISO8601 timestamp of the last password change",
"type": ["string", "null"]
},
"last_voice_activity_sharing_change_at": {
"description": "ISO8601 timestamp of the last bulk voice-activity-sharing change. Drives the 24-hour cooldown for re-toggling the Active Now sharing default.",
"type": ["string", "null"]
},
"required_actions": {
"type": "array",
"items": {"type": "string"},
"description": "Deprecated. Always empty."
},
"nsfw_allowed": {"type": "boolean", "description": "Whether the user is allowed to view NSFW content"},
"has_dismissed_premium_onboarding": {
"type": "boolean",
"description": "Whether the user has dismissed the premium onboarding flow"
},
"has_ever_purchased": {"type": "boolean", "description": "Whether the user has ever made a purchase"},
"has_unread_gift_inventory": {
"type": "boolean",
"description": "Whether there are unread items in the gift inventory"
},
"unread_gift_inventory_count": {
"description": "The number of unread gift inventory items",
"$ref": "#/components/schemas/Int32Type"
},
"pending_bulk_message_deletion": {
"anyOf": [
{
"type": "object",
"properties": {
"scheduled_at": {
"type": "string",
"description": "ISO8601 timestamp of when the deletion was scheduled"
},
"channel_count": {
"description": "The number of channels with messages to delete",
"$ref": "#/components/schemas/Int32Type"
},
"message_count": {
"description": "The total number of messages to delete",
"$ref": "#/components/schemas/Int32Type"
}
},
"required": ["scheduled_at", "channel_count", "message_count"],
"additionalProperties": false
},
{"type": "null"}
],
"description": "Information about a pending bulk message deletion request. Only populated when the legacy delayed-deletion flow is in progress; the new immediate-deletion flow does not surface a pending state here."
},
"age_verified_adult": {
"description": "Whether the user has verified their age as an adult via credit card verification",
"type": "boolean"
},
"terms_agreed_at": {
"description": "ISO8601 timestamp of when the user last agreed to the terms of service",
"type": ["string", "null"]
},
"privacy_agreed_at": {
"description": "ISO8601 timestamp of when the user last agreed to the privacy policy",
"type": ["string", "null"]
},
"token": {
"description": "Authentication token for the replacement session, present when the password was changed",
"type": "string"
},
"auth_session_id_hash": {
"description": "Base64url-encoded hash of the replacement authentication session, present when the password was changed",
"type": "string"
}
},
"required": [
"id",
"username",
"discriminator",
"global_name",
"avatar",
"avatar_color",
"flags",
"is_staff",
"acls",
"traits",
"email",
"has_verified_phone",
"bio",
"pronouns",
"accent_color",
"banner",
"banner_color",
"mfa_enabled",
"verified",
"premium_type",
"premium_since",
"premium_until",
"premium_will_cancel",
"premium_billing_cycle",
"premium_lifetime_sequence",
"premium_grace_ends_at",
"premium_discriminator",
"premium_badge_hidden",
"premium_badge_masked",
"premium_badge_timestamp_hidden",
"premium_badge_sequence_hidden",
"premium_purchase_disabled",
"premium_enabled_override",
"premium_perks_disabled",
"password_last_changed_at",
"last_voice_activity_sharing_change_at",
"required_actions",
"nsfw_allowed",
"has_dismissed_premium_onboarding",
"has_ever_purchased",
"has_unread_gift_inventory",
"unread_gift_inventory_count",
"pending_bulk_message_deletion",
"terms_agreed_at",
"privacy_agreed_at"
],
"additionalProperties": false
},
"UnfurlRequest": {
"type": "object",
"properties": {"url": {"description": "The URL to unfurl", "type": "string"}},
@@ -30548,7 +30792,7 @@
"original": {"type": "string", "description": "The requested URL, echoed back unchanged"},
"refreshed": {
"type": "string",
"description": "The same URL carrying a fresh signature, or the original when it is not an attachment URL of ours"
"description": "The same URL with a fresh signature, or the original when it is not an attachment URL of ours"
}
},
"required": ["original", "refreshed"],
@@ -32300,9 +32544,15 @@
"description": "The template-local channel ID"
},
"type": {"type": "number", "description": "The channel type (0 = text, 2 = voice, 4 = category)"},
"name": {"description": "The name of the channel", "type": ["string", "null"]},
"topic": {"description": "The channel topic", "type": ["string", "null"]},
"position": {"type": "number", "description": "The position of the channel"},
"name": {
"description": "The name of the channel",
"anyOf": [{"type": "string", "maxLength": 100}, {"type": "null"}]
},
"topic": {
"description": "The channel topic",
"anyOf": [{"type": "string", "maxLength": 1024}, {"type": "null"}]
},
"position": {"description": "The position of the channel", "$ref": "#/components/schemas/Int32Type"},
"parent_id": {
"description": "The template-local ID of the parent category",
"anyOf": [
@@ -32313,14 +32563,25 @@
{"type": "null"}
]
},
"bitrate": {"description": "The bitrate for voice channels", "type": ["number", "null"]},
"user_limit": {"description": "The user limit for voice channels", "type": ["number", "null"]},
"bitrate": {
"description": "The bitrate for voice channels",
"anyOf": [{"type": "integer", "minimum": 0, "maximum": 9007199254740991}, {"type": "null"}]
},
"user_limit": {
"description": "The user limit for voice channels",
"anyOf": [{"type": "integer", "minimum": 0, "maximum": 9007199254740991}, {"type": "null"}]
},
"voice_connection_limit": {
"description": "The per-user voice connection limit for voice channels",
"type": ["number", "null"]
"anyOf": [{"type": "integer", "minimum": 1, "maximum": 100}, {"type": "null"}]
},
"nsfw": {"description": "Whether the channel is NSFW", "type": "boolean"},
"rate_limit_per_user": {"description": "Slowmode rate limit in seconds", "type": "number"},
"rate_limit_per_user": {
"description": "Slowmode rate limit in seconds",
"type": "integer",
"minimum": 0,
"maximum": 21600
},
"permission_overwrites": {
"description": "Permission overwrites for this channel",
"type": "array",
@@ -32357,7 +32618,10 @@
"anyOf": [{"type": "integer", "minimum": 0, "maximum": 9007199254740991}, {"type": "string"}],
"description": "The template-local role ID"
},
"name": {"description": "The name of the role", "type": ["string", "null"]},
"name": {
"description": "The name of the role",
"anyOf": [{"type": "string", "maxLength": 100}, {"type": "null"}]
},
"permissions": {
"description": "The permissions bitfield as a string (legacy)",
"anyOf": [{"type": "string"}, {"type": "integer", "minimum": 0, "maximum": 9007199254740991}]
@@ -32366,7 +32630,7 @@
"description": "The permissions bitfield as a string (preferred)",
"anyOf": [{"type": "string"}, {"type": "integer", "minimum": 0, "maximum": 9007199254740991}]
},
"color": {"description": "The colour of the role as an integer", "type": "number"},
"color": {"description": "The colour of the role as an integer", "$ref": "#/components/schemas/ColorType"},
"hoist": {"description": "Whether the role is hoisted", "type": "boolean"},
"mentionable": {"description": "Whether the role is mentionable", "type": "boolean"},
"unicode_emoji": {"description": "The unicode emoji for the role icon", "type": ["string", "null"]}
@@ -35032,6 +35296,14 @@
"required": ["src", "proxy_src", "width", "height"],
"additionalProperties": false
},
"UserAuthenticatorTypes": {
"description": "Authenticator type",
"type": "integer",
"enum": [0, 2],
"format": "int32",
"x-enumNames": ["TOTP", "WEBAUTHN"],
"x-enumDescriptions": ["Time-based one-time password authenticator", "WebAuthn authenticator"]
},
"ProfileFieldPrivacyFlags": {
"type": "integer",
"minimum": 0,
@@ -35283,14 +35555,6 @@
"required": ["id", "rawId", "type", "clientExtensionResults", "response"],
"additionalProperties": {}
},
"UserAuthenticatorTypes": {
"description": "Authenticator type",
"type": "integer",
"enum": [0, 2],
"format": "int32",
"x-enumNames": ["TOTP", "WEBAUTHN"],
"x-enumDescriptions": ["Time-based one-time password authenticator", "WebAuthn authenticator"]
},
"HexString32Type": {"type": "string", "pattern": "^[a-f0-9]{32}$"},
"CompletedPasskeyBridgeSudoRedeemResponse": {
"type": "object",