@greatwait/contracts 0.1.0-alpha.7 → 0.1.0-alpha.8

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.
Files changed (36) hide show
  1. package/dist/billing.d.ts +2 -1
  2. package/dist/billing.js +8 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/operations.d.ts +42 -5
  6. package/dist/operations.js +3 -1
  7. package/dist/policy.d.ts +5 -4
  8. package/dist/policy.js +5 -4
  9. package/dist/project-notifications.d.ts +238 -0
  10. package/dist/project-notifications.js +236 -0
  11. package/dist/scheduling.js +5 -4
  12. package/dist/workspace.d.ts +4 -4
  13. package/generated/v1/examples/projectnotifications.read.response.json +12 -0
  14. package/generated/v1/examples/projectnotifications.rotateSigningKey.request.json +3 -0
  15. package/generated/v1/examples/projectnotifications.rotateSigningKey.response.json +25 -0
  16. package/generated/v1/examples/projectnotifications.update.request.json +10 -0
  17. package/generated/v1/examples/projectnotifications.update.response.json +12 -0
  18. package/generated/v1/examples/statusdeliveries.list.response.json +3 -0
  19. package/generated/v1/manifest.json +110 -0
  20. package/generated/v1/openapi.json +2525 -3
  21. package/generated/v1/policy-matrix.json +28 -0
  22. package/generated/v1/schemas/billing.notices.response.json +3 -2
  23. package/generated/v1/schemas/billing.purchase.request.json +4 -0
  24. package/generated/v1/schemas/projectnotifications.read.response.json +101 -0
  25. package/generated/v1/schemas/projectnotifications.rotateSigningKey.request.json +13 -0
  26. package/generated/v1/schemas/projectnotifications.rotateSigningKey.response.json +119 -0
  27. package/generated/v1/schemas/projectnotifications.update.request-headers.json +13 -0
  28. package/generated/v1/schemas/projectnotifications.update.request.json +90 -0
  29. package/generated/v1/schemas/projectnotifications.update.response.json +101 -0
  30. package/generated/v1/schemas/statusdeliveries.list.query.json +16 -0
  31. package/generated/v1/schemas/statusdeliveries.list.response.json +82 -0
  32. package/generated/v1/snippets/projectnotifications.read.json +6 -0
  33. package/generated/v1/snippets/projectnotifications.rotateSigningKey.json +6 -0
  34. package/generated/v1/snippets/projectnotifications.update.json +6 -0
  35. package/generated/v1/snippets/statusdeliveries.list.json +6 -0
  36. package/package.json +1 -1
