@greatwait/contracts 0.1.0-alpha.5 → 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.
Files changed (135) hide show
  1. package/README.md +1 -1
  2. package/dist/attempt-diagnostics.d.ts +8 -0
  3. package/dist/attempt-diagnostics.js +68 -0
  4. package/dist/authority.d.ts +4 -1
  5. package/dist/authority.js +1 -0
  6. package/dist/billing.d.ts +11 -10
  7. package/dist/billing.js +7 -4
  8. package/dist/data-export.d.ts +2 -0
  9. package/dist/delivery.d.ts +43 -40
  10. package/dist/delivery.js +14 -37
  11. package/dist/effective-limits.d.ts +4 -4
  12. package/dist/endpoints.d.ts +173 -5
  13. package/dist/endpoints.js +72 -1
  14. package/dist/first-value-journey.js +4 -4
  15. package/dist/http-request.d.ts +193 -0
  16. package/dist/http-request.js +305 -0
  17. package/dist/identity.d.ts +7 -7
  18. package/dist/index.d.ts +6 -3
  19. package/dist/index.js +5 -2
  20. package/dist/mcp.d.ts +2 -1
  21. package/dist/members.d.ts +141 -0
  22. package/dist/members.js +223 -0
  23. package/dist/oauth.d.ts +7 -0
  24. package/dist/operation-definitions.d.ts +20 -4
  25. package/dist/operation-definitions.js +9 -1
  26. package/dist/operations.d.ts +999 -135
  27. package/dist/operations.js +83 -10
  28. package/dist/organization-lifecycle.d.ts +10 -0
  29. package/dist/policy.js +5 -2
  30. package/dist/scheduling-records.d.ts +332 -8
  31. package/dist/scheduling-records.js +5 -0
  32. package/dist/scheduling.d.ts +485 -18
  33. package/dist/scheduling.js +77 -5
  34. package/dist/secrets.d.ts +7 -0
  35. package/dist/signatures.d.ts +1 -1
  36. package/dist/tenancy.d.ts +1 -1
  37. package/dist/tenancy.js +1 -1
  38. package/dist/test-sink.d.ts +27 -41
  39. package/dist/test-sink.js +12 -31
  40. package/dist/zod-values.d.ts +2 -2
  41. package/dist/zod-values.js +1 -1
  42. package/generated/v1/callback-receiver.json +4 -4
  43. package/generated/v1/examples/endpoints.ensure.request.json +3 -0
  44. package/generated/v1/examples/endpoints.ensure.response.json +20 -0
  45. package/generated/v1/examples/invitations.create.request.json +5 -0
  46. package/generated/v1/examples/invitations.create.response.json +7 -0
  47. package/generated/v1/examples/invitations.list.response.json +11 -0
  48. package/generated/v1/examples/invitations.resend.request.json +1 -0
  49. package/generated/v1/examples/invitations.resend.response.json +4 -0
  50. package/generated/v1/examples/invitations.revoke.request.json +3 -0
  51. package/generated/v1/examples/invitations.revoke.response.json +4 -0
  52. package/generated/v1/examples/members.list.response.json +13 -0
  53. package/generated/v1/examples/members.remove.request.json +3 -0
  54. package/generated/v1/examples/members.remove.response.json +4 -0
  55. package/generated/v1/examples/members.role.request.json +3 -0
  56. package/generated/v1/examples/members.role.response.json +4 -0
  57. package/generated/v1/examples/projectmembers.add.request.json +1 -0
  58. package/generated/v1/examples/projectmembers.add.response.json +4 -0
  59. package/generated/v1/examples/projectmembers.remove.request.json +3 -0
  60. package/generated/v1/examples/projectmembers.remove.response.json +4 -0
  61. package/generated/v1/first-value-journey.json +4 -4
  62. package/generated/v1/manifest.json +284 -0
  63. package/generated/v1/openapi.json +9387 -1021
  64. package/generated/v1/policy-matrix.json +72 -0
  65. package/generated/v1/schemas/attempts.list.response.json +105 -0
  66. package/generated/v1/schemas/attempts.read.response.json +105 -0
  67. package/generated/v1/schemas/billing.notices.response.json +16 -6
  68. package/generated/v1/schemas/context.read.response.json +1 -0
  69. package/generated/v1/schemas/credentials.connection.response.json +1 -0
  70. package/generated/v1/schemas/credentials.create.request.json +1 -0
  71. package/generated/v1/schemas/credentials.create.response.json +1 -0
  72. package/generated/v1/schemas/credentials.list.response.json +1 -0
  73. package/generated/v1/schemas/credentials.revoke.response.json +1 -0
  74. package/generated/v1/schemas/credentials.rotate.response.json +2 -0
  75. package/generated/v1/schemas/endpoints.acknowledgeSigningKeyRotation.response.json +59 -0
  76. package/generated/v1/schemas/endpoints.create.request.json +74 -0
  77. package/generated/v1/schemas/endpoints.create.response.json +59 -0
  78. package/generated/v1/schemas/endpoints.disable.response.json +59 -0
  79. package/generated/v1/schemas/endpoints.enable.response.json +59 -0
  80. package/generated/v1/schemas/endpoints.ensure.request.json +91 -0
  81. package/generated/v1/schemas/endpoints.ensure.response.json +169 -0
  82. package/generated/v1/schemas/endpoints.list.response.json +59 -0
  83. package/generated/v1/schemas/endpoints.read.response.json +59 -0
  84. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +59 -0
  85. package/generated/v1/schemas/endpoints.update.request.json +74 -0
  86. package/generated/v1/schemas/endpoints.update.response.json +59 -0
  87. package/generated/v1/schemas/grants.list.response.json +1 -0
  88. package/generated/v1/schemas/grants.revoke.response.json +1 -0
  89. package/generated/v1/schemas/invitations.create.request-headers.json +13 -0
  90. package/generated/v1/schemas/invitations.create.request.json +24 -0
  91. package/generated/v1/schemas/invitations.create.response.json +31 -0
  92. package/generated/v1/schemas/invitations.list.response.json +40 -0
  93. package/generated/v1/schemas/invitations.resend.request-headers.json +13 -0
  94. package/generated/v1/schemas/invitations.resend.request.json +6 -0
  95. package/generated/v1/schemas/invitations.resend.response.json +27 -0
  96. package/generated/v1/schemas/invitations.revoke.request-headers.json +13 -0
  97. package/generated/v1/schemas/invitations.revoke.request.json +12 -0
  98. package/generated/v1/schemas/invitations.revoke.response.json +27 -0
  99. package/generated/v1/schemas/members.list.response.json +53 -0
  100. package/generated/v1/schemas/members.remove.request-headers.json +13 -0
  101. package/generated/v1/schemas/members.remove.request.json +12 -0
  102. package/generated/v1/schemas/members.remove.response.json +27 -0
  103. package/generated/v1/schemas/members.role.request-headers.json +13 -0
  104. package/generated/v1/schemas/members.role.request.json +12 -0
  105. package/generated/v1/schemas/members.role.response.json +27 -0
  106. package/generated/v1/schemas/occurrences.redeliver.response.json +105 -0
  107. package/generated/v1/schemas/projectmembers.add.request-headers.json +13 -0
  108. package/generated/v1/schemas/projectmembers.add.request.json +6 -0
  109. package/generated/v1/schemas/projectmembers.add.response.json +27 -0
  110. package/generated/v1/schemas/projectmembers.remove.request-headers.json +13 -0
  111. package/generated/v1/schemas/projectmembers.remove.request.json +12 -0
  112. package/generated/v1/schemas/projectmembers.remove.response.json +27 -0
  113. package/generated/v1/schemas/schedules.archive.response.json +188 -1
  114. package/generated/v1/schemas/schedules.cancel.response.json +188 -1
  115. package/generated/v1/schemas/schedules.create.request.json +164 -1
  116. package/generated/v1/schemas/schedules.create.response.json +206 -1
  117. package/generated/v1/schemas/schedules.list.response.json +188 -1
  118. package/generated/v1/schemas/schedules.pause.response.json +188 -1
  119. package/generated/v1/schemas/schedules.read.response.json +188 -1
  120. package/generated/v1/schemas/schedules.replace.request.json +164 -1
  121. package/generated/v1/schemas/schedules.replace.response.json +206 -1
  122. package/generated/v1/schemas/schedules.resume.response.json +188 -1
  123. package/generated/v1/snippets/endpoints.create.json +1 -1
  124. package/generated/v1/snippets/endpoints.ensure.json +6 -0
  125. package/generated/v1/snippets/invitations.create.json +6 -0
  126. package/generated/v1/snippets/invitations.list.json +6 -0
  127. package/generated/v1/snippets/invitations.resend.json +6 -0
  128. package/generated/v1/snippets/invitations.revoke.json +6 -0
  129. package/generated/v1/snippets/journey/create-destination.json +1 -1
  130. package/generated/v1/snippets/members.list.json +6 -0
  131. package/generated/v1/snippets/members.remove.json +6 -0
  132. package/generated/v1/snippets/members.role.json +6 -0
  133. package/generated/v1/snippets/projectmembers.add.json +6 -0
  134. package/generated/v1/snippets/projectmembers.remove.json +6 -0
  135. package/package.json +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@ The public contracts for [GreatWait](https://greatwait.dev): the schemas every
4
4
  response is parsed with, the stable refusal catalog, the operation registry, and
5
5
  the generated OpenAPI documents.
6
6
 
7
- > **Invited alpha.** This package publishes on the `alpha` dist-tag and has no
7
+ > **Alpha.** This package publishes on the `alpha` dist-tag and has no
8
8
  > `latest`. Install it explicitly, and pin the exact version in anything you
9
9
  > care about.
10
10
 
@@ -0,0 +1,8 @@
1
+ import type { Attempt, AttemptResponse } from "./scheduling.js";
2
+ /** Render customer-controlled text without terminal escapes, controls or bidi overrides. */
3
+ export declare function sanitizedDiagnosticText(value: string): string;
4
+ export declare function responseBodySentence(state: AttemptResponse["bodyState"], noServerResponse?: boolean): string;
5
+ export declare function requestCaptureSentence(state: Attempt["requestState"], inProgress?: boolean): string;
6
+ export declare function attemptStatusGuidance(status: number | undefined): string | undefined;
7
+ /** A safe text preview, independently of the exact retained/download bytes. */
8
+ export declare function diagnosticBodyText(body: NonNullable<AttemptResponse["body"]>): string | undefined;
@@ -0,0 +1,68 @@
1
+ /** Render customer-controlled text without terminal escapes, controls or bidi overrides. */
2
+ export function sanitizedDiagnosticText(value) {
3
+ return Array.from(value.replace(/\r\n/gu, "\n"), (c) => {
4
+ const n = c.codePointAt(0);
5
+ return c === "\n" ||
6
+ c === "\t" ||
7
+ c === "\u200C" ||
8
+ c === "\u200D" ||
9
+ c === "\uFEFF" ||
10
+ (!/\p{Cc}|\p{Cf}/u.test(c) && n !== 0x7f)
11
+ ? c
12
+ : "�";
13
+ }).join("");
14
+ }
15
+ export function responseBodySentence(state, noServerResponse = false) {
16
+ switch (state) {
17
+ case "empty":
18
+ return "The server answered with an empty body.";
19
+ case "expired":
20
+ return "The response has expired after 7 days.";
21
+ case "not_captured":
22
+ return noServerResponse
23
+ ? "No server response was received for this attempt."
24
+ : "The response body was not captured.";
25
+ case "captured":
26
+ return "What the server answered:";
27
+ }
28
+ }
29
+ export function requestCaptureSentence(state, inProgress = false) {
30
+ return state === "expired"
31
+ ? "The request body has expired. Request evidence is kept for at most 3 days and never beyond payload retention."
32
+ : inProgress
33
+ ? "The request is still in progress; sent-request evidence is not available yet."
34
+ : "The request was not captured.";
35
+ }
36
+ export function attemptStatusGuidance(status) {
37
+ if (status === 401 || status === 403)
38
+ return "Your server rejected the credentials we sent. Check the Authorization header on this endpoint.";
39
+ if (status === 404 || status === 410)
40
+ return "The server could not find this endpoint. Check the URL we sent.";
41
+ if (status === 405)
42
+ return "The server refused this HTTP method. Check the method we sent.";
43
+ if (status === 429)
44
+ return "The server asked us to slow down. Check its Retry-After header.";
45
+ if (status === 408)
46
+ return "The server timed out while receiving the request. Check its response and timeout settings.";
47
+ if (status !== undefined && status >= 500)
48
+ return "The server reported an error. Use its response to diagnose the failure.";
49
+ if (status !== undefined && status >= 300 && status < 400)
50
+ return "The server redirected the request. Call the final HTTPS URL directly; redirects are disabled.";
51
+ if (status !== undefined && status >= 400)
52
+ return "The server refused this request. Check its response against what we sent.";
53
+ return undefined;
54
+ }
55
+ /** A safe text preview, independently of the exact retained/download bytes. */
56
+ export function diagnosticBodyText(body) {
57
+ if (body.encoding === "utf8")
58
+ return body.content;
59
+ const media = (body.contentType.split(";")[0] ?? "").trim().toLowerCase();
60
+ if (!/^(?:text\/[a-z0-9.+-]+|application\/(?:[a-z0-9.+-]+\+)?(?:json|xml)|application\/javascript)$/u.test(media))
61
+ return undefined;
62
+ try {
63
+ return new TextDecoder().decode(Uint8Array.from(atob(body.content), (c) => c.charCodeAt(0)));
64
+ }
65
+ catch {
66
+ return undefined;
67
+ }
68
+ }
@@ -50,8 +50,9 @@ export type Authority = z.infer<typeof authoritySchema>;
50
50
  * client is permitted, and what the granting member's current role allows.
51
51
  * Nothing here can exceed a human's own access.
52
52
  */
53
- export declare const SCOPES: readonly ["credentials:administer", "billing:write", "credentials:read", "credentials:write", "endpoints:read", "endpoints:write", "forecast:read", "grants:read", "grants:write", "occurrences:read", "occurrences:redeliver", "projects:administer", "projects:read", "projects:write", "schedules:read", "schedules:write", "usage:read"];
53
+ export declare const SCOPES: readonly ["members:manage", "credentials:administer", "billing:write", "credentials:read", "credentials:write", "endpoints:read", "endpoints:write", "forecast:read", "grants:read", "grants:write", "occurrences:read", "occurrences:redeliver", "projects:administer", "projects:read", "projects:write", "schedules:read", "schedules:write", "usage:read"];
54
54
  export declare const scopeSchema: import("zod").ZodEnum<{
55
+ "members:manage": "members:manage";
55
56
  "credentials:administer": "credentials:administer";
56
57
  "billing:write": "billing:write";
57
58
  "credentials:read": "credentials:read";
@@ -114,6 +115,7 @@ export declare const principalSchema: import("zod").ZodObject<{
114
115
  project: import("zod").ZodString;
115
116
  }, import("zod/v4/core").$strip>;
116
117
  scopes: import("zod").ZodArray<import("zod").ZodEnum<{
118
+ "members:manage": "members:manage";
117
119
  "credentials:administer": "credentials:administer";
118
120
  "billing:write": "billing:write";
119
121
  "credentials:read": "credentials:read";
@@ -258,6 +260,7 @@ export declare const credentialContextSchema: import("zod").ZodObject<{
258
260
  }>;
259
261
  project: import("zod").ZodString;
260
262
  scopes: import("zod").ZodArray<import("zod").ZodEnum<{
263
+ "members:manage": "members:manage";
261
264
  "credentials:administer": "credentials:administer";
262
265
  "billing:write": "billing:write";
263
266
  "credentials:read": "credentials:read";
package/dist/authority.js CHANGED
@@ -43,6 +43,7 @@ export const authoritySchema = z.object({
43
43
  * Nothing here can exceed a human's own access.
44
44
  */
45
45
  export const SCOPES = [
46
+ "members:manage",
46
47
  /**
47
48
  * Act on a credential somebody else issued.
48
49
  *
package/dist/billing.d.ts CHANGED
@@ -253,16 +253,16 @@ export declare const billingPaymentOperationSchema: import("zod").ZodObject<{
253
253
  }, import("zod/v4/core").$strip>>;
254
254
  id: import("zod").ZodString;
255
255
  kind: import("zod").ZodEnum<{
256
- manual: "manual";
257
256
  automatic: "automatic";
257
+ manual: "manual";
258
258
  }>;
259
259
  paymentUrl: import("zod").ZodOptional<import("zod").ZodString>;
260
260
  reason: import("zod").ZodOptional<import("zod").ZodString>;
261
261
  receiptUrl: import("zod").ZodOptional<import("zod").ZodString>;
262
262
  state: import("zod").ZodEnum<{
263
+ failed: "failed";
263
264
  pending: "pending";
264
265
  paid: "paid";
265
- failed: "failed";
266
266
  "authentication-required": "authentication-required";
267
267
  "action-required": "action-required";
268
268
  canceled: "canceled";
@@ -393,16 +393,16 @@ export declare const billingFundingViewSchema: import("zod").ZodObject<{
393
393
  }, import("zod/v4/core").$strip>>;
394
394
  id: import("zod").ZodString;
395
395
  kind: import("zod").ZodEnum<{
396
- manual: "manual";
397
396
  automatic: "automatic";
397
+ manual: "manual";
398
398
  }>;
399
399
  paymentUrl: import("zod").ZodOptional<import("zod").ZodString>;
400
400
  reason: import("zod").ZodOptional<import("zod").ZodString>;
401
401
  receiptUrl: import("zod").ZodOptional<import("zod").ZodString>;
402
402
  state: import("zod").ZodEnum<{
403
+ failed: "failed";
403
404
  pending: "pending";
404
405
  paid: "paid";
405
- failed: "failed";
406
406
  "authentication-required": "authentication-required";
407
407
  "action-required": "action-required";
408
408
  canceled: "canceled";
@@ -427,7 +427,7 @@ export declare const billingFundingViewSchema: import("zod").ZodObject<{
427
427
  scale: import("zod").ZodLiteral<6>;
428
428
  }, import("zod/v4/core").$strip>;
429
429
  }, import("zod/v4/core").$strict>;
430
- export declare const BILLING_NOTICE_KINDS: readonly ["budget-warning", "budget-exhausted", "low-credit", "automatic-top-up-cap-reached", "funding-blocked", "payment-pending", "payment-succeeded", "payment-failed", "payment-authentication-required", "payment-outcome-unresolved", "service-restored"];
430
+ export declare const BILLING_NOTICE_KINDS: readonly ["budget-warning", "budget-exhausted", "low-credit", "automatic-top-up-cap-reached", "funding-blocked", "payment-pending", "payment-succeeded", "payment-failed", "payment-authentication-required", "payment-outcome-unresolved", "service-restored", "schedule-auto-paused"];
431
431
  type BillingNoticeMoney = z.infer<typeof nonnegativeExactMoneySchema>;
432
432
  export interface BillingNotice {
433
433
  readonly amounts: {
@@ -450,7 +450,8 @@ export interface BillingNotice {
450
450
  readonly operation: string;
451
451
  readonly state: (typeof BILLING_PAYMENT_STATES)[number];
452
452
  } | null;
453
- readonly recoveryPath: "#billing" | "#billing-funding" | "#billing-notification-settings";
453
+ /** A fixed billing anchor or a scoped schedule recovery route. */
454
+ readonly recoveryPath: string;
454
455
  readonly resolvedAt: string | null;
455
456
  readonly scope: {
456
457
  readonly kind: "organization";
@@ -493,11 +494,11 @@ export interface BillingNotificationSettingsUpdateRequest {
493
494
  readonly lowCreditThreshold?: z.infer<typeof exactCentMoneySchema> | null | undefined;
494
495
  readonly noncriticalEmail: boolean;
495
496
  }
496
- export declare const billingNoticeRecoveryPathSchema: import("zod").ZodEnum<{
497
+ export declare const billingNoticeRecoveryPathSchema: import("zod").ZodUnion<readonly [import("zod").ZodEnum<{
497
498
  "#billing": "#billing";
498
499
  "#billing-funding": "#billing-funding";
499
500
  "#billing-notification-settings": "#billing-notification-settings";
500
- }>;
501
+ }>, import("zod").ZodString]>;
501
502
  export declare const billingNoticeSchema: z.ZodType<BillingNotice>;
502
503
  export declare const billingNoticePageSchema: z.ZodType<BillingNoticePage>;
503
504
  export declare const billingNotificationSettingsSchema: z.ZodType<BillingNotificationSettings>;
@@ -1118,16 +1119,16 @@ export declare const billingPaymentHistoryPageSchema: import("zod").ZodObject<{
1118
1119
  }, import("zod/v4/core").$strip>>;
1119
1120
  id: import("zod").ZodString;
1120
1121
  kind: import("zod").ZodEnum<{
1121
- manual: "manual";
1122
1122
  automatic: "automatic";
1123
+ manual: "manual";
1123
1124
  }>;
1124
1125
  paymentUrl: import("zod").ZodOptional<import("zod").ZodString>;
1125
1126
  reason: import("zod").ZodOptional<import("zod").ZodString>;
1126
1127
  receiptUrl: import("zod").ZodOptional<import("zod").ZodString>;
1127
1128
  state: import("zod").ZodEnum<{
1129
+ failed: "failed";
1128
1130
  pending: "pending";
1129
1131
  paid: "paid";
1130
- failed: "failed";
1131
1132
  "authentication-required": "authentication-required";
1132
1133
  "action-required": "action-required";
1133
1134
  canceled: "canceled";
package/dist/billing.js CHANGED
@@ -406,11 +406,14 @@ export const BILLING_NOTICE_KINDS = [
406
406
  "payment-authentication-required",
407
407
  "payment-outcome-unresolved",
408
408
  "service-restored",
409
+ "schedule-auto-paused",
409
410
  ];
410
- export const billingNoticeRecoveryPathSchema = z.enum([
411
- "#billing",
412
- "#billing-funding",
413
- "#billing-notification-settings",
411
+ export const billingNoticeRecoveryPathSchema = z.union([
412
+ z.enum(["#billing", "#billing-funding", "#billing-notification-settings"]),
413
+ z
414
+ .string()
415
+ .max(1024)
416
+ .regex(/^\/o\/[A-Za-z0-9_%.-]+\/p\/proj_[0-9abcdefghjkmnpqrstvwxyz]{26}\/(?:live|test)\/schedules\/sch_[0-9abcdefghjkmnpqrstvwxyz]{26}$/u, "must be a scoped schedule recovery route"),
414
417
  ]);
415
418
  export const billingNoticeSchema = z
416
419
  .object({
@@ -58,6 +58,8 @@ export type DataExportPart = z.infer<typeof dataExportPartSchema>;
58
58
  /** Additive operation declarations, merged into the canonical registry by the API wiring. */
59
59
  export declare const DATA_EXPORT_OPERATIONS: readonly [import("./operations.js").OperationDefinition & {
60
60
  readonly id: "exports.create";
61
+ } & {
62
+ readonly request: import("zod").ZodObject<{}, import("zod/v4/core").$strict>;
61
63
  }, import("./operations.js").OperationDefinition & {
62
64
  readonly id: "exports.read";
63
65
  }, import("./operations.js").OperationDefinition & {
@@ -21,6 +21,31 @@ export interface EncryptedSchedulePayload {
21
21
  readonly keyId: string;
22
22
  readonly nonce: string;
23
23
  }
24
+ /** Encrypted custom HTTP settings, internal only; never a public read shape. */
25
+ export type StoredHttpHeader = {
26
+ readonly name: string;
27
+ readonly secret: false;
28
+ readonly value: string;
29
+ readonly valueBytes: number;
30
+ } | {
31
+ readonly name: string;
32
+ readonly secret: true;
33
+ readonly envelope: EncryptedSchedulePayload;
34
+ readonly valueBytes: number;
35
+ readonly ownerKind: "endpoint" | "schedule";
36
+ readonly ownerId: string;
37
+ } | {
38
+ readonly name: string;
39
+ readonly suppressed: true;
40
+ };
41
+ export interface StoredHttpRequest {
42
+ readonly method: "POST" | "PUT" | "GET";
43
+ readonly bodyMode: "envelope" | "json" | "none";
44
+ readonly headers: readonly StoredHttpHeader[];
45
+ readonly encryptedTemplate?: EncryptedSchedulePayload;
46
+ }
47
+ export declare const HTTP_HEADER_AAD_VERSION: "greatwait.http-header.v1";
48
+ export declare const HTTP_TEMPLATE_AAD_VERSION: "greatwait.http-template.v1";
24
49
  /**
25
50
  * One immutable delivery attempt, minted by the Scheduler Partition from its
26
51
  * verified authority. No member of this tuple comes from callback request
@@ -46,6 +71,7 @@ export interface CallbackAttemptDispatch {
46
71
  /** Monotonic partition fence for duplicate/late dispatch and report RPCs. */
47
72
  readonly dispatchEpoch: number;
48
73
  readonly encryptedPayloadEnvelope: EncryptedSchedulePayload;
74
+ readonly http?: StoredHttpRequest;
49
75
  readonly endpointId: EndpointId;
50
76
  readonly latencyClass: "realtime" | "bulk";
51
77
  /**
@@ -226,41 +252,17 @@ export declare function effectiveCompletionDeadlineMs(requestedMs: number | unde
226
252
  export declare const CALLBACK_ATTEMPT_DIAGNOSTICS: readonly ["completion_timed_out", "delivered", "duplicate_inflight", "endpoint_unavailable", "endpoint_unsafe", "http_refused", "http_retryable", "http_terminal", "identity_conflict", "network_ambiguous", "payload_unavailable", "rate_limited"];
227
253
  export type CallbackAttemptDiagnostic = (typeof CALLBACK_ATTEMPT_DIAGNOSTICS)[number];
228
254
  /**
229
- * Statuses where the receiver is refusing *this delivery, right now* rather
230
- * than objecting to the message it carries.
231
- *
232
- * **The line is whether resending the identical bytes could ever get a
233
- * different answer.** Every callback attempt re-sends the same signed envelope,
234
- * so a receiver that rejects the message itself — malformed, too large, wrong
235
- * media type, gone, refused for legal reasons — will reject it identically for
236
- * as long as the occurrence lives, and retrying is pure cost on the population
237
- * least likely to recover. A receiver that refuses *us* has a cause someone
238
- * fixes: an expired or rotated credential, a WAF rule that started matching, a
239
- * deploy window where the route is briefly absent.
240
- *
241
- * | Status | Why it is here |
242
- * | ------ | -------------- |
243
- * | 401 | credential expired, rotated, or not yet deployed |
244
- * | 402 | receiver's own service suspended, restored on payment |
245
- * | 403 | WAF or bot rule, revoked permission, IP block |
246
- * | 404 | route absent during a deploy or a partial rollout |
247
- * | 405 | method absent during a deploy or a partial rollout |
248
- * | 407 | an egress proxy in front of the receiver wants credentials |
249
- * | 421 | misdirected during a routing or certificate change |
250
- * | 423 | the target resource is temporarily locked |
251
- * | 424 | the receiver's own dependency failed |
252
- * | 425 | the receiver asked us not to risk a replay yet — literally "retry later" |
255
+ * Receiver refusals that retain the ordinary five-failure retry budget.
253
256
  *
254
- * **409 is deliberately not here**, though it is a refusal in the plain
255
- * reading. From a callback receiver a conflict overwhelmingly means "I already
256
- * have this delivery", which the identical retry cannot resolve and which is
257
- * the receiver's idempotency working rather than failing.
257
+ * W9-50 reverses FXO-1596 for 401/403/404/405: credentials, permissions,
258
+ * missing routes and unsupported methods need a customer change, so an
259
+ * automatic retry bills another attempt without fixing them. They now end
260
+ * the occurrence immediately; manual redelivery remains available.
258
261
  *
259
- * **An unrecognised 4xx is not here either.** RFC 7231 says an unknown 4xx must
260
- * be treated as a 400, so the default is terminal and this list is the whole of
261
- * the exception. Adding to it is a product decision, not a lookup.
262
+ * 402, 407, 421, 423, 424 and 425 retain the budget. 408, 429 and 5xx are
263
+ * retryable separately. Other responses outside 2xx are terminal.
262
264
  */
263
- export declare const CALLBACK_REFUSAL_STATUSES: readonly [401, 402, 403, 404, 405, 407, 421, 423, 424, 425];
265
+ export declare const CALLBACK_REFUSAL_STATUSES: readonly [402, 407, 421, 423, 424, 425];
264
266
  /** Whether a receiver refused this delivery in a way that may recover. */
265
267
  export declare function isCallbackRefusalStatus(status: number): boolean;
266
268
  /** Stable outcome of the one network attempt an executor invocation may run. */
@@ -313,18 +315,17 @@ export declare const CALLBACK_RESPONSE_HEADER_MAX_BYTES = 256;
313
315
  /**
314
316
  * How much of a failed response body may be retained, in bytes.
315
317
  *
316
- * Four kibibytes of the *start* of the body, read as a bounded prefix and with
318
+ * Ten kibibytes of the *start* of any media type, read as a bounded prefix and with
317
319
  * the rest of the stream cancelled rather than buffered. It is enough for a
318
320
  * stack trace's first frames or a validation error list, which is what makes a
319
321
  * failing receiver diagnosable without turning this product into a log store.
320
322
  */
321
- export declare const CALLBACK_FAILURE_SNIPPET_MAX_BYTES = 4096;
323
+ export declare const CALLBACK_FAILURE_SNIPPET_MAX_BYTES = 10240;
322
324
  /**
323
325
  * Media types whose body may be retained as a failure snippet.
324
326
  *
325
- * Text and JSON only. A binary body has nothing a person reads in its first
326
- * four kibibytes, and retaining one would mean storing an arbitrary fragment
327
- * of an arbitrary file because a receiver set a header.
327
+ * Legacy text detection, also used as a hint for decoding invalid UTF-8.
328
+ * Full failed-response capture accepts every media type.
328
329
  */
329
330
  export declare const CALLBACK_FAILURE_SNIPPET_CONTENT_TYPES: readonly ["application/json", "application/problem+json", "application/xml", "text/"];
330
331
  /** One retained response header, already bounded and lowercased by name. */
@@ -347,14 +348,16 @@ export interface CallbackFailureSnippet {
347
348
  /**
348
349
  * Bounded evidence about one HTTP response.
349
350
  *
350
- * Deliberately not "the response": there is no body for a success, no header
351
- * outside the allowlist, and no representation at all for a transport failure
352
- * that produced no response.
351
+ * Failed responses retain every header and bounded body before encryption.
352
+ * Success and pending responses keep only legacy diagnostic headers.
353
+ * The sent request is independent of whether a response arrived.
353
354
  */
354
355
  export interface CallbackResponseEvidence {
355
356
  readonly headers: readonly CallbackResponseHeader[];
356
357
  /** Absent for a success, a pending acknowledgement, and a non-text body. */
357
358
  readonly snippet?: CallbackFailureSnippet;
359
+ readonly response?: import("./scheduling.js").AttemptResponse;
360
+ readonly request?: import("./scheduling.js").AttemptRequest;
358
361
  }
359
362
  /**
360
363
  * What one network attempt did, including the answer that is not an outcome.
package/dist/delivery.js CHANGED
@@ -7,6 +7,8 @@
7
7
  * decryption oracle.
8
8
  */
9
9
  export const SCHEDULE_PAYLOAD_AAD_VERSION = "greatwait.schedule-payload.v1";
10
+ export const HTTP_HEADER_AAD_VERSION = "greatwait.http-header.v1";
11
+ export const HTTP_TEMPLATE_AAD_VERSION = "greatwait.http-template.v1";
10
12
  /**
11
13
  * What a receiver says about work it acknowledged and then finished.
12
14
  *
@@ -206,42 +208,18 @@ export const CALLBACK_ATTEMPT_DIAGNOSTICS = [
206
208
  "rate_limited",
207
209
  ];
208
210
  /**
209
- * Statuses where the receiver is refusing *this delivery, right now* rather
210
- * than objecting to the message it carries.
211
+ * Receiver refusals that retain the ordinary five-failure retry budget.
211
212
  *
212
- * **The line is whether resending the identical bytes could ever get a
213
- * different answer.** Every callback attempt re-sends the same signed envelope,
214
- * so a receiver that rejects the message itself — malformed, too large, wrong
215
- * media type, gone, refused for legal reasons — will reject it identically for
216
- * as long as the occurrence lives, and retrying is pure cost on the population
217
- * least likely to recover. A receiver that refuses *us* has a cause someone
218
- * fixes: an expired or rotated credential, a WAF rule that started matching, a
219
- * deploy window where the route is briefly absent.
213
+ * W9-50 reverses FXO-1596 for 401/403/404/405: credentials, permissions,
214
+ * missing routes and unsupported methods need a customer change, so an
215
+ * automatic retry bills another attempt without fixing them. They now end
216
+ * the occurrence immediately; manual redelivery remains available.
220
217
  *
221
- * | Status | Why it is here |
222
- * | ------ | -------------- |
223
- * | 401 | credential expired, rotated, or not yet deployed |
224
- * | 402 | receiver's own service suspended, restored on payment |
225
- * | 403 | WAF or bot rule, revoked permission, IP block |
226
- * | 404 | route absent during a deploy or a partial rollout |
227
- * | 405 | method absent during a deploy or a partial rollout |
228
- * | 407 | an egress proxy in front of the receiver wants credentials |
229
- * | 421 | misdirected during a routing or certificate change |
230
- * | 423 | the target resource is temporarily locked |
231
- * | 424 | the receiver's own dependency failed |
232
- * | 425 | the receiver asked us not to risk a replay yet — literally "retry later" |
233
- *
234
- * **409 is deliberately not here**, though it is a refusal in the plain
235
- * reading. From a callback receiver a conflict overwhelmingly means "I already
236
- * have this delivery", which the identical retry cannot resolve and which is
237
- * the receiver's idempotency working rather than failing.
238
- *
239
- * **An unrecognised 4xx is not here either.** RFC 7231 says an unknown 4xx must
240
- * be treated as a 400, so the default is terminal and this list is the whole of
241
- * the exception. Adding to it is a product decision, not a lookup.
218
+ * 402, 407, 421, 423, 424 and 425 retain the budget. 408, 429 and 5xx are
219
+ * retryable separately. Other responses outside 2xx are terminal.
242
220
  */
243
221
  export const CALLBACK_REFUSAL_STATUSES = [
244
- 401, 402, 403, 404, 405, 407, 421, 423, 424, 425,
222
+ 402, 407, 421, 423, 424, 425,
245
223
  ];
246
224
  /** Whether a receiver refused this delivery in a way that may recover. */
247
225
  export function isCallbackRefusalStatus(status) {
@@ -286,18 +264,17 @@ export const CALLBACK_RESPONSE_HEADER_MAX_BYTES = 256;
286
264
  /**
287
265
  * How much of a failed response body may be retained, in bytes.
288
266
  *
289
- * Four kibibytes of the *start* of the body, read as a bounded prefix and with
267
+ * Ten kibibytes of the *start* of any media type, read as a bounded prefix and with
290
268
  * the rest of the stream cancelled rather than buffered. It is enough for a
291
269
  * stack trace's first frames or a validation error list, which is what makes a
292
270
  * failing receiver diagnosable without turning this product into a log store.
293
271
  */
294
- export const CALLBACK_FAILURE_SNIPPET_MAX_BYTES = 4_096;
272
+ export const CALLBACK_FAILURE_SNIPPET_MAX_BYTES = 10_240;
295
273
  /**
296
274
  * Media types whose body may be retained as a failure snippet.
297
275
  *
298
- * Text and JSON only. A binary body has nothing a person reads in its first
299
- * four kibibytes, and retaining one would mean storing an arbitrary fragment
300
- * of an arbitrary file because a receiver set a header.
276
+ * Legacy text detection, also used as a hint for decoding invalid UTF-8.
277
+ * Full failed-response capture accepts every media type.
301
278
  */
302
279
  export const CALLBACK_FAILURE_SNIPPET_CONTENT_TYPES = [
303
280
  "application/json",
@@ -8,26 +8,26 @@ export declare const effectiveCustomerLimitsSchema: import("zod").ZodObject<{
8
8
  }, import("zod/v4/core").$strict>;
9
9
  provenance: import("zod").ZodObject<{
10
10
  inlinePayloadBytes: import("zod").ZodEnum<{
11
- organization: "organization";
12
11
  default: "default";
12
+ organization: "organization";
13
13
  global: "global";
14
14
  deployment: "deployment";
15
15
  }>;
16
16
  partitionKeyCeiling: import("zod").ZodOptional<import("zod").ZodEnum<{
17
- organization: "organization";
18
17
  default: "default";
18
+ organization: "organization";
19
19
  global: "global";
20
20
  deployment: "deployment";
21
21
  }>>;
22
22
  forecastHorizonSeconds: import("zod").ZodEnum<{
23
- organization: "organization";
24
23
  default: "default";
24
+ organization: "organization";
25
25
  global: "global";
26
26
  deployment: "deployment";
27
27
  }>;
28
28
  usageWindowDays: import("zod").ZodEnum<{
29
- organization: "organization";
30
29
  default: "default";
30
+ organization: "organization";
31
31
  global: "global";
32
32
  deployment: "deployment";
33
33
  }>;