Fetch account security reminders through app-server (#60082)

## Why

Security reminder requests need to use app-server's active authentication and HTTP runtime, with results bound to the login that fetched them.

## What changed

- Add `account/securitySetup/read`, returning an optional notice with account and user IDs, plus generated protocol schemas and bindings.
- Fetch reminders in app-server only for a matching saved ChatGPT login. Return `notice: null` for ineligible, unavailable, or timed-out reads, and discard results when the login changes during the request.
- Route TUI reminder reads through the new method while retaining notice validation and identity checks. Unsupported servers produce no reminder.

## Testing

Add coverage for shared runtime use across restarts, ineligible authentication modes, and login changes during a fetch. Update TUI coverage for unavailable, unsupported, and mismatched notices.

GitOrigin-RevId: 426fee7ce98df17970957c06876881bc5b005196
This commit is contained in:
cooper-oai
2026-11-07 08:11:37 +00:00
committed by copyberry
parent c4f0e09912
commit 4be90eb069
22 changed files with 707 additions and 78 deletions
@@ -1421,6 +1421,12 @@ client_request_definitions! {
response: v2::LogoutAccountResponse,
},
GetAccountSecuritySetup => "account/securitySetup/read" {
params: #[ts(type = "undefined")] #[serde(skip_serializing_if = "Option::is_none")] Option<()>,
serialization: None,
response: v2::GetAccountSecuritySetupResponse,
},
GetAccountRateLimits => "account/rateLimits/read" {
params: #[ts(optional, as = "Option<GetAccountRateLimitsParamsTypeScript>", inline)] #[serde(default, skip_serializing_if = "Option::is_none")] v2::NullableGetAccountRateLimitsParams,
serialization: None,
@@ -884,3 +884,31 @@ pub struct AccountLoginCompletedNotification {
pub enum DesktopOnboardingEntrypoint {
LifeSciences,
}
/// Optional security reminder bound to the account that fetched it. Unavailable or
/// ineligible accounts return no notice; this read never changes account security.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct GetAccountSecuritySetupResponse {
pub notice: Option<AccountSecuritySetupNotice>,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct AccountSecuritySetupNotice {
pub account_id: String,
pub user_id: String,
pub title: String,
pub description: String,
pub action: AccountSecuritySetupAction,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct AccountSecuritySetupAction {
pub label: String,
pub url: String,
}