@greatwait/contracts 0.1.0-alpha.6 → 0.1.0-alpha.7
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 +1 -1
- package/dist/attempt-diagnostics.d.ts +8 -0
- package/dist/attempt-diagnostics.js +68 -0
- package/dist/billing.d.ts +11 -10
- package/dist/billing.js +7 -4
- package/dist/delivery.d.ts +17 -40
- package/dist/delivery.js +12 -37
- package/dist/effective-limits.d.ts +4 -4
- package/dist/endpoints.d.ts +6 -6
- package/dist/first-value-journey.js +4 -4
- package/dist/identity.d.ts +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/members.d.ts +4 -4
- package/dist/operations.d.ts +296 -98
- package/dist/scheduling-records.d.ts +112 -8
- package/dist/scheduling.d.ts +253 -22
- package/dist/scheduling.js +46 -5
- package/dist/signatures.d.ts +1 -1
- package/dist/test-sink.d.ts +27 -41
- package/dist/test-sink.js +12 -31
- package/generated/v1/callback-receiver.json +4 -4
- package/generated/v1/first-value-journey.json +4 -4
- package/generated/v1/manifest.json +0 -1
- package/generated/v1/openapi.json +810 -10
- package/generated/v1/schemas/attempts.list.response.json +105 -0
- package/generated/v1/schemas/attempts.read.response.json +105 -0
- package/generated/v1/schemas/billing.notices.response.json +16 -6
- package/generated/v1/schemas/occurrences.redeliver.response.json +105 -0
- package/generated/v1/schemas/schedules.archive.response.json +50 -0
- package/generated/v1/schemas/schedules.cancel.response.json +50 -0
- package/generated/v1/schemas/schedules.create.request.json +14 -0
- package/generated/v1/schemas/schedules.create.response.json +50 -0
- package/generated/v1/schemas/schedules.list.response.json +50 -0
- package/generated/v1/schemas/schedules.pause.response.json +50 -0
- package/generated/v1/schemas/schedules.read.response.json +50 -0
- package/generated/v1/schemas/schedules.replace.request.json +14 -0
- package/generated/v1/schemas/schedules.replace.response.json +50 -0
- package/generated/v1/schemas/schedules.resume.response.json +50 -0
- package/package.json +1 -1
package/dist/test-sink.d.ts
CHANGED
|
@@ -55,8 +55,8 @@ import { type CallbackCompletionOutcome } from "./delivery.js";
|
|
|
55
55
|
*/
|
|
56
56
|
export declare const TEST_SINK_BEHAVIORS: readonly ["client_error", "defer_abandon", "defer_fail", "defer_succeed", "delay", "disconnect", "duplicate", "invalid_signature", "rate_limited", "server_error", "success", "timeout"];
|
|
57
57
|
export declare const testSinkBehaviorSchema: import("zod").ZodEnum<{
|
|
58
|
-
rate_limited: "rate_limited";
|
|
59
58
|
success: "success";
|
|
59
|
+
rate_limited: "rate_limited";
|
|
60
60
|
server_error: "server_error";
|
|
61
61
|
client_error: "client_error";
|
|
62
62
|
defer_abandon: "defer_abandon";
|
|
@@ -118,14 +118,9 @@ export declare const TEST_SINK_BOUNDS: {
|
|
|
118
118
|
/**
|
|
119
119
|
* Selected 4xx a sink may answer with.
|
|
120
120
|
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* ordinary five-failure budget. `TEST_SINK_REFUSAL_STATUSES` below is the
|
|
125
|
-
* subset of this list that the sender will retry, and `test-sink.test.ts`
|
|
126
|
-
* holds it equal to what `classifyStatus` actually says, so a status moved in
|
|
127
|
-
* `CALLBACK_REFUSAL_STATUSES` and not here fails a test rather than teaching an
|
|
128
|
-
* integrator the wrong lesson.
|
|
121
|
+
* The sender settles these selected statuses on the first attempt. W9-42
|
|
122
|
+
* stops retrying 401/403/404/405 to avoid billing for a broken configuration.
|
|
123
|
+
* The broader classification is owned by CALLBACK_REFUSAL_STATUSES.
|
|
129
124
|
*
|
|
130
125
|
* Nothing is removed from what a caller may request: every status here was
|
|
131
126
|
* accepted before and still is.
|
|
@@ -134,11 +129,9 @@ export declare const TEST_SINK_CLIENT_ERROR_STATUSES: readonly [400, 401, 403, 4
|
|
|
134
129
|
/**
|
|
135
130
|
* The statuses above that the sender retries rather than settling on.
|
|
136
131
|
*
|
|
137
|
-
*
|
|
138
|
-
* (403) can see five attempts arrive, and one simulating a malformed body (400)
|
|
139
|
-
* or a duplicate (409) can see exactly one.
|
|
132
|
+
* Every selected client-error status is terminal under W9-42.
|
|
140
133
|
*/
|
|
141
|
-
export declare const TEST_SINK_REFUSAL_STATUSES: readonly [
|
|
134
|
+
export declare const TEST_SINK_REFUSAL_STATUSES: readonly [];
|
|
142
135
|
/** Selected 5xx a sink may answer with. Each is retryable to the sender. */
|
|
143
136
|
export declare const TEST_SINK_SERVER_ERROR_STATUSES: readonly [500, 502, 503, 504];
|
|
144
137
|
/**
|
|
@@ -156,8 +149,8 @@ export declare const TEST_SINK_SERVER_ERROR_STATUSES: readonly [500, 502, 503, 5
|
|
|
156
149
|
*/
|
|
157
150
|
export declare const testSinkProgramSchema: import("zod").ZodObject<{
|
|
158
151
|
behavior: import("zod").ZodEnum<{
|
|
159
|
-
rate_limited: "rate_limited";
|
|
160
152
|
success: "success";
|
|
153
|
+
rate_limited: "rate_limited";
|
|
161
154
|
server_error: "server_error";
|
|
162
155
|
client_error: "client_error";
|
|
163
156
|
defer_abandon: "defer_abandon";
|
|
@@ -175,8 +168,8 @@ export declare const testSinkProgramSchema: import("zod").ZodObject<{
|
|
|
175
168
|
retryAfterSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
176
169
|
status: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
177
170
|
then: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
178
|
-
rate_limited: "rate_limited";
|
|
179
171
|
success: "success";
|
|
172
|
+
rate_limited: "rate_limited";
|
|
180
173
|
server_error: "server_error";
|
|
181
174
|
client_error: "client_error";
|
|
182
175
|
defer_abandon: "defer_abandon";
|
|
@@ -213,7 +206,7 @@ export declare const TEST_SINK_BEHAVIOR_FACTS: {
|
|
|
213
206
|
readonly deferredReport: undefined;
|
|
214
207
|
readonly receiverActed: false;
|
|
215
208
|
readonly senderOutcome: "terminal";
|
|
216
|
-
readonly summary: "Answers a selected 4xx.
|
|
209
|
+
readonly summary: "Answers a selected 4xx. Every selected status settles the run on the first attempt, including 401, 403 and 404. Fix the destination, then redeliver manually.";
|
|
217
210
|
};
|
|
218
211
|
readonly defer_abandon: {
|
|
219
212
|
readonly defaultStatus: 202;
|
|
@@ -261,8 +254,8 @@ export declare const TEST_SINK_BEHAVIOR_FACTS: {
|
|
|
261
254
|
readonly defaultStatus: 401;
|
|
262
255
|
readonly deferredReport: undefined;
|
|
263
256
|
readonly receiverActed: false;
|
|
264
|
-
readonly senderOutcome: "
|
|
265
|
-
readonly summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The
|
|
257
|
+
readonly senderOutcome: "terminal";
|
|
258
|
+
readonly summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The run stops after one attempt; fix the key and redeliver manually.";
|
|
266
259
|
};
|
|
267
260
|
readonly rate_limited: {
|
|
268
261
|
readonly defaultStatus: 429;
|
|
@@ -439,16 +432,9 @@ export type TestSinkDisposition = z.infer<typeof testSinkDispositionSchema>;
|
|
|
439
432
|
* the network for six minutes is not, and every attempt re-signs with a fresh
|
|
440
433
|
* timestamp, so the transient case self-heals and the permanent case exhausts
|
|
441
434
|
* the attempt bound honestly.
|
|
442
|
-
* - `invalid_signature`, `invalid_headers` — 401,
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
* answer would spend the give-up budget hiding a misconfiguration. That is
|
|
446
|
-
* true of a mismatch in *our* signing and false of the population that
|
|
447
|
-
* actually reaches a 401: a receiver holding a credential it has rotated,
|
|
448
|
-
* expired, or not yet deployed. Those recover on the receiver's next release,
|
|
449
|
-
* and the delivery after it carries a fresh signature. The misconfiguration
|
|
450
|
-
* is not hidden either — five identical 401s settle the occurrence 82 seconds
|
|
451
|
-
* later with the same `inspect_receiver` advice, five rows instead of one.
|
|
435
|
+
* - `invalid_signature`, `invalid_headers` — 401, terminal since W9-42.
|
|
436
|
+
* Repeating a broken credential spends paid attempts without fixing it.
|
|
437
|
+
* Correct the key or receiver configuration, then redeliver manually.
|
|
452
438
|
* - `invalid_envelope` — 400, terminal. The bytes authenticated and did not
|
|
453
439
|
* parse, so the sender and receiver disagree about the contract.
|
|
454
440
|
* - `body_too_large` — 413, terminal, and matched to the `payload_too_large`
|
|
@@ -500,8 +486,8 @@ export declare const testSinkSchema: import("zod").ZodObject<{
|
|
|
500
486
|
id: import("zod").ZodString;
|
|
501
487
|
program: import("zod").ZodObject<{
|
|
502
488
|
behavior: import("zod").ZodEnum<{
|
|
503
|
-
rate_limited: "rate_limited";
|
|
504
489
|
success: "success";
|
|
490
|
+
rate_limited: "rate_limited";
|
|
505
491
|
server_error: "server_error";
|
|
506
492
|
client_error: "client_error";
|
|
507
493
|
defer_abandon: "defer_abandon";
|
|
@@ -519,8 +505,8 @@ export declare const testSinkSchema: import("zod").ZodObject<{
|
|
|
519
505
|
retryAfterSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
520
506
|
status: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
521
507
|
then: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
522
|
-
rate_limited: "rate_limited";
|
|
523
508
|
success: "success";
|
|
509
|
+
rate_limited: "rate_limited";
|
|
524
510
|
server_error: "server_error";
|
|
525
511
|
client_error: "client_error";
|
|
526
512
|
defer_abandon: "defer_abandon";
|
|
@@ -547,8 +533,8 @@ export declare const testSinkPageSchema: import("zod").ZodObject<{
|
|
|
547
533
|
id: import("zod").ZodString;
|
|
548
534
|
program: import("zod").ZodObject<{
|
|
549
535
|
behavior: import("zod").ZodEnum<{
|
|
550
|
-
rate_limited: "rate_limited";
|
|
551
536
|
success: "success";
|
|
537
|
+
rate_limited: "rate_limited";
|
|
552
538
|
server_error: "server_error";
|
|
553
539
|
client_error: "client_error";
|
|
554
540
|
defer_abandon: "defer_abandon";
|
|
@@ -566,8 +552,8 @@ export declare const testSinkPageSchema: import("zod").ZodObject<{
|
|
|
566
552
|
retryAfterSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
567
553
|
status: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
568
554
|
then: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
569
|
-
rate_limited: "rate_limited";
|
|
570
555
|
success: "success";
|
|
556
|
+
rate_limited: "rate_limited";
|
|
571
557
|
server_error: "server_error";
|
|
572
558
|
client_error: "client_error";
|
|
573
559
|
defer_abandon: "defer_abandon";
|
|
@@ -598,8 +584,8 @@ export declare const testSinkCreateRequestSchema: import("zod").ZodObject<{
|
|
|
598
584
|
endpoint: import("zod").ZodString;
|
|
599
585
|
program: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
600
586
|
behavior: import("zod").ZodEnum<{
|
|
601
|
-
rate_limited: "rate_limited";
|
|
602
587
|
success: "success";
|
|
588
|
+
rate_limited: "rate_limited";
|
|
603
589
|
server_error: "server_error";
|
|
604
590
|
client_error: "client_error";
|
|
605
591
|
defer_abandon: "defer_abandon";
|
|
@@ -617,8 +603,8 @@ export declare const testSinkCreateRequestSchema: import("zod").ZodObject<{
|
|
|
617
603
|
retryAfterSeconds: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
618
604
|
status: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
619
605
|
then: import("zod").ZodOptional<import("zod").ZodEnum<{
|
|
620
|
-
rate_limited: "rate_limited";
|
|
621
606
|
success: "success";
|
|
607
|
+
rate_limited: "rate_limited";
|
|
622
608
|
server_error: "server_error";
|
|
623
609
|
client_error: "client_error";
|
|
624
610
|
defer_abandon: "defer_abandon";
|
|
@@ -642,8 +628,8 @@ export type TestSinkCreateRequest = z.infer<typeof testSinkCreateRequestSchema>;
|
|
|
642
628
|
*/
|
|
643
629
|
export declare const testSinkDeliverySchema: import("zod").ZodObject<{
|
|
644
630
|
behavior: import("zod").ZodEnum<{
|
|
645
|
-
rate_limited: "rate_limited";
|
|
646
631
|
success: "success";
|
|
632
|
+
rate_limited: "rate_limited";
|
|
647
633
|
server_error: "server_error";
|
|
648
634
|
client_error: "client_error";
|
|
649
635
|
defer_abandon: "defer_abandon";
|
|
@@ -681,8 +667,8 @@ export type TestSinkDelivery = z.infer<typeof testSinkDeliverySchema>;
|
|
|
681
667
|
export declare const testSinkDeliveryPageSchema: import("zod").ZodObject<{
|
|
682
668
|
data: import("zod").ZodArray<import("zod").ZodObject<{
|
|
683
669
|
behavior: import("zod").ZodEnum<{
|
|
684
|
-
rate_limited: "rate_limited";
|
|
685
670
|
success: "success";
|
|
671
|
+
rate_limited: "rate_limited";
|
|
686
672
|
server_error: "server_error";
|
|
687
673
|
client_error: "client_error";
|
|
688
674
|
defer_abandon: "defer_abandon";
|
|
@@ -747,8 +733,8 @@ export type TestSinkDeliveryPage = z.infer<typeof testSinkDeliveryPageSchema>;
|
|
|
747
733
|
*/
|
|
748
734
|
export declare const testSinkDeliveryBodySchema: import("zod").ZodObject<{
|
|
749
735
|
behavior: import("zod").ZodEnum<{
|
|
750
|
-
rate_limited: "rate_limited";
|
|
751
736
|
success: "success";
|
|
737
|
+
rate_limited: "rate_limited";
|
|
752
738
|
server_error: "server_error";
|
|
753
739
|
client_error: "client_error";
|
|
754
740
|
defer_abandon: "defer_abandon";
|
|
@@ -874,7 +860,7 @@ export declare const CALLBACK_RECEIVER_PROTOCOL: {
|
|
|
874
860
|
readonly deferredReport: undefined;
|
|
875
861
|
readonly receiverActed: false;
|
|
876
862
|
readonly senderOutcome: "terminal";
|
|
877
|
-
readonly summary: "Answers a selected 4xx.
|
|
863
|
+
readonly summary: "Answers a selected 4xx. Every selected status settles the run on the first attempt, including 401, 403 and 404. Fix the destination, then redeliver manually.";
|
|
878
864
|
};
|
|
879
865
|
readonly defer_abandon: {
|
|
880
866
|
readonly defaultStatus: 202;
|
|
@@ -922,8 +908,8 @@ export declare const CALLBACK_RECEIVER_PROTOCOL: {
|
|
|
922
908
|
readonly defaultStatus: 401;
|
|
923
909
|
readonly deferredReport: undefined;
|
|
924
910
|
readonly receiverActed: false;
|
|
925
|
-
readonly senderOutcome: "
|
|
926
|
-
readonly summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The
|
|
911
|
+
readonly senderOutcome: "terminal";
|
|
912
|
+
readonly summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The run stops after one attempt; fix the key and redeliver manually.";
|
|
927
913
|
};
|
|
928
914
|
readonly rate_limited: {
|
|
929
915
|
readonly defaultStatus: 429;
|
|
@@ -993,7 +979,7 @@ export declare const CALLBACK_RECEIVER_PROTOCOL: {
|
|
|
993
979
|
readonly maxRetainedBodyBytes: 4096;
|
|
994
980
|
};
|
|
995
981
|
readonly clientErrorStatuses: readonly [400, 401, 403, 404, 409, 410, 422];
|
|
996
|
-
readonly clientErrorStatusesRetried: readonly [
|
|
982
|
+
readonly clientErrorStatusesRetried: readonly [];
|
|
997
983
|
readonly deferral: {
|
|
998
984
|
readonly acknowledgement: string;
|
|
999
985
|
readonly note: "A deferring behavior answers this exact body with this status, then reports with the bearer credential from the delivery's own signed envelope — to the one completion address the stage is configured with, which the envelope's own URL must match. A delivery whose envelope carries no completion material, or names a different address, cannot defer, and the sink answers it as an ordinary success instead.";
|
package/dist/test-sink.js
CHANGED
|
@@ -125,14 +125,9 @@ export const TEST_SINK_BOUNDS = {
|
|
|
125
125
|
/**
|
|
126
126
|
* Selected 4xx a sink may answer with.
|
|
127
127
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* ordinary five-failure budget. `TEST_SINK_REFUSAL_STATUSES` below is the
|
|
132
|
-
* subset of this list that the sender will retry, and `test-sink.test.ts`
|
|
133
|
-
* holds it equal to what `classifyStatus` actually says, so a status moved in
|
|
134
|
-
* `CALLBACK_REFUSAL_STATUSES` and not here fails a test rather than teaching an
|
|
135
|
-
* integrator the wrong lesson.
|
|
128
|
+
* The sender settles these selected statuses on the first attempt. W9-42
|
|
129
|
+
* stops retrying 401/403/404/405 to avoid billing for a broken configuration.
|
|
130
|
+
* The broader classification is owned by CALLBACK_REFUSAL_STATUSES.
|
|
136
131
|
*
|
|
137
132
|
* Nothing is removed from what a caller may request: every status here was
|
|
138
133
|
* accepted before and still is.
|
|
@@ -143,11 +138,9 @@ export const TEST_SINK_CLIENT_ERROR_STATUSES = [
|
|
|
143
138
|
/**
|
|
144
139
|
* The statuses above that the sender retries rather than settling on.
|
|
145
140
|
*
|
|
146
|
-
*
|
|
147
|
-
* (403) can see five attempts arrive, and one simulating a malformed body (400)
|
|
148
|
-
* or a duplicate (409) can see exactly one.
|
|
141
|
+
* Every selected client-error status is terminal under W9-42.
|
|
149
142
|
*/
|
|
150
|
-
export const TEST_SINK_REFUSAL_STATUSES = [
|
|
143
|
+
export const TEST_SINK_REFUSAL_STATUSES = [];
|
|
151
144
|
/** Selected 5xx a sink may answer with. Each is retryable to the sender. */
|
|
152
145
|
export const TEST_SINK_SERVER_ERROR_STATUSES = [500, 502, 503, 504];
|
|
153
146
|
/**
|
|
@@ -275,7 +268,7 @@ export const TEST_SINK_BEHAVIOR_FACTS = {
|
|
|
275
268
|
deferredReport: undefined,
|
|
276
269
|
receiverActed: false,
|
|
277
270
|
senderOutcome: "terminal",
|
|
278
|
-
summary: "Answers a selected 4xx.
|
|
271
|
+
summary: "Answers a selected 4xx. Every selected status settles the run on the first attempt, including 401, 403 and 404. Fix the destination, then redeliver manually.",
|
|
279
272
|
},
|
|
280
273
|
defer_abandon: {
|
|
281
274
|
defaultStatus: CALLBACK_DEFERRAL_STATUS,
|
|
@@ -327,14 +320,9 @@ export const TEST_SINK_BEHAVIOR_FACTS = {
|
|
|
327
320
|
defaultStatus: 401,
|
|
328
321
|
deferredReport: undefined,
|
|
329
322
|
receiverActed: false,
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
// about the population that actually occurs, which is a receiver holding a
|
|
334
|
-
// credential it has rotated or not yet deployed. That fixes itself on their
|
|
335
|
-
// next release, and the delivery that follows carries a fresh signature.
|
|
336
|
-
senderOutcome: "retryable",
|
|
337
|
-
summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The sender retries on the receiver's ordinary budget, because the usual cause is a credential the receiver is about to redeploy.",
|
|
323
|
+
// W9-42 stops a broken credential after one billed attempt.
|
|
324
|
+
senderOutcome: "terminal",
|
|
325
|
+
summary: "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The run stops after one attempt; fix the key and redeliver manually.",
|
|
338
326
|
},
|
|
339
327
|
rate_limited: {
|
|
340
328
|
defaultStatus: 429,
|
|
@@ -514,16 +502,9 @@ export const testSinkDispositionSchema = z.enum(TEST_SINK_DISPOSITIONS);
|
|
|
514
502
|
* the network for six minutes is not, and every attempt re-signs with a fresh
|
|
515
503
|
* timestamp, so the transient case self-heals and the permanent case exhausts
|
|
516
504
|
* the attempt bound honestly.
|
|
517
|
-
* - `invalid_signature`, `invalid_headers` — 401,
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
* answer would spend the give-up budget hiding a misconfiguration. That is
|
|
521
|
-
* true of a mismatch in *our* signing and false of the population that
|
|
522
|
-
* actually reaches a 401: a receiver holding a credential it has rotated,
|
|
523
|
-
* expired, or not yet deployed. Those recover on the receiver's next release,
|
|
524
|
-
* and the delivery after it carries a fresh signature. The misconfiguration
|
|
525
|
-
* is not hidden either — five identical 401s settle the occurrence 82 seconds
|
|
526
|
-
* later with the same `inspect_receiver` advice, five rows instead of one.
|
|
505
|
+
* - `invalid_signature`, `invalid_headers` — 401, terminal since W9-42.
|
|
506
|
+
* Repeating a broken credential spends paid attempts without fixing it.
|
|
507
|
+
* Correct the key or receiver configuration, then redeliver manually.
|
|
527
508
|
* - `invalid_envelope` — 400, terminal. The bytes authenticated and did not
|
|
528
509
|
* parse, so the sender and receiver disagree about the contract.
|
|
529
510
|
* - `body_too_large` — 413, terminal, and matched to the `payload_too_large`
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"defaultStatus": 422,
|
|
57
57
|
"receiverActed": false,
|
|
58
58
|
"senderOutcome": "terminal",
|
|
59
|
-
"summary": "Answers a selected 4xx.
|
|
59
|
+
"summary": "Answers a selected 4xx. Every selected status settles the run on the first attempt, including 401, 403 and 404. Fix the destination, then redeliver manually."
|
|
60
60
|
},
|
|
61
61
|
"defer_abandon": {
|
|
62
62
|
"defaultStatus": 202,
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"invalid_signature": {
|
|
100
100
|
"defaultStatus": 401,
|
|
101
101
|
"receiverActed": false,
|
|
102
|
-
"senderOutcome": "
|
|
103
|
-
"summary": "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The
|
|
102
|
+
"senderOutcome": "terminal",
|
|
103
|
+
"summary": "Rejects the delivery as unauthenticated regardless of whether the signature verified. Exercises the key-mismatch path without forging a signature. The run stops after one attempt; fix the key and redeliver manually."
|
|
104
104
|
},
|
|
105
105
|
"rate_limited": {
|
|
106
106
|
"defaultStatus": 429,
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
"maxRetainedBodyBytes": 4096
|
|
137
137
|
},
|
|
138
138
|
"clientErrorStatuses": [400, 401, 403, 404, 409, 410, 422],
|
|
139
|
-
"clientErrorStatusesRetried": [
|
|
139
|
+
"clientErrorStatusesRetried": [],
|
|
140
140
|
"deferral": {
|
|
141
141
|
"acknowledgement": "{\"greatwait\":{\"status\":\"pending\"}}",
|
|
142
142
|
"note": "A deferring behavior answers this exact body with this status, then reports with the bearer credential from the delivery's own signed envelope — to the one completion address the stage is configured with, which the envelope's own URL must match. A delivery whose envelope carries no completion material, or names a different address, cannot defer, and the sink answers it as an ordinary success instead.",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"contractVersion": "2026-08-22",
|
|
3
3
|
"prerequisites": [
|
|
4
4
|
{
|
|
5
|
-
"action": "
|
|
5
|
+
"action": "Sign up at https://app.greatwait.dev/sign-up and name your organization, or sign in. Then create a project in the dashboard, or pick an existing one.",
|
|
6
6
|
"because": "projects.create accepts only a signed-in member, so a project is created by a person rather than by an API credential.",
|
|
7
7
|
"id": "project",
|
|
8
8
|
"title": "A project"
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"title": "An API credential"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
"action": "
|
|
18
|
-
"because": "GreatWait
|
|
17
|
+
"action": "Get a test URL from webhook.site, which shows every request it receives, or use your own app's HTTPS URL. It must answer with a 2xx status and be reachable from the public internet.",
|
|
18
|
+
"because": "GreatWait calls the URL you give it. Don't send real data to a public tester.",
|
|
19
19
|
"id": "receiver",
|
|
20
|
-
"title": "
|
|
20
|
+
"title": "A URL to call"
|
|
21
21
|
}
|
|
22
22
|
],
|
|
23
23
|
"steps": [
|