@@ -0,0 +1,236 @@
1
+ import { z } from "./zod.js";
2
+ import { environmentKindSchema } from "./authority.js";
3
+ import { callbackSigningKeyIdSchema, occurrenceIdSchema, projectIdSchema, scheduleIdSchema, } from "./identifiers.js";
4
+ import { memberIdSchema } from "./members.js";
5
+ import { timestampSchema } from "./time.js";
6
+ import { pageRequestSchema, requiredIdempotencyRequestHeaderSchema, } from "./protocol.js";
7
+ import { API_UNUSED_RESPONSE_SCHEMA, defineOperations, } from "./operation-definitions.js";
8
+ /** Per-project/environment preferences. Billing-safety notices are separate. */
9
+ export const notificationEmailRecipientsSchema = z.discriminatedUnion("kind", [
10
+ z.strictObject({ kind: z.literal("admins") }),
11
+ z.strictObject({
12
+ kind: z.literal("members"),
13
+ memberIds: z
14
+ .array(memberIdSchema)
15
+ .min(1)
16
+ .max(100)
17
+ .refine((ids) => new Set(ids).size === ids.length, "members must be unique"),
18
+ }),
19
+ ]);
20
+ export const notificationEmailSettingsSchema = z.strictObject({
21
+ enabled: z.boolean(),
22
+ recipients: notificationEmailRecipientsSchema,
23
+ scheduleKinds: z.enum(["both", "one-shot", "recurring"]),
24
+ });
25
+ export const statusWebhookEventSchema = z.enum(["failed"]);
26
+ export const statusWebhookConfigurationSchema = z.strictObject({
27
+ url: z.string().url().max(2_048),
28
+ events: z
29
+ .array(statusWebhookEventSchema)
30
+ .min(1)
31
+ .max(1)
32
+ .refine((events) => new Set(events).size === events.length, "events must be unique"),
33
+ });
34
+ export const projectNotificationSettingsSchema = z.strictObject({
35
+ project: projectIdSchema,
36
+ environmentKind: environmentKindSchema,
37
+ revision: z.number().int().positive(),
38
+ email: notificationEmailSettingsSchema,
39
+ statusWebhook: statusWebhookConfigurationSchema
40
+ .extend({
41
+ signingKey: z.strictObject({ id: callbackSigningKeyIdSchema }).optional(),
42
+ revision: z.number().int().positive(),
43
+ })
44
+ .optional(),
45
+ });
46
+ export const projectNotificationSettingsUpdateRequestSchema = z
47
+ .strictObject({
48
+ expectedRevision: z.number().int().positive(),
49
+ email: notificationEmailSettingsSchema.optional(),
50
+ statusWebhook: statusWebhookConfigurationSchema.nullable().optional(),
51
+ })
52
+ .refine((request) => request.email !== undefined || request.statusWebhook !== undefined, "choose settings to change");
53
+ export const statusSigningKeyRequestSchema = z.strictObject({
54
+ expectedRevision: z.number().int().positive(),
55
+ });
56
+ export const statusSigningKeyCreatedSchema = z.strictObject({
57
+ settings: projectNotificationSettingsSchema,
58
+ keyId: callbackSigningKeyIdSchema,
59
+ secret: z.string().min(1),
60
+ shownOnce: z.literal(true),
61
+ });
62
+ /** Safe notification payload: no customer request or response content. */
63
+ export const statusWebhookPayloadSchema = z.object({
64
+ version: z.literal("2026-10-08"),
65
+ eventId: z.string().min(1).max(255),
66
+ type: statusWebhookEventSchema,
67
+ projectId: projectIdSchema,
68
+ environmentKind: environmentKindSchema,
69
+ scheduleId: scheduleIdSchema,
70
+ occurrenceId: occurrenceIdSchema,
71
+ occurredAt: timestampSchema,
72
+ outcomeOrigin: z.enum(["platform", "customer"]),
73
+ diagnostic: z.string().max(512).optional(),
74
+ statusCode: z.number().int().min(100).max(599).optional(),
75
+ pause: z.unknown().optional(),
76
+ });
77
+ export const statusWebhookDeliverySchema = z.strictObject({
78
+ id: z.string().min(1).max(255),
79
+ event: statusWebhookEventSchema,
80
+ schedule: scheduleIdSchema,
81
+ occurrence: occurrenceIdSchema,
82
+ occurredAt: timestampSchema,
83
+ url: z.string().url(),
84
+ state: z.enum(["pending", "delivering", "delivered", "failed", "suppressed"]),
85
+ attempts: z.number().int().nonnegative(),
86
+ nextAttemptAt: timestampSchema.optional(),
87
+ lastStatus: z.number().int().min(100).max(599).optional(),
88
+ lastError: z.string().max(128).optional(),
89
+ });
90
+ export const statusWebhookDeliveryPageSchema = z.strictObject({
91
+ data: z.array(statusWebhookDeliverySchema),
92
+ nextCursor: z.string().min(1).optional(),
93
+ });
94
+ const globals = globalThis;
95
+ const settings = {
96
+ project: "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
97
+ environmentKind: "live",
98
+ revision: 1,
99
+ email: {
100
+ enabled: true,
101
+ recipients: { kind: "admins" },
102
+ scheduleKinds: "both",
103
+ },
104
+ };
105
+ const common = {
106
+ creates: false,
107
+ principals: ["api-credential", "oauth", "session"],
108
+ sessionAuthority: "headers",
109
+ surfaces: ["api", "mock"],
110
+ problems: ["invalid_request", "not_found", "service_unavailable"],
111
+ };
112
+ export const PROJECT_NOTIFICATION_OPERATIONS = defineOperations([
113
+ {
114
+ ...common,
115
+ id: "projectnotifications.read",
116
+ method: "GET",
117
+ path: "/v1/projects/{projectId}/notification-settings",
118
+ idempotent: true,
119
+ mutates: false,
120
+ mcp: { kind: "tool", destructive: false, openWorld: false },
121
+ scopes: ["projects:read"],
122
+ response: globals.GREATWAIT_API_REQUEST_REGISTRY
123
+ ? API_UNUSED_RESPONSE_SCHEMA
124
+ : projectNotificationSettingsSchema,
125
+ example: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES ? {} : settings,
126
+ summary: globals.GREATWAIT_API_REQUEST_REGISTRY
127
+ ? ""
128
+ : "Read delivery notification settings",
129
+ description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
130
+ ? ""
131
+ : "Read the verified project and environment's email failure alerts and failure webhook preferences. Defaults are email on to current organization admins and both one-shot and recurring schedules. Every terminal failed occurrence creates a separate email for each eligible recipient. Signing secrets are absent. Manual redelivery does not repeat occurrence lifecycle events.",
132
+ },
133
+ {
134
+ ...common,
135
+ id: "projectnotifications.update",
136
+ method: "PATCH",
137
+ path: "/v1/projects/{projectId}/notification-settings",
138
+ idempotent: true,
139
+ mutates: true,
140
+ mcp: { kind: "tool", destructive: false, openWorld: true },
141
+ scopes: ["projects:administer"],
142
+ problems: [
143
+ ...common.problems,
144
+ "revision_conflict",
145
+ "idempotency_key_reused",
146
+ "rate_limited",
147
+ ],
148
+ requestHeaders: requiredIdempotencyRequestHeaderSchema,
149
+ request: projectNotificationSettingsUpdateRequestSchema,
150
+ requestExample: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
151
+ ? {}
152
+ : { expectedRevision: 1, email: settings.email },
153
+ response: globals.GREATWAIT_API_REQUEST_REGISTRY
154
+ ? API_UNUSED_RESPONSE_SCHEMA
155
+ : projectNotificationSettingsSchema,
156
+ example: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
157
+ ? {}
158
+ : { ...settings, revision: 2 },
159
+ summary: globals.GREATWAIT_API_REQUEST_REGISTRY
160
+ ? ""
161
+ : "Update delivery notification settings",
162
+ description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
163
+ ? ""
164
+ : "An admin updates this project's environment preferences at an expected revision. Selected recipients must be current organization members; arbitrary email addresses are not accepted. Null disables the status webhook. Changing URL or filters never reveals a signing secret. Mint the first key through the secure signing-key operation before webhook delivery starts. Failed means final unsuccessful settlement. Redelivery never repeats it. Failed-event webhook calls and their retries are free. Every failed occurrence is emailed separately; no summary window suppresses failures.",
165
+ },
166
+ {
167
+ ...common,
168
+ id: "projectnotifications.rotateSigningKey",
169
+ method: "POST",
170
+ path: "/v1/projects/{projectId}/notification-settings/status-signing-key",
171
+ idempotent: false,
172
+ mutates: true,
173
+ mcp: {
174
+ kind: "unavailable",
175
+ reason: "Minting or rotating returns a one-time signing secret. MCP has no negotiated secure-result channel that keeps it out of ordinary tool history. Configure preferences with projectnotifications_update, then use the dashboard or an authenticated REST/SDK/CLI client for the secret.",
176
+ },
177
+ scopes: ["projects:administer"],
178
+ problems: [
179
+ ...common.problems,
180
+ "revision_conflict",
181
+ "state_conflict",
182
+ "capability_not_configured",
183
+ ],
184
+ request: statusSigningKeyRequestSchema,
185
+ requestExample: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
186
+ ? {}
187
+ : { expectedRevision: 1 },
188
+ response: globals.GREATWAIT_API_REQUEST_REGISTRY
189
+ ? API_UNUSED_RESPONSE_SCHEMA
190
+ : statusSigningKeyCreatedSchema,
191
+ example: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES
192
+ ? {}
193
+ : {
194
+ settings: {
195
+ ...settings,
196
+ revision: 2,
197
+ statusWebhook: {
198
+ url: "https://hooks.example.com/status",
199
+ events: ["failed"],
200
+ revision: 2,
201
+ signingKey: { id: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8" },
202
+ },
203
+ },
204
+ keyId: "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
205
+ secret: "ptsk_live_<the-one-time-status-secret>",
206
+ shownOnce: true,
207
+ },
208
+ summary: globals.GREATWAIT_API_REQUEST_REGISTRY
209
+ ? ""
210
+ : "Mint or rotate the status webhook signing key",
211
+ description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
212
+ ? ""
213
+ : "An admin mints the first key or replaces the current key for an already configured status webhook at an expected revision. The secret appears only in this successful response and cannot be read back. A lost response requires a fresh revision read and another rotation. Queued deliveries using the replaced signing key are suppressed. The request is not automatically replayable; stale retries are refused. The signature covers the exact emitted body bytes.",
214
+ },
215
+ {
216
+ ...common,
217
+ id: "statusdeliveries.list",
218
+ method: "GET",
219
+ path: "/v1/projects/{projectId}/status-deliveries",
220
+ idempotent: true,
221
+ mutates: false,
222
+ mcp: { kind: "tool", destructive: false, openWorld: false },
223
+ scopes: ["occurrences:read"],
224
+ query: pageRequestSchema,
225
+ response: globals.GREATWAIT_API_REQUEST_REGISTRY
226
+ ? API_UNUSED_RESPONSE_SCHEMA
227
+ : statusWebhookDeliveryPageSchema,
228
+ example: globals.GREATWAIT_RUNTIME_WITHOUT_EXAMPLES ? {} : { data: [] },
229
+ summary: globals.GREATWAIT_API_REQUEST_REGISTRY
230
+ ? ""
231
+ : "List failure webhook deliveries",
232
+ description: globals.GREATWAIT_RUNTIME_CONTRACTS_ONLY
233
+ ? ""
234
+ : "Read the verified project and environment's failure delivery trail, including retry state and actual outbound calls. Failed events and every retry are free. Status delivery failures never create another notification or change the customer's schedule outcome. Customer callback contents and signing secrets are absent.",
235
+ },
236
+ ]);
@@ -1407,10 +1407,11 @@ export const scheduleRequestSchema = z
1407
1407
  *
1408
1408
  * Two schedules with different keys are paced independently, so one key's
1409
1409
  * herd does not delay another's work. It is a label and a lane and nothing
1410
- * more: it cannot widen the authority tuple, cannot select a different
1411
- * database shard or timer actor, and cannot raise anybody's rate — the
1412
- * lanes share the project's ceiling, so minting more keys divides the same
1413
- * budget rather than multiplying it.
1410
+ * more: it cannot widen the authority tuple or select a different database
1411
+ * shard or timer actor. Each key is paced on its own, but every lane that
1412
+ * delivers to the same receiver host shares that host's pacing, so more keys
1413
+ * never raise the rate any one receiver sees; the plan's
1414
+ * `partitionKeyCeiling` bounds how many distinct keys an organization holds.
1414
1415
  *
1415
1416
  * **Fixed once the schedule exists.** A replace may carry the key it read
1416
1417
  * back or omit it to preserve the stored value. Adding, changing, or
@@ -9,8 +9,8 @@ import { z } from "./zod.js";
9
9
  */
10
10
  export declare const WORKSPACE_LAYERS: readonly ["contract", "platform", "domain", "application", "adapter", "test-support"];
11
11
  export declare const workspaceLayerSchema: import("zod").ZodEnum<{
12
- contract: "contract";
13
12
  platform: "platform";
13
+ contract: "contract";
14
14
  domain: "domain";
15
15
  application: "application";
16
16
  adapter: "adapter";
@@ -19,8 +19,8 @@ export declare const workspaceLayerSchema: import("zod").ZodEnum<{
19
19
  export type WorkspaceLayer = z.infer<typeof workspaceLayerSchema>;
20
20
  export declare const workspaceIdentitySchema: import("zod").ZodObject<{
21
21
  layer: import("zod").ZodEnum<{
22
- contract: "contract";
23
22
  platform: "platform";
23
+ contract: "contract";
24
24
  domain: "domain";
25
25
  application: "application";
26
26
  adapter: "adapter";
@@ -39,16 +39,16 @@ export type ScaffoldVersion = z.infer<typeof scaffoldVersionSchema>;
39
39
  /** Shape of the scaffold description an adapter reads from the application. */
40
40
  export declare const workspaceScaffoldSchema: import("zod").ZodObject<{
41
41
  dependsOn: import("zod").ZodArray<import("zod").ZodEnum<{
42
- contract: "contract";
43
42
  platform: "platform";
43
+ contract: "contract";
44
44
  domain: "domain";
45
45
  application: "application";
46
46
  adapter: "adapter";
47
47
  "test-support": "test-support";
48
48
  }>>;
49
49
  layer: import("zod").ZodEnum<{
50
- contract: "contract";
51
50
  platform: "platform";
51
+ contract: "contract";
52
52
  domain: "domain";
53
53
  application: "application";
54
54
  adapter: "adapter";
@@ -0,0 +1,12 @@
1
+ {
2
+ "project": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
3
+ "environmentKind": "live",
4
+ "revision": 1,
5
+ "email": {
6
+ "enabled": true,
7
+ "recipients": {
8
+ "kind": "admins"
9
+ },
10
+ "scheduleKinds": "both"
11
+ }
12
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "expectedRevision": 1
3
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "settings": {
3
+ "project": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
4
+ "environmentKind": "live",
5
+ "revision": 2,
6
+ "email": {
7
+ "enabled": true,
8
+ "recipients": {
9
+ "kind": "admins"
10
+ },
11
+ "scheduleKinds": "both"
12
+ },
13
+ "statusWebhook": {
14
+ "url": "https://hooks.example.com/status",
15
+ "events": ["failed"],
16
+ "signingKey": {
17
+ "id": "csk_01h8xyz9k2m4n6p8r0t2v4w6y8"
18
+ },
19
+ "revision": 2
20
+ }
21
+ },
22
+ "keyId": "csk_01h8xyz9k2m4n6p8r0t2v4w6y8",
23
+ "secret": "ptsk_live_<the-one-time-status-secret>",
24
+ "shownOnce": true
25
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "expectedRevision": 1,
3
+ "email": {
4
+ "enabled": true,
5
+ "recipients": {
6
+ "kind": "admins"
7
+ },
8
+ "scheduleKinds": "both"
9
+ }
10
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "project": "proj_01h8xyz9k2m4n6p8r0t2v4w6y8",
3
+ "environmentKind": "live",
4
+ "revision": 2,
5
+ "email": {
6
+ "enabled": true,
7
+ "recipients": {
8
+ "kind": "admins"
9
+ },
10
+ "scheduleKinds": "both"
11
+ }
12
+ }
@@ -124,6 +124,11 @@
124
124
  "examples/projectmembers.add.response.json",
125
125
  "examples/projectmembers.remove.request.json",
126
126
  "examples/projectmembers.remove.response.json",
127
+ "examples/projectnotifications.read.response.json",
128
+ "examples/projectnotifications.rotateSigningKey.request.json",
129
+ "examples/projectnotifications.rotateSigningKey.response.json",
130
+ "examples/projectnotifications.update.request.json",
131
+ "examples/projectnotifications.update.response.json",
127
132
  "examples/projects.archive.request.json",
128
133
  "examples/projects.archive.response.json",
129
134
  "examples/projects.create.request.json",
@@ -144,6 +149,7 @@
144
149
  "examples/schedules.resume.response.json",
145
150
  "examples/sinkdeliveries.list.response.json",
146
151
  "examples/sinkdeliveries.read.response.json",
152
+ "examples/statusdeliveries.list.response.json",
147
153
  "examples/testsinks.configure.request.json",
148
154
  "examples/testsinks.configure.response.json",
149
155
  "examples/testsinks.create.request.json",
@@ -310,6 +316,12 @@
310
316
  "schemas/projectmembers.remove.request-headers.json",
311
317
  "schemas/projectmembers.remove.request.json",
312
318
  "schemas/projectmembers.remove.response.json",
319
+ "schemas/projectnotifications.read.response.json",
320
+ "schemas/projectnotifications.rotateSigningKey.request.json",
321
+ "schemas/projectnotifications.rotateSigningKey.response.json",
322
+ "schemas/projectnotifications.update.request-headers.json",
323
+ "schemas/projectnotifications.update.request.json",
324
+ "schemas/projectnotifications.update.response.json",
313
325
  "schemas/projects.archive.request-headers.json",
314
326
  "schemas/projects.archive.request.json",
315
327
  "schemas/projects.archive.response-headers.json",
@@ -350,6 +362,8 @@
350
362
  "schemas/sinkdeliveries.list.query.json",
351
363
  "schemas/sinkdeliveries.list.response.json",
352
364
  "schemas/sinkdeliveries.read.response.json",
365
+ "schemas/statusdeliveries.list.query.json",
366
+ "schemas/statusdeliveries.list.response.json",
353
367
  "schemas/testsinks.configure.request.json",
354
368
  "schemas/testsinks.configure.response.json",
355
369
  "schemas/testsinks.create.request.json",
@@ -445,6 +459,9 @@
445
459
  "snippets/organizations.restore.json",
446
460
  "snippets/projectmembers.add.json",
447
461
  "snippets/projectmembers.remove.json",
462
+ "snippets/projectnotifications.read.json",
463
+ "snippets/projectnotifications.rotateSigningKey.json",
464
+ "snippets/projectnotifications.update.json",
448
465
  "snippets/projects.archive.json",
449
466
  "snippets/projects.create.json",
450
467
  "snippets/projects.delete.json",
@@ -460,6 +477,7 @@
460
477
  "snippets/schedules.resume.json",
461
478
  "snippets/sinkdeliveries.list.json",
462
479
  "snippets/sinkdeliveries.read.json",
480
+ "snippets/statusdeliveries.list.json",
463
481
  "snippets/testsinks.configure.json",
464
482
  "snippets/testsinks.create.json",
465
483
  "snippets/testsinks.delete.json",
@@ -808,6 +826,98 @@
808
826
  "sessionAuthority": "headers",
809
827
  "surfaces": ["api", "mock"]
810
828
  },
829
+ {
830
+ "id": "projectnotifications.read",
831
+ "method": "GET",
832
+ "mutates": false,
833
+ "path": "/v1/projects/{projectId}/notification-settings",
834
+ "principals": ["api-credential", "oauth", "session"],
835
+ "problems": [
836
+ "authentication_required",
837
+ "capability_not_configured",
838
+ "credential_expired",
839
+ "credential_revoked",
840
+ "invalid_request",
841
+ "not_found",
842
+ "project_archived",
843
+ "rate_limited",
844
+ "scope_missing",
845
+ "service_unavailable"
846
+ ],
847
+ "scopes": ["projects:read"],
848
+ "sessionAuthority": "headers",
849
+ "surfaces": ["api", "mock"]
850
+ },
851
+ {
852
+ "id": "projectnotifications.update",
853
+ "method": "PATCH",
854
+ "mutates": true,
855
+ "path": "/v1/projects/{projectId}/notification-settings",
856
+ "principals": ["api-credential", "oauth", "session"],
857
+ "problems": [
858
+ "authentication_required",
859
+ "capability_not_configured",
860
+ "credential_expired",
861
+ "credential_revoked",
862
+ "idempotency_key_reused",
863
+ "invalid_request",
864
+ "not_found",
865
+ "project_archived",
866
+ "rate_limited",
867
+ "revision_conflict",
868
+ "scope_missing",
869
+ "service_unavailable"
870
+ ],
871
+ "scopes": ["projects:administer"],
872
+ "sessionAuthority": "headers",
873
+ "surfaces": ["api", "mock"]
874
+ },
875
+ {
876
+ "id": "projectnotifications.rotateSigningKey",
877
+ "method": "POST",
878
+ "mutates": true,
879
+ "path": "/v1/projects/{projectId}/notification-settings/status-signing-key",
880
+ "principals": ["api-credential", "oauth", "session"],
881
+ "problems": [
882
+ "authentication_required",
883
+ "capability_not_configured",
884
+ "credential_expired",
885
+ "credential_revoked",
886
+ "invalid_request",
887
+ "not_found",
888
+ "project_archived",
889
+ "rate_limited",
890
+ "revision_conflict",
891
+ "scope_missing",
892
+ "service_unavailable",
893
+ "state_conflict"
894
+ ],
895
+ "scopes": ["projects:administer"],
896
+ "sessionAuthority": "headers",
897
+ "surfaces": ["api", "mock"]
898
+ },
899
+ {
900
+ "id": "statusdeliveries.list",
901
+ "method": "GET",
902
+ "mutates": false,
903
+ "path": "/v1/projects/{projectId}/status-deliveries",
904
+ "principals": ["api-credential", "oauth", "session"],
905
+ "problems": [
906
+ "authentication_required",
907
+ "capability_not_configured",
908
+ "credential_expired",
909
+ "credential_revoked",
910
+ "invalid_request",
911
+ "not_found",
912
+ "project_archived",
913
+ "rate_limited",
914
+ "scope_missing",
915
+ "service_unavailable"
916
+ ],
917
+ "scopes": ["occurrences:read"],
918
+ "sessionAuthority": "headers",
919
+ "surfaces": ["api", "mock"]
920
+ },
811
921
  {
812
922
  "id": "organizations.lifecycle",
813
923
  "method": "GET",