Compare commits

..

2 Commits

Author SHA1 Message Date
dean
63e1a7090a feat: Add auth handoff mutation operations
Adds GraphQL operations for:
- CreateAuthHandoffToken: Get handoff token for mobile-to-web auth
- ExchangeAuthHandoffToken: Exchange token for Firebase custom token

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 10:45:01 -08:00
dean
85c4ec6d40 feat: Add auth handoff mutations for mobile-to-web authentication
Adds GraphQL types and schema for:
- createAuthHandoffToken: Creates short-lived token for auth handoff
- exchangeAuthHandoffToken: Exchanges handoff token for Firebase custom token

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-27 10:44:38 -08:00
4 changed files with 90 additions and 9 deletions

View File

@@ -79,6 +79,12 @@ export enum AlignedIntervalEnum {
Year = "YEAR",
}
export type AuthHandoffTokenGql = {
__typename?: "AuthHandoffTokenGQL";
expiresInSeconds: Scalars["Int"]["output"];
token: Scalars["String"]["output"];
};
export type BankFeaturesGql = {
__typename?: "BankFeaturesGQL";
bankAngle: Scalars["Float"]["output"];
@@ -140,6 +146,21 @@ export type BucketSetInputGql = {
feature: Scalars["String"]["input"];
};
export type CancellationFeedbackMetadataInput = {
appVersion?: InputMaybe<Scalars["String"]["input"]>;
gitRevision?: InputMaybe<Scalars["String"]["input"]>;
platform?: InputMaybe<Scalars["String"]["input"]>;
};
export enum CancellationReasonEnum {
DataNotAccurate = "DATA_NOT_ACCURATE",
DontPlayEnough = "DONT_PLAY_ENOUGH",
MissingFeatures = "MISSING_FEATURES",
Other = "OTHER",
TechnicalIssues = "TECHNICAL_ISSUES",
TooExpensive = "TOO_EXPENSIVE",
}
export type Challenge = {
__typename?: "Challenge";
createdAt: Scalars["DateTime"]["output"];
@@ -303,6 +324,12 @@ export type EnumAggregation = {
feature: Scalars["String"]["input"];
};
export type ExchangeAuthHandoffResultGql = {
__typename?: "ExchangeAuthHandoffResultGQL";
customToken: Scalars["String"]["output"];
userId: Scalars["Int"]["output"];
};
export type FilterInput =
| {
andFilters: Array<FilterInput>;
@@ -2327,6 +2354,7 @@ export type Mutation = {
blockUser: Scalars["Boolean"]["output"];
cancelSubscription: UserSubscriptionStatusGql;
commentOnVideo: Scalars["Boolean"]["output"];
createAuthHandoffToken: AuthHandoffTokenGql;
createBucketSet: BucketSetGql;
createChallenge: Challenge;
createRuleSet: RuleSet;
@@ -2344,6 +2372,7 @@ export type Mutation = {
editUploadStream: Scalars["Boolean"]["output"];
editUser: UserGql;
ensureStripeCustomerExists: UserGql;
exchangeAuthHandoffToken: ExchangeAuthHandoffResultGql;
findPrerecordTableLayout?: Maybe<HomographyInfoGql>;
followUser: UserGql;
getHlsInitUploadLink: GetUploadLinkReturn;
@@ -2361,6 +2390,7 @@ export type Mutation = {
setLoggerLevel: Scalars["Boolean"]["output"];
setSegmentDuration: Scalars["Boolean"]["output"];
startChallenge: ChallengeEntry;
submitCancellationFeedback: Scalars["Boolean"]["output"];
submitChallengeEntry: ChallengeEntry;
undismissChallenge: Scalars["Boolean"]["output"];
unfollowUser: UserGql;
@@ -2463,6 +2493,10 @@ export type MutationEditUserArgs = {
input: EditUserInputGql;
};
export type MutationExchangeAuthHandoffTokenArgs = {
token: Scalars["String"]["input"];
};
export type MutationFindPrerecordTableLayoutArgs = {
b64Image: Scalars["String"]["input"];
videoId: Scalars["Int"]["input"];
@@ -2537,6 +2571,12 @@ export type MutationStartChallengeArgs = {
challengeId: Scalars["ID"]["input"];
};
export type MutationSubmitCancellationFeedbackArgs = {
feedback?: InputMaybe<Scalars["String"]["input"]>;
metadata?: InputMaybe<CancellationFeedbackMetadataInput>;
reasons?: InputMaybe<Array<CancellationReasonEnum>>;
};
export type MutationSubmitChallengeEntryArgs = {
entryId: Scalars["ID"]["input"];
videoId: Scalars["ID"]["input"];
@@ -4017,7 +4057,6 @@ export type GetFeedQuery = {
private: boolean;
elapsedTime?: number | null;
tableSize: number;
pocketSize?: number | null;
owner?: {
__typename?: "UserGQL";
id: number;
@@ -4119,7 +4158,6 @@ export type VideoCardFieldsFragment = {
private: boolean;
elapsedTime?: number | null;
tableSize: number;
pocketSize?: number | null;
owner?: {
__typename?: "UserGQL";
id: number;
@@ -4217,7 +4255,6 @@ export type GetVideoFeedQuery = {
private: boolean;
elapsedTime?: number | null;
tableSize: number;
pocketSize?: number | null;
owner?: {
__typename?: "UserGQL";
id: number;
@@ -6385,7 +6422,6 @@ export const VideoCardFieldsFragmentDoc = gql`
streamSegmentType
}
tableSize
pocketSize
tags {
tagClasses {
name

View File

@@ -50,7 +50,6 @@ fragment VideoCardFields on VideoGQL {
streamSegmentType
}
tableSize
pocketSize
tags {
tagClasses {
name

View File

@@ -63,3 +63,17 @@ mutation CancelSubscription {
stripeSubscriptionId
}
}
mutation CreateAuthHandoffToken {
createAuthHandoffToken {
token
expiresInSeconds
}
}
mutation ExchangeAuthHandoffToken($token: String!) {
exchangeAuthHandoffToken(token: $token) {
customToken
userId
}
}

View File

@@ -1072,6 +1072,13 @@ type Mutation {
deleteUser: Boolean!
createSubscription(priceId: String!): CreateSubscriptionResultGQL!
cancelSubscription: UserSubscriptionStatusGQL!
submitCancellationFeedback(
reasons: [CancellationReasonEnum!] = null
feedback: String = null
metadata: CancellationFeedbackMetadataInput = null
): Boolean!
createAuthHandoffToken: AuthHandoffTokenGQL!
exchangeAuthHandoffToken(token: String!): ExchangeAuthHandoffResultGQL!
findPrerecordTableLayout(b64Image: String!, videoId: Int!): HomographyInfoGQL
createUploadStream(
videoMetadata: VideoMetadataInput!
@@ -1108,7 +1115,7 @@ type AddShotAnnotationReturn {
}
union SuccessfulAddAddShotAnnotationErrors =
| SuccessfulAdd
SuccessfulAdd
| AddShotAnnotationErrors
type SuccessfulAdd {
@@ -1120,7 +1127,7 @@ type AddShotAnnotationErrors {
}
union DoesNotOwnShotErrOtherErrorNeedsNote =
| DoesNotOwnShotErr
DoesNotOwnShotErr
| OtherErrorNeedsNote
type DoesNotOwnShotErr {
@@ -1163,7 +1170,7 @@ type GetProfileUploadLinkReturn {
}
union UploadLinkGetProfileUploadLinkErrors =
| UploadLink
UploadLink
| GetProfileUploadLinkErrors
type UploadLink {
@@ -1196,6 +1203,31 @@ type CreateSubscriptionResultGQL {
sessionId: String!
}
enum CancellationReasonEnum {
DONT_PLAY_ENOUGH
TOO_EXPENSIVE
MISSING_FEATURES
TECHNICAL_ISSUES
DATA_NOT_ACCURATE
OTHER
}
input CancellationFeedbackMetadataInput {
appVersion: String = null
gitRevision: String = null
platform: String = null
}
type AuthHandoffTokenGQL {
token: String!
expiresInSeconds: Int!
}
type ExchangeAuthHandoffResultGQL {
customToken: String!
userId: Int!
}
type CreateUploadStreamReturn {
videoId: Int!
}
@@ -1239,7 +1271,7 @@ type GetUploadLinkErrors {
}
union MustHaveSetForUploadLinkErrSegmentAlreadyUploadedErrProcessingFailedErrNoInitForChunkedUploadErrTooManyProfileImageUploadsErrInitUploadAlreadyCompletedErrTooManyInitUploadsErr =
| MustHaveSetForUploadLinkErr
MustHaveSetForUploadLinkErr
| SegmentAlreadyUploadedErr
| ProcessingFailedErr
| NoInitForChunkedUploadErr