@greatwait/contracts 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/authority.d.ts +217 -0
- package/dist/authority.js +261 -0
- package/dist/callback-ownership.d.ts +58 -0
- package/dist/callback-ownership.js +71 -0
- package/dist/callback-safety.d.ts +38 -0
- package/dist/callback-safety.js +403 -0
- package/dist/compatibility.d.ts +82 -0
- package/dist/compatibility.js +115 -0
- package/dist/delivery.d.ts +401 -0
- package/dist/delivery.js +311 -0
- package/dist/endpoints.d.ts +305 -0
- package/dist/endpoints.js +179 -0
- package/dist/events.d.ts +62 -0
- package/dist/events.js +38 -0
- package/dist/first-value-journey.d.ts +305 -0
- package/dist/first-value-journey.js +466 -0
- package/dist/forecast.d.ts +443 -0
- package/dist/forecast.js +729 -0
- package/dist/identifiers.d.ts +109 -0
- package/dist/identifiers.js +131 -0
- package/dist/identity.d.ts +196 -0
- package/dist/identity.js +182 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mcp.d.ts +51 -0
- package/dist/mcp.js +56 -0
- package/dist/oauth.d.ts +796 -0
- package/dist/oauth.js +708 -0
- package/dist/operations.d.ts +3985 -0
- package/dist/operations.js +1837 -0
- package/dist/partition.d.ts +771 -0
- package/dist/partition.js +206 -0
- package/dist/policy.d.ts +93 -0
- package/dist/policy.js +180 -0
- package/dist/problems.d.ts +158 -0
- package/dist/problems.js +104 -0
- package/dist/protocol.d.ts +308 -0
- package/dist/protocol.js +515 -0
- package/dist/scheduling-records.d.ts +395 -0
- package/dist/scheduling-records.js +284 -0
- package/dist/scheduling.d.ts +1098 -0
- package/dist/scheduling.js +1116 -0
- package/dist/secrets.d.ts +383 -0
- package/dist/secrets.js +272 -0
- package/dist/signatures.d.ts +704 -0
- package/dist/signatures.js +867 -0
- package/dist/tenancy.d.ts +178 -0
- package/dist/tenancy.js +145 -0
- package/dist/test-sink.d.ts +986 -0
- package/dist/test-sink.js +755 -0
- package/dist/time.d.ts +45 -0
- package/dist/time.js +128 -0
- package/dist/usage.d.ts +121 -0
- package/dist/usage.js +200 -0
- package/dist/webhooks.d.ts +116 -0
- package/dist/webhooks.js +161 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.js +59 -0
- package/generated/v1/callback-delivery-signature.json +467 -0
- package/generated/v1/callback-endpoint-verification.json +59 -0
- package/generated/v1/callback-receiver.json +241 -0
- package/generated/v1/examples/attempts.list.response.json +24 -0
- package/generated/v1/examples/attempts.read.response.json +20 -0
- package/generated/v1/examples/credentials.create.request.json +5 -0
- package/generated/v1/examples/credentials.create.response.json +10 -0
- package/generated/v1/examples/credentials.list.response.json +17 -0
- package/generated/v1/examples/credentials.revoke.response.json +11 -0
- package/generated/v1/examples/credentials.rotate.request.json +3 -0
- package/generated/v1/examples/credentials.rotate.response.json +22 -0
- package/generated/v1/examples/endpoints.create.request.json +3 -0
- package/generated/v1/examples/endpoints.create.response.json +16 -0
- package/generated/v1/examples/endpoints.disable.response.json +15 -0
- package/generated/v1/examples/endpoints.list.response.json +21 -0
- package/generated/v1/examples/endpoints.read.response.json +14 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.request.json +3 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.response.json +23 -0
- package/generated/v1/examples/endpoints.update.request.json +3 -0
- package/generated/v1/examples/endpoints.update.response.json +13 -0
- package/generated/v1/examples/endpoints.verify.response.json +15 -0
- package/generated/v1/examples/forecast.read.response.json +28 -0
- package/generated/v1/examples/forecast.windows.response.json +21 -0
- package/generated/v1/examples/grants.list.response.json +17 -0
- package/generated/v1/examples/grants.revoke.response.json +16 -0
- package/generated/v1/examples/meta.scaffold.response.json +5 -0
- package/generated/v1/examples/meta.version.response.json +5 -0
- package/generated/v1/examples/occurrences.list.response.json +17 -0
- package/generated/v1/examples/occurrences.read.response.json +15 -0
- package/generated/v1/examples/occurrences.redeliver.response.json +16 -0
- package/generated/v1/examples/projects.create.request.json +3 -0
- package/generated/v1/examples/projects.create.response.json +5 -0
- package/generated/v1/examples/projects.list.response.json +9 -0
- package/generated/v1/examples/schedules.archive.response.json +25 -0
- package/generated/v1/examples/schedules.cancel.response.json +24 -0
- package/generated/v1/examples/schedules.create.request.json +9 -0
- package/generated/v1/examples/schedules.create.response.json +25 -0
- package/generated/v1/examples/schedules.list.response.json +23 -0
- package/generated/v1/examples/schedules.pause.response.json +23 -0
- package/generated/v1/examples/schedules.read.response.json +25 -0
- package/generated/v1/examples/schedules.replace.request.json +8 -0
- package/generated/v1/examples/schedules.replace.response.json +25 -0
- package/generated/v1/examples/schedules.resume.response.json +23 -0
- package/generated/v1/examples/sinkdeliveries.list.response.json +19 -0
- package/generated/v1/examples/sinkdeliveries.read.response.json +16 -0
- package/generated/v1/examples/testsinks.configure.request.json +3 -0
- package/generated/v1/examples/testsinks.configure.response.json +13 -0
- package/generated/v1/examples/testsinks.create.request.json +8 -0
- package/generated/v1/examples/testsinks.create.response.json +13 -0
- package/generated/v1/examples/testsinks.delete.response.json +13 -0
- package/generated/v1/examples/testsinks.list.response.json +20 -0
- package/generated/v1/examples/testsinks.read.response.json +14 -0
- package/generated/v1/examples/usage.read.response.json +20 -0
- package/generated/v1/first-value-journey.json +436 -0
- package/generated/v1/manifest.json +1037 -0
- package/generated/v1/openapi.json +23665 -0
- package/generated/v1/policy-matrix.json +305 -0
- package/generated/v1/schemas/attempts.list.query.json +16 -0
- package/generated/v1/schemas/attempts.list.response.json +175 -0
- package/generated/v1/schemas/attempts.read.response.json +168 -0
- package/generated/v1/schemas/credentials.create.request.json +39 -0
- package/generated/v1/schemas/credentials.create.response.json +88 -0
- package/generated/v1/schemas/credentials.list.query.json +16 -0
- package/generated/v1/schemas/credentials.list.response.json +124 -0
- package/generated/v1/schemas/credentials.revoke.response.json +84 -0
- package/generated/v1/schemas/credentials.rotate.request.json +11 -0
- package/generated/v1/schemas/credentials.rotate.response.json +171 -0
- package/generated/v1/schemas/endpoints.create.request.json +12 -0
- package/generated/v1/schemas/endpoints.create.response.json +115 -0
- package/generated/v1/schemas/endpoints.disable.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.disable.response.json +100 -0
- package/generated/v1/schemas/endpoints.list.query.json +16 -0
- package/generated/v1/schemas/endpoints.list.response.json +146 -0
- package/generated/v1/schemas/endpoints.read.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.read.response.json +100 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +118 -0
- package/generated/v1/schemas/endpoints.update.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.update.request.json +12 -0
- package/generated/v1/schemas/endpoints.update.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.update.response.json +100 -0
- package/generated/v1/schemas/endpoints.verify.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.verify.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.verify.response.json +100 -0
- package/generated/v1/schemas/forecast.read.query.json +26 -0
- package/generated/v1/schemas/forecast.read.response.json +100 -0
- package/generated/v1/schemas/forecast.windows.query.json +26 -0
- package/generated/v1/schemas/forecast.windows.response.json +94 -0
- package/generated/v1/schemas/grants.list.response.json +98 -0
- package/generated/v1/schemas/grants.revoke.response.json +95 -0
- package/generated/v1/schemas/meta.scaffold.response.json +36 -0
- package/generated/v1/schemas/meta.version.response.json +19 -0
- package/generated/v1/schemas/occurrences.list.query.json +16 -0
- package/generated/v1/schemas/occurrences.list.response.json +83 -0
- package/generated/v1/schemas/occurrences.read.response.json +76 -0
- package/generated/v1/schemas/occurrences.redeliver.request-headers.json +13 -0
- package/generated/v1/schemas/occurrences.redeliver.response-headers.json +10 -0
- package/generated/v1/schemas/occurrences.redeliver.response.json +168 -0
- package/generated/v1/schemas/projects.create.request.json +12 -0
- package/generated/v1/schemas/projects.create.response.json +25 -0
- package/generated/v1/schemas/projects.list.response.json +35 -0
- package/generated/v1/schemas/schedules.archive.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.archive.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.archive.response.json +189 -0
- package/generated/v1/schemas/schedules.cancel.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.cancel.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.cancel.response.json +189 -0
- package/generated/v1/schemas/schedules.create.request-headers.json +12 -0
- package/generated/v1/schemas/schedules.create.request.json +99 -0
- package/generated/v1/schemas/schedules.create.response-headers.json +15 -0
- package/generated/v1/schemas/schedules.create.response.json +189 -0
- package/generated/v1/schemas/schedules.list.query.json +16 -0
- package/generated/v1/schemas/schedules.list.response.json +170 -0
- package/generated/v1/schemas/schedules.pause.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.pause.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.pause.response.json +189 -0
- package/generated/v1/schemas/schedules.read.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.read.response.json +189 -0
- package/generated/v1/schemas/schedules.replace.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.replace.request.json +99 -0
- package/generated/v1/schemas/schedules.replace.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.replace.response.json +189 -0
- package/generated/v1/schemas/schedules.resume.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.resume.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.resume.response.json +189 -0
- package/generated/v1/schemas/sinkdeliveries.list.query.json +16 -0
- package/generated/v1/schemas/sinkdeliveries.list.response.json +126 -0
- package/generated/v1/schemas/sinkdeliveries.read.response.json +98 -0
- package/generated/v1/schemas/testsinks.configure.request.json +66 -0
- package/generated/v1/schemas/testsinks.configure.response.json +115 -0
- package/generated/v1/schemas/testsinks.create.request.json +76 -0
- package/generated/v1/schemas/testsinks.create.response.json +115 -0
- package/generated/v1/schemas/testsinks.delete.response.json +115 -0
- package/generated/v1/schemas/testsinks.list.query.json +16 -0
- package/generated/v1/schemas/testsinks.list.response.json +161 -0
- package/generated/v1/schemas/testsinks.read.response.json +115 -0
- package/generated/v1/schemas/usage.read.query.json +15 -0
- package/generated/v1/schemas/usage.read.response.json +71 -0
- package/generated/v1/snippets/attempts.list.json +5 -0
- package/generated/v1/snippets/attempts.read.json +5 -0
- package/generated/v1/snippets/credentials.create.json +5 -0
- package/generated/v1/snippets/credentials.list.json +5 -0
- package/generated/v1/snippets/credentials.revoke.json +5 -0
- package/generated/v1/snippets/credentials.rotate.json +5 -0
- package/generated/v1/snippets/endpoints.create.json +5 -0
- package/generated/v1/snippets/endpoints.disable.json +5 -0
- package/generated/v1/snippets/endpoints.list.json +5 -0
- package/generated/v1/snippets/endpoints.read.json +5 -0
- package/generated/v1/snippets/endpoints.rotateSigningKey.json +5 -0
- package/generated/v1/snippets/endpoints.update.json +5 -0
- package/generated/v1/snippets/endpoints.verify.json +5 -0
- package/generated/v1/snippets/forecast.read.json +5 -0
- package/generated/v1/snippets/forecast.windows.json +5 -0
- package/generated/v1/snippets/grants.list.json +5 -0
- package/generated/v1/snippets/grants.revoke.json +5 -0
- package/generated/v1/snippets/meta.scaffold.json +5 -0
- package/generated/v1/snippets/meta.version.json +5 -0
- package/generated/v1/snippets/occurrences.list.json +5 -0
- package/generated/v1/snippets/occurrences.read.json +5 -0
- package/generated/v1/snippets/occurrences.redeliver.json +5 -0
- package/generated/v1/snippets/projects.create.json +5 -0
- package/generated/v1/snippets/projects.list.json +5 -0
- package/generated/v1/snippets/schedules.archive.json +5 -0
- package/generated/v1/snippets/schedules.cancel.json +5 -0
- package/generated/v1/snippets/schedules.create.json +5 -0
- package/generated/v1/snippets/schedules.list.json +5 -0
- package/generated/v1/snippets/schedules.pause.json +5 -0
- package/generated/v1/snippets/schedules.read.json +5 -0
- package/generated/v1/snippets/schedules.replace.json +5 -0
- package/generated/v1/snippets/schedules.resume.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.list.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.read.json +5 -0
- package/generated/v1/snippets/testsinks.configure.json +5 -0
- package/generated/v1/snippets/testsinks.create.json +5 -0
- package/generated/v1/snippets/testsinks.delete.json +5 -0
- package/generated/v1/snippets/testsinks.list.json +5 -0
- package/generated/v1/snippets/testsinks.read.json +5 -0
- package/generated/v1/snippets/usage.read.json +5 -0
- package/package.json +153 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const portableScheduleRecordSchema: z.ZodObject<{
|
|
3
|
+
authority: z.ZodObject<{
|
|
4
|
+
environment: z.ZodString;
|
|
5
|
+
environmentKind: z.ZodEnum<{
|
|
6
|
+
test: "test";
|
|
7
|
+
live: "live";
|
|
8
|
+
}>;
|
|
9
|
+
organization: z.ZodString;
|
|
10
|
+
project: z.ZodString;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
retentionClass: z.ZodString;
|
|
13
|
+
archivedAt: z.ZodOptional<z.ZodString>;
|
|
14
|
+
createdAt: z.ZodString;
|
|
15
|
+
delivery: z.ZodOptional<z.ZodObject<{
|
|
16
|
+
completion: z.ZodEnum<{
|
|
17
|
+
response: "response";
|
|
18
|
+
callback: "callback";
|
|
19
|
+
}>;
|
|
20
|
+
maxDurationSeconds: z.ZodNumber;
|
|
21
|
+
onOverlap: z.ZodEnum<{
|
|
22
|
+
skip: "skip";
|
|
23
|
+
queue: "queue";
|
|
24
|
+
}>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
endpoint: z.ZodOptional<z.ZodString>;
|
|
27
|
+
generation: z.ZodNumber;
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
latencyClass: z.ZodEnum<{
|
|
30
|
+
realtime: "realtime";
|
|
31
|
+
bulk: "bulk";
|
|
32
|
+
}>;
|
|
33
|
+
partitionKey: z.ZodOptional<z.ZodString>;
|
|
34
|
+
recurrence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
35
|
+
kind: z.ZodLiteral<"at">;
|
|
36
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
37
|
+
everySeconds: z.ZodNumber;
|
|
38
|
+
kind: z.ZodLiteral<"every">;
|
|
39
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
40
|
+
cron: z.ZodString;
|
|
41
|
+
kind: z.ZodLiteral<"cron">;
|
|
42
|
+
timeZone: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
43
|
+
}, z.core.$strip>], "kind">;
|
|
44
|
+
status: z.ZodEnum<{
|
|
45
|
+
paused: "paused";
|
|
46
|
+
active: "active";
|
|
47
|
+
cancelled: "cancelled";
|
|
48
|
+
completed: "completed";
|
|
49
|
+
}>;
|
|
50
|
+
updatedAt: z.ZodString;
|
|
51
|
+
version: z.ZodNumber;
|
|
52
|
+
}, z.core.$strict>;
|
|
53
|
+
export type PortableScheduleRecord = z.infer<typeof portableScheduleRecordSchema>;
|
|
54
|
+
export declare const portableReceiptRecordSchema: z.ZodObject<{
|
|
55
|
+
attempt: z.ZodOptional<z.ZodString>;
|
|
56
|
+
authority: z.ZodObject<{
|
|
57
|
+
environment: z.ZodString;
|
|
58
|
+
environmentKind: z.ZodEnum<{
|
|
59
|
+
test: "test";
|
|
60
|
+
live: "live";
|
|
61
|
+
}>;
|
|
62
|
+
organization: z.ZodString;
|
|
63
|
+
project: z.ZodString;
|
|
64
|
+
}, z.core.$strict>;
|
|
65
|
+
expiresAt: z.ZodString;
|
|
66
|
+
idempotencyKey: z.ZodString;
|
|
67
|
+
operation: z.ZodEnum<{
|
|
68
|
+
"schedules.create": "schedules.create";
|
|
69
|
+
"occurrences.redeliver": "occurrences.redeliver";
|
|
70
|
+
"schedules.replace": "schedules.replace";
|
|
71
|
+
}>;
|
|
72
|
+
requestFingerprint: z.ZodString;
|
|
73
|
+
schedule: z.ZodString;
|
|
74
|
+
storedAt: z.ZodString;
|
|
75
|
+
}, z.core.$strict>;
|
|
76
|
+
export type PortableReceiptRecord = z.infer<typeof portableReceiptRecordSchema>;
|
|
77
|
+
export declare const portableOccurrenceRecordSchema: z.ZodObject<{
|
|
78
|
+
attemptCount: z.ZodNumber;
|
|
79
|
+
generation: z.ZodNumber;
|
|
80
|
+
id: z.ZodString;
|
|
81
|
+
plannedFor: z.ZodString;
|
|
82
|
+
schedule: z.ZodString;
|
|
83
|
+
sequence: z.ZodNumber;
|
|
84
|
+
settledAt: z.ZodOptional<z.ZodString>;
|
|
85
|
+
state: z.ZodEnum<{
|
|
86
|
+
succeeded: "succeeded";
|
|
87
|
+
ambiguous: "ambiguous";
|
|
88
|
+
cancelled: "cancelled";
|
|
89
|
+
planned: "planned";
|
|
90
|
+
due: "due";
|
|
91
|
+
dispatching: "dispatching";
|
|
92
|
+
retry_wait: "retry_wait";
|
|
93
|
+
terminal_failed: "terminal_failed";
|
|
94
|
+
skipped_stale: "skipped_stale";
|
|
95
|
+
}>;
|
|
96
|
+
authority: z.ZodObject<{
|
|
97
|
+
environment: z.ZodString;
|
|
98
|
+
environmentKind: z.ZodEnum<{
|
|
99
|
+
test: "test";
|
|
100
|
+
live: "live";
|
|
101
|
+
}>;
|
|
102
|
+
organization: z.ZodString;
|
|
103
|
+
project: z.ZodString;
|
|
104
|
+
}, z.core.$strict>;
|
|
105
|
+
createdAt: z.ZodString;
|
|
106
|
+
retentionDueAt: z.ZodOptional<z.ZodString>;
|
|
107
|
+
updatedAt: z.ZodString;
|
|
108
|
+
}, z.core.$strict>;
|
|
109
|
+
export type PortableOccurrenceRecord = z.infer<typeof portableOccurrenceRecordSchema>;
|
|
110
|
+
export declare const portableAttemptRecordSchema: z.ZodObject<{
|
|
111
|
+
attemptNumber: z.ZodNumber;
|
|
112
|
+
classifiedAt: z.ZodOptional<z.ZodString>;
|
|
113
|
+
delivery: z.ZodString;
|
|
114
|
+
diagnostic: z.ZodOptional<z.ZodEnum<{
|
|
115
|
+
rate_limited: "rate_limited";
|
|
116
|
+
completion_timed_out: "completion_timed_out";
|
|
117
|
+
delivered: "delivered";
|
|
118
|
+
duplicate_inflight: "duplicate_inflight";
|
|
119
|
+
endpoint_unavailable: "endpoint_unavailable";
|
|
120
|
+
endpoint_unsafe: "endpoint_unsafe";
|
|
121
|
+
http_refused: "http_refused";
|
|
122
|
+
http_retryable: "http_retryable";
|
|
123
|
+
http_terminal: "http_terminal";
|
|
124
|
+
identity_conflict: "identity_conflict";
|
|
125
|
+
network_ambiguous: "network_ambiguous";
|
|
126
|
+
payload_unavailable: "payload_unavailable";
|
|
127
|
+
}>>;
|
|
128
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
129
|
+
id: z.ZodString;
|
|
130
|
+
occurrence: z.ZodString;
|
|
131
|
+
remediation: z.ZodOptional<z.ZodEnum<{
|
|
132
|
+
none: "none";
|
|
133
|
+
review_retry_policy: "review_retry_policy";
|
|
134
|
+
inspect_receiver: "inspect_receiver";
|
|
135
|
+
verify_endpoint: "verify_endpoint";
|
|
136
|
+
replace_payload: "replace_payload";
|
|
137
|
+
contact_support: "contact_support";
|
|
138
|
+
review_before_redelivery: "review_before_redelivery";
|
|
139
|
+
}>>;
|
|
140
|
+
failureSnippet: z.ZodOptional<z.ZodObject<{
|
|
141
|
+
contentType: z.ZodString;
|
|
142
|
+
text: z.ZodString;
|
|
143
|
+
truncated: z.ZodBoolean;
|
|
144
|
+
}, z.core.$strip>>;
|
|
145
|
+
responseHeaders: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
146
|
+
name: z.ZodString;
|
|
147
|
+
value: z.ZodString;
|
|
148
|
+
}, z.core.$strip>>>;
|
|
149
|
+
responseStatus: z.ZodOptional<z.ZodNumber>;
|
|
150
|
+
startedAt: z.ZodString;
|
|
151
|
+
state: z.ZodOptional<z.ZodEnum<{
|
|
152
|
+
succeeded: "succeeded";
|
|
153
|
+
ambiguous: "ambiguous";
|
|
154
|
+
retryable_failure: "retryable_failure";
|
|
155
|
+
terminal_failure: "terminal_failure";
|
|
156
|
+
}>>;
|
|
157
|
+
trigger: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
158
|
+
kind: z.ZodLiteral<"automatic">;
|
|
159
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
160
|
+
kind: z.ZodLiteral<"redelivery">;
|
|
161
|
+
sourceAttemptId: z.ZodString;
|
|
162
|
+
}, z.core.$strip>], "kind">;
|
|
163
|
+
authority: z.ZodObject<{
|
|
164
|
+
environment: z.ZodString;
|
|
165
|
+
environmentKind: z.ZodEnum<{
|
|
166
|
+
test: "test";
|
|
167
|
+
live: "live";
|
|
168
|
+
}>;
|
|
169
|
+
organization: z.ZodString;
|
|
170
|
+
project: z.ZodString;
|
|
171
|
+
}, z.core.$strict>;
|
|
172
|
+
dispatchEpoch: z.ZodNumber;
|
|
173
|
+
schedule: z.ZodString;
|
|
174
|
+
updatedAt: z.ZodString;
|
|
175
|
+
}, z.core.$strict>;
|
|
176
|
+
export type PortableAttemptRecord = z.infer<typeof portableAttemptRecordSchema>;
|
|
177
|
+
export declare const portableEncryptedPayloadRecordSchema: z.ZodObject<{
|
|
178
|
+
aadVersion: z.ZodLiteral<"greatwait.schedule-payload.v1">;
|
|
179
|
+
authority: z.ZodObject<{
|
|
180
|
+
environment: z.ZodString;
|
|
181
|
+
environmentKind: z.ZodEnum<{
|
|
182
|
+
test: "test";
|
|
183
|
+
live: "live";
|
|
184
|
+
}>;
|
|
185
|
+
organization: z.ZodString;
|
|
186
|
+
project: z.ZodString;
|
|
187
|
+
}, z.core.$strict>;
|
|
188
|
+
envelope: z.ZodObject<{
|
|
189
|
+
ciphertext: z.ZodString;
|
|
190
|
+
keyId: z.ZodString;
|
|
191
|
+
nonce: z.ZodString;
|
|
192
|
+
}, z.core.$strict>;
|
|
193
|
+
plaintextBytes: z.ZodNumber;
|
|
194
|
+
retentionDueAt: z.ZodOptional<z.ZodString>;
|
|
195
|
+
schedule: z.ZodString;
|
|
196
|
+
sealedAt: z.ZodString;
|
|
197
|
+
updatedAt: z.ZodString;
|
|
198
|
+
}, z.core.$strict>;
|
|
199
|
+
export type PortableEncryptedPayloadRecord = z.infer<typeof portableEncryptedPayloadRecordSchema>;
|
|
200
|
+
export declare const portableSchedulingRecordSetSchema: z.ZodObject<{
|
|
201
|
+
attempts: z.ZodArray<z.ZodObject<{
|
|
202
|
+
attemptNumber: z.ZodNumber;
|
|
203
|
+
classifiedAt: z.ZodOptional<z.ZodString>;
|
|
204
|
+
delivery: z.ZodString;
|
|
205
|
+
diagnostic: z.ZodOptional<z.ZodEnum<{
|
|
206
|
+
rate_limited: "rate_limited";
|
|
207
|
+
completion_timed_out: "completion_timed_out";
|
|
208
|
+
delivered: "delivered";
|
|
209
|
+
duplicate_inflight: "duplicate_inflight";
|
|
210
|
+
endpoint_unavailable: "endpoint_unavailable";
|
|
211
|
+
endpoint_unsafe: "endpoint_unsafe";
|
|
212
|
+
http_refused: "http_refused";
|
|
213
|
+
http_retryable: "http_retryable";
|
|
214
|
+
http_terminal: "http_terminal";
|
|
215
|
+
identity_conflict: "identity_conflict";
|
|
216
|
+
network_ambiguous: "network_ambiguous";
|
|
217
|
+
payload_unavailable: "payload_unavailable";
|
|
218
|
+
}>>;
|
|
219
|
+
durationMs: z.ZodOptional<z.ZodNumber>;
|
|
220
|
+
id: z.ZodString;
|
|
221
|
+
occurrence: z.ZodString;
|
|
222
|
+
remediation: z.ZodOptional<z.ZodEnum<{
|
|
223
|
+
none: "none";
|
|
224
|
+
review_retry_policy: "review_retry_policy";
|
|
225
|
+
inspect_receiver: "inspect_receiver";
|
|
226
|
+
verify_endpoint: "verify_endpoint";
|
|
227
|
+
replace_payload: "replace_payload";
|
|
228
|
+
contact_support: "contact_support";
|
|
229
|
+
review_before_redelivery: "review_before_redelivery";
|
|
230
|
+
}>>;
|
|
231
|
+
failureSnippet: z.ZodOptional<z.ZodObject<{
|
|
232
|
+
contentType: z.ZodString;
|
|
233
|
+
text: z.ZodString;
|
|
234
|
+
truncated: z.ZodBoolean;
|
|
235
|
+
}, z.core.$strip>>;
|
|
236
|
+
responseHeaders: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
237
|
+
name: z.ZodString;
|
|
238
|
+
value: z.ZodString;
|
|
239
|
+
}, z.core.$strip>>>;
|
|
240
|
+
responseStatus: z.ZodOptional<z.ZodNumber>;
|
|
241
|
+
startedAt: z.ZodString;
|
|
242
|
+
state: z.ZodOptional<z.ZodEnum<{
|
|
243
|
+
succeeded: "succeeded";
|
|
244
|
+
ambiguous: "ambiguous";
|
|
245
|
+
retryable_failure: "retryable_failure";
|
|
246
|
+
terminal_failure: "terminal_failure";
|
|
247
|
+
}>>;
|
|
248
|
+
trigger: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
249
|
+
kind: z.ZodLiteral<"automatic">;
|
|
250
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
251
|
+
kind: z.ZodLiteral<"redelivery">;
|
|
252
|
+
sourceAttemptId: z.ZodString;
|
|
253
|
+
}, z.core.$strip>], "kind">;
|
|
254
|
+
authority: z.ZodObject<{
|
|
255
|
+
environment: z.ZodString;
|
|
256
|
+
environmentKind: z.ZodEnum<{
|
|
257
|
+
test: "test";
|
|
258
|
+
live: "live";
|
|
259
|
+
}>;
|
|
260
|
+
organization: z.ZodString;
|
|
261
|
+
project: z.ZodString;
|
|
262
|
+
}, z.core.$strict>;
|
|
263
|
+
dispatchEpoch: z.ZodNumber;
|
|
264
|
+
schedule: z.ZodString;
|
|
265
|
+
updatedAt: z.ZodString;
|
|
266
|
+
}, z.core.$strict>>;
|
|
267
|
+
occurrences: z.ZodArray<z.ZodObject<{
|
|
268
|
+
attemptCount: z.ZodNumber;
|
|
269
|
+
generation: z.ZodNumber;
|
|
270
|
+
id: z.ZodString;
|
|
271
|
+
plannedFor: z.ZodString;
|
|
272
|
+
schedule: z.ZodString;
|
|
273
|
+
sequence: z.ZodNumber;
|
|
274
|
+
settledAt: z.ZodOptional<z.ZodString>;
|
|
275
|
+
state: z.ZodEnum<{
|
|
276
|
+
succeeded: "succeeded";
|
|
277
|
+
ambiguous: "ambiguous";
|
|
278
|
+
cancelled: "cancelled";
|
|
279
|
+
planned: "planned";
|
|
280
|
+
due: "due";
|
|
281
|
+
dispatching: "dispatching";
|
|
282
|
+
retry_wait: "retry_wait";
|
|
283
|
+
terminal_failed: "terminal_failed";
|
|
284
|
+
skipped_stale: "skipped_stale";
|
|
285
|
+
}>;
|
|
286
|
+
authority: z.ZodObject<{
|
|
287
|
+
environment: z.ZodString;
|
|
288
|
+
environmentKind: z.ZodEnum<{
|
|
289
|
+
test: "test";
|
|
290
|
+
live: "live";
|
|
291
|
+
}>;
|
|
292
|
+
organization: z.ZodString;
|
|
293
|
+
project: z.ZodString;
|
|
294
|
+
}, z.core.$strict>;
|
|
295
|
+
createdAt: z.ZodString;
|
|
296
|
+
retentionDueAt: z.ZodOptional<z.ZodString>;
|
|
297
|
+
updatedAt: z.ZodString;
|
|
298
|
+
}, z.core.$strict>>;
|
|
299
|
+
payload: z.ZodOptional<z.ZodObject<{
|
|
300
|
+
aadVersion: z.ZodLiteral<"greatwait.schedule-payload.v1">;
|
|
301
|
+
authority: z.ZodObject<{
|
|
302
|
+
environment: z.ZodString;
|
|
303
|
+
environmentKind: z.ZodEnum<{
|
|
304
|
+
test: "test";
|
|
305
|
+
live: "live";
|
|
306
|
+
}>;
|
|
307
|
+
organization: z.ZodString;
|
|
308
|
+
project: z.ZodString;
|
|
309
|
+
}, z.core.$strict>;
|
|
310
|
+
envelope: z.ZodObject<{
|
|
311
|
+
ciphertext: z.ZodString;
|
|
312
|
+
keyId: z.ZodString;
|
|
313
|
+
nonce: z.ZodString;
|
|
314
|
+
}, z.core.$strict>;
|
|
315
|
+
plaintextBytes: z.ZodNumber;
|
|
316
|
+
retentionDueAt: z.ZodOptional<z.ZodString>;
|
|
317
|
+
schedule: z.ZodString;
|
|
318
|
+
sealedAt: z.ZodString;
|
|
319
|
+
updatedAt: z.ZodString;
|
|
320
|
+
}, z.core.$strict>>;
|
|
321
|
+
receipts: z.ZodArray<z.ZodObject<{
|
|
322
|
+
attempt: z.ZodOptional<z.ZodString>;
|
|
323
|
+
authority: z.ZodObject<{
|
|
324
|
+
environment: z.ZodString;
|
|
325
|
+
environmentKind: z.ZodEnum<{
|
|
326
|
+
test: "test";
|
|
327
|
+
live: "live";
|
|
328
|
+
}>;
|
|
329
|
+
organization: z.ZodString;
|
|
330
|
+
project: z.ZodString;
|
|
331
|
+
}, z.core.$strict>;
|
|
332
|
+
expiresAt: z.ZodString;
|
|
333
|
+
idempotencyKey: z.ZodString;
|
|
334
|
+
operation: z.ZodEnum<{
|
|
335
|
+
"schedules.create": "schedules.create";
|
|
336
|
+
"occurrences.redeliver": "occurrences.redeliver";
|
|
337
|
+
"schedules.replace": "schedules.replace";
|
|
338
|
+
}>;
|
|
339
|
+
requestFingerprint: z.ZodString;
|
|
340
|
+
schedule: z.ZodString;
|
|
341
|
+
storedAt: z.ZodString;
|
|
342
|
+
}, z.core.$strict>>;
|
|
343
|
+
schedule: z.ZodObject<{
|
|
344
|
+
authority: z.ZodObject<{
|
|
345
|
+
environment: z.ZodString;
|
|
346
|
+
environmentKind: z.ZodEnum<{
|
|
347
|
+
test: "test";
|
|
348
|
+
live: "live";
|
|
349
|
+
}>;
|
|
350
|
+
organization: z.ZodString;
|
|
351
|
+
project: z.ZodString;
|
|
352
|
+
}, z.core.$strict>;
|
|
353
|
+
retentionClass: z.ZodString;
|
|
354
|
+
archivedAt: z.ZodOptional<z.ZodString>;
|
|
355
|
+
createdAt: z.ZodString;
|
|
356
|
+
delivery: z.ZodOptional<z.ZodObject<{
|
|
357
|
+
completion: z.ZodEnum<{
|
|
358
|
+
response: "response";
|
|
359
|
+
callback: "callback";
|
|
360
|
+
}>;
|
|
361
|
+
maxDurationSeconds: z.ZodNumber;
|
|
362
|
+
onOverlap: z.ZodEnum<{
|
|
363
|
+
skip: "skip";
|
|
364
|
+
queue: "queue";
|
|
365
|
+
}>;
|
|
366
|
+
}, z.core.$strip>>;
|
|
367
|
+
endpoint: z.ZodOptional<z.ZodString>;
|
|
368
|
+
generation: z.ZodNumber;
|
|
369
|
+
id: z.ZodString;
|
|
370
|
+
latencyClass: z.ZodEnum<{
|
|
371
|
+
realtime: "realtime";
|
|
372
|
+
bulk: "bulk";
|
|
373
|
+
}>;
|
|
374
|
+
partitionKey: z.ZodOptional<z.ZodString>;
|
|
375
|
+
recurrence: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
376
|
+
kind: z.ZodLiteral<"at">;
|
|
377
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
378
|
+
everySeconds: z.ZodNumber;
|
|
379
|
+
kind: z.ZodLiteral<"every">;
|
|
380
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
381
|
+
cron: z.ZodString;
|
|
382
|
+
kind: z.ZodLiteral<"cron">;
|
|
383
|
+
timeZone: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
384
|
+
}, z.core.$strip>], "kind">;
|
|
385
|
+
status: z.ZodEnum<{
|
|
386
|
+
paused: "paused";
|
|
387
|
+
active: "active";
|
|
388
|
+
cancelled: "cancelled";
|
|
389
|
+
completed: "completed";
|
|
390
|
+
}>;
|
|
391
|
+
updatedAt: z.ZodString;
|
|
392
|
+
version: z.ZodNumber;
|
|
393
|
+
}, z.core.$strict>;
|
|
394
|
+
}, z.core.$strict>;
|
|
395
|
+
export type PortableSchedulingRecordSet = z.infer<typeof portableSchedulingRecordSetSchema>;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { authoritySchema } from "./authority.js";
|
|
3
|
+
import { SCHEDULE_PAYLOAD_AAD_VERSION } from "./delivery.js";
|
|
4
|
+
import { attemptIdSchema, scheduleIdSchema } from "./identifiers.js";
|
|
5
|
+
import { SCHEDULING_BOUNDS, attemptSchema, isTerminalOccurrenceState, occurrenceSchema, scheduleSchema, } from "./scheduling.js";
|
|
6
|
+
import { timestampSchema } from "./time.js";
|
|
7
|
+
/** Backend-neutral scheduling records frozen before PostgreSQL onboarding. */
|
|
8
|
+
const portableAuthoritySchema = z.strictObject(authoritySchema.shape);
|
|
9
|
+
const retentionClassSchema = z
|
|
10
|
+
.string()
|
|
11
|
+
.regex(/^[a-z][a-z0-9_-]{0,63}$/u, "must be a bounded lower-case retention class");
|
|
12
|
+
export const portableScheduleRecordSchema = z
|
|
13
|
+
.strictObject({
|
|
14
|
+
...scheduleSchema.shape,
|
|
15
|
+
authority: portableAuthoritySchema,
|
|
16
|
+
retentionClass: retentionClassSchema,
|
|
17
|
+
})
|
|
18
|
+
.superRefine((schedule, context) => {
|
|
19
|
+
requireAtOrAfter(schedule.updatedAt, schedule.createdAt, "updatedAt must not precede createdAt", ["updatedAt"], context);
|
|
20
|
+
if (schedule.archivedAt !== undefined) {
|
|
21
|
+
if (schedule.status !== "cancelled" && schedule.status !== "completed") {
|
|
22
|
+
context.addIssue({
|
|
23
|
+
code: "custom",
|
|
24
|
+
message: "archivedAt is allowed only on a terminal schedule",
|
|
25
|
+
path: ["archivedAt"],
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
requireAtOrAfter(schedule.archivedAt, schedule.createdAt, "archivedAt must not precede createdAt", ["archivedAt"], context);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
export const portableReceiptRecordSchema = z
|
|
32
|
+
.strictObject({
|
|
33
|
+
attempt: attemptIdSchema.optional(),
|
|
34
|
+
authority: portableAuthoritySchema,
|
|
35
|
+
expiresAt: timestampSchema,
|
|
36
|
+
idempotencyKey: z.string().min(1).max(255),
|
|
37
|
+
operation: z.enum([
|
|
38
|
+
"occurrences.redeliver",
|
|
39
|
+
"schedules.create",
|
|
40
|
+
"schedules.replace",
|
|
41
|
+
]),
|
|
42
|
+
requestFingerprint: z
|
|
43
|
+
.string()
|
|
44
|
+
.regex(/^[0-9a-f]{64}$/u, "must be a lower-case SHA-256 digest"),
|
|
45
|
+
schedule: scheduleIdSchema,
|
|
46
|
+
storedAt: timestampSchema,
|
|
47
|
+
})
|
|
48
|
+
.superRefine((receipt, context) => {
|
|
49
|
+
requireAfter(receipt.expiresAt, receipt.storedAt, "expiresAt must follow storedAt", ["expiresAt"], context);
|
|
50
|
+
if (receipt.operation === "occurrences.redeliver" &&
|
|
51
|
+
receipt.attempt === undefined) {
|
|
52
|
+
context.addIssue({
|
|
53
|
+
code: "custom",
|
|
54
|
+
message: "a redelivery receipt must name the attempt it minted",
|
|
55
|
+
path: ["attempt"],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (receipt.operation !== "occurrences.redeliver" &&
|
|
59
|
+
receipt.attempt !== undefined) {
|
|
60
|
+
context.addIssue({
|
|
61
|
+
code: "custom",
|
|
62
|
+
message: "only a redelivery receipt may name an attempt",
|
|
63
|
+
path: ["attempt"],
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
export const portableOccurrenceRecordSchema = occurrenceSchema
|
|
68
|
+
.safeExtend({
|
|
69
|
+
authority: portableAuthoritySchema,
|
|
70
|
+
createdAt: timestampSchema,
|
|
71
|
+
retentionDueAt: timestampSchema.optional(),
|
|
72
|
+
updatedAt: timestampSchema,
|
|
73
|
+
})
|
|
74
|
+
.strict()
|
|
75
|
+
.superRefine((occurrence, context) => {
|
|
76
|
+
requireAtOrAfter(occurrence.updatedAt, occurrence.createdAt, "updatedAt must not precede createdAt", ["updatedAt"], context);
|
|
77
|
+
if (isTerminalOccurrenceState(occurrence.state) !==
|
|
78
|
+
(occurrence.retentionDueAt !== undefined)) {
|
|
79
|
+
context.addIssue({
|
|
80
|
+
code: "custom",
|
|
81
|
+
message: "retentionDueAt must be present for a terminal state and absent otherwise",
|
|
82
|
+
path: ["retentionDueAt"],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (occurrence.settledAt !== undefined) {
|
|
86
|
+
requireAtOrAfter(occurrence.settledAt, occurrence.plannedFor, "settledAt must not precede plannedFor", ["settledAt"], context);
|
|
87
|
+
}
|
|
88
|
+
if (occurrence.retentionDueAt !== undefined &&
|
|
89
|
+
occurrence.settledAt !== undefined) {
|
|
90
|
+
requireAtOrAfter(occurrence.retentionDueAt, occurrence.settledAt, "retentionDueAt must not precede settledAt", ["retentionDueAt"], context);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
export const portableAttemptRecordSchema = attemptSchema
|
|
94
|
+
.safeExtend({
|
|
95
|
+
authority: portableAuthoritySchema,
|
|
96
|
+
dispatchEpoch: z.number().int().positive(),
|
|
97
|
+
schedule: scheduleIdSchema,
|
|
98
|
+
updatedAt: timestampSchema,
|
|
99
|
+
})
|
|
100
|
+
.strict()
|
|
101
|
+
.superRefine((attempt, context) => {
|
|
102
|
+
requireAtOrAfter(attempt.updatedAt, attempt.startedAt, "updatedAt must not precede startedAt", ["updatedAt"], context);
|
|
103
|
+
if (attempt.classifiedAt !== undefined) {
|
|
104
|
+
requireAtOrAfter(attempt.classifiedAt, attempt.startedAt, "classifiedAt must not precede startedAt", ["classifiedAt"], context);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const base64UrlBytesSchema = z
|
|
108
|
+
.string()
|
|
109
|
+
.min(1)
|
|
110
|
+
.regex(/^[A-Za-z0-9_-]+$/u, "must be unpadded base64url")
|
|
111
|
+
.refine((value) => decodeBase64UrlBytes(value) !== undefined, {
|
|
112
|
+
message: "must canonically encode base64url bytes",
|
|
113
|
+
});
|
|
114
|
+
export const portableEncryptedPayloadRecordSchema = z
|
|
115
|
+
.strictObject({
|
|
116
|
+
aadVersion: z.literal(SCHEDULE_PAYLOAD_AAD_VERSION),
|
|
117
|
+
authority: portableAuthoritySchema,
|
|
118
|
+
envelope: z.strictObject({
|
|
119
|
+
ciphertext: base64UrlBytesSchema,
|
|
120
|
+
keyId: z
|
|
121
|
+
.string()
|
|
122
|
+
.min(1)
|
|
123
|
+
.max(128)
|
|
124
|
+
.regex(/^[A-Za-z0-9._:-]+$/u, "must be a safe key identifier"),
|
|
125
|
+
nonce: base64UrlBytesSchema.refine((value) => decodeBase64UrlBytes(value)?.length === 12, { message: "must encode exactly 12 bytes" }),
|
|
126
|
+
}),
|
|
127
|
+
plaintextBytes: z
|
|
128
|
+
.number()
|
|
129
|
+
.int()
|
|
130
|
+
.nonnegative()
|
|
131
|
+
.max(SCHEDULING_BOUNDS.payloadBytes),
|
|
132
|
+
retentionDueAt: timestampSchema.optional(),
|
|
133
|
+
schedule: scheduleIdSchema,
|
|
134
|
+
sealedAt: timestampSchema,
|
|
135
|
+
updatedAt: timestampSchema,
|
|
136
|
+
})
|
|
137
|
+
.superRefine((payload, context) => {
|
|
138
|
+
const ciphertext = decodeBase64UrlBytes(payload.envelope.ciphertext);
|
|
139
|
+
if (ciphertext !== undefined &&
|
|
140
|
+
ciphertext.length !== payload.plaintextBytes + 16) {
|
|
141
|
+
context.addIssue({
|
|
142
|
+
code: "custom",
|
|
143
|
+
message: "ciphertext must contain the plaintext bytes and a 16-byte AES-GCM tag",
|
|
144
|
+
path: ["envelope", "ciphertext"],
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
requireAtOrAfter(payload.updatedAt, payload.sealedAt, "updatedAt must not precede sealedAt", ["updatedAt"], context);
|
|
148
|
+
if (payload.retentionDueAt !== undefined) {
|
|
149
|
+
requireAtOrAfter(payload.retentionDueAt, payload.sealedAt, "retentionDueAt must not precede sealedAt", ["retentionDueAt"], context);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
export const portableSchedulingRecordSetSchema = z
|
|
153
|
+
.strictObject({
|
|
154
|
+
attempts: z.array(portableAttemptRecordSchema),
|
|
155
|
+
occurrences: z.array(portableOccurrenceRecordSchema),
|
|
156
|
+
payload: portableEncryptedPayloadRecordSchema.optional(),
|
|
157
|
+
receipts: z.array(portableReceiptRecordSchema),
|
|
158
|
+
schedule: portableScheduleRecordSchema,
|
|
159
|
+
})
|
|
160
|
+
.superRefine((records, context) => {
|
|
161
|
+
const authority = authorityKey(records.schedule.authority);
|
|
162
|
+
const occurrenceIds = new Set(records.occurrences.map((item) => item.id));
|
|
163
|
+
const attemptIds = new Set(records.attempts.map((item) => item.id));
|
|
164
|
+
const attemptsById = new Map(records.attempts.map((item) => [item.id, item]));
|
|
165
|
+
checkUnique(records.occurrences.map((item) => item.id), "occurrence identity", ["occurrences"], context);
|
|
166
|
+
checkUnique(records.occurrences.map((item) => `${item.schedule}:${String(item.generation)}:${String(item.sequence)}`), "schedule/generation/sequence", ["occurrences"], context);
|
|
167
|
+
checkUnique(records.attempts.map((item) => item.id), "attempt identity", ["attempts"], context);
|
|
168
|
+
checkUnique(records.attempts.map((item) => item.delivery), "delivery identity", ["attempts"], context);
|
|
169
|
+
checkUnique(records.attempts.map((item) => `${item.occurrence}:${String(item.attemptNumber)}`), "occurrence/attempt number", ["attempts"], context);
|
|
170
|
+
checkUnique(records.receipts.map((item) => `${item.operation}:${item.idempotencyKey}`), "operation/idempotency key", ["receipts"], context);
|
|
171
|
+
for (const [index, item] of records.occurrences.entries()) {
|
|
172
|
+
requireAuthority(authority, item.authority, ["occurrences", index], context);
|
|
173
|
+
if (item.schedule !== records.schedule.id) {
|
|
174
|
+
addIdentityIssue("occurrence names another schedule", ["occurrences", index, "schedule"], context);
|
|
175
|
+
}
|
|
176
|
+
if (item.generation > records.schedule.generation) {
|
|
177
|
+
addIdentityIssue("occurrence generation is newer than its schedule", ["occurrences", index, "generation"], context);
|
|
178
|
+
}
|
|
179
|
+
const attemptNumbers = records.attempts
|
|
180
|
+
.filter((attempt) => attempt.occurrence === item.id)
|
|
181
|
+
.map((attempt) => attempt.attemptNumber)
|
|
182
|
+
.sort((left, right) => left - right);
|
|
183
|
+
if (attemptNumbers.length !== item.attemptCount) {
|
|
184
|
+
addIdentityIssue("occurrence attemptCount differs from its retained attempts", ["occurrences", index, "attemptCount"], context);
|
|
185
|
+
}
|
|
186
|
+
if (attemptNumbers.some((attemptNumber, attemptIndex) => attemptNumber !== attemptIndex + 1)) {
|
|
187
|
+
addIdentityIssue("occurrence attempts must be numbered contiguously from one", ["occurrences", index, "attemptCount"], context);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
for (const [index, item] of records.attempts.entries()) {
|
|
191
|
+
requireAuthority(authority, item.authority, ["attempts", index], context);
|
|
192
|
+
if (item.schedule !== records.schedule.id) {
|
|
193
|
+
addIdentityIssue("attempt names another schedule", ["attempts", index, "schedule"], context);
|
|
194
|
+
}
|
|
195
|
+
if (!occurrenceIds.has(item.occurrence)) {
|
|
196
|
+
addIdentityIssue("attempt names an occurrence outside this record set", ["attempts", index, "occurrence"], context);
|
|
197
|
+
}
|
|
198
|
+
if (item.trigger.kind === "redelivery") {
|
|
199
|
+
const source = attemptsById.get(item.trigger.sourceAttemptId);
|
|
200
|
+
if (source === undefined) {
|
|
201
|
+
addIdentityIssue("redelivery trigger names an attempt outside this record set", ["attempts", index, "trigger", "sourceAttemptId"], context);
|
|
202
|
+
}
|
|
203
|
+
else if (source.occurrence !== item.occurrence) {
|
|
204
|
+
addIdentityIssue("redelivery trigger names an attempt from another occurrence", ["attempts", index, "trigger", "sourceAttemptId"], context);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const [index, item] of records.receipts.entries()) {
|
|
209
|
+
requireAuthority(authority, item.authority, ["receipts", index], context);
|
|
210
|
+
if (item.schedule !== records.schedule.id) {
|
|
211
|
+
addIdentityIssue("receipt names another schedule", ["receipts", index, "schedule"], context);
|
|
212
|
+
}
|
|
213
|
+
if (item.attempt !== undefined && !attemptIds.has(item.attempt)) {
|
|
214
|
+
addIdentityIssue("receipt names an attempt outside this record set", ["receipts", index, "attempt"], context);
|
|
215
|
+
}
|
|
216
|
+
if (item.operation === "occurrences.redeliver") {
|
|
217
|
+
const minted = item.attempt === undefined
|
|
218
|
+
? undefined
|
|
219
|
+
: attemptsById.get(item.attempt);
|
|
220
|
+
if (minted !== undefined && minted.trigger.kind !== "redelivery") {
|
|
221
|
+
addIdentityIssue("redelivery receipt must name the redelivery attempt it minted", ["receipts", index, "attempt"], context);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (records.payload !== undefined) {
|
|
226
|
+
requireAuthority(authority, records.payload.authority, ["payload"], context);
|
|
227
|
+
if (records.payload.schedule !== records.schedule.id) {
|
|
228
|
+
addIdentityIssue("payload names another schedule", ["payload", "schedule"], context);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
function decodeBase64UrlBytes(value) {
|
|
233
|
+
if (value.length === 0 || !/^[A-Za-z0-9_-]+$/u.test(value)) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
const remainder = value.length % 4;
|
|
237
|
+
if (remainder === 1)
|
|
238
|
+
return undefined;
|
|
239
|
+
const padding = remainder === 0 ? "" : "=".repeat(4 - remainder);
|
|
240
|
+
try {
|
|
241
|
+
const binary = atob(value.replace(/-/gu, "+").replace(/_/gu, "/") + padding);
|
|
242
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
243
|
+
let encoded = "";
|
|
244
|
+
for (const byte of bytes)
|
|
245
|
+
encoded += String.fromCharCode(byte);
|
|
246
|
+
encoded = btoa(encoded)
|
|
247
|
+
.replace(/\+/gu, "-")
|
|
248
|
+
.replace(/\//gu, "_")
|
|
249
|
+
.replace(/=+$/u, "");
|
|
250
|
+
return encoded === value ? bytes : undefined;
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function authorityKey(authority) {
|
|
257
|
+
return [
|
|
258
|
+
authority.organization,
|
|
259
|
+
authority.project,
|
|
260
|
+
authority.environment,
|
|
261
|
+
authority.environmentKind,
|
|
262
|
+
].join(":");
|
|
263
|
+
}
|
|
264
|
+
function requireAuthority(expected, actual, path, context) {
|
|
265
|
+
if (authorityKey(actual) !== expected) {
|
|
266
|
+
addIdentityIssue("record authority differs from its schedule", path, context);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function checkUnique(values, name, path, context) {
|
|
270
|
+
if (new Set(values).size !== values.length) {
|
|
271
|
+
addIdentityIssue(`duplicate ${name}`, path, context);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function addIdentityIssue(message, path, context) {
|
|
275
|
+
context.addIssue({ code: "custom", message, path });
|
|
276
|
+
}
|
|
277
|
+
function requireAfter(actual, boundary, message, path, context) {
|
|
278
|
+
if (actual <= boundary)
|
|
279
|
+
addIdentityIssue(message, path, context);
|
|
280
|
+
}
|
|
281
|
+
function requireAtOrAfter(actual, boundary, message, path, context) {
|
|
282
|
+
if (actual < boundary)
|
|
283
|
+
addIdentityIssue(message, path, context);
|
|
284
|
+
}
|