@grantjs/schema 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grantjs/schema",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -444,6 +444,7 @@ export type MeQuery = {
444
444
  requiresEmailVerification: boolean | null;
445
445
  verificationExpiry: Date | null;
446
446
  email: string | null;
447
+ hasOrganizationMembership: boolean;
447
448
  accounts: Array<{
448
449
  id: string;
449
450
  type: Types.AccountType;
@@ -582,6 +583,14 @@ export type MyUserDataExportQuery = {
582
583
  lastUsedAt: Date | null;
583
584
  createdAt: Date;
584
585
  }>;
586
+ credentials: Array<{
587
+ scope: string;
588
+ projectId: string | null;
589
+ source: string;
590
+ lastUsedAt: Date | null;
591
+ createdAt: Date;
592
+ updatedAt: Date;
593
+ }>;
585
594
  sessions: Array<{
586
595
  userAgent: string | null;
587
596
  ipAddress: string | null;
@@ -4179,6 +4188,7 @@ export const MeDocument = {
4179
4188
  { kind: 'Field', name: { kind: 'Name', value: 'requiresEmailVerification' } },
4180
4189
  { kind: 'Field', name: { kind: 'Name', value: 'verificationExpiry' } },
4181
4190
  { kind: 'Field', name: { kind: 'Name', value: 'email' } },
4191
+ { kind: 'Field', name: { kind: 'Name', value: 'hasOrganizationMembership' } },
4182
4192
  ],
4183
4193
  },
4184
4194
  },
@@ -4518,6 +4528,21 @@ export const MyUserDataExportDocument = {
4518
4528
  ],
4519
4529
  },
4520
4530
  },
