@greatwait/contracts 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/authority.d.ts +217 -0
- package/dist/authority.js +261 -0
- package/dist/callback-ownership.d.ts +58 -0
- package/dist/callback-ownership.js +71 -0
- package/dist/callback-safety.d.ts +38 -0
- package/dist/callback-safety.js +403 -0
- package/dist/compatibility.d.ts +82 -0
- package/dist/compatibility.js +115 -0
- package/dist/delivery.d.ts +401 -0
- package/dist/delivery.js +311 -0
- package/dist/endpoints.d.ts +305 -0
- package/dist/endpoints.js +179 -0
- package/dist/events.d.ts +62 -0
- package/dist/events.js +38 -0
- package/dist/first-value-journey.d.ts +305 -0
- package/dist/first-value-journey.js +466 -0
- package/dist/forecast.d.ts +443 -0
- package/dist/forecast.js +729 -0
- package/dist/identifiers.d.ts +109 -0
- package/dist/identifiers.js +131 -0
- package/dist/identity.d.ts +196 -0
- package/dist/identity.js +182 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mcp.d.ts +51 -0
- package/dist/mcp.js +56 -0
- package/dist/oauth.d.ts +796 -0
- package/dist/oauth.js +708 -0
- package/dist/operations.d.ts +3985 -0
- package/dist/operations.js +1837 -0
- package/dist/partition.d.ts +771 -0
- package/dist/partition.js +206 -0
- package/dist/policy.d.ts +93 -0
- package/dist/policy.js +180 -0
- package/dist/problems.d.ts +158 -0
- package/dist/problems.js +104 -0
- package/dist/protocol.d.ts +308 -0
- package/dist/protocol.js +515 -0
- package/dist/scheduling-records.d.ts +395 -0
- package/dist/scheduling-records.js +284 -0
- package/dist/scheduling.d.ts +1098 -0
- package/dist/scheduling.js +1116 -0
- package/dist/secrets.d.ts +383 -0
- package/dist/secrets.js +272 -0
- package/dist/signatures.d.ts +704 -0
- package/dist/signatures.js +867 -0
- package/dist/tenancy.d.ts +178 -0
- package/dist/tenancy.js +145 -0
- package/dist/test-sink.d.ts +986 -0
- package/dist/test-sink.js +755 -0
- package/dist/time.d.ts +45 -0
- package/dist/time.js +128 -0
- package/dist/usage.d.ts +121 -0
- package/dist/usage.js +200 -0
- package/dist/webhooks.d.ts +116 -0
- package/dist/webhooks.js +161 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.js +59 -0
- package/generated/v1/callback-delivery-signature.json +467 -0
- package/generated/v1/callback-endpoint-verification.json +59 -0
- package/generated/v1/callback-receiver.json +241 -0
- package/generated/v1/examples/attempts.list.response.json +24 -0
- package/generated/v1/examples/attempts.read.response.json +20 -0
- package/generated/v1/examples/credentials.create.request.json +5 -0
- package/generated/v1/examples/credentials.create.response.json +10 -0
- package/generated/v1/examples/credentials.list.response.json +17 -0
- package/generated/v1/examples/credentials.revoke.response.json +11 -0
- package/generated/v1/examples/credentials.rotate.request.json +3 -0
- package/generated/v1/examples/credentials.rotate.response.json +22 -0
- package/generated/v1/examples/endpoints.create.request.json +3 -0
- package/generated/v1/examples/endpoints.create.response.json +16 -0
- package/generated/v1/examples/endpoints.disable.response.json +15 -0
- package/generated/v1/examples/endpoints.list.response.json +21 -0
- package/generated/v1/examples/endpoints.read.response.json +14 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.request.json +3 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.response.json +23 -0
- package/generated/v1/examples/endpoints.update.request.json +3 -0
- package/generated/v1/examples/endpoints.update.response.json +13 -0
- package/generated/v1/examples/endpoints.verify.response.json +15 -0
- package/generated/v1/examples/forecast.read.response.json +28 -0
- package/generated/v1/examples/forecast.windows.response.json +21 -0
- package/generated/v1/examples/grants.list.response.json +17 -0
- package/generated/v1/examples/grants.revoke.response.json +16 -0
- package/generated/v1/examples/meta.scaffold.response.json +5 -0
- package/generated/v1/examples/meta.version.response.json +5 -0
- package/generated/v1/examples/occurrences.list.response.json +17 -0
- package/generated/v1/examples/occurrences.read.response.json +15 -0
- package/generated/v1/examples/occurrences.redeliver.response.json +16 -0
- package/generated/v1/examples/projects.create.request.json +3 -0
- package/generated/v1/examples/projects.create.response.json +5 -0
- package/generated/v1/examples/projects.list.response.json +9 -0
- package/generated/v1/examples/schedules.archive.response.json +25 -0
- package/generated/v1/examples/schedules.cancel.response.json +24 -0
- package/generated/v1/examples/schedules.create.request.json +9 -0
- package/generated/v1/examples/schedules.create.response.json +25 -0
- package/generated/v1/examples/schedules.list.response.json +23 -0
- package/generated/v1/examples/schedules.pause.response.json +23 -0
- package/generated/v1/examples/schedules.read.response.json +25 -0
- package/generated/v1/examples/schedules.replace.request.json +8 -0
- package/generated/v1/examples/schedules.replace.response.json +25 -0
- package/generated/v1/examples/schedules.resume.response.json +23 -0
- package/generated/v1/examples/sinkdeliveries.list.response.json +19 -0
- package/generated/v1/examples/sinkdeliveries.read.response.json +16 -0
- package/generated/v1/examples/testsinks.configure.request.json +3 -0
- package/generated/v1/examples/testsinks.configure.response.json +13 -0
- package/generated/v1/examples/testsinks.create.request.json +8 -0
- package/generated/v1/examples/testsinks.create.response.json +13 -0
- package/generated/v1/examples/testsinks.delete.response.json +13 -0
- package/generated/v1/examples/testsinks.list.response.json +20 -0
- package/generated/v1/examples/testsinks.read.response.json +14 -0
- package/generated/v1/examples/usage.read.response.json +20 -0
- package/generated/v1/first-value-journey.json +436 -0
- package/generated/v1/manifest.json +1037 -0
- package/generated/v1/openapi.json +23665 -0
- package/generated/v1/policy-matrix.json +305 -0
- package/generated/v1/schemas/attempts.list.query.json +16 -0
- package/generated/v1/schemas/attempts.list.response.json +175 -0
- package/generated/v1/schemas/attempts.read.response.json +168 -0
- package/generated/v1/schemas/credentials.create.request.json +39 -0
- package/generated/v1/schemas/credentials.create.response.json +88 -0
- package/generated/v1/schemas/credentials.list.query.json +16 -0
- package/generated/v1/schemas/credentials.list.response.json +124 -0
- package/generated/v1/schemas/credentials.revoke.response.json +84 -0
- package/generated/v1/schemas/credentials.rotate.request.json +11 -0
- package/generated/v1/schemas/credentials.rotate.response.json +171 -0
- package/generated/v1/schemas/endpoints.create.request.json +12 -0
- package/generated/v1/schemas/endpoints.create.response.json +115 -0
- package/generated/v1/schemas/endpoints.disable.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.disable.response.json +100 -0
- package/generated/v1/schemas/endpoints.list.query.json +16 -0
- package/generated/v1/schemas/endpoints.list.response.json +146 -0
- package/generated/v1/schemas/endpoints.read.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.read.response.json +100 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +118 -0
- package/generated/v1/schemas/endpoints.update.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.update.request.json +12 -0
- package/generated/v1/schemas/endpoints.update.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.update.response.json +100 -0
- package/generated/v1/schemas/endpoints.verify.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.verify.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.verify.response.json +100 -0
- package/generated/v1/schemas/forecast.read.query.json +26 -0
- package/generated/v1/schemas/forecast.read.response.json +100 -0
- package/generated/v1/schemas/forecast.windows.query.json +26 -0
- package/generated/v1/schemas/forecast.windows.response.json +94 -0
- package/generated/v1/schemas/grants.list.response.json +98 -0
- package/generated/v1/schemas/grants.revoke.response.json +95 -0
- package/generated/v1/schemas/meta.scaffold.response.json +36 -0
- package/generated/v1/schemas/meta.version.response.json +19 -0
- package/generated/v1/schemas/occurrences.list.query.json +16 -0
- package/generated/v1/schemas/occurrences.list.response.json +83 -0
- package/generated/v1/schemas/occurrences.read.response.json +76 -0
- package/generated/v1/schemas/occurrences.redeliver.request-headers.json +13 -0
- package/generated/v1/schemas/occurrences.redeliver.response-headers.json +10 -0
- package/generated/v1/schemas/occurrences.redeliver.response.json +168 -0
- package/generated/v1/schemas/projects.create.request.json +12 -0
- package/generated/v1/schemas/projects.create.response.json +25 -0
- package/generated/v1/schemas/projects.list.response.json +35 -0
- package/generated/v1/schemas/schedules.archive.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.archive.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.archive.response.json +189 -0
- package/generated/v1/schemas/schedules.cancel.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.cancel.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.cancel.response.json +189 -0
- package/generated/v1/schemas/schedules.create.request-headers.json +12 -0
- package/generated/v1/schemas/schedules.create.request.json +99 -0
- package/generated/v1/schemas/schedules.create.response-headers.json +15 -0
- package/generated/v1/schemas/schedules.create.response.json +189 -0
- package/generated/v1/schemas/schedules.list.query.json +16 -0
- package/generated/v1/schemas/schedules.list.response.json +170 -0
- package/generated/v1/schemas/schedules.pause.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.pause.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.pause.response.json +189 -0
- package/generated/v1/schemas/schedules.read.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.read.response.json +189 -0
- package/generated/v1/schemas/schedules.replace.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.replace.request.json +99 -0
- package/generated/v1/schemas/schedules.replace.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.replace.response.json +189 -0
- package/generated/v1/schemas/schedules.resume.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.resume.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.resume.response.json +189 -0
- package/generated/v1/schemas/sinkdeliveries.list.query.json +16 -0
- package/generated/v1/schemas/sinkdeliveries.list.response.json +126 -0
- package/generated/v1/schemas/sinkdeliveries.read.response.json +98 -0
- package/generated/v1/schemas/testsinks.configure.request.json +66 -0
- package/generated/v1/schemas/testsinks.configure.response.json +115 -0
- package/generated/v1/schemas/testsinks.create.request.json +76 -0
- package/generated/v1/schemas/testsinks.create.response.json +115 -0
- package/generated/v1/schemas/testsinks.delete.response.json +115 -0
- package/generated/v1/schemas/testsinks.list.query.json +16 -0
- package/generated/v1/schemas/testsinks.list.response.json +161 -0
- package/generated/v1/schemas/testsinks.read.response.json +115 -0
- package/generated/v1/schemas/usage.read.query.json +15 -0
- package/generated/v1/schemas/usage.read.response.json +71 -0
- package/generated/v1/snippets/attempts.list.json +5 -0
- package/generated/v1/snippets/attempts.read.json +5 -0
- package/generated/v1/snippets/credentials.create.json +5 -0
- package/generated/v1/snippets/credentials.list.json +5 -0
- package/generated/v1/snippets/credentials.revoke.json +5 -0
- package/generated/v1/snippets/credentials.rotate.json +5 -0
- package/generated/v1/snippets/endpoints.create.json +5 -0
- package/generated/v1/snippets/endpoints.disable.json +5 -0
- package/generated/v1/snippets/endpoints.list.json +5 -0
- package/generated/v1/snippets/endpoints.read.json +5 -0
- package/generated/v1/snippets/endpoints.rotateSigningKey.json +5 -0
- package/generated/v1/snippets/endpoints.update.json +5 -0
- package/generated/v1/snippets/endpoints.verify.json +5 -0
- package/generated/v1/snippets/forecast.read.json +5 -0
- package/generated/v1/snippets/forecast.windows.json +5 -0
- package/generated/v1/snippets/grants.list.json +5 -0
- package/generated/v1/snippets/grants.revoke.json +5 -0
- package/generated/v1/snippets/meta.scaffold.json +5 -0
- package/generated/v1/snippets/meta.version.json +5 -0
- package/generated/v1/snippets/occurrences.list.json +5 -0
- package/generated/v1/snippets/occurrences.read.json +5 -0
- package/generated/v1/snippets/occurrences.redeliver.json +5 -0
- package/generated/v1/snippets/projects.create.json +5 -0
- package/generated/v1/snippets/projects.list.json +5 -0
- package/generated/v1/snippets/schedules.archive.json +5 -0
- package/generated/v1/snippets/schedules.cancel.json +5 -0
- package/generated/v1/snippets/schedules.create.json +5 -0
- package/generated/v1/snippets/schedules.list.json +5 -0
- package/generated/v1/snippets/schedules.pause.json +5 -0
- package/generated/v1/snippets/schedules.read.json +5 -0
- package/generated/v1/snippets/schedules.replace.json +5 -0
- package/generated/v1/snippets/schedules.resume.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.list.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.read.json +5 -0
- package/generated/v1/snippets/testsinks.configure.json +5 -0
- package/generated/v1/snippets/testsinks.create.json +5 -0
- package/generated/v1/snippets/testsinks.delete.json +5 -0
- package/generated/v1/snippets/testsinks.list.json +5 -0
- package/generated/v1/snippets/testsinks.read.json +5 -0
- package/generated/v1/snippets/usage.read.json +5 -0
- package/package.json +153 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { environmentKindSchema } from "./authority.js";
|
|
3
|
+
import { evaluateCallbackUrl } from "./callback-safety.js";
|
|
4
|
+
import { callbackSigningKeyIdSchema, endpointIdSchema, projectIdSchema, } from "./identifiers.js";
|
|
5
|
+
import { pageSchema } from "./protocol.js";
|
|
6
|
+
import { timestampSchema } from "./time.js";
|
|
7
|
+
/**
|
|
8
|
+
* Reusable callback endpoints.
|
|
9
|
+
*
|
|
10
|
+
* The URL belongs to one verified authority tuple for its whole life. The
|
|
11
|
+
* public resource deliberately has no organization or environment identifier
|
|
12
|
+
* a caller can use to widen that tuple: `project` and `environmentKind` are
|
|
13
|
+
* display metadata, while every lookup is scoped by the verified principal.
|
|
14
|
+
*/
|
|
15
|
+
export const CALLBACK_ENDPOINT_STATUSES = [
|
|
16
|
+
"pending",
|
|
17
|
+
"verified",
|
|
18
|
+
"disabled",
|
|
19
|
+
];
|
|
20
|
+
export const callbackEndpointStatusSchema = z.enum(CALLBACK_ENDPOINT_STATUSES);
|
|
21
|
+
export const CALLBACK_VERIFICATION_FAILURES = [
|
|
22
|
+
"address_forbidden",
|
|
23
|
+
"challenge_failed",
|
|
24
|
+
"connection_failed",
|
|
25
|
+
"dns_unresolved",
|
|
26
|
+
"rate_limited",
|
|
27
|
+
"redirect_refused",
|
|
28
|
+
"response_too_large",
|
|
29
|
+
"timed_out",
|
|
30
|
+
"unexpected_status",
|
|
31
|
+
];
|
|
32
|
+
export const callbackVerificationFailureSchema = z.enum(CALLBACK_VERIFICATION_FAILURES);
|
|
33
|
+
/**
|
|
34
|
+
* A safety ceiling on retained endpoint records, independent of later
|
|
35
|
+
* commercial plan limits. Disabled records remain readable for audit and count
|
|
36
|
+
* toward it; changing that lifetime semantic needs a product decision.
|
|
37
|
+
*/
|
|
38
|
+
export const CALLBACK_ENDPOINT_LIMIT_PER_ENVIRONMENT = 50;
|
|
39
|
+
/** Verification egress is admitted through both buckets before DNS or fetch. */
|
|
40
|
+
export const CALLBACK_VERIFICATION_RATE_LIMITS = {
|
|
41
|
+
destinationPerMinute: 5,
|
|
42
|
+
projectPerMinute: 20,
|
|
43
|
+
windowSeconds: 60,
|
|
44
|
+
};
|
|
45
|
+
/** Total bytes a verification response may return before it is refused. */
|
|
46
|
+
export const CALLBACK_VERIFICATION_RESPONSE_BYTES = 1_024;
|
|
47
|
+
/** Total DNS + connect + response bound for one verification attempt. */
|
|
48
|
+
export const CALLBACK_VERIFICATION_TIMEOUT_MILLISECONDS = 5_000;
|
|
49
|
+
/** Longest period during which a receiver may accept current and next keys. */
|
|
50
|
+
export const CALLBACK_SIGNING_KEY_ROTATION_OVERLAP_SECONDS = 86_400;
|
|
51
|
+
export const callbackSigningKeysSchema = z.object({
|
|
52
|
+
current: callbackSigningKeyIdSchema,
|
|
53
|
+
next: z
|
|
54
|
+
.object({
|
|
55
|
+
id: callbackSigningKeyIdSchema,
|
|
56
|
+
overlapEndsAt: timestampSchema,
|
|
57
|
+
})
|
|
58
|
+
.optional(),
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* A metadata-only endpoint shape. The sealed signing secret has no public
|
|
62
|
+
* field, so list/get/update/verify/disable cannot accidentally recover it.
|
|
63
|
+
*/
|
|
64
|
+
export const callbackEndpointSchema = z.object({
|
|
65
|
+
createdAt: timestampSchema,
|
|
66
|
+
disabledAt: timestampSchema.optional(),
|
|
67
|
+
environmentKind: environmentKindSchema,
|
|
68
|
+
id: endpointIdSchema,
|
|
69
|
+
lastVerificationAttemptAt: timestampSchema.optional(),
|
|
70
|
+
lastVerificationFailure: callbackVerificationFailureSchema.optional(),
|
|
71
|
+
project: projectIdSchema,
|
|
72
|
+
signingKeys: callbackSigningKeysSchema,
|
|
73
|
+
status: callbackEndpointStatusSchema,
|
|
74
|
+
updatedAt: timestampSchema,
|
|
75
|
+
url: z.string().url(),
|
|
76
|
+
verifiedAt: timestampSchema.optional(),
|
|
77
|
+
version: z.number().int().positive(),
|
|
78
|
+
});
|
|
79
|
+
export const callbackEndpointPageSchema = pageSchema(callbackEndpointSchema);
|
|
80
|
+
/** The one response that carries the per-endpoint secret. */
|
|
81
|
+
export const callbackEndpointCreatedSchema = callbackEndpointSchema.extend({
|
|
82
|
+
keyId: callbackSigningKeyIdSchema,
|
|
83
|
+
secret: z.string().min(1),
|
|
84
|
+
shownOnce: z.literal(true),
|
|
85
|
+
});
|
|
86
|
+
export const callbackSigningKeyRotationRequestSchema = z.object({
|
|
87
|
+
overlapSeconds: z
|
|
88
|
+
.number()
|
|
89
|
+
.int()
|
|
90
|
+
.min(0)
|
|
91
|
+
.max(CALLBACK_SIGNING_KEY_ROTATION_OVERLAP_SECONDS, "must not exceed the maximum endpoint-key overlap")
|
|
92
|
+
.optional(),
|
|
93
|
+
});
|
|
94
|
+
export const callbackEndpointRotatedSchema = z.object({
|
|
95
|
+
endpoint: callbackEndpointSchema,
|
|
96
|
+
keyId: callbackSigningKeyIdSchema,
|
|
97
|
+
secret: z.string().min(1),
|
|
98
|
+
shownOnce: z.literal(true),
|
|
99
|
+
});
|
|
100
|
+
function callbackUrlSchema() {
|
|
101
|
+
return z
|
|
102
|
+
.string()
|
|
103
|
+
.url()
|
|
104
|
+
.max(2_048)
|
|
105
|
+
.superRefine((value, context) => {
|
|
106
|
+
const verdict = evaluateCallbackUrl(value);
|
|
107
|
+
if (!verdict.ok) {
|
|
108
|
+
context.addIssue({
|
|
109
|
+
code: "custom",
|
|
110
|
+
message: verdict.reason,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
export const callbackEndpointRequestSchema = z.object({
|
|
116
|
+
url: callbackUrlSchema(),
|
|
117
|
+
});
|
|
118
|
+
export const CALLBACK_VERIFICATION_PROTOCOL_VERSION = "2026-08-05";
|
|
119
|
+
export const CALLBACK_VERIFICATION_TYPE = "callback.endpoint.verification";
|
|
120
|
+
/**
|
|
121
|
+
* Exact verification bytes sent to the receiver. The receiver validates the
|
|
122
|
+
* request signature and proves possession of the one-time secret by returning
|
|
123
|
+
* an HMAC of `challenge` in `Callback-Verification-Response`.
|
|
124
|
+
*/
|
|
125
|
+
export const callbackVerificationChallengeSchema = z.object({
|
|
126
|
+
challenge: z.string().regex(/^cvc_[A-Za-z0-9_-]{43}$/u),
|
|
127
|
+
endpointId: endpointIdSchema,
|
|
128
|
+
type: z.literal(CALLBACK_VERIFICATION_TYPE),
|
|
129
|
+
version: z.literal(CALLBACK_VERIFICATION_PROTOCOL_VERSION),
|
|
130
|
+
});
|
|
131
|
+
export const CALLBACK_VERIFICATION_HEADERS = {
|
|
132
|
+
challenge: "Callback-Verification-Challenge",
|
|
133
|
+
requestSignature: "Callback-Verification-Signature",
|
|
134
|
+
responseSignature: "Callback-Verification-Response",
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Machine-readable receiver contract for endpoint ownership verification.
|
|
138
|
+
*
|
|
139
|
+
* This is deliberately separate from W3-02's occurrence-delivery signature:
|
|
140
|
+
* the request proves control of a receiver before the endpoint may be used,
|
|
141
|
+
* while a delivery signature authenticates an occurrence body later. The
|
|
142
|
+
* generator publishes this object beside OpenAPI and the JSON Schema.
|
|
143
|
+
*/
|
|
144
|
+
export const CALLBACK_VERIFICATION_PROTOCOL = {
|
|
145
|
+
purpose: "Prove that the receiver possesses the one-time endpoint secret before Greatwait marks the endpoint verified.",
|
|
146
|
+
request: {
|
|
147
|
+
bodyEncoding: "UTF-8 bytes of the compact JSON object in schema property order: challenge, endpointId, type, version.",
|
|
148
|
+
contentType: "application/json",
|
|
149
|
+
method: "POST",
|
|
150
|
+
redirectPolicy: "manual; every 3xx response is refused",
|
|
151
|
+
signature: {
|
|
152
|
+
algorithm: "HMAC-SHA-256",
|
|
153
|
+
format: "v1=<64 lowercase hexadecimal characters>",
|
|
154
|
+
header: CALLBACK_VERIFICATION_HEADERS.requestSignature,
|
|
155
|
+
input: "the exact request body bytes",
|
|
156
|
+
key: "the one-time endpoint secret returned by REST endpoint creation",
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
response: {
|
|
160
|
+
body: "ignored after enforcing the 1024-byte response limit; return an empty body",
|
|
161
|
+
proof: {
|
|
162
|
+
algorithm: "HMAC-SHA-256",
|
|
163
|
+
format: "v1=<64 lowercase hexadecimal characters>",
|
|
164
|
+
header: CALLBACK_VERIFICATION_HEADERS.responseSignature,
|
|
165
|
+
input: "the UTF-8 bytes of the challenge string",
|
|
166
|
+
key: "the same endpoint secret",
|
|
167
|
+
},
|
|
168
|
+
status: "any 2xx status",
|
|
169
|
+
},
|
|
170
|
+
testVector: {
|
|
171
|
+
challenge: "cvc_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
|
172
|
+
endpointId: "ep_00000000000000000000000000",
|
|
173
|
+
exactBodyBase64: "eyJjaGFsbGVuZ2UiOiJjdmNfQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQSIsImVuZHBvaW50SWQiOiJlcF8wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsInR5cGUiOiJjYWxsYmFjay5lbmRwb2ludC52ZXJpZmljYXRpb24iLCJ2ZXJzaW9uIjoiMjAyNi0wOC0wNSJ9",
|
|
174
|
+
requestSignature: "v1=0d24c7fed4d752411b88025a9923627b329e0eb9d53978a6ebcf92c0678c731e",
|
|
175
|
+
responseSignature: "v1=efc690a23f1870930ff3388313162c0e06406902a7a4d3f9273ffe0abcef86bd",
|
|
176
|
+
secret: "verification-vector-secret",
|
|
177
|
+
},
|
|
178
|
+
version: CALLBACK_VERIFICATION_PROTOCOL_VERSION,
|
|
179
|
+
};
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Product events.
|
|
4
|
+
*
|
|
5
|
+
* One envelope for every event the product emits, whether it reaches a customer
|
|
6
|
+
* or only an internal projection. Delivery is at-least-once everywhere, so
|
|
7
|
+
* `id` is the deduplication key and consumers must be idempotent on it.
|
|
8
|
+
*
|
|
9
|
+
* `occurredAt` is when the thing happened; `recordedAt` is when we learned. A
|
|
10
|
+
* projection that lags can be reasoned about only if both are present, and
|
|
11
|
+
* collapsing them is how "why is this event from the future" bugs start.
|
|
12
|
+
*/
|
|
13
|
+
export declare const EVENT_TYPES: readonly ["endpoint.verified", "occurrence.attempt.recorded", "occurrence.due", "occurrence.succeeded", "occurrence.terminal_failed", "schedule.cancelled", "schedule.completed", "schedule.created", "schedule.replaced"];
|
|
14
|
+
export declare const eventTypeSchema: z.ZodEnum<{
|
|
15
|
+
"endpoint.verified": "endpoint.verified";
|
|
16
|
+
"occurrence.attempt.recorded": "occurrence.attempt.recorded";
|
|
17
|
+
"occurrence.due": "occurrence.due";
|
|
18
|
+
"occurrence.succeeded": "occurrence.succeeded";
|
|
19
|
+
"occurrence.terminal_failed": "occurrence.terminal_failed";
|
|
20
|
+
"schedule.cancelled": "schedule.cancelled";
|
|
21
|
+
"schedule.completed": "schedule.completed";
|
|
22
|
+
"schedule.created": "schedule.created";
|
|
23
|
+
"schedule.replaced": "schedule.replaced";
|
|
24
|
+
}>;
|
|
25
|
+
export type EventType = z.infer<typeof eventTypeSchema>;
|
|
26
|
+
export declare function eventEnvelopeSchema<TData extends z.ZodTypeAny>(data: TData): z.ZodObject<{
|
|
27
|
+
data: TData;
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
occurredAt: z.ZodString;
|
|
30
|
+
recordedAt: z.ZodString;
|
|
31
|
+
schemaVersion: z.ZodNumber;
|
|
32
|
+
type: z.ZodEnum<{
|
|
33
|
+
"endpoint.verified": "endpoint.verified";
|
|
34
|
+
"occurrence.attempt.recorded": "occurrence.attempt.recorded";
|
|
35
|
+
"occurrence.due": "occurrence.due";
|
|
36
|
+
"occurrence.succeeded": "occurrence.succeeded";
|
|
37
|
+
"occurrence.terminal_failed": "occurrence.terminal_failed";
|
|
38
|
+
"schedule.cancelled": "schedule.cancelled";
|
|
39
|
+
"schedule.completed": "schedule.completed";
|
|
40
|
+
"schedule.created": "schedule.created";
|
|
41
|
+
"schedule.replaced": "schedule.replaced";
|
|
42
|
+
}>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
export declare const genericEventSchema: z.ZodObject<{
|
|
45
|
+
data: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
46
|
+
id: z.ZodString;
|
|
47
|
+
occurredAt: z.ZodString;
|
|
48
|
+
recordedAt: z.ZodString;
|
|
49
|
+
schemaVersion: z.ZodNumber;
|
|
50
|
+
type: z.ZodEnum<{
|
|
51
|
+
"endpoint.verified": "endpoint.verified";
|
|
52
|
+
"occurrence.attempt.recorded": "occurrence.attempt.recorded";
|
|
53
|
+
"occurrence.due": "occurrence.due";
|
|
54
|
+
"occurrence.succeeded": "occurrence.succeeded";
|
|
55
|
+
"occurrence.terminal_failed": "occurrence.terminal_failed";
|
|
56
|
+
"schedule.cancelled": "schedule.cancelled";
|
|
57
|
+
"schedule.completed": "schedule.completed";
|
|
58
|
+
"schedule.created": "schedule.created";
|
|
59
|
+
"schedule.replaced": "schedule.replaced";
|
|
60
|
+
}>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
export type GenericEvent = z.infer<typeof genericEventSchema>;
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { eventIdSchema } from "./identifiers.js";
|
|
3
|
+
import { timestampSchema } from "./time.js";
|
|
4
|
+
/**
|
|
5
|
+
* Product events.
|
|
6
|
+
*
|
|
7
|
+
* One envelope for every event the product emits, whether it reaches a customer
|
|
8
|
+
* or only an internal projection. Delivery is at-least-once everywhere, so
|
|
9
|
+
* `id` is the deduplication key and consumers must be idempotent on it.
|
|
10
|
+
*
|
|
11
|
+
* `occurredAt` is when the thing happened; `recordedAt` is when we learned. A
|
|
12
|
+
* projection that lags can be reasoned about only if both are present, and
|
|
13
|
+
* collapsing them is how "why is this event from the future" bugs start.
|
|
14
|
+
*/
|
|
15
|
+
export const EVENT_TYPES = [
|
|
16
|
+
"endpoint.verified",
|
|
17
|
+
"occurrence.attempt.recorded",
|
|
18
|
+
"occurrence.due",
|
|
19
|
+
"occurrence.succeeded",
|
|
20
|
+
"occurrence.terminal_failed",
|
|
21
|
+
"schedule.cancelled",
|
|
22
|
+
"schedule.completed",
|
|
23
|
+
"schedule.created",
|
|
24
|
+
"schedule.replaced",
|
|
25
|
+
];
|
|
26
|
+
export const eventTypeSchema = z.enum(EVENT_TYPES);
|
|
27
|
+
export function eventEnvelopeSchema(data) {
|
|
28
|
+
return z.object({
|
|
29
|
+
data,
|
|
30
|
+
id: eventIdSchema,
|
|
31
|
+
occurredAt: timestampSchema,
|
|
32
|
+
recordedAt: timestampSchema,
|
|
33
|
+
/** Bumped only when this event's `data` changes incompatibly. */
|
|
34
|
+
schemaVersion: z.number().int().positive(),
|
|
35
|
+
type: eventTypeSchema,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export const genericEventSchema = eventEnvelopeSchema(z.record(z.string(), z.unknown()));
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ProblemCode } from "./problems.js";
|
|
3
|
+
/**
|
|
4
|
+
* The one bounded sequence that takes a developer from a credential to an
|
|
5
|
+
* observed callback.
|
|
6
|
+
*
|
|
7
|
+
* **Declared once, here, because W9-03 is not the only story that has to tell
|
|
8
|
+
* it.** The curl quickstart, the JavaScript quickstart, the website journey
|
|
9
|
+
* W9-01 owns, the DocsAlot pages W9-04 publishes, and the command-line
|
|
10
|
+
* ergonomics W10 owns are all the *same* sequence rendered for a different
|
|
11
|
+
* reader. Written separately they diverge silently — the legacy scheduler's
|
|
12
|
+
* hand-maintained client and documentation are the worked example, and the
|
|
13
|
+
* thing that made them wrong was never a typo but a step somebody added in one
|
|
14
|
+
* place.
|
|
15
|
+
*
|
|
16
|
+
* So a step names an operation in `OPERATIONS` and nothing else. The method,
|
|
17
|
+
* the path, the scopes, the refusals, the request shape and the response shape
|
|
18
|
+
* come from the registry, and `scripts/contract-projection.ts` renders them.
|
|
19
|
+
* What lives here is the part that genuinely is not derivable from a single
|
|
20
|
+
* operation: **what order the calls go in, why each one is there, what a reader
|
|
21
|
+
* should see, and what to do when they do not see it.**
|
|
22
|
+
*
|
|
23
|
+
* The three things it deliberately does *not* contain:
|
|
24
|
+
*
|
|
25
|
+
* - **A wire shape.** `request` bodies here are validated against the owning
|
|
26
|
+
* operation's `request` schema when artifacts are generated, so a body that
|
|
27
|
+
* the service would refuse cannot be published.
|
|
28
|
+
* - **A credential.** Every value a reader supplies is a declared variable with
|
|
29
|
+
* a placeholder, and `journeyVariable` refuses one whose placeholder looks
|
|
30
|
+
* like a real credential.
|
|
31
|
+
* - **A receiver we chose for them.** `GREATWAIT_RECEIVER_URL` is a
|
|
32
|
+
* prerequisite the reader brings. See {@link FIRST_VALUE_PREREQUISITES}.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Something a reader must already have, that no API call in this journey can
|
|
36
|
+
* produce for them.
|
|
37
|
+
*
|
|
38
|
+
* **This list exists because the alternative is an invented shortcut.** Two of
|
|
39
|
+
* the three entries name a step that legitimately requires a signed-in human:
|
|
40
|
+
* a project and an API credential are created through the dashboard, because
|
|
41
|
+
* `projects.create` and `credentials.create` accept only a session principal.
|
|
42
|
+
* A quickstart that papered over that would either publish a call nobody can
|
|
43
|
+
* make or quietly hand out a privileged path. The third is the receiver, and
|
|
44
|
+
* the reason it is the reader's is recorded in
|
|
45
|
+
* `docs/projects/w9-invited-alpha-journeys/implementation-guide.md`: until
|
|
46
|
+
* FXO-1746 delivers an accepted first-party receiver, sending a sample payload
|
|
47
|
+
* to an arbitrary third party is not something this product does on somebody's
|
|
48
|
+
* behalf.
|
|
49
|
+
*/
|
|
50
|
+
export interface JourneyPrerequisite {
|
|
51
|
+
/** What the reader has to do, in one imperative sentence. */
|
|
52
|
+
readonly action: string;
|
|
53
|
+
/** Why an API call cannot do it for them. */
|
|
54
|
+
readonly because: string;
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly title: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A value the reader supplies, named identically for curl and for JavaScript.
|
|
60
|
+
*
|
|
61
|
+
* One derivation for both surfaces, so a reader who exported the shell
|
|
62
|
+
* variables can see at a glance which `process.env` name is the same value.
|
|
63
|
+
* Before W9-03 the two disagreed — curl read `$API` and `$TEST_KEY` while the
|
|
64
|
+
* JavaScript read `GREATWAIT_API_URL` and `GREATWAIT_TEST_KEY` — and one of
|
|
65
|
+
* those four named a *test* credential in examples published for a product
|
|
66
|
+
* whose test environment is not offered to customers.
|
|
67
|
+
*/
|
|
68
|
+
export interface JourneyVariable {
|
|
69
|
+
/**
|
|
70
|
+
* How a rendering invents a value when the reader supplies none.
|
|
71
|
+
*
|
|
72
|
+
* Declared for exactly one variable and deliberately not for the others.
|
|
73
|
+
* An idempotency key is a value the *caller* chooses and nothing else can
|
|
74
|
+
* choose for them, so it has to be nameable — but a quickstart that demanded
|
|
75
|
+
* one before the reader had learned what it was for would be asking them to
|
|
76
|
+
* make a decision they cannot yet make. The API origin, the credential and
|
|
77
|
+
* the receiver have no honest default at all: inventing one is how a
|
|
78
|
+
* quickstart ends up sending somebody's payload somewhere they did not
|
|
79
|
+
* choose.
|
|
80
|
+
*/
|
|
81
|
+
readonly defaultExpression?: {
|
|
82
|
+
readonly javascript: string;
|
|
83
|
+
readonly shell: string;
|
|
84
|
+
};
|
|
85
|
+
/** Why it is needed, and where the reader gets it. */
|
|
86
|
+
readonly detail: string;
|
|
87
|
+
readonly name: string;
|
|
88
|
+
/**
|
|
89
|
+
* What to show in place of a value.
|
|
90
|
+
*
|
|
91
|
+
* Never a credential, and `journeyVariableSchema` refuses one that looks
|
|
92
|
+
* like it might be: a placeholder is copied into generated pages, and a
|
|
93
|
+
* generated page is exactly where a real credential must never appear.
|
|
94
|
+
*/
|
|
95
|
+
readonly placeholder: string;
|
|
96
|
+
/** Whether the value is a secret, which decides how it is handled and shown. */
|
|
97
|
+
readonly secret: boolean;
|
|
98
|
+
readonly title: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* One thing that can go wrong at a step, and the next move.
|
|
102
|
+
*
|
|
103
|
+
* `when` is a `ProblemCode` when the service refuses, and one of the named
|
|
104
|
+
* conditions below when the failure has no problem document — a timeout, a
|
|
105
|
+
* receiver that answered badly, an outcome that never settled. Both kinds
|
|
106
|
+
* exist because an integrator hits both, and a recovery table that only covers
|
|
107
|
+
* refusals leaves the reader alone at exactly the point they are stuck.
|
|
108
|
+
*/
|
|
109
|
+
export declare const JOURNEY_CONDITIONS: readonly ["attempt-failed", "no-response", "not-settled", "receiver-unreachable", "unexpected-answer"];
|
|
110
|
+
export type JourneyCondition = (typeof JOURNEY_CONDITIONS)[number];
|
|
111
|
+
export interface JourneyRecovery {
|
|
112
|
+
/** What the reader does next. Imperative, and specific enough to act on. */
|
|
113
|
+
readonly nextMove: string;
|
|
114
|
+
readonly when: JourneyCondition | ProblemCode;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A value carried from one step's response into a later step's request.
|
|
118
|
+
*
|
|
119
|
+
* `from` is a dotted path into the parsed response body, so the same
|
|
120
|
+
* declaration drives `jq` in the shell rendering and property access in the
|
|
121
|
+
* JavaScript one. `header` reads a response header instead, which is how the
|
|
122
|
+
* replay step observes `Idempotency-Replayed`.
|
|
123
|
+
*/
|
|
124
|
+
export interface JourneyCapture {
|
|
125
|
+
readonly from: string;
|
|
126
|
+
/** True when `from` names a response header rather than a body path. */
|
|
127
|
+
readonly header?: boolean;
|
|
128
|
+
/** Whether the captured value is a secret, and must never be printed. */
|
|
129
|
+
readonly secret?: boolean;
|
|
130
|
+
/** The variable it becomes, which a later step may reference. */
|
|
131
|
+
readonly variable: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Something a step checks about what it captured.
|
|
135
|
+
*
|
|
136
|
+
* **Added because a linter noticed the gap the step was written to close.**
|
|
137
|
+
* The replay step captured `Idempotency-Replayed` and then did nothing with
|
|
138
|
+
* it, so the published quickstart *demonstrated* idempotency without ever
|
|
139
|
+
* *checking* it: a service that quietly created a second schedule would have
|
|
140
|
+
* produced a transcript that read exactly the same, and a reader following the
|
|
141
|
+
* page would have two schedules and two callbacks.
|
|
142
|
+
*
|
|
143
|
+
* `equals` may name another variable with `{{…}}`, which is how the replay
|
|
144
|
+
* proves it got the same schedule back rather than merely a schedule.
|
|
145
|
+
*/
|
|
146
|
+
export interface JourneyExpectation {
|
|
147
|
+
/** The value it must have — a literal, or a `{{VARIABLE}}` reference. */
|
|
148
|
+
readonly equals: string;
|
|
149
|
+
/** What it means when it does not, in the reader's terms. */
|
|
150
|
+
readonly message: string;
|
|
151
|
+
/** The captured variable being checked. */
|
|
152
|
+
readonly subject: string;
|
|
153
|
+
}
|
|
154
|
+
/** A bounded wait, for the one step whose answer arrives when it arrives. */
|
|
155
|
+
export interface JourneyPoll {
|
|
156
|
+
/** Human sentence describing the condition, for the generated prose. */
|
|
157
|
+
readonly describe: string;
|
|
158
|
+
readonly intervalSeconds: number;
|
|
159
|
+
readonly timeoutSeconds: number;
|
|
160
|
+
}
|
|
161
|
+
export interface JourneyStep {
|
|
162
|
+
readonly capture?: readonly JourneyCapture[];
|
|
163
|
+
/** What this step checks about what it captured. */
|
|
164
|
+
readonly expect?: readonly JourneyExpectation[];
|
|
165
|
+
/** Stable machine name for this step, used by every consumer. */
|
|
166
|
+
readonly key: string;
|
|
167
|
+
/** The operation this step calls, by registry id. */
|
|
168
|
+
readonly operationId: string;
|
|
169
|
+
/** What the reader should see when it worked. */
|
|
170
|
+
readonly observe: string;
|
|
171
|
+
readonly poll?: JourneyPoll;
|
|
172
|
+
/** Why this step is in the journey at all. */
|
|
173
|
+
readonly purpose: string;
|
|
174
|
+
/**
|
|
175
|
+
* Query parameters, as literal strings. Values may carry `{{VARIABLE}}`.
|
|
176
|
+
*/
|
|
177
|
+
readonly query?: Readonly<Record<string, string>>;
|
|
178
|
+
readonly recovery: readonly JourneyRecovery[];
|
|
179
|
+
/**
|
|
180
|
+
* The request body. String values may carry `{{VARIABLE}}` references, which
|
|
181
|
+
* are resolved against the declared placeholders before the body is
|
|
182
|
+
* validated against the operation's own request schema.
|
|
183
|
+
*/
|
|
184
|
+
readonly request?: unknown;
|
|
185
|
+
/** Request headers this step sends, with the same `{{VARIABLE}}` support. */
|
|
186
|
+
readonly requestHeaders?: Readonly<Record<string, string>>;
|
|
187
|
+
readonly title: string;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* A variable name, and a placeholder that is provably not a credential.
|
|
191
|
+
*
|
|
192
|
+
* The three patterns are the product's own credential shapes, taken from
|
|
193
|
+
* `scripts/secret-patterns.ts` in spirit rather than by import — this package
|
|
194
|
+
* is the contract and may not depend on a repository script. A generated page
|
|
195
|
+
* carrying a real one would be a leak that no reviewer reads carefully enough
|
|
196
|
+
* to catch, so the refusal is here rather than in a convention.
|
|
197
|
+
*/
|
|
198
|
+
export declare const journeyVariableSchema: z.ZodObject<{
|
|
199
|
+
defaultExpression: z.ZodOptional<z.ZodObject<{
|
|
200
|
+
javascript: z.ZodString;
|
|
201
|
+
shell: z.ZodString;
|
|
202
|
+
}, z.core.$strip>>;
|
|
203
|
+
detail: z.ZodString;
|
|
204
|
+
name: z.ZodString;
|
|
205
|
+
placeholder: z.ZodString;
|
|
206
|
+
secret: z.ZodBoolean;
|
|
207
|
+
title: z.ZodString;
|
|
208
|
+
}, z.core.$strip>;
|
|
209
|
+
export declare const journeyStepSchema: z.ZodObject<{
|
|
210
|
+
capture: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
211
|
+
from: z.ZodString;
|
|
212
|
+
header: z.ZodOptional<z.ZodBoolean>;
|
|
213
|
+
secret: z.ZodOptional<z.ZodBoolean>;
|
|
214
|
+
variable: z.ZodString;
|
|
215
|
+
}, z.core.$strip>>>;
|
|
216
|
+
expect: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
217
|
+
equals: z.ZodString;
|
|
218
|
+
message: z.ZodString;
|
|
219
|
+
subject: z.ZodString;
|
|
220
|
+
}, z.core.$strip>>>;
|
|
221
|
+
key: z.ZodString;
|
|
222
|
+
observe: z.ZodString;
|
|
223
|
+
operationId: z.ZodString;
|
|
224
|
+
poll: z.ZodOptional<z.ZodObject<{
|
|
225
|
+
describe: z.ZodString;
|
|
226
|
+
intervalSeconds: z.ZodNumber;
|
|
227
|
+
timeoutSeconds: z.ZodNumber;
|
|
228
|
+
}, z.core.$strip>>;
|
|
229
|
+
purpose: z.ZodString;
|
|
230
|
+
query: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
231
|
+
recovery: z.ZodArray<z.ZodObject<{
|
|
232
|
+
nextMove: z.ZodString;
|
|
233
|
+
when: z.ZodString;
|
|
234
|
+
}, z.core.$strip>>;
|
|
235
|
+
request: z.ZodOptional<z.ZodUnknown>;
|
|
236
|
+
requestHeaders: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
237
|
+
title: z.ZodString;
|
|
238
|
+
}, z.core.$strip>;
|
|
239
|
+
/**
|
|
240
|
+
* The lowest curl that runs the generated commands.
|
|
241
|
+
*
|
|
242
|
+
* `--variable` and `--expand-header` arrived in curl 8.3.0, and they are what
|
|
243
|
+
* keeps the credential out of the process arguments: the command line names
|
|
244
|
+
* `%GREATWAIT_API_KEY`, and curl reads the value out of its own environment.
|
|
245
|
+
* The ordinary `-H "Authorization: Bearer $GREATWAIT_API_KEY"` spelling puts
|
|
246
|
+
* the secret in `argv`, where any other user on the machine can read it out of
|
|
247
|
+
* `ps`.
|
|
248
|
+
*
|
|
249
|
+
* Stated as a constant because the requirement is published in three places —
|
|
250
|
+
* both quickstarts and the journey artifact — and a version number written
|
|
251
|
+
* three times is a version number that will disagree with itself.
|
|
252
|
+
*/
|
|
253
|
+
export declare const MINIMUM_CURL_VERSION = "8.3.0";
|
|
254
|
+
/** The tools the shell rendering of the journey needs on the reader's PATH. */
|
|
255
|
+
export declare const CURL_JOURNEY_TOOLS: readonly [{
|
|
256
|
+
readonly name: "curl";
|
|
257
|
+
readonly version: "8.3.0";
|
|
258
|
+
}, {
|
|
259
|
+
readonly name: "jq";
|
|
260
|
+
readonly version: "1.6";
|
|
261
|
+
}];
|
|
262
|
+
export declare const FIRST_VALUE_PREREQUISITES: readonly JourneyPrerequisite[];
|
|
263
|
+
export declare const FIRST_VALUE_VARIABLES: readonly JourneyVariable[];
|
|
264
|
+
/**
|
|
265
|
+
* The sequence.
|
|
266
|
+
*
|
|
267
|
+
* Nine steps, and the shape of them is the acceptance criterion: verify the
|
|
268
|
+
* context and the credential, create a destination, create an idempotent
|
|
269
|
+
* one-shot, prove the idempotency, read the schedule back, wait for the
|
|
270
|
+
* occurrence to settle, read the delivery attempt, and clean up. Creating a
|
|
271
|
+
* resource is not first value; **step `read-attempt` is**, because it is the
|
|
272
|
+
* first point at which the customer can read what happened at their own
|
|
273
|
+
* receiver.
|
|
274
|
+
*
|
|
275
|
+
* `delaySeconds` rather than `at`, deliberately. An absolute instant published
|
|
276
|
+
* in an example is stale the day after it is written, and a reader who pastes
|
|
277
|
+
* it is refused for a reason that has nothing to do with what they were
|
|
278
|
+
* learning. A delay is converted to an instant when the request is accepted,
|
|
279
|
+
* so the schedule reads back afterwards exactly as an `at` schedule would.
|
|
280
|
+
*/
|
|
281
|
+
export declare const FIRST_VALUE_STEPS: readonly JourneyStep[];
|
|
282
|
+
export interface FirstValueJourney {
|
|
283
|
+
readonly prerequisites: readonly JourneyPrerequisite[];
|
|
284
|
+
readonly steps: readonly JourneyStep[];
|
|
285
|
+
readonly variables: readonly JourneyVariable[];
|
|
286
|
+
}
|
|
287
|
+
export declare const FIRST_VALUE_JOURNEY: FirstValueJourney;
|
|
288
|
+
/** The declared variable of that name, or `undefined`. */
|
|
289
|
+
export declare function journeyVariable(name: string): JourneyVariable | undefined;
|
|
290
|
+
/** Every `{{VARIABLE}}` reference inside a value, in first-appearance order. */
|
|
291
|
+
export declare function journeyReferences(value: unknown): readonly string[];
|
|
292
|
+
/**
|
|
293
|
+
* Replaces every `{{VARIABLE}}` reference using `resolve`.
|
|
294
|
+
*
|
|
295
|
+
* A whole-string reference becomes the resolved value; an embedded one is
|
|
296
|
+
* substituted in place. An unresolved name throws rather than leaving the
|
|
297
|
+
* braces behind, because a `{{…}}` that reached a published page is a page
|
|
298
|
+
* that teaches a reader to send a literal brace.
|
|
299
|
+
*/
|
|
300
|
+
export declare function resolveJourneyReferences<T>(value: T, resolve: (name: string) => string | undefined): T;
|
|
301
|
+
/**
|
|
302
|
+
* The variables a step's own capture list produces, so a consumer can tell a
|
|
303
|
+
* value the reader supplies from one an earlier call handed them.
|
|
304
|
+
*/
|
|
305
|
+
export declare function journeyCapturedVariables(): readonly string[];
|