@gscdump/contracts 3.6.3 → 3.8.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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Shared protocol contracts for gscdump.com integrations.
4
4
 
5
5
  Use `@gscdump/contracts/v1` for operation definitions, request and response schemas, and protocol constants.
6
- The registry describes 55 HTTP operations and the realtime protocol.
6
+ The registry describes 58 HTTP operations and the realtime protocol.
7
7
  For HTTP calls, install [`@gscdump/sdk`](../sdk/README.md).
8
8
 
9
9
  ```bash
@@ -11,7 +11,7 @@ export declare const HTTP_V1_CREDENTIAL_SCOPES: {
11
11
  readonly user_key: readonly ["users:read", "users:write", "sites:read", "sites:write", "analytics:read", "analytics:execute", "indexing:read", "indexing:write", "sitemaps:read", "sitemaps:write", "settings:read", "settings:write", "realtime:connect"];
12
12
  readonly partner_key: readonly ["users:read", "users:write", "sites:read", "sites:write", "analytics:read", "analytics:execute", "indexing:read", "indexing:write", "sitemaps:read", "sitemaps:write", "settings:read", "settings:write", "realtime:connect", "teams:read", "teams:write"];
13
13
  };
14
- export declare const HTTP_V1_ERROR_CODES: readonly ["invalid_request", "unauthorized", "forbidden", "user_not_found", "site_not_found", "rate_limited", "realtime_unavailable", "internal_error", "contract_violation"];
14
+ export declare const HTTP_V1_ERROR_CODES: readonly ["invalid_request", "unauthorized", "forbidden", "user_not_found", "site_not_found", "api_key_not_found", "api_key_limit_reached", "rate_limited", "realtime_unavailable", "internal_error", "contract_violation"];
15
15
  export type HttpV1SurfaceName = HttpV1RouteSurfaceName;
16
16
  export type HttpV1Method = HttpV1RouteMethod;
17
17
  export type HttpV1Credential = typeof HTTP_V1_CREDENTIALS[number];
@@ -41,6 +41,8 @@ const HTTP_V1_ERROR_CODES = [
41
41
  "forbidden",
42
42
  "user_not_found",
43
43
  "site_not_found",
44
+ "api_key_not_found",
45
+ "api_key_limit_reached",
44
46
  "rate_limited",
45
47
  "realtime_unavailable",
46
48
  "internal_error",
@@ -104,7 +106,7 @@ function assertPathContract(operation) {
104
106
  if (names.join("\0") !== schemaKeys.join("\0")) throw new TypeError(`${operation.id}: params schema keys (${schemaKeys.join(", ")}) must match path order (${names.join(", ")})`);
105
107
  }
106
108
  function assertOperation(operation) {
107
- if (!/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/.test(operation.id)) throw new TypeError(`${operation.id}: operation ID must be a stable dotted lowercase identifier`);
109
+ if (!/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*(?:\.[a-z][a-z0-9]*(?:_[a-z0-9]+)*)+$/.test(operation.id)) throw new TypeError(`${operation.id}: operation ID must be a stable dotted lowercase identifier`);
108
110
  if (!isSafePathTemplate(operation.path)) throw new TypeError(`${operation.id}: path must be a safe literal surface-relative template`);
109
111
  assertRequestLocations(operation.request, operation.id);
110
112
  assertPathContract(operation);
@@ -697,6 +697,8 @@ export declare function createGscdumpV1Protocol(): {
697
697
  forbidden: "forbidden";
698
698
  user_not_found: "user_not_found";
699
699
  site_not_found: "site_not_found";
700
+ api_key_not_found: "api_key_not_found";
701
+ api_key_limit_reached: "api_key_limit_reached";
700
702
  rate_limited: "rate_limited";
701
703
  realtime_unavailable: "realtime_unavailable";
702
704
  contract_violation: "contract_violation";
@@ -715,6 +717,8 @@ export declare function createGscdumpV1Protocol(): {
715
717
  forbidden: "forbidden";
716
718
  user_not_found: "user_not_found";
717
719
  site_not_found: "site_not_found";
720
+ api_key_not_found: "api_key_not_found";
721
+ api_key_limit_reached: "api_key_limit_reached";
718
722
  rate_limited: "rate_limited";
719
723
  realtime_unavailable: "realtime_unavailable";
720
724
  contract_violation: "contract_violation";
@@ -12824,6 +12828,410 @@ export declare function createGscdumpV1Protocol(): {
12824
12828
  readonly method: "POST";
12825
12829
  readonly path: "/users/{userId}/sites/verify";
12826
12830
  };
12831
+ readonly createUserApiKey: {
12832
+ readonly visibility: "public";
12833
+ readonly semantics: {
12834
+ readonly kind: "mutation";
12835
+ readonly sideEffects: "state";
12836
+ readonly idempotent: false;
12837
+ readonly retry: "never";
12838
+ readonly readConsistency: null;
12839
+ };
12840
+ readonly auth: {
12841
+ readonly credentials: readonly ["partner_key"];
12842
+ readonly scopes: readonly ["users:write"];
12843
+ readonly ownership: readonly [{
12844
+ readonly credential: "partner_key";
12845
+ readonly rule: "linked_user";
12846
+ }];
12847
+ };
12848
+ readonly request: {
12849
+ readonly params: z.ZodObject<{
12850
+ userId: z.ZodString;
12851
+ }, z.core.$strict>;
12852
+ readonly query: null;
12853
+ readonly headers: z.ZodObject<{
12854
+ 'x-request-id': z.ZodOptional<z.ZodString>;
12855
+ }, z.core.$strict>;
12856
+ readonly body: z.ZodObject<{
12857
+ label: z.ZodString;
12858
+ }, z.core.$strict>;
12859
+ };
12860
+ readonly responses: {
12861
+ readonly 201: CompatibleResponseSchema<z.ZodObject<{
12862
+ data: z.ZodObject<{
12863
+ readonly keyId: z.ZodString;
12864
+ readonly apiKey: z.ZodString;
12865
+ readonly preview: z.ZodString;
12866
+ readonly label: z.ZodString;
12867
+ readonly createdAt: z.ZodNumber;
12868
+ }, z.core.$strip>;
12869
+ meta: z.ZodObject<{
12870
+ readonly requestId: z.ZodString;
12871
+ readonly surface: z.ZodLiteral<"partner">;
12872
+ readonly version: z.ZodLiteral<"1.0">;
12873
+ }, z.core.$strip>;
12874
+ }, z.core.$strip>, z.ZodObject<{
12875
+ data: z.ZodObject<{
12876
+ readonly keyId: z.ZodString;
12877
+ readonly apiKey: z.ZodString;
12878
+ readonly preview: z.ZodString;
12879
+ readonly label: z.ZodString;
12880
+ readonly createdAt: z.ZodNumber;
12881
+ }, z.core.$strip>;
12882
+ meta: z.ZodObject<{
12883
+ readonly requestId: z.ZodString;
12884
+ readonly surface: z.ZodLiteral<"partner">;
12885
+ readonly version: z.ZodLiteral<"1.0">;
12886
+ }, z.core.$strip>;
12887
+ }, z.core.$strip>>;
12888
+ };
12889
+ readonly errors: readonly ["invalid_request", "unauthorized", "forbidden", "user_not_found", "rate_limited", "internal_error", "contract_violation", "api_key_limit_reached"];
12890
+ readonly errorResponse: CompatibleResponseSchema<z.ZodObject<{
12891
+ readonly error: z.ZodObject<{
12892
+ code: z.ZodEnum<{
12893
+ internal_error: "internal_error";
12894
+ invalid_request: "invalid_request";
12895
+ unauthorized: "unauthorized";
12896
+ forbidden: "forbidden";
12897
+ user_not_found: "user_not_found";
12898
+ api_key_limit_reached: "api_key_limit_reached";
12899
+ rate_limited: "rate_limited";
12900
+ contract_violation: "contract_violation";
12901
+ }>;
12902
+ message: z.ZodString;
12903
+ requestId: z.ZodString;
12904
+ retryable: z.ZodBoolean;
12905
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
12906
+ }, z.core.$strict>;
12907
+ }, z.core.$strip>, z.ZodObject<{
12908
+ readonly error: z.ZodObject<{
12909
+ code: z.ZodEnum<{
12910
+ internal_error: "internal_error";
12911
+ invalid_request: "invalid_request";
12912
+ unauthorized: "unauthorized";
12913
+ forbidden: "forbidden";
12914
+ user_not_found: "user_not_found";
12915
+ api_key_limit_reached: "api_key_limit_reached";
12916
+ rate_limited: "rate_limited";
12917
+ contract_violation: "contract_violation";
12918
+ }>;
12919
+ message: z.ZodString;
12920
+ requestId: z.ZodString;
12921
+ retryable: z.ZodBoolean;
12922
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
12923
+ }, z.core.$loose>;
12924
+ }, z.core.$strip>>;
12925
+ readonly resources: {
12926
+ readonly reads: readonly [{
12927
+ readonly type: "partner.user";
12928
+ readonly idFrom: "params.userId";
12929
+ }];
12930
+ readonly changes: readonly [{
12931
+ readonly type: "partner.user";
12932
+ readonly idFrom: "params.userId";
12933
+ }];
12934
+ };
12935
+ readonly lifecycle: {
12936
+ readonly introduced: "3.8.0";
12937
+ };
12938
+ readonly docs: {
12939
+ readonly summary: "Create a user API key";
12940
+ readonly description: "Issues a new revocable API key for a partner-linked user. The raw key appears only in this response; store or show it once. Each partner may hold at most 10 API keys per user; a create beyond the limit fails with `409 api_key_limit_reached`.";
12941
+ readonly tags: readonly ["Users"];
12942
+ readonly examples: {
12943
+ readonly request: {
12944
+ readonly params: {
12945
+ readonly userId: "u_01";
12946
+ };
12947
+ readonly body: {
12948
+ readonly label: "Laptop CLI";
12949
+ };
12950
+ };
12951
+ readonly response: {
12952
+ readonly data: {
12953
+ readonly keyId: "ak_01";
12954
+ readonly apiKey: "gsd_user_0123456789abcdef";
12955
+ readonly preview: "gsd_user_012345...cdef";
12956
+ readonly label: "Laptop CLI";
12957
+ readonly createdAt: 1789516800;
12958
+ };
12959
+ readonly meta: {
12960
+ readonly requestId: "req_01";
12961
+ readonly surface: "partner";
12962
+ readonly version: "1.0";
12963
+ };
12964
+ };
12965
+ };
12966
+ };
12967
+ readonly id: "partner.users.api_keys.create";
12968
+ readonly method: "POST";
12969
+ readonly path: "/users/{userId}/api-keys";
12970
+ };
12971
+ readonly listUserApiKeys: {
12972
+ readonly visibility: "public";
12973
+ readonly semantics: {
12974
+ readonly kind: "query";
12975
+ readonly sideEffects: "none";
12976
+ readonly idempotent: true;
12977
+ readonly retry: "idempotent";
12978
+ readonly readConsistency: "primary";
12979
+ };
12980
+ readonly auth: {
12981
+ readonly credentials: readonly ["partner_key"];
12982
+ readonly scopes: readonly ["users:read"];
12983
+ readonly ownership: readonly [{
12984
+ readonly credential: "partner_key";
12985
+ readonly rule: "linked_user";
12986
+ }];
12987
+ };
12988
+ readonly request: {
12989
+ readonly params: z.ZodObject<{
12990
+ userId: z.ZodString;
12991
+ }, z.core.$strict>;
12992
+ readonly query: null;
12993
+ readonly headers: z.ZodObject<{
12994
+ 'x-request-id': z.ZodOptional<z.ZodString>;
12995
+ }, z.core.$strict>;
12996
+ readonly body: null;
12997
+ };
12998
+ readonly responses: {
12999
+ readonly 200: CompatibleResponseSchema<z.ZodObject<{
13000
+ data: z.ZodObject<{
13001
+ readonly keys: z.ZodArray<z.ZodObject<{
13002
+ readonly keyId: z.ZodString;
13003
+ readonly preview: z.ZodString;
13004
+ readonly label: z.ZodString;
13005
+ readonly createdAt: z.ZodNumber;
13006
+ readonly lastUsedAt: z.ZodNullable<z.ZodNumber>;
13007
+ }, z.core.$strip>>;
13008
+ }, z.core.$strip>;
13009
+ meta: z.ZodObject<{
13010
+ readonly requestId: z.ZodString;
13011
+ readonly surface: z.ZodLiteral<"partner">;
13012
+ readonly version: z.ZodLiteral<"1.0">;
13013
+ }, z.core.$strip>;
13014
+ }, z.core.$strip>, z.ZodObject<{
13015
+ data: z.ZodObject<{
13016
+ readonly keys: z.ZodArray<z.ZodObject<{
13017
+ readonly keyId: z.ZodString;
13018
+ readonly preview: z.ZodString;
13019
+ readonly label: z.ZodString;
13020
+ readonly createdAt: z.ZodNumber;
13021
+ readonly lastUsedAt: z.ZodNullable<z.ZodNumber>;
13022
+ }, z.core.$strip>>;
13023
+ }, z.core.$strip>;
13024
+ meta: z.ZodObject<{
13025
+ readonly requestId: z.ZodString;
13026
+ readonly surface: z.ZodLiteral<"partner">;
13027
+ readonly version: z.ZodLiteral<"1.0">;
13028
+ }, z.core.$strip>;
13029
+ }, z.core.$strip>>;
13030
+ };
13031
+ readonly errors: readonly ["invalid_request", "unauthorized", "forbidden", "user_not_found", "rate_limited", "internal_error", "contract_violation"];
13032
+ readonly errorResponse: CompatibleResponseSchema<z.ZodObject<{
13033
+ readonly error: z.ZodObject<{
13034
+ code: z.ZodEnum<{
13035
+ internal_error: "internal_error";
13036
+ invalid_request: "invalid_request";
13037
+ unauthorized: "unauthorized";
13038
+ forbidden: "forbidden";
13039
+ user_not_found: "user_not_found";
13040
+ rate_limited: "rate_limited";
13041
+ contract_violation: "contract_violation";
13042
+ }>;
13043
+ message: z.ZodString;
13044
+ requestId: z.ZodString;
13045
+ retryable: z.ZodBoolean;
13046
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
13047
+ }, z.core.$strict>;
13048
+ }, z.core.$strip>, z.ZodObject<{
13049
+ readonly error: z.ZodObject<{
13050
+ code: z.ZodEnum<{
13051
+ internal_error: "internal_error";
13052
+ invalid_request: "invalid_request";
13053
+ unauthorized: "unauthorized";
13054
+ forbidden: "forbidden";
13055
+ user_not_found: "user_not_found";
13056
+ rate_limited: "rate_limited";
13057
+ contract_violation: "contract_violation";
13058
+ }>;
13059
+ message: z.ZodString;
13060
+ requestId: z.ZodString;
13061
+ retryable: z.ZodBoolean;
13062
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
13063
+ }, z.core.$loose>;
13064
+ }, z.core.$strip>>;
13065
+ readonly resources: {
13066
+ readonly reads: readonly [{
13067
+ readonly type: "partner.user";
13068
+ readonly idFrom: "params.userId";
13069
+ }];
13070
+ readonly changes: readonly [];
13071
+ };
13072
+ readonly lifecycle: {
13073
+ readonly introduced: "3.8.0";
13074
+ };
13075
+ readonly docs: {
13076
+ readonly summary: "List user API keys";
13077
+ readonly description: "Lists the active API keys the authenticated partner issued for a user. Keys issued by other partners or by the user are excluded. Raw keys are never returned.";
13078
+ readonly tags: readonly ["Users"];
13079
+ readonly examples: {
13080
+ readonly request: {
13081
+ readonly params: {
13082
+ readonly userId: "u_01";
13083
+ };
13084
+ };
13085
+ readonly response: {
13086
+ readonly data: {
13087
+ readonly keys: readonly [{
13088
+ readonly keyId: "ak_01";
13089
+ readonly preview: "gsd_user_012345...cdef";
13090
+ readonly label: "Laptop CLI";
13091
+ readonly createdAt: 1789516800;
13092
+ readonly lastUsedAt: null;
13093
+ }];
13094
+ };
13095
+ readonly meta: {
13096
+ readonly requestId: "req_01";
13097
+ readonly surface: "partner";
13098
+ readonly version: "1.0";
13099
+ };
13100
+ };
13101
+ };
13102
+ };
13103
+ readonly id: "partner.users.api_keys.list";
13104
+ readonly method: "GET";
13105
+ readonly path: "/users/{userId}/api-keys";
13106
+ };
13107
+ readonly revokeUserApiKey: {
13108
+ readonly visibility: "public";
13109
+ readonly semantics: {
13110
+ readonly kind: "mutation";
13111
+ readonly sideEffects: "state";
13112
+ readonly idempotent: true;
13113
+ readonly retry: "idempotent";
13114
+ readonly readConsistency: null;
13115
+ };
13116
+ readonly auth: {
13117
+ readonly credentials: readonly ["partner_key"];
13118
+ readonly scopes: readonly ["users:write"];
13119
+ readonly ownership: readonly [{
13120
+ readonly credential: "partner_key";
13121
+ readonly rule: "linked_user";
13122
+ }];
13123
+ };
13124
+ readonly request: {
13125
+ readonly params: z.ZodObject<{
13126
+ userId: z.ZodString;
13127
+ keyId: z.ZodString;
13128
+ }, z.core.$strict>;
13129
+ readonly query: null;
13130
+ readonly headers: z.ZodObject<{
13131
+ 'x-request-id': z.ZodOptional<z.ZodString>;
13132
+ }, z.core.$strict>;
13133
+ readonly body: null;
13134
+ };
13135
+ readonly responses: {
13136
+ readonly 200: CompatibleResponseSchema<z.ZodObject<{
13137
+ data: z.ZodObject<{
13138
+ readonly ok: z.ZodLiteral<true>;
13139
+ readonly keyId: z.ZodString;
13140
+ }, z.core.$strip>;
13141
+ meta: z.ZodObject<{
13142
+ readonly requestId: z.ZodString;
13143
+ readonly surface: z.ZodLiteral<"partner">;
13144
+ readonly version: z.ZodLiteral<"1.0">;
13145
+ }, z.core.$strip>;
13146
+ }, z.core.$strip>, z.ZodObject<{
13147
+ data: z.ZodObject<{
13148
+ readonly ok: z.ZodLiteral<true>;
13149
+ readonly keyId: z.ZodString;
13150
+ }, z.core.$strip>;
13151
+ meta: z.ZodObject<{
13152
+ readonly requestId: z.ZodString;
13153
+ readonly surface: z.ZodLiteral<"partner">;
13154
+ readonly version: z.ZodLiteral<"1.0">;
13155
+ }, z.core.$strip>;
13156
+ }, z.core.$strip>>;
13157
+ };
13158
+ readonly errors: readonly ["invalid_request", "unauthorized", "forbidden", "user_not_found", "rate_limited", "internal_error", "contract_violation", "api_key_not_found"];
13159
+ readonly errorResponse: CompatibleResponseSchema<z.ZodObject<{
13160
+ readonly error: z.ZodObject<{
13161
+ code: z.ZodEnum<{
13162
+ internal_error: "internal_error";
13163
+ invalid_request: "invalid_request";
13164
+ unauthorized: "unauthorized";
13165
+ forbidden: "forbidden";
13166
+ user_not_found: "user_not_found";
13167
+ api_key_not_found: "api_key_not_found";
13168
+ rate_limited: "rate_limited";
13169
+ contract_violation: "contract_violation";
13170
+ }>;
13171
+ message: z.ZodString;
13172
+ requestId: z.ZodString;
13173
+ retryable: z.ZodBoolean;
13174
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
13175
+ }, z.core.$strict>;
13176
+ }, z.core.$strip>, z.ZodObject<{
13177
+ readonly error: z.ZodObject<{
13178
+ code: z.ZodEnum<{
13179
+ internal_error: "internal_error";
13180
+ invalid_request: "invalid_request";
13181
+ unauthorized: "unauthorized";
13182
+ forbidden: "forbidden";
13183
+ user_not_found: "user_not_found";
13184
+ api_key_not_found: "api_key_not_found";
13185
+ rate_limited: "rate_limited";
13186
+ contract_violation: "contract_violation";
13187
+ }>;
13188
+ message: z.ZodString;
13189
+ requestId: z.ZodString;
13190
+ retryable: z.ZodBoolean;
13191
+ details: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
13192
+ }, z.core.$loose>;
13193
+ }, z.core.$strip>>;
13194
+ readonly resources: {
13195
+ readonly reads: readonly [{
13196
+ readonly type: "partner.user";
13197
+ readonly idFrom: "params.userId";
13198
+ }];
13199
+ readonly changes: readonly [{
13200
+ readonly type: "partner.user";
13201
+ readonly idFrom: "params.userId";
13202
+ }];
13203
+ };
13204
+ readonly lifecycle: {
13205
+ readonly introduced: "3.8.0";
13206
+ };
13207
+ readonly docs: {
13208
+ readonly summary: "Revoke a user API key";
13209
+ readonly description: "Revokes an API key the authenticated partner issued for a user. The key stops working immediately. Revoking an already revoked key succeeds again. An unknown key, or a key issued by another partner or by the user, fails with `404 api_key_not_found`.";
13210
+ readonly tags: readonly ["Users"];
13211
+ readonly examples: {
13212
+ readonly request: {
13213
+ readonly params: {
13214
+ readonly userId: "u_01";
13215
+ readonly keyId: "ak_01";
13216
+ };
13217
+ };
13218
+ readonly response: {
13219
+ readonly data: {
13220
+ readonly ok: true;
13221
+ readonly keyId: "ak_01";
13222
+ };
13223
+ readonly meta: {
13224
+ readonly requestId: "req_01";
13225
+ readonly surface: "partner";
13226
+ readonly version: "1.0";
13227
+ };
13228
+ };
13229
+ };
13230
+ };
13231
+ readonly id: "partner.users.api_keys.revoke";
13232
+ readonly method: "DELETE";
13233
+ readonly path: "/users/{userId}/api-keys/{keyId}";
13234
+ };
12827
13235
  }>;
12828
13236
  analytics: HttpV1Surface<{
12829
13237
  readonly queryRows: {
@@ -348,6 +348,33 @@ function createGscdumpV1Protocol() {
348
348
  updated: z.boolean(),
349
349
  sites: z.array(gscdumpAvailableSiteSchema)
350
350
  }), partnerResponseMeta);
351
+ const partnerUserApiKeyLabel = z.string().min(1).max(64);
352
+ const partnerUserApiKeyId = z.string().regex(/^ak_[\w-]+$/);
353
+ const partnerUserApiKeyParams = z.strictObject({
354
+ userId: realtimeSchemas.publicUserId,
355
+ keyId: partnerUserApiKeyId
356
+ });
357
+ const createUserApiKeyRequest = z.strictObject({ label: z.string().trim().min(1).max(64) });
358
+ const partnerUserApiKeyCreatedAt = z.number().int().nonnegative();
359
+ const createUserApiKeyResponse = defineSuccessResponse(defineResponseObject({
360
+ keyId: partnerUserApiKeyId,
361
+ apiKey: z.string().regex(/^gsd_user_[\w-]+$/),
362
+ preview: z.string().min(1),
363
+ label: partnerUserApiKeyLabel,
364
+ createdAt: partnerUserApiKeyCreatedAt
365
+ }), partnerResponseMeta);
366
+ const partnerUserApiKey = defineResponseObject({
367
+ keyId: partnerUserApiKeyId,
368
+ preview: z.string().min(1),
369
+ label: partnerUserApiKeyLabel,
370
+ createdAt: partnerUserApiKeyCreatedAt,
371
+ lastUsedAt: z.number().int().nonnegative().nullable()
372
+ });
373
+ const listUserApiKeysResponse = defineSuccessResponse(defineResponseObject({ keys: z.array(partnerUserApiKey.producer) }, { keys: z.array(partnerUserApiKey.client) }), partnerResponseMeta);
374
+ const revokeUserApiKeyResponse = defineSuccessResponse(defineResponseObject({
375
+ ok: z.literal(true),
376
+ keyId: partnerUserApiKeyId
377
+ }), partnerResponseMeta);
351
378
  const trendQuery = z.strictObject({
352
379
  startDate: calendarDate,
353
380
  endDate: calendarDate,
@@ -681,6 +708,8 @@ function createGscdumpV1Protocol() {
681
708
  "internal_error",
682
709
  "contract_violation"
683
710
  ];
711
+ const partnerUserApiKeyCreateErrors = [...partnerUserErrors, "api_key_limit_reached"];
712
+ const partnerUserApiKeyRevokeErrors = [...partnerUserErrors, "api_key_not_found"];
684
713
  const analyticsRowsErrors = [
685
714
  "invalid_request",
686
715
  "unauthorized",
@@ -4109,6 +4138,189 @@ function createGscdumpV1Protocol() {
4109
4138
  }
4110
4139
  }
4111
4140
  }
4141
+ }),
4142
+ createUserApiKey: defineHttpOperation({
4143
+ ...gscdumpV1OperationRoute("partner.users.api_keys.create"),
4144
+ visibility: "public",
4145
+ semantics: {
4146
+ kind: "mutation",
4147
+ sideEffects: "state",
4148
+ idempotent: false,
4149
+ retry: "never",
4150
+ readConsistency: null
4151
+ },
4152
+ auth: {
4153
+ credentials: ["partner_key"],
4154
+ scopes: ["users:write"],
4155
+ ownership: [{
4156
+ credential: "partner_key",
4157
+ rule: "linked_user"
4158
+ }]
4159
+ },
4160
+ request: {
4161
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
4162
+ query: null,
4163
+ headers: requestHeaders,
4164
+ body: createUserApiKeyRequest
4165
+ },
4166
+ responses: { 201: createUserApiKeyResponse },
4167
+ errors: partnerUserApiKeyCreateErrors,
4168
+ errorResponse: errorEnvelopeSchemas(partnerUserApiKeyCreateErrors, realtimeSchemas.publicRequestId),
4169
+ resources: {
4170
+ reads: [{
4171
+ type: "partner.user",
4172
+ idFrom: "params.userId"
4173
+ }],
4174
+ changes: [{
4175
+ type: "partner.user",
4176
+ idFrom: "params.userId"
4177
+ }]
4178
+ },
4179
+ lifecycle: { introduced: "3.8.0" },
4180
+ docs: {
4181
+ summary: "Create a user API key",
4182
+ description: "Issues a new revocable API key for a partner-linked user. The raw key appears only in this response; store or show it once. Each partner may hold at most 10 API keys per user; a create beyond the limit fails with `409 api_key_limit_reached`.",
4183
+ tags: ["Users"],
4184
+ examples: {
4185
+ request: {
4186
+ params: { userId: "u_01" },
4187
+ body: { label: "Laptop CLI" }
4188
+ },
4189
+ response: {
4190
+ data: {
4191
+ keyId: "ak_01",
4192
+ apiKey: "gsd_user_0123456789abcdef",
4193
+ preview: "gsd_user_012345...cdef",
4194
+ label: "Laptop CLI",
4195
+ createdAt: 1789516800
4196
+ },
4197
+ meta: {
4198
+ requestId: "req_01",
4199
+ surface: "partner",
4200
+ version: "1.0"
4201
+ }
4202
+ }
4203
+ }
4204
+ }
4205
+ }),
4206
+ listUserApiKeys: defineHttpOperation({
4207
+ ...gscdumpV1OperationRoute("partner.users.api_keys.list"),
4208
+ visibility: "public",
4209
+ semantics: {
4210
+ kind: "query",
4211
+ sideEffects: "none",
4212
+ idempotent: true,
4213
+ retry: "idempotent",
4214
+ readConsistency: "primary"
4215
+ },
4216
+ auth: {
4217
+ credentials: ["partner_key"],
4218
+ scopes: ["users:read"],
4219
+ ownership: [{
4220
+ credential: "partner_key",
4221
+ rule: "linked_user"
4222
+ }]
4223
+ },
4224
+ request: {
4225
+ params: z.strictObject({ userId: realtimeSchemas.publicUserId }),
4226
+ query: null,
4227
+ headers: requestHeaders,
4228
+ body: null
4229
+ },
4230
+ responses: { 200: listUserApiKeysResponse },
4231
+ errors: partnerUserErrors,
4232
+ errorResponse: errorEnvelopeSchemas(partnerUserErrors, realtimeSchemas.publicRequestId),
4233
+ resources: {
4234
+ reads: [{
4235
+ type: "partner.user",
4236
+ idFrom: "params.userId"
4237
+ }],
4238
+ changes: []
4239
+ },
4240
+ lifecycle: { introduced: "3.8.0" },
4241
+ docs: {
4242
+ summary: "List user API keys",
4243
+ description: "Lists the active API keys the authenticated partner issued for a user. Keys issued by other partners or by the user are excluded. Raw keys are never returned.",
4244
+ tags: ["Users"],
4245
+ examples: {
4246
+ request: { params: { userId: "u_01" } },
4247
+ response: {
4248
+ data: { keys: [{
4249
+ keyId: "ak_01",
4250
+ preview: "gsd_user_012345...cdef",
4251
+ label: "Laptop CLI",
4252
+ createdAt: 1789516800,
4253
+ lastUsedAt: null
4254
+ }] },
4255
+ meta: {
4256
+ requestId: "req_01",
4257
+ surface: "partner",
4258
+ version: "1.0"
4259
+ }
4260
+ }
4261
+ }
4262
+ }
4263
+ }),
4264
+ revokeUserApiKey: defineHttpOperation({
4265
+ ...gscdumpV1OperationRoute("partner.users.api_keys.revoke"),
4266
+ visibility: "public",
4267
+ semantics: {
4268
+ kind: "mutation",
4269
+ sideEffects: "state",
4270
+ idempotent: true,
4271
+ retry: "idempotent",
4272
+ readConsistency: null
4273
+ },
4274
+ auth: {
4275
+ credentials: ["partner_key"],
4276
+ scopes: ["users:write"],
4277
+ ownership: [{
4278
+ credential: "partner_key",
4279
+ rule: "linked_user"
4280
+ }]
4281
+ },
4282
+ request: {
4283
+ params: partnerUserApiKeyParams,
4284
+ query: null,
4285
+ headers: requestHeaders,
4286
+ body: null
4287
+ },
4288
+ responses: { 200: revokeUserApiKeyResponse },
4289
+ errors: partnerUserApiKeyRevokeErrors,
4290
+ errorResponse: errorEnvelopeSchemas(partnerUserApiKeyRevokeErrors, realtimeSchemas.publicRequestId),
4291
+ resources: {
4292
+ reads: [{
4293
+ type: "partner.user",
4294
+ idFrom: "params.userId"
4295
+ }],
4296
+ changes: [{
4297
+ type: "partner.user",
4298
+ idFrom: "params.userId"
4299
+ }]
4300
+ },
4301
+ lifecycle: { introduced: "3.8.0" },
4302
+ docs: {
4303
+ summary: "Revoke a user API key",
4304
+ description: "Revokes an API key the authenticated partner issued for a user. The key stops working immediately. Revoking an already revoked key succeeds again. An unknown key, or a key issued by another partner or by the user, fails with `404 api_key_not_found`.",
4305
+ tags: ["Users"],
4306
+ examples: {
4307
+ request: { params: {
4308
+ userId: "u_01",
4309
+ keyId: "ak_01"
4310
+ } },
4311
+ response: {
4312
+ data: {
4313
+ ok: true,
4314
+ keyId: "ak_01"
4315
+ },
4316
+ meta: {
4317
+ requestId: "req_01",
4318
+ surface: "partner",
4319
+ version: "1.0"
4320
+ }
4321
+ }
4322
+ }
4323
+ }
4112
4324
  })
4113
4325
  }
4114
4326
  });
@@ -266,6 +266,21 @@ export declare const GSCDUMP_V1_ROUTE_CATALOG: {
266
266
  readonly method: "POST";
267
267
  readonly template: "/users/{userId}/sites/verify";
268
268
  };
269
+ readonly 'partner.users.api_keys.create': {
270
+ readonly surface: "partner";
271
+ readonly method: "POST";
272
+ readonly template: "/users/{userId}/api-keys";
273
+ };
274
+ readonly 'partner.users.api_keys.list': {
275
+ readonly surface: "partner";
276
+ readonly method: "GET";
277
+ readonly template: "/users/{userId}/api-keys";
278
+ };
279
+ readonly 'partner.users.api_keys.revoke': {
280
+ readonly surface: "partner";
281
+ readonly method: "DELETE";
282
+ readonly template: "/users/{userId}/api-keys/{keyId}";
283
+ };
269
284
  readonly 'analytics.rows.query': {
270
285
  readonly surface: "analytics";
271
286
  readonly method: "POST";
@@ -253,6 +253,21 @@ const GSCDUMP_V1_ROUTE_CATALOG = {
253
253
  method: "POST",
254
254
  template: "/users/{userId}/sites/verify"
255
255
  },
256
+ "partner.users.api_keys.create": {
257
+ surface: "partner",
258
+ method: "POST",
259
+ template: "/users/{userId}/api-keys"
260
+ },
261
+ "partner.users.api_keys.list": {
262
+ surface: "partner",
263
+ method: "GET",
264
+ template: "/users/{userId}/api-keys"
265
+ },
266
+ "partner.users.api_keys.revoke": {
267
+ surface: "partner",
268
+ method: "DELETE",
269
+ template: "/users/{userId}/api-keys/{keyId}"
270
+ },
256
271
  "analytics.rows.query": {
257
272
  surface: "analytics",
258
273
  method: "POST",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/contracts",
3
3
  "type": "module",
4
- "version": "3.6.3",
4
+ "version": "3.8.0",
5
5
  "description": "Shared gscdump.com API, webhook, realtime, and lifecycle contracts.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",