4531
+ {
4532
+ kind: 'Field',
4533
+ name: { kind: 'Name', value: 'credentials' },
4534
+ selectionSet: {
4535
+ kind: 'SelectionSet',
4536
+ selections: [
4537
+ { kind: 'Field', name: { kind: 'Name', value: 'scope' } },
4538
+ { kind: 'Field', name: { kind: 'Name', value: 'projectId' } },
4539
+ { kind: 'Field', name: { kind: 'Name', value: 'source' } },
4540
+ { kind: 'Field', name: { kind: 'Name', value: 'lastUsedAt' } },
4541
+ { kind: 'Field', name: { kind: 'Name', value: 'createdAt' } },
4542
+ { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } },
4543
+ ],
4544
+ },
4545
+ },
4521
4546
  {
4522
4547
  kind: 'Field',
4523
4548
  name: { kind: 'Name', value: 'sessions' },
@@ -270,6 +270,7 @@ export type ResolversTypes = ResolversObject<{
270
270
  CreateUserInput: Types.CreateUserInput;
271
271
  CreateUserSessionInput: Types.CreateUserSessionInput;
272
272
  CreateWebhookSubscriptionMutationInput: Types.CreateWebhookSubscriptionMutationInput;
273
+ CredentialExportData: ResolverTypeWrapper<Types.CredentialExportData>;
273
274
  Date: ResolverTypeWrapper<Types.Scalars['Date']['output']>;
274
275
  DeleteApiKeyInput: Types.DeleteApiKeyInput;
275
276
  DeleteMyAccountsInput: Types.DeleteMyAccountsInput;
@@ -680,6 +681,7 @@ export type ResolversParentTypes = ResolversObject<{
680
681
  CreateUserInput: Types.CreateUserInput;
681
682
  CreateUserSessionInput: Types.CreateUserSessionInput;
682
683
  CreateWebhookSubscriptionMutationInput: Types.CreateWebhookSubscriptionMutationInput;
684
+ CredentialExportData: Types.CredentialExportData;
683
685
  Date: Types.Scalars['Date']['output'];
684
686
  DeleteApiKeyInput: Types.DeleteApiKeyInput;
685
687
  DeleteMyAccountsInput: Types.DeleteMyAccountsInput;
@@ -1295,6 +1297,19 @@ export type CreateProjectAppResultResolvers<
1295
1297
  signUpRoleId?: Resolver<Types.Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
1296
1298
  }>;
1297
1299
 
1300
+ export type CredentialExportDataResolvers<
1301
+ ContextType = any,
1302
+ ParentType extends ResolversParentTypes['CredentialExportData'] =
1303
+ ResolversParentTypes['CredentialExportData'],
1304
+ > = ResolversObject<{
1305
+ createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
1306
+ lastUsedAt?: Resolver<Types.Maybe<ResolversTypes['Date']>, ParentType, ContextType>;
1307
+ projectId?: Resolver<Types.Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
1308
+ scope?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1309
+ source?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
1310
+ updatedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
1311
+ }>;
1312
+
1298
1313
  export interface DateScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['Date'], any> {
1299
1314
  name: 'Date';
1300
1315
  }
@@ -1433,6 +1448,7 @@ export type MeResponseResolvers<
1433
1448
  > = ResolversObject<{
1434
1449
  accounts?: Resolver<Array<ResolversTypes['Account']>, ParentType, ContextType>;
1435
1450
  email?: Resolver<Types.Maybe<ResolversTypes['String']>, ParentType, ContextType>;
1451
+ hasOrganizationMembership?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
1436
1452
  mfaVerified?: Resolver<Types.Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
1437
1453
  requiresEmailVerification?: Resolver<
1438
1454
  Types.Maybe<ResolversTypes['Boolean']>,
@@ -3468,6 +3484,7 @@ export type UserDataExportResolvers<
3468
3484
  ParentType,
3469
3485
  ContextType
3470
3486
  >;
3487
+ credentials?: Resolver<Array<ResolversTypes['CredentialExportData']>, ParentType, ContextType>;
3471
3488
  exportedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
3472
3489
  organizationMemberships?: Resolver<
3473
3490
  Array<ResolversTypes['OrganizationMembershipExportData']>,
@@ -3735,6 +3752,7 @@ export type Resolvers<ContextType = any> = ResolversObject<{
3735
3752
  CreateApiKeyResult?: CreateApiKeyResultResolvers<ContextType>;
3736
3753
  CreateMySecondaryAccountResult?: CreateMySecondaryAccountResultResolvers<ContextType>;
3737
3754
  CreateProjectAppResult?: CreateProjectAppResultResolvers<ContextType>;
3755
+ CredentialExportData?: CredentialExportDataResolvers<ContextType>;
3738
3756
  Date?: GraphQLScalarType;
3739
3757
  ExchangeApiKeyResult?: ExchangeApiKeyResultResolvers<ContextType>;
3740
3758
  Group?: GroupResolvers<ContextType>;
@@ -448,8 +448,8 @@ export enum CdmIfMissing {
448
448
  export type CdmKeyResolverInput = {
449
449
  /**
450
450
  * `id` references an existing Grant user id. `email` resolves or creates a
451
- * global email authentication method, passwordless unless the user carries a
452
- * `password`. Other values are treated as CDM-local external keys for project
451
+ * global email authentication method, passwordless on the platform; a `password`
452
+ * becomes a credential of the importing project only. Other values are treated as CDM-local external keys for project
453
453
  * import/export.
454
454
  */
455
455
  findBy?: InputMaybe<CdmFindBy>;
@@ -489,8 +489,8 @@ export enum CdmPasswordAlgorithm {
489
489
  }
490
490
 
491
491
  /**
492
- * A password hash the importer already holds, to be stored as the user's email
493
- * password credential (ADR 0010). Never the plaintext password.
492
+ * A password hash the importer already holds, to be stored as the importing project's
493
+ * password credential (ADR 0011). Never the plaintext password.
494
494
  */
495
495
  export type CdmPasswordInput = {
496
496
  algorithm: CdmPasswordAlgorithm;
@@ -677,7 +677,7 @@ export type CreatePermissionInput = {
677
677
  export type CreateProjectAppInput = {
678
678
  /** Allow new users to sign up when authenticating via this app. Default true. */
679
679
  allowSignUp?: InputMaybe<Scalars['Boolean']['input']>;
680
- /** Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers. */
680
+ /** Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here. */
681
681
  enabledProviders?: InputMaybe<Array<Scalars['String']['input']>>;
682
682
  name?: InputMaybe<Scalars['String']['input']>;
683
683
  primaryTagId?: InputMaybe<Scalars['ID']['input']>;
@@ -699,7 +699,7 @@ export type CreateProjectAppResult = {
699
699
  /** Shown only once at creation. Null for public clients. */
700
700
  clientSecret?: Maybe<Scalars['String']['output']>;
701
701
  createdAt: Scalars['Date']['output'];
702
- /** Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers. */
702
+ /** Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here. */
703
703
  enabledProviders?: Maybe<Array<Scalars['String']['output']>>;
704
704
  id: Scalars['ID']['output'];
705
705
  name?: Maybe<Scalars['String']['output']>;
@@ -787,6 +787,22 @@ export type CreateWebhookSubscriptionMutationInput = {
787
787
  url: Scalars['String']['input'];
788
788
  };
789
789
 
790
+ /**
791
+ * A password credential the user holds, per scope. Existence, scope, source and dates only:
792
+ * the hash is never exported.
793
+ */
794
+ export type CredentialExportData = {
795
+ __typename?: 'CredentialExportData';
796
+ createdAt: Scalars['Date']['output'];
797
+ lastUsedAt?: Maybe<Scalars['Date']['output']>;
798
+ /** Set for a project credential */
799
+ projectId?: Maybe<Scalars['ID']['output']>;
800
+ /** platform (the Grant console) or project (that project's apps) */
801
+ scope: Scalars['String']['output'];
802
+ source: Scalars['String']['output'];
803
+ updatedAt: Scalars['Date']['output'];
804
+ };
805
+
790
806
  export type DeleteApiKeyInput = {
791
807
  hardDelete?: InputMaybe<Scalars['Boolean']['input']>;
792
808
  id: Scalars['ID']['input'];
@@ -1010,6 +1026,11 @@ export type MeResponse = {
1010
1026
  __typename?: 'MeResponse';
1011
1027
  accounts: Array<Account>;
1012
1028
  email?: Maybe<Scalars['String']['output']>;
1029
+ /**
1030
+ * Whether the user belongs to at least one organization. A user with no accounts and no
1031
+ * organization membership has no workspace on this installation.
1032
+ */
1033
+ hasOrganizationMembership: Scalars['Boolean']['output'];
1013
1034
  mfaVerified?: Maybe<Scalars['Boolean']['output']>;
1014
1035
  requiresEmailVerification?: Maybe<Scalars['Boolean']['output']>;
1015
1036
  verificationExpiry?: Maybe<Scalars['Date']['output']>;
@@ -2180,7 +2201,7 @@ export type ProjectApp = Auditable & {
2180
2201
  clientId: Scalars['String']['output'];
2181
2202
  createdAt: Scalars['Date']['output'];
2182
2203
  deletedAt?: Maybe<Scalars['Date']['output']>;
2183
- /** Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers. */
2204
+ /** Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here. */
2184
2205
  enabledProviders?: Maybe<Array<Scalars['String']['output']>>;
2185
2206
  id: Scalars['ID']['output'];
2186
2207
  name?: Maybe<Scalars['String']['output']>;
@@ -3612,20 +3633,24 @@ export type SyncProjectResult = {
3612
3633
  groupTagsLinked: Scalars['Int']['output'];
3613
3634
  groupsCreated: Scalars['Int']['output'];
3614
3635
  importId?: Maybe<Scalars['String']['output']>;
3615
- /** Users whose `password` hash was stored as their email credential for the first time. */
3636
+ /**
3637
+ * Users whose `password` hash was stored as the importing project's credential for the
3638
+ * first time.
3639
+ */
3616
3640
  passwordsImported: Scalars['Int']['output'];
3617
3641
  /**
3618
- * Users whose `password` hash was not stored because the credential or the identity is
3619
- * not the import's to write: a password set in Grant, an address the owner has verified,
3620
- * or an identity that already existed and was not created by an earlier import of this
3621
- * project.
3642
+ * Users whose project credential was not written because the person owns it: it was set or
3643
+ * reset in Grant, not imported.
3622
3644
  */
3623
3645
  passwordsSkippedExisting: Scalars['Int']['output'];
3624
- /** Users whose imported credential already equalled the hash in the document. */
3646
+ /**
3647
+ * Users whose project credential, stored by an earlier import of this project, already
3648
+ * equalled the hash in the document.
3649
+ */
3625
3650
  passwordsUnchanged: Scalars['Int']['output'];
3626
3651
  /**
3627
- * Users whose imported credential was replaced because the document carried a different
3628
- * hash for it.
3652
+ * Users whose project credential was replaced because an earlier import of this project had
3653
+ * stored a different hash.
3629
3654
  */
3630
3655
  passwordsUpdated: Scalars['Int']['output'];
3631
3656
  permissionsCreated: Scalars['Int']['output'];
@@ -3825,7 +3850,7 @@ export type UpdatePermissionTagInput = {
3825
3850
  export type UpdateProjectAppInput = {
3826
3851
  /** Allow new users to sign up when authenticating via this app. */
3827
3852
  allowSignUp?: InputMaybe<Scalars['Boolean']['input']>;
3828
- /** Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers. */
3853
+ /** Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here. */
3829
3854
  enabledProviders?: InputMaybe<Array<Scalars['String']['input']>>;
3830
3855
  /** Display name for the app. */
3831
3856
  name?: InputMaybe<Scalars['String']['input']>;
@@ -4132,19 +4157,22 @@ export type UserCdmInput = {
4132
4157
  metadata?: InputMaybe<Scalars['JSON']['input']>;
4133
4158
  name: Scalars['String']['input'];
4134
4159
  /**
4135
- * Existing password credential to import for this user. Only valid with
4136
- * `key.findBy: email`, because the credential lives on the email authentication
4137
- * method; any other resolver is a validation error.
4160
+ * Existing password credential to import for this user as a credential of the importing
4161
+ * project only. Only valid with `key.findBy: email`, because the person is resolved by
4162
+ * address; any other resolver is a validation error.
4163
+ *
4164
+ * The person must be a member of the project after the import: assigned in the same
4165
+ * document (`roles`, `groups` or `permissions`) or already a member. A password for anyone
4166
+ * else is a validation error raised when the import is applied, which rolls the import back
4167
+ * and names the position in `users`.
4138
4168
  *
4139
- * Ownership is forward-only. An imported credential is marked as imported and stays
4140
- * owned by the importing system while the email is unverified: a later import of this
4141
- * project with a different hash replaces it, an identical one changes nothing. Once the
4142
- * owner verifies the address, or the password is set, changed or reset in Grant, Grant owns
4143
- * it and imports never touch it again. A credential is written only for an identity the
4144
- * import creates, or one an earlier import of this project created whose email is still
4145
- * unverified; any other existing identity, including one found through GitHub or Google,
4146
- * is left untouched. An absent `password` never removes a
4147
- * stored credential. See `SyncProjectResult` for the counters.
4169
+ * Ownership is forward-only. An imported credential is marked as imported and stays owned
4170
+ * by the importing system until the person resets or changes it: a later import of this
4171
+ * project with a different hash replaces it, an identical one changes nothing. Once it is
4172
+ * set, changed or reset in Grant, Grant owns it and imports never touch it again. Verified
4173
+ * and GitHub or Google linked identities are not excluded: the credential opens this
4174
+ * project's apps only. An absent `password` never removes a stored credential. See
4175
+ * `SyncProjectResult` for the counters.
4148
4176
  */
4149
4177
  password?: InputMaybe<CdmPasswordInput>;
4150
4178
  /** Direct user → permission grants (document keys or catalog `resourceSlug:action` refs). */
@@ -4161,6 +4189,7 @@ export type UserDataExport = {
4161
4189
  __typename?: 'UserDataExport';
4162
4190
  accounts: Array<AccountExportData>;
4163
4191
  authenticationMethods: Array<AuthenticationMethodExportData>;
4192
+ credentials: Array<CredentialExportData>;
4164
4193
  exportedAt: Scalars['Date']['output'];
4165
4194
  organizationMemberships: Array<OrganizationMembershipExportData>;
4166
4195
  projectMemberships: Array<ProjectMembershipExportData>;
package/src/index.ts CHANGED
@@ -13,5 +13,6 @@ export {
13
13
  type ProjectConsentInfoUser,
14
14
  type ProjectConsentRedirectResult,
15
15
  type ProjectOAuthThemeMode,
16
+ type ProjectPasswordSignInResult,
16
17
  } from './project-oauth.types';
17
18
  export * from './webhooks/webhook.types';
@@ -23,5 +23,6 @@ query Me {
23
23
  requiresEmailVerification
24
24
  verificationExpiry
25
25
  email
26
+ hasOrganizationMembership
26
27
  }
27
28
  }
@@ -21,6 +21,14 @@ query MyUserDataExport {
21
21
  lastUsedAt
22
22
  createdAt
23
23
  }
24
+ credentials {
25
+ scope
26
+ projectId
27
+ source
28
+ lastUsedAt
29
+ createdAt
30
+ updatedAt
31
+ }
24
32
  sessions {
25
33
  userAgent
26
34
  ipAddress
@@ -62,3 +62,10 @@ export interface ProjectConsentInfo {
62
62
  export interface ProjectConsentRedirectResult {
63
63
  redirectUrl: string;
64
64
  }
65
+
66
+ /**
67
+ * Response from POST /api/auth/project/password: the consent page to continue to, or a
68
+ * pending MFA step when the platform requires MFA at sign-in (ADR 0011 slice 4).
69
+ */
70
+ export type ProjectPasswordSignInResult =
71
+ { status: 'authenticated'; redirectUrl: string } | { status: 'mfa_required'; mfaToken: string };
@@ -4,4 +4,9 @@ type MeResponse {
4
4
  requiresEmailVerification: Boolean
5
5
  verificationExpiry: Date
6
6
  email: String
7
+ """
8
+ Whether the user belongs to at least one organization. A user with no accounts and no
9
+ organization membership has no workspace on this installation.
10
+ """
11
+ hasOrganizationMembership: Boolean!
7
12
  }
@@ -10,7 +10,7 @@ input CreateProjectAppInput {
10
10
  """
11
11
  scopes: [String!]
12
12
  """
13
- Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers.
13
+ Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here.
14
14
  """
15
15
  enabledProviders: [String!]
16
16
  """
@@ -25,7 +25,7 @@ input UpdateProjectAppInput {
25
25
  """
26
26
  scopes: [String!]
27
27
  """
28
- Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers.
28
+ Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here.
29
29
  """
30
30
  enabledProviders: [String!]
31
31
  """
@@ -8,7 +8,7 @@ type CreateProjectAppResult {
8
8
  name: String
9
9
  redirectUris: [String!]!
10
10
  """
11
- Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers.
11
+ Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here.
12
12
  """
13
13
  enabledProviders: [String!]
14
14
  """
@@ -19,7 +19,7 @@ type ProjectApp implements Auditable {
19
19
  redirectUris: [String!]!
20
20
  scopes: [String!]
21
21
  """
22
- Auth providers enabled for this app (e.g. github, email). Empty/null = all configured providers.
22
+ Auth providers enabled for this app: `email` (magic link), `github`, `google` and `password` (email and password, checked against the project's own credential). Empty/null = every provider except `password`, which is opt-in and is on only when named here.
23
23
  """
24
24
  enabledProviders: [String!]
25
25
  """
@@ -47,8 +47,8 @@ input CdmKeyResolverInput {
47
47
  value: String!
48
48
  """
49
49
  `id` references an existing Grant user id. `email` resolves or creates a
50
- global email authentication method, passwordless unless the user carries a
51
- `password`. Other values are treated as CDM-local external keys for project
50
+ global email authentication method, passwordless on the platform; a `password`
51
+ becomes a credential of the importing project only. Other values are treated as CDM-local external keys for project
52
52
  import/export.
53
53
  """
54
54
  findBy: CdmFindBy
@@ -138,8 +138,8 @@ input UserApiKeyCdmInput {
138
138
  }
139
139
 
140
140
  """
141
- A password hash the importer already holds, to be stored as the user's email
142
- password credential (ADR 0010). Never the plaintext password.
141
+ A password hash the importer already holds, to be stored as the importing project's
142
+ password credential (ADR 0011). Never the plaintext password.
143
143
  """
144
144
  input CdmPasswordInput {
145
145
  algorithm: CdmPasswordAlgorithm!
@@ -173,19 +173,22 @@ input UserCdmInput {
173
173
  primaryTag: String
174
174
  apiKeys: [UserApiKeyCdmInput!]
175
175
  """
176
- Existing password credential to import for this user. Only valid with
177
- `key.findBy: email`, because the credential lives on the email authentication
178
- method; any other resolver is a validation error.
179
-
180
- Ownership is forward-only. An imported credential is marked as imported and stays
181
- owned by the importing system while the email is unverified: a later import of this
182
- project with a different hash replaces it, an identical one changes nothing. Once the
183
- owner verifies the address, or the password is set, changed or reset in Grant, Grant owns
184
- it and imports never touch it again. A credential is written only for an identity the
185
- import creates, or one an earlier import of this project created whose email is still
186
- unverified; any other existing identity, including one found through GitHub or Google,
187
- is left untouched. An absent `password` never removes a
188
- stored credential. See `SyncProjectResult` for the counters.
176
+ Existing password credential to import for this user as a credential of the importing
177
+ project only. Only valid with `key.findBy: email`, because the person is resolved by
178
+ address; any other resolver is a validation error.
179
+
180
+ The person must be a member of the project after the import: assigned in the same
181
+ document (`roles`, `groups` or `permissions`) or already a member. A password for anyone
182
+ else is a validation error raised when the import is applied, which rolls the import back
183
+ and names the position in `users`.
184
+
185
+ Ownership is forward-only. An imported credential is marked as imported and stays owned
186
+ by the importing system until the person resets or changes it: a later import of this
187
+ project with a different hash replaces it, an identical one changes nothing. Once it is
188
+ set, changed or reset in Grant, Grant owns it and imports never touch it again. Verified
189
+ and GitHub or Google linked identities are not excluded: the credential opens this
190
+ project's apps only. An absent `password` never removes a stored credential. See
191
+ `SyncProjectResult` for the counters.
189
192
  """
190
193
  password: CdmPasswordInput
191
194
  """
@@ -17,23 +17,23 @@ type SyncProjectResult {
17
17
  userRolesAssigned: Int!
18
18
  projectUserApiKeysCreated: Int!
19
19
  """
20
- Users whose `password` hash was stored as their email credential for the first time.
20
+ Users whose `password` hash was stored as the importing project's credential for the
21
+ first time.
21
22
  """
22
23
  passwordsImported: Int!
23
24
  """
24
- Users whose imported credential was replaced because the document carried a different
25
- hash for it.
25
+ Users whose project credential was replaced because an earlier import of this project had
26
+ stored a different hash.
26
27
  """
27
28
  passwordsUpdated: Int!
28
29
  """
29
- Users whose imported credential already equalled the hash in the document.
30
+ Users whose project credential, stored by an earlier import of this project, already
31
+ equalled the hash in the document.
30
32
  """
31
33
  passwordsUnchanged: Int!
32
34
  """
33
- Users whose `password` hash was not stored because the credential or the identity is
34
- not the import's to write: a password set in Grant, an address the owner has verified,
35
- or an identity that already existed and was not created by an earlier import of this
36
- project.
35
+ Users whose project credential was not written because the person owns it: it was set or
36
+ reset in Grant, not imported.
37
37
  """
38
38
  passwordsSkippedExisting: Int!
39
39
  resourcesCreated: Int!
@@ -2,6 +2,7 @@ type UserDataExport {
2
2
  user: UserExportData!
3
3
  accounts: [AccountExportData!]!
4
4
  authenticationMethods: [AuthenticationMethodExportData!]!
5
+ credentials: [CredentialExportData!]!
5
6
  sessions: [SessionExportData!]!
6
7
  organizationMemberships: [OrganizationMembershipExportData!]!
7
8
  projectMemberships: [ProjectMembershipExportData!]!
@@ -32,6 +33,21 @@ type AuthenticationMethodExportData {
32
33
  createdAt: Date!
33
34
  }
34
35
 
36
+ """
37
+ A password credential the user holds, per scope. Existence, scope, source and dates only:
38
+ the hash is never exported.
39
+ """
40
+ type CredentialExportData {
41
+ "platform (the Grant console) or project (that project's apps)"
42
+ scope: String!
43
+ "Set for a project credential"
44
+ projectId: ID
45
+ source: String!
46
+ lastUsedAt: Date
47
+ createdAt: Date!
48
+ updatedAt: Date!
49
+ }
50
+
35
51
  type SessionExportData {
36
52
  userAgent: String
37
53
  ipAddress: String