@greatwait/contracts 0.3.0 → 0.3.2

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 (104) hide show
  1. package/dist/attempt-diagnostics.d.ts +1 -1
  2. package/dist/attempt-diagnostics.js +13 -1
  3. package/dist/attempt-search.d.ts +2 -0
  4. package/dist/attempt-search.js +22 -19
  5. package/dist/authority.js +9 -9
  6. package/dist/billing.d.ts +46 -0
  7. package/dist/billing.js +29 -0
  8. package/dist/callback-safety.js +5 -1
  9. package/dist/configuration.d.ts +6 -2
  10. package/dist/configuration.js +93 -52
  11. package/dist/delivery.d.ts +13 -1
  12. package/dist/delivery.js +2 -0
  13. package/dist/effective-limits.d.ts +4 -4
  14. package/dist/endpoints.d.ts +29 -0
  15. package/dist/endpoints.js +57 -26
  16. package/dist/forecast.d.ts +2 -2
  17. package/dist/http-request.d.ts +12 -2
  18. package/dist/http-request.js +56 -24
  19. package/dist/identifiers.js +20 -20
  20. package/dist/index.d.ts +8 -7
  21. package/dist/index.js +8 -7
  22. package/dist/mcp.js +1 -0
  23. package/dist/operational-config.d.ts +174 -22
  24. package/dist/operational-config.js +213 -79
  25. package/dist/operations.d.ts +334 -52
  26. package/dist/operations.js +195 -34
  27. package/dist/project-notifications.d.ts +35 -9
  28. package/dist/project-notifications.js +43 -12
  29. package/dist/protocol.d.ts +28 -0
  30. package/dist/protocol.js +56 -33
  31. package/dist/schedule-selection.js +2 -2
  32. package/dist/scheduling-records.d.ts +106 -16
  33. package/dist/scheduling-records.js +36 -12
  34. package/dist/scheduling.d.ts +200 -43
  35. package/dist/scheduling.js +280 -131
  36. package/dist/service-mode.d.ts +88 -0
  37. package/dist/service-mode.js +130 -0
  38. package/dist/signatures.d.ts +6 -6
  39. package/dist/signatures.js +24 -24
  40. package/dist/stored-http.d.ts +18 -0
  41. package/dist/stored-http.js +106 -0
  42. package/dist/tenancy.d.ts +54 -30
  43. package/dist/tenancy.js +35 -17
  44. package/dist/time.js +7 -7
  45. package/dist/timing.d.ts +39 -0
  46. package/dist/timing.js +51 -0
  47. package/dist/zod-values.d.ts +1 -1
  48. package/dist/zod-values.js +1 -1
  49. package/dist/zod.d.ts +1 -1
  50. package/dist/zod.js +1 -1
  51. package/generated/v1/examples/billing.noticesdismiss.request.json +3 -0
  52. package/generated/v1/examples/billing.noticesdismiss.response.json +6 -0
  53. package/generated/v1/examples/billing.reconcile.response.json +12 -0
  54. package/generated/v1/examples/billing.summary.response.json +12 -0
  55. package/generated/v1/examples/executions.list.response.json +1 -0
  56. package/generated/v1/examples/limits.read.response.json +1 -1
  57. package/generated/v1/examples/projectnotifications.rotateSigningKey.response.json +1 -0
  58. package/generated/v1/examples/projects.list.response.json +0 -6
  59. package/generated/v1/examples/projects.read.response.json +14 -0
  60. package/generated/v1/examples/schedules.list.response.json +1 -3
  61. package/generated/v1/examples/schedules.summary.response.json +174 -0
  62. package/generated/v1/examples/timing.summary.response.json +33 -1
  63. package/generated/v1/manifest.json +79 -2
  64. package/generated/v1/openapi.json +4084 -2023
  65. package/generated/v1/policy-matrix.json +22 -1
  66. package/generated/v1/schemas/attempts.list.response.json +10 -0
  67. package/generated/v1/schemas/attempts.read.response.json +10 -0
  68. package/generated/v1/schemas/attempts.search.response.json +4 -0
  69. package/generated/v1/schemas/billing.notices.query.json +4 -0
  70. package/generated/v1/schemas/billing.noticesdismiss.request.json +12 -0
  71. package/generated/v1/schemas/billing.noticesdismiss.response.json +22 -0
  72. package/generated/v1/schemas/billing.reconcile.response.json +43 -0
  73. package/generated/v1/schemas/billing.summary.response.json +43 -0
  74. package/generated/v1/schemas/endpoints.list.query.json +15 -0
  75. package/generated/v1/schemas/executions.list.response.json +4 -0
  76. package/generated/v1/schemas/occurrences.list.response.json +4 -0
  77. package/generated/v1/schemas/occurrences.read.response.json +4 -0
  78. package/generated/v1/schemas/occurrences.redeliver.response.json +10 -0
  79. package/generated/v1/schemas/projectnotifications.read.response.json +4 -0
  80. package/generated/v1/schemas/projectnotifications.rotateSigningKey.response.json +4 -0
  81. package/generated/v1/schemas/projectnotifications.update.request.json +41 -17
  82. package/generated/v1/schemas/projectnotifications.update.response.json +4 -0
  83. package/generated/v1/schemas/projects.list.response.json +0 -27
  84. package/generated/v1/schemas/projects.read.response-headers.json +11 -0
  85. package/generated/v1/schemas/projects.read.response.json +79 -0
  86. package/generated/v1/schemas/schedules.archive.response.json +8 -0
  87. package/generated/v1/schemas/schedules.cancel.response.json +8 -0
  88. package/generated/v1/schemas/schedules.create.request.json +1 -1
  89. package/generated/v1/schemas/schedules.create.response.json +8 -0
  90. package/generated/v1/schemas/schedules.list.query.json +6 -0
  91. package/generated/v1/schemas/schedules.list.response.json +4 -0
  92. package/generated/v1/schemas/schedules.pause.response.json +8 -0
  93. package/generated/v1/schemas/schedules.read.response.json +8 -0
  94. package/generated/v1/schemas/schedules.replace.request.json +1 -1
  95. package/generated/v1/schemas/schedules.replace.response.json +8 -0
  96. package/generated/v1/schemas/schedules.resume.response.json +8 -0
  97. package/generated/v1/schemas/schedules.summary.query.json +11 -0
  98. package/generated/v1/schemas/schedules.summary.response.json +144 -0
  99. package/generated/v1/schemas/timing.summary.response.json +69 -0
  100. package/generated/v1/snippets/billing.noticesdismiss.json +6 -0
  101. package/generated/v1/snippets/projectnotifications.rotateSigningKey.json +1 -1
  102. package/generated/v1/snippets/projects.read.json +6 -0
  103. package/generated/v1/snippets/schedules.summary.json +6 -0
  104. package/package.json +1 -1
@@ -2,7 +2,7 @@ import type { Attempt, AttemptResponse } from "./scheduling.js";
2
2
  /** Render customer-controlled text without terminal escapes, controls or bidi overrides. */
3
3
  export declare function sanitizedDiagnosticText(value: string): string;
4
4
  export declare function responseBodySentence(state: AttemptResponse["bodyState"], noServerResponse?: boolean): string;
5
- export declare function requestCaptureSentence(state: Attempt["requestState"], inProgress?: boolean): string;
5
+ export declare function requestCaptureSentence(state: Attempt["requestState"], inProgress?: boolean, unavailable?: Attempt["requestUnavailable"]): string;
6
6
  export declare function attemptStatusGuidance(status: number | undefined): string | undefined;
7
7
  /** A safe text preview, independently of the exact retained/download bytes. */
8
8
  export declare function diagnosticBodyText(body: NonNullable<AttemptResponse["body"]>): string | undefined;
@@ -26,7 +26,19 @@ export function responseBodySentence(state, noServerResponse = false) {
26
26
  return "What the server answered:";
27
27
  }
28
28
  }
29
- export function requestCaptureSentence(state, inProgress = false) {
29
+ export function requestCaptureSentence(state, inProgress = false, unavailable) {
30
+ switch (unavailable) {
31
+ case "schedule_changed":
32
+ return "This schedule was edited after this run, so the request it sent can't be shown.";
33
+ case "endpoint_changed":
34
+ return "This run's endpoint was edited after it ran, so the request it sent can't be shown.";
35
+ case "endpoint_deleted":
36
+ return "This run's endpoint has been deleted, so the request it sent can't be shown.";
37
+ case "payload_deleted":
38
+ return "This schedule's payload has been deleted, so the request this run sent can't be shown.";
39
+ case undefined:
40
+ break;
41
+ }
30
42
  return state === "expired"
31
43
  ? "The request body has expired. Request evidence is kept for at most 3 days and never beyond payload retention."
32
44
  : inProgress
@@ -107,6 +107,7 @@ export declare const projectAttemptSearchResultSchema: import("zod").ZodObject<{
107
107
  id: import("zod").ZodString;
108
108
  plannedFor: import("zod").ZodString;
109
109
  schedule: import("zod").ZodString;
110
+ scheduleName: import("zod").ZodOptional<import("zod").ZodString>;
110
111
  sequence: import("zod").ZodNumber;
111
112
  settledAt: import("zod").ZodOptional<import("zod").ZodString>;
112
113
  state: import("zod").ZodEnum<{
@@ -191,6 +192,7 @@ export declare const projectAttemptPageSchema: import("zod").ZodObject<{
191
192
  id: import("zod").ZodString;
192
193
  plannedFor: import("zod").ZodString;
193
194
  schedule: import("zod").ZodString;
195
+ scheduleName: import("zod").ZodOptional<import("zod").ZodString>;
194
196
  sequence: import("zod").ZodNumber;
195
197
  settledAt: import("zod").ZodOptional<import("zod").ZodString>;
196
198
  state: import("zod").ZodEnum<{
@@ -3,9 +3,9 @@ import { pageRequestSchema, pageSchema } from "./protocol.js";
3
3
  import { endpointIdSchema, scheduleIdSchema } from "./identifiers.js";
4
4
  import { externalIdentifierSchema, scheduleTagSchema, scheduleTagsSchema, } from "./host-correlation.js";
5
5
  import { timestampSchema } from "./time.js";
6
- import { attemptSchema, attemptStateSchema, attemptDiagnosticSchema, occurrenceSchema, scheduleNameSchema, } from "./scheduling.js";
6
+ import { attemptSearchSummaryShape, attemptStateSchema, attemptDiagnosticSchema, occurrenceSchema, scheduleNameSchema, } from "./scheduling.js";
7
7
  /** Actual attempt start, never occurrence planned time. Boundaries are [start, end). */
8
- export const projectAttemptSearchRequestSchema = pageRequestSchema
8
+ export const projectAttemptSearchRequestSchema = /* @__PURE__ */ (() => pageRequestSchema
9
9
  .extend({
10
10
  startedFrom: timestampSchema,
11
11
  startedBefore: timestampSchema,
@@ -21,7 +21,7 @@ export const projectAttemptSearchRequestSchema = pageRequestSchema
21
21
  .refine((value) => Date.parse(value.startedFrom) < Date.parse(value.startedBefore), {
22
22
  message: "must be later than startedFrom",
23
23
  path: ["startedBefore"],
24
- });
24
+ }))();
25
25
  export function normalizeAttemptSelection(request) {
26
26
  return Object.fromEntries(Object.entries(request).filter(([key, value]) => key !== "cursor" && key !== "limit" && value !== undefined));
27
27
  }
@@ -68,19 +68,19 @@ export function parseProjectAttemptSearchRequest(query) {
68
68
  };
69
69
  }
70
70
  /** Safe search summary: content and secret-bearing HTTP evidence is detail-only. */
71
- export const projectAttemptSearchResultSchema = z.object({
71
+ export const projectAttemptSearchResultSchema = /* @__PURE__ */ (() => z.object({
72
72
  attempt: z.object({
73
- id: attemptSchema.shape.id,
74
- attemptNumber: attemptSchema.shape.attemptNumber,
75
- occurrence: attemptSchema.shape.occurrence,
76
- startedAt: attemptSchema.shape.startedAt,
77
- state: attemptSchema.shape.state,
78
- classifiedAt: attemptSchema.shape.classifiedAt,
79
- durationMs: attemptSchema.shape.durationMs,
80
- responseStatus: attemptSchema.shape.responseStatus,
81
- diagnostic: attemptSchema.shape.diagnostic,
82
- remediation: attemptSchema.shape.remediation,
83
- trigger: attemptSchema.shape.trigger,
73
+ id: attemptSearchSummaryShape.id,
74
+ attemptNumber: attemptSearchSummaryShape.attemptNumber,
75
+ occurrence: attemptSearchSummaryShape.occurrence,
76
+ startedAt: attemptSearchSummaryShape.startedAt,
77
+ state: attemptSearchSummaryShape.state,
78
+ classifiedAt: attemptSearchSummaryShape.classifiedAt,
79
+ durationMs: attemptSearchSummaryShape.durationMs,
80
+ responseStatus: attemptSearchSummaryShape.responseStatus,
81
+ diagnostic: attemptSearchSummaryShape.diagnostic,
82
+ remediation: attemptSearchSummaryShape.remediation,
83
+ trigger: attemptSearchSummaryShape.trigger,
84
84
  }),
85
85
  occurrence: occurrenceSchema,
86
86
  schedule: z.object({
@@ -90,9 +90,12 @@ export const projectAttemptSearchResultSchema = z.object({
90
90
  external_identifier: externalIdentifierSchema.optional(),
91
91
  tags: scheduleTagsSchema.optional(),
92
92
  }),
93
- });
94
- export const projectAttemptPageSchema = pageSchema(projectAttemptSearchResultSchema).extend({
93
+ }))();
94
+ export const projectAttemptPageSchema = /* @__PURE__ */ (() => pageSchema(projectAttemptSearchResultSchema).extend({
95
95
  freshness: z.object({ kind: z.literal("authoritative") }),
96
96
  /** Normal plan horizons; older live/retained records may still be returned. */
97
- retention: z.object({ from: timestampSchema, detailsFrom: timestampSchema }),
98
- });
97
+ retention: z.object({
98
+ from: timestampSchema,
99
+ detailsFrom: timestampSchema,
100
+ }),
101
+ }))();
package/dist/authority.js CHANGED
@@ -26,13 +26,13 @@ import { environmentIdSchema, organizationIdSchema, projectIdSchema, } from "./i
26
26
  * third if one is ever added.
27
27
  */
28
28
  export const ENVIRONMENT_KINDS_IN_ORDER = ["test", "live"];
29
- export const environmentKindSchema = z.enum(ENVIRONMENT_KINDS_IN_ORDER);
30
- export const authoritySchema = z.object({
29
+ export const environmentKindSchema = /* @__PURE__ */ (() => z.enum(ENVIRONMENT_KINDS_IN_ORDER))();
30
+ export const authoritySchema = /* @__PURE__ */ (() => z.object({
31
31
  environment: environmentIdSchema,
32
32
  environmentKind: environmentKindSchema,
33
33
  organization: organizationIdSchema,
34
34
  project: projectIdSchema,
35
- });
35
+ }))();
36
36
  /**
37
37
  * The initial scope vocabulary. Scopes are `resource:action`, lower case, and
38
38
  * additive — a new scope is a compatible change, removing or narrowing one is
@@ -126,7 +126,7 @@ export const SCOPES = [
126
126
  */
127
127
  "usage:read",
128
128
  ];
129
- export const scopeSchema = z.enum(SCOPES);
129
+ export const scopeSchema = /* @__PURE__ */ (() => z.enum(SCOPES))();
130
130
  /** Read scopes implied by the matching write scope. */
131
131
  const IMPLIED_BY_WRITE = {
132
132
  "credentials:write": "credentials:read",
@@ -170,13 +170,13 @@ export function effectiveScopes(granted) {
170
170
  * gives for one that does not exist.
171
171
  */
172
172
  export const PRINCIPAL_KINDS = ["api-credential", "oauth", "session"];
173
- export const principalKindSchema = z.enum(PRINCIPAL_KINDS);
174
- export const principalSchema = z.object({
173
+ export const principalKindSchema = /* @__PURE__ */ (() => z.enum(PRINCIPAL_KINDS))();
174
+ export const principalSchema = /* @__PURE__ */ (() => z.object({
175
175
  authority: authoritySchema,
176
176
  scopes: z.array(scopeSchema).min(1),
177
177
  /** How the principal was established, for audit and refusal messages. */
178
178
  via: principalKindSchema,
179
- });
179
+ }))();
180
180
  /**
181
181
  * Whether a principal may act on an already-resolved resource.
182
182
  *
@@ -298,10 +298,10 @@ export const SESSION_AUTHORITY_HEADERS = {
298
298
  * know whether a scope is implied can apply the same published expansion the
299
299
  * service does.
300
300
  */
301
- export const credentialContextSchema = z.object({
301
+ export const credentialContextSchema = /* @__PURE__ */ (() => z.object({
302
302
  environmentKind: environmentKindSchema,
303
303
  /** How this credential authenticated. Never `session`: see the operation. */
304
304
  principal: z.enum(["api-credential", "oauth"]),
305
305
  project: projectIdSchema,
306
306
  scopes: z.array(scopeSchema).min(1),
307
- });
307
+ }))();
package/dist/billing.d.ts CHANGED
@@ -502,6 +502,40 @@ export declare const billingNoticeRecoveryPathSchema: import("zod").ZodUnion<rea
502
502
  }>, import("zod").ZodString]>;
503
503
  export declare const billingNoticeSchema: z.ZodType<BillingNotice>;
504
504
  export declare const billingNoticePageSchema: z.ZodType<BillingNoticePage>;
505
+ /**
506
+ * A billing-notice listing (W9-79): the page, and optionally one state. With
507
+ * `state=active` the page holds only notices still open, so a reader counting
508
+ * them is not cut short by a run of resolved ones newer than they are.
509
+ */
510
+ export declare const billingNoticeListRequestSchema: import("zod").ZodObject<{
511
+ cursor: import("zod").ZodOptional<import("zod").ZodString>;
512
+ limit: import("zod").ZodDefault<import("zod").ZodNumber>;
513
+ state: import("zod").ZodOptional<import("zod").ZodEnum<{
514
+ active: "active";
515
+ resolved: "resolved";
516
+ }>>;
517
+ }, import("zod/v4/core").$strip>;
518
+ export type BillingNoticeListRequest = z.infer<typeof billingNoticeListRequestSchema>;
519
+ /** The notice kinds a delivery failure writes (W9-54) and dismiss resolves. */
520
+ export declare const DELIVERY_FAILURE_NOTICE_KINDS: readonly ["delivery-failed", "schedule-auto-paused"];
521
+ /**
522
+ * Dismiss this project's delivery-failure notices (W9-79): every active one
523
+ * in the principal's project and environment that occurred at or before
524
+ * `through`, for every member at once. `through` is the newest notice the
525
+ * caller saw, so a failure that arrives after it stays.
526
+ */
527
+ export interface BillingNoticeDismissRequest {
528
+ readonly through: string;
529
+ }
530
+ export declare const billingNoticeDismissRequestSchema: z.ZodType<BillingNoticeDismissRequest>;
531
+ export interface BillingNoticeDismissResult {
532
+ /** How many notices this request resolved; 0 when none were still open. */
533
+ readonly dismissed: number;
534
+ readonly freshness: {
535
+ readonly kind: "authoritative";
536
+ };
537
+ }
538
+ export declare const billingNoticeDismissResultSchema: z.ZodType<BillingNoticeDismissResult>;
505
539
  export declare const billingNotificationSettingsSchema: z.ZodType<BillingNotificationSettings>;
506
540
  export declare const billingNotificationSettingsUpdateRequestSchema: z.ZodType<BillingNotificationSettingsUpdateRequest>;
507
541
  export declare const billingRefundRequestCreateSchema: import("zod").ZodObject<{
@@ -665,6 +699,18 @@ export declare const billingSummarySchema: import("zod").ZodObject<{
665
699
  enforced: "enforced";
666
700
  }>;
667
701
  }, import("zod/v4/core").$strip>;
702
+ attemptPrice: import("zod").ZodOptional<import("zod").ZodObject<{
703
+ bulk: import("zod").ZodObject<{
704
+ currency: import("zod").ZodLiteral<"USD">;
705
+ microdollars: import("zod").ZodString;
706
+ scale: import("zod").ZodLiteral<6>;
707
+ }, import("zod/v4/core").$strip>;
708
+ realtime: import("zod").ZodObject<{
709
+ currency: import("zod").ZodLiteral<"USD">;
710
+ microdollars: import("zod").ZodString;
711
+ scale: import("zod").ZodLiteral<6>;
712
+ }, import("zod/v4/core").$strip>;
713
+ }, import("zod/v4/core").$strip>>;
668
714
  blockingReasons: import("zod").ZodArray<import("zod").ZodEnum<{
669
715
  "billing-state-missing": "billing-state-missing";
670
716
  "billing-account-closed": "billing-account-closed";
package/dist/billing.js CHANGED
@@ -485,6 +485,26 @@ export const billingNoticeSchema = z
485
485
  export const billingNoticePageSchema = pageSchema(billingNoticeSchema).extend({
486
486
  freshness: z.object({ kind: z.literal("authoritative") }),
487
487
  });
488
+ /**
489
+ * A billing-notice listing (W9-79): the page, and optionally one state. With
490
+ * `state=active` the page holds only notices still open, so a reader counting
491
+ * them is not cut short by a run of resolved ones newer than they are.
492
+ */
493
+ export const billingNoticeListRequestSchema = pageRequestSchema.extend({
494
+ state: z.enum(["active", "resolved"]).optional(),
495
+ });
496
+ /** The notice kinds a delivery failure writes (W9-54) and dismiss resolves. */
497
+ export const DELIVERY_FAILURE_NOTICE_KINDS = [
498
+ "delivery-failed",
499
+ "schedule-auto-paused",
500
+ ];
501
+ export const billingNoticeDismissRequestSchema = z.object({ through: timestampSchema }).strict();
502
+ export const billingNoticeDismissResultSchema = z
503
+ .object({
504
+ dismissed: z.number().int().nonnegative(),
505
+ freshness: z.object({ kind: z.literal("authoritative") }).strict(),
506
+ })
507
+ .strict();
488
508
  export const billingNotificationSettingsSchema = z
489
509
  .object({
490
510
  criticalEmail: z.literal(true),
@@ -616,6 +636,15 @@ export const billingSummarySchema = z
616
636
  boundary: timestampSchema,
617
637
  mode: z.enum(BILLING_ACTIVATION_MODES),
618
638
  }),
639
+ attemptPrice: z
640
+ .object({
641
+ bulk: nonnegativeExactMoneySchema,
642
+ realtime: nonnegativeExactMoneySchema,
643
+ })
644
+ .meta({
645
+ description: "What one billable delivery attempt costs under priceVersion, by latency class: the same tariff the usage meter charges. Retries and failed attempts that reach the receiver are billable; attempts answered with 429 and attempts this service could not start are not.",
646
+ })
647
+ .optional(),
619
648
  blockingReasons: z.array(z.enum(BILLING_BLOCK_REASONS)),
620
649
  budgetPolicy: billingBudgetPolicySchema,
621
650
  closedAt: timestampSchema.optional(),
@@ -146,8 +146,12 @@ const FORBIDDEN_NAME_SUFFIXES = [
146
146
  * **The apex joined it at W9-05**, when the marketing site started serving
147
147
  * `greatwait.dev` itself rather than only forwarding it. It is an address this
148
148
  * product answers on as itself, so it is refused on the same argument.
149
+ *
150
+ * **W13-03 nests the stage** (`api.staging.greatwait.dev`), so a runtime label
151
+ * may carry one further label before the zone. The sink keeps its absence:
152
+ * `sink.staging.greatwait.dev` begins with no runtime label and is accepted.
149
153
  */
150
- const GREATWAIT_RUNTIME_NAME = /^(?:greatwait-(?:api|app|docs|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?\.flowxo\.com|(?:api|app|docs|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?\.greatwait\.dev|greatwait\.dev)$/u;
154
+ const GREATWAIT_RUNTIME_NAME = /^(?:greatwait-(?:api|app|docs|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?\.flowxo\.com|(?:api|app|docs|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?(?:\.[a-z0-9-]+)?\.greatwait\.dev|greatwait\.dev)$/u;
151
155
  const GREATWAIT_PROVIDER_NAME = /^greatwait-(?:api|app|docs|marketing|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?(?:\..+)?\.(?:workers|pages)\.dev$/u;
152
156
  const GREATWAIT_WORKER_NAME = /^greatwait-(?:api|app|docs|marketing|scheduler|contract-mock|postgres-runtime)(?:-[a-z0-9-]+)?$/u;
153
157
  /** Evaluate the URL-only half of the callback destination policy. */
@@ -11,8 +11,8 @@ export declare const CONFIGURATION_DEFAULTS: Readonly<{
11
11
  attemptDetailRetentionSeconds: 604800;
12
12
  forecastHorizonSeconds: number;
13
13
  historyRetentionSeconds: 1209600;
14
- inlinePayloadBytes: 65536;
15
- payloadRetentionSeconds: 259200;
14
+ inlinePayloadBytes: 8192;
15
+ payloadRetentionSeconds: 1209600;
16
16
  usageWindowDays: 366;
17
17
  }>;
18
18
  export type DeploymentContext = "local" | "staging" | "production";
@@ -51,6 +51,10 @@ export interface ConfigurationSetting {
51
51
  readonly exhaustion: string;
52
52
  readonly visibility: "customer";
53
53
  }
54
+ /** Bounds and edit authority shared by validation and the descriptive catalog. */
55
+ export type ConfigurationRule = Pick<ConfigurationSetting, "key" | "unit" | "minimum" | "maximum" | "layers">;
56
+ export declare const CONFIGURATION_RULES: readonly ConfigurationRule[];
57
+ /** Descriptive metadata is only initialized by catalog consumers. */
54
58
  export declare const CONFIGURATION_CATALOG: readonly ConfigurationSetting[];
55
59
  export declare function validateConfigurationValues(value: unknown, scope: ConfigurationScope): ConfigurationValues;
56
60
  export interface EffectiveConfiguration {
@@ -18,13 +18,16 @@ export const CONFIGURATION_DEFAULTS = Object.freeze({
18
18
  attemptDetailRetentionSeconds: 604_800,
19
19
  forecastHorizonSeconds: MAX_FORECAST_HORIZON_SECONDS,
20
20
  historyRetentionSeconds: 1_209_600,
21
- inlinePayloadBytes: MAX_INLINE_PAYLOAD_BYTES,
22
- payloadRetentionSeconds: 259_200,
21
+ inlinePayloadBytes: 8_192,
22
+ // 14 days, with attempt history (W9-91, operator decision 2026-10-26): a
23
+ // successful run's sent request is rebuilt from the payload, and
24
+ // redelivery needs it, for as long as the run is in history.
25
+ payloadRetentionSeconds: 1_209_600,
23
26
  usageWindowDays: MAX_USAGE_WINDOW_DAYS,
24
27
  });
25
28
  const allowanceLayers = ["default", "global", "organization"];
26
29
  const deploymentLayers = ["default", "deployment"];
27
- export const CONFIGURATION_CATALOG = Object.freeze([
30
+ export const CONFIGURATION_RULES = Object.freeze([
28
31
  ...[
29
32
  "bulkMaxTargets",
30
33
  "bulkExecutionLifetimeSeconds",
@@ -37,72 +40,38 @@ export const CONFIGURATION_CATALOG = Object.freeze([
37
40
  "bulkCarrierBatchSize",
38
41
  ].map((key) => ({
39
42
  key,
40
- type: "integer",
41
43
  unit: key.endsWith("Seconds") ? "seconds" : "count",
42
- default: CONFIGURATION_DEFAULTS[key],
43
44
  minimum: 1,
44
45
  maximum: BULK_CONFIGURATION_MAXIMA[key],
45
46
  layers: allowanceLayers,
46
- change: "live",
47
- visibility: "customer",
48
- rationale: "Owner-approved bounded bulk preparation and execution. Backlog limits do not increase in-flight work or ordinary delivery quotas; result retention is additionally capped by effective history retention.",
49
- enforcement: ["bulk-operations"],
50
- exhaustion: "Oversized selections refuse; deadlines expire remaining work; durable checkpoints preserve completed effects.",
51
47
  })),
52
48
  {
53
49
  key: "inlinePayloadBytes",
54
- type: "integer",
55
50
  unit: "bytes",
56
- default: CONFIGURATION_DEFAULTS.inlinePayloadBytes,
57
51
  minimum: 0,
58
52
  maximum: MAX_INLINE_PAYLOAD_BYTES,
59
53
  layers: allowanceLayers,
60
- change: "live",
61
- rationale: "The operator removed the lower storage allowance. Default is the existing public payload envelope; a deliberate override may narrow it. Unbounded bodies would exceed the existing SQL and receiver representations.",
62
- enforcement: ["authority-service", "schedule-draft"],
63
- exhaustion: "Local validation and authoritative plan-limit-reached",
64
- visibility: "customer",
65
54
  },
66
55
  {
67
56
  key: "partitionKeyCeiling",
68
- type: "integer",
69
57
  unit: "count",
70
58
  minimum: 1,
71
59
  maximum: MAX_PARTITION_KEY_CEILING,
72
60
  layers: allowanceLayers,
73
- change: "live",
74
- rationale: "No inherited count cap. A deliberate override uses indexed successor seeks bounded to ceiling plus one; its supported bound preserves the existing transaction work envelope.",
75
- enforcement: ["authority-service", "postgres-repository"],
76
- exhaustion: "New keys refused; existing keys and committed schedules preserved",
77
- visibility: "customer",
78
61
  },
79
62
  {
80
63
  key: "forecastHorizonSeconds",
81
- type: "integer",
82
64
  unit: "seconds",
83
- default: CONFIGURATION_DEFAULTS.forecastHorizonSeconds,
84
65
  minimum: 60,
85
66
  maximum: MAX_FORECAST_HORIZON_SECONDS,
86
67
  layers: allowanceLayers,
87
- change: "live",
88
- rationale: "The operator removed the six-hour allowance. Default is the existing public forecast horizon; explicit work exhaustion cannot masquerade as complete coverage.",
89
- enforcement: ["authority-reads"],
90
- exhaustion: "Window clipped; exhausted work returns explicit incomplete refusal",
91
- visibility: "customer",
92
68
  },
93
69
  {
94
70
  key: "usageWindowDays",
95
- type: "integer",
96
71
  unit: "days",
97
- default: CONFIGURATION_DEFAULTS.usageWindowDays,
98
72
  minimum: 1,
99
73
  maximum: MAX_USAGE_WINDOW_DAYS,
100
74
  layers: allowanceLayers,
101
- change: "live",
102
- rationale: "The operator removed the 31-day allowance. Default is the existing public usage envelope; it does not extend retention or restore purged data.",
103
- enforcement: ["authority-reads"],
104
- exhaustion: "Read window constrained to effective policy",
105
- visibility: "customer",
106
75
  },
107
76
  ...[
108
77
  "attemptDetailRetentionSeconds",
@@ -110,32 +79,104 @@ export const CONFIGURATION_CATALOG = Object.freeze([
110
79
  "payloadRetentionSeconds",
111
80
  ].map((key) => ({
112
81
  key,
113
- type: "integer",
114
82
  unit: "seconds",
115
- default: CONFIGURATION_DEFAULTS[key],
116
83
  minimum: 0,
117
84
  maximum: 9_007_199_254_740,
118
85
  layers: deploymentLayers,
119
- change: "deployment",
120
- rationale: "Accepted retention policy, separately governed. Stored schedule durations preserve committed policy; increases cannot restore purged data.",
121
- enforcement: ["authority-service", "authority-reads", "retention"],
122
- exhaustion: "Read cutoff and bounded purge; no organization override",
123
- visibility: "customer",
124
86
  })),
125
87
  {
126
88
  key: "pageLimit",
127
- type: "integer",
128
89
  unit: "count",
129
90
  minimum: PUBLIC_PAGE_SIZE.min,
130
91
  maximum: PUBLIC_PAGE_SIZE.max,
131
92
  layers: deploymentLayers,
132
- change: "deployment",
133
- rationale: "Public page protocol maximum; continuation preserves completeness.",
134
- enforcement: ["authority-reads"],
135
- exhaustion: "Bounded page with continuation",
136
- visibility: "customer",
137
93
  },
138
94
  ]);
95
+ /** Descriptive metadata is only initialized by catalog consumers. */
96
+ export const CONFIGURATION_CATALOG =
97
+ /* @__PURE__ */ (() => {
98
+ const metadata = [
99
+ ...[
100
+ "bulkMaxTargets",
101
+ "bulkExecutionLifetimeSeconds",
102
+ "bulkPreviewLifetimeSeconds",
103
+ "bulkResultRetentionSeconds",
104
+ "bulkBatchSize",
105
+ "bulkWorkerConcurrency",
106
+ "bulkActiveJobLimit",
107
+ "bulkWorkBudgetSeconds",
108
+ "bulkCarrierBatchSize",
109
+ ].map((key) => ({
110
+ key,
111
+ change: "live",
112
+ visibility: "customer",
113
+ rationale: "Owner-approved bounded bulk preparation and execution. Backlog limits do not increase in-flight work or ordinary delivery quotas; result retention is additionally capped by effective history retention.",
114
+ enforcement: ["bulk-operations"],
115
+ exhaustion: "Oversized selections refuse; deadlines expire remaining work; durable checkpoints preserve completed effects.",
116
+ })),
117
+ {
118
+ key: "inlinePayloadBytes",
119
+ change: "live",
120
+ rationale: "The default is 8 KiB for ordinary callbacks. An audited organization override may raise it up to the 64 KiB protocol maximum when a customer needs a larger payload. Unbounded bodies would exceed the existing SQL and receiver representations.",
121
+ enforcement: ["authority-service", "schedule-draft"],
122
+ exhaustion: "Local validation and authoritative plan-limit-reached",
123
+ visibility: "customer",
124
+ },
125
+ {
126
+ key: "partitionKeyCeiling",
127
+ change: "live",
128
+ rationale: "No inherited count cap. A deliberate override uses indexed successor seeks bounded to ceiling plus one; its supported bound preserves the existing transaction work envelope.",
129
+ enforcement: ["authority-service", "postgres-repository"],
130
+ exhaustion: "New keys refused; existing keys and committed schedules preserved",
131
+ visibility: "customer",
132
+ },
133
+ {
134
+ key: "forecastHorizonSeconds",
135
+ change: "live",
136
+ rationale: "The operator removed the six-hour allowance. Default is the existing public forecast horizon; explicit work exhaustion cannot masquerade as complete coverage.",
137
+ enforcement: ["authority-reads"],
138
+ exhaustion: "Window clipped; exhausted work returns explicit incomplete refusal",
139
+ visibility: "customer",
140
+ },
141
+ {
142
+ key: "usageWindowDays",
143
+ change: "live",
144
+ rationale: "The operator removed the 31-day allowance. Default is the existing public usage envelope; it does not extend retention or restore purged data.",
145
+ enforcement: ["authority-reads"],
146
+ exhaustion: "Read window constrained to effective policy",
147
+ visibility: "customer",
148
+ },
149
+ ...[
150
+ "attemptDetailRetentionSeconds",
151
+ "historyRetentionSeconds",
152
+ "payloadRetentionSeconds",
153
+ ].map((key) => ({
154
+ key,
155
+ change: "deployment",
156
+ rationale: "Accepted retention policy, separately governed. Stored schedule durations preserve committed policy; increases cannot restore purged data.",
157
+ enforcement: ["authority-service", "authority-reads", "retention"],
158
+ exhaustion: "Read cutoff and bounded purge; no organization override",
159
+ visibility: "customer",
160
+ })),
161
+ {
162
+ key: "pageLimit",
163
+ change: "deployment",
164
+ rationale: "Public page protocol maximum; continuation preserves completeness.",
165
+ enforcement: ["authority-reads"],
166
+ exhaustion: "Bounded page with continuation",
167
+ visibility: "customer",
168
+ },
169
+ ];
170
+ const defaults = CONFIGURATION_DEFAULTS;
171
+ return Object.freeze(metadata.map((entry) => ({
172
+ ...CONFIGURATION_RULES.find((rule) => rule.key === entry.key),
173
+ type: "integer",
174
+ ...(defaults[entry.key] === undefined
175
+ ? {}
176
+ : { default: defaults[entry.key] }),
177
+ ...entry,
178
+ })));
179
+ })();
139
180
  export function validateConfigurationValues(value, scope) {
140
181
  if (value === null || typeof value !== "object" || Array.isArray(value))
141
182
  throw new TypeError("configuration values must be an object");
@@ -143,7 +184,7 @@ export function validateConfigurationValues(value, scope) {
143
184
  throw new TypeError("unsupported configuration scope");
144
185
  const parsed = {};
145
186
  for (const [key, candidate] of Object.entries(value)) {
146
- const definition = CONFIGURATION_CATALOG.find((entry) => entry.key === key);
187
+ const definition = CONFIGURATION_RULES.find((entry) => entry.key === key);
147
188
  if (definition === undefined || !definition.layers.includes(scope))
148
189
  throw new TypeError(`configuration setting ${key} does not support ${scope} edits`);
149
190
  if (typeof candidate !== "number" ||
@@ -170,7 +211,7 @@ export function resolveEffectiveConfiguration(input) {
170
211
  };
171
212
  if (input.baseline !== undefined) {
172
213
  for (const [key, candidate] of Object.entries(input.baseline)) {
173
- const setting = CONFIGURATION_CATALOG.find((entry) => entry.key === key);
214
+ const setting = CONFIGURATION_RULES.find((entry) => entry.key === key);
174
215
  if (setting === undefined ||
175
216
  typeof candidate !== "number" ||
176
217
  !Number.isSafeInteger(candidate) ||
@@ -10,17 +10,28 @@ import type { CallbackTrigger as AttemptTrigger } from "./signatures.js";
10
10
  * decryption oracle.
11
11
  */
12
12
  export declare const SCHEDULE_PAYLOAD_AAD_VERSION: "greatwait.schedule-payload.v1";
13
+ export declare const SCHEDULE_PAYLOAD_AAD_VERSION_V2: "greatwait.schedule-payload.v2";
13
14
  /**
14
15
  * The encrypted customer data carried from its authoritative partition to the
15
16
  * network boundary. This is an internal Durable Object RPC shape, not a public
16
17
  * schema. Its application-encryption key is deliberately distinct from the key
17
18
  * which wraps endpoint signing secrets.
18
19
  */
19
- export interface EncryptedSchedulePayload {
20
+ export interface LegacyEncryptedSchedulePayload {
20
21
  readonly ciphertext: string;
21
22
  readonly keyId: string;
22
23
  readonly nonce: string;
24
+ readonly version?: never;
23
25
  }
26
+ export interface EncodedSchedulePayload {
27
+ readonly ciphertext: string;
28
+ readonly keyId: string;
29
+ readonly nonce: string;
30
+ readonly version: 2;
31
+ readonly codec: "identity" | "gzip";
32
+ readonly originalBytes: number;
33
+ }
34
+ export type EncryptedSchedulePayload = LegacyEncryptedSchedulePayload | EncodedSchedulePayload;
24
35
  /** Encrypted custom HTTP settings, internal only; never a public read shape. */
25
36
  export type StoredHttpHeader = {
26
37
  readonly name: string;
@@ -45,6 +56,7 @@ export interface StoredHttpRequest {
45
56
  readonly encryptedTemplate?: EncryptedSchedulePayload;
46
57
  }
47
58
  export declare const HTTP_HEADER_AAD_VERSION: "greatwait.http-header.v1";
59
+ export { mergeStoredHttpHeaders, validScheduleHttp, validStoredHttpHeaders, } from "./stored-http.js";
48
60
  export declare const HTTP_TEMPLATE_AAD_VERSION: "greatwait.http-template.v1";
49
61
  /**
50
62
  * One immutable delivery attempt, minted by the Scheduler Partition from its
package/dist/delivery.js CHANGED
@@ -7,7 +7,9 @@
7
7
  * decryption oracle.
8
8
  */
9
9
  export const SCHEDULE_PAYLOAD_AAD_VERSION = "greatwait.schedule-payload.v1";
10
+ export const SCHEDULE_PAYLOAD_AAD_VERSION_V2 = "greatwait.schedule-payload.v2";
10
11
  export const HTTP_HEADER_AAD_VERSION = "greatwait.http-header.v1";
12
+ export { mergeStoredHttpHeaders, validScheduleHttp, validStoredHttpHeaders, } from "./stored-http.js";
11
13
  export const HTTP_TEMPLATE_AAD_VERSION = "greatwait.http-template.v1";
12
14
  /**
13
15
  * What a receiver says about work it acknowledged and then finished.
@@ -10,26 +10,26 @@ export declare const effectiveCustomerLimitsSchema: import("zod").ZodObject<{
10
10
  inlinePayloadBytes: import("zod").ZodEnum<{
11
11
  organization: "organization";
12
12
  default: "default";
13
- global: "global";
14
13
  deployment: "deployment";
14
+ global: "global";
15
15
  }>;
16
16
  partitionKeyCeiling: import("zod").ZodOptional<import("zod").ZodEnum<{
17
17
  organization: "organization";
18
18
  default: "default";
19
- global: "global";
20
19
  deployment: "deployment";
20
+ global: "global";
21
21
  }>>;
22
22
  forecastHorizonSeconds: import("zod").ZodEnum<{
23
23
  organization: "organization";
24
24
  default: "default";
25
- global: "global";
26
25
  deployment: "deployment";
26
+ global: "global";
27
27
  }>;
28
28
  usageWindowDays: import("zod").ZodEnum<{
29
29
  organization: "organization";
30
30
  default: "default";
31
- global: "global";
32
31
  deployment: "deployment";
32
+ global: "global";
33
33
  }>;
34
34
  }, import("zod/v4/core").$strict>;
35
35
  revision: import("zod").ZodObject<{