@forklaunch/core 2.1.1 → 3.0.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.
Files changed (52) hide show
  1. package/bin/gateway-mock/routes/email.mjs +233 -0
  2. package/bin/gateway-mock/routes/models.mjs +192 -0
  3. package/bin/gateway-mock/routes/payments.mjs +541 -0
  4. package/bin/gateway-mock/routes/sms.mjs +209 -0
  5. package/bin/gateway-mock/routes/voice.mjs +237 -0
  6. package/bin/gateway-mock/routes/whatsapp.mjs +227 -0
  7. package/bin/gateway-mock/server.mjs +321 -0
  8. package/bin/migrate-compliant-fields.mjs +312 -0
  9. package/bin/model-gateway-mock.mjs +13 -0
  10. package/lib/http/emailClient.d.ts +102 -0
  11. package/lib/http/emailClient.d.ts.map +1 -0
  12. package/lib/http/index.d.ts +7 -0
  13. package/lib/http/index.d.ts.map +1 -1
  14. package/lib/http/index.js +850 -4
  15. package/lib/http/index.js.map +1 -1
  16. package/lib/http/index.mjs +809 -1
  17. package/lib/http/index.mjs.map +1 -1
  18. package/lib/http/instanceGateway.d.ts +113 -0
  19. package/lib/http/instanceGateway.d.ts.map +1 -0
  20. package/lib/http/modelGatewayClient.d.ts +126 -0
  21. package/lib/http/modelGatewayClient.d.ts.map +1 -0
  22. package/lib/http/paymentsClient.d.ts +123 -0
  23. package/lib/http/paymentsClient.d.ts.map +1 -0
  24. package/lib/http/smsClient.d.ts +123 -0
  25. package/lib/http/smsClient.d.ts.map +1 -0
  26. package/lib/http/voiceClient.d.ts +105 -0
  27. package/lib/http/voiceClient.d.ts.map +1 -0
  28. package/lib/http/whatsappClient.d.ts +118 -0
  29. package/lib/http/whatsappClient.d.ts.map +1 -0
  30. package/lib/objectstore/interfaces/objectstore.interface.d.ts +45 -0
  31. package/lib/objectstore/interfaces/objectstore.interface.d.ts.map +1 -1
  32. package/lib/persistence/compliancePropertyBuilder.d.ts.map +1 -1
  33. package/lib/persistence/complianceTypes.d.ts +10 -1
  34. package/lib/persistence/complianceTypes.d.ts.map +1 -1
  35. package/lib/persistence/compliantField.d.ts +203 -0
  36. package/lib/persistence/compliantField.d.ts.map +1 -0
  37. package/lib/persistence/defineComplianceEntity.d.ts.map +1 -1
  38. package/lib/persistence/encryptedType.d.ts +8 -1
  39. package/lib/persistence/encryptedType.d.ts.map +1 -1
  40. package/lib/persistence/fieldEncryptor.d.ts +47 -6
  41. package/lib/persistence/fieldEncryptor.d.ts.map +1 -1
  42. package/lib/persistence/index.d.ts +3 -2
  43. package/lib/persistence/index.d.ts.map +1 -1
  44. package/lib/persistence/index.js +987 -259
  45. package/lib/persistence/index.js.map +1 -1
  46. package/lib/persistence/index.mjs +976 -257
  47. package/lib/persistence/index.mjs.map +1 -1
  48. package/lib/persistence/keyRotation.d.ts +5 -0
  49. package/lib/persistence/keyRotation.d.ts.map +1 -1
  50. package/lib/services/index.js.map +1 -1
  51. package/lib/services/index.mjs.map +1 -1
  52. package/package.json +27 -11
@@ -0,0 +1,113 @@
1
+ /**
2
+ * The instance gateway: how a managed instance reaches platform-held services
3
+ * (models, payments, email, SMS, WhatsApp, voice) without holding a vendor
4
+ * credential, and how the platform delivers vendor events back to it.
5
+ *
6
+ * Outbound, every request is signed with the instance's own HMAC key
7
+ * (`INSTANCE_HMAC_KEY`, key id `INSTANCE_ID`) over the router-relative path,
8
+ * with a timestamp and a single-use nonce; the platform checks the signature,
9
+ * the product's limits and the instance's own vendor account, then calls the
10
+ * vendor with credentials that never leave it.
11
+ *
12
+ * Inbound, the platform POSTs events (a payment succeeded, an email bounced, a
13
+ * text arrived) to `/platform-events/<feature>` on the service that declared
14
+ * the capability, signed with the same instance key under key id `platform`.
15
+ * `verifyPlatformEvent` checks that signature, the timestamp and the nonce.
16
+ *
17
+ * The platform injects `PLATFORM_GATEWAY_URL`, `INSTANCE_ID` and
18
+ * `INSTANCE_HMAC_KEY` into a hosted instance. Their absence means the service
19
+ * is not running in managed mode, and a client refuses to be created rather
20
+ * than failing on its first call.
21
+ */
22
+ /** Where the gateway router is mounted on the platform service. */
23
+ export declare const INSTANCE_GATEWAY_MOUNT = "/instance-gateway";
24
+ /** The key id the platform signs events with. */
25
+ export declare const PLATFORM_EVENT_KEY_ID = "platform";
26
+ /** Where a service receives platform events, per feature. */
27
+ export declare const PLATFORM_EVENTS_PATH = "/platform-events";
28
+ export interface InstanceGatewayOptions {
29
+ /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */
30
+ gatewayUrl?: string;
31
+ /** This instance's id. Default: `INSTANCE_ID`. */
32
+ instanceId?: string;
33
+ /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */
34
+ hmacKey?: string;
35
+ fetch?: typeof fetch;
36
+ }
37
+ /** A refusal or failure from the gateway, with the status it answered. */
38
+ export declare class InstanceGatewayRequestError extends Error {
39
+ readonly status: number;
40
+ /** Seconds to wait before retrying, on a 429. */
41
+ readonly retryAfterSeconds?: number | undefined;
42
+ readonly name: string;
43
+ constructor(status: number, message: string,
44
+ /** Seconds to wait before retrying, on a 429. */
45
+ retryAfterSeconds?: number | undefined);
46
+ }
47
+ export interface InstanceGatewayTransport {
48
+ readonly instanceId: string;
49
+ /** A signed request; throws `InstanceGatewayRequestError` on a non-2xx. */
50
+ request(method: 'GET' | 'POST' | 'PUT' | 'DELETE', route: string, body?: Record<string, unknown>, options?: {
51
+ signal?: AbortSignal;
52
+ headers?: Record<string, string>;
53
+ }): Promise<Response>;
54
+ /** `request`, then the JSON body. */
55
+ json<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', route: string, body?: Record<string, unknown>, options?: {
56
+ signal?: AbortSignal;
57
+ headers?: Record<string, string>;
58
+ }): Promise<T>;
59
+ }
60
+ /** Resolve the managed-mode settings, or explain which are missing. */
61
+ export declare function instanceGatewaySettings(options?: InstanceGatewayOptions, feature?: string): {
62
+ gatewayUrl: string;
63
+ instanceId: string;
64
+ hmacKey: string;
65
+ };
66
+ /** Whether this process runs as a managed instance. */
67
+ export declare function isManagedInstance(env?: Record<string, string | undefined>): boolean;
68
+ /** A signed transport to the instance gateway. */
69
+ export declare function createInstanceGatewayTransport(options?: InstanceGatewayOptions, feature?: string): InstanceGatewayTransport;
70
+ /** An event the platform delivered to this instance. */
71
+ export interface PlatformEvent<Data = Record<string, unknown>> {
72
+ /** Unique per event; deliveries can repeat, so handlers dedupe on it. */
73
+ id: string;
74
+ /** The capability it belongs to: payments, email, sms, whatsapp, voice. */
75
+ feature: string;
76
+ /** e.g. `checkout.session.completed`, `email.bounced`, `sms.received`. */
77
+ type: string;
78
+ occurredAt: string;
79
+ data: Data;
80
+ }
81
+ export declare class PlatformEventVerificationError extends Error {
82
+ readonly name = "PlatformEventVerificationError";
83
+ }
84
+ /**
85
+ * Verify an event the platform delivered and return it.
86
+ *
87
+ * `path` is the path the request arrived on (`/platform-events/payments`);
88
+ * `rawBody` is the exact request body (a string or Buffer) — pass the raw
89
+ * bytes when the framework captured them, else the parsed body. Throws
90
+ * `PlatformEventVerificationError` for a missing, stale, forged or replayed
91
+ * delivery; answer 401 then, and the platform retries.
92
+ */
93
+ export declare function verifyPlatformEvent<Data = Record<string, unknown>>(request: {
94
+ method: string;
95
+ path: string;
96
+ headers: Record<string, string | string[] | undefined>;
97
+ body: unknown;
98
+ }, options?: {
99
+ hmacKey?: string;
100
+ now?: () => number;
101
+ }): PlatformEvent<Data>;
102
+ /**
103
+ * Sign an event delivery the way the platform does. For tests and the local
104
+ * gateway mock; the platform has its own copy.
105
+ */
106
+ export declare function signPlatformEvent(params: {
107
+ hmacKey: string;
108
+ path: string;
109
+ body: string;
110
+ }): {
111
+ authorization: string;
112
+ };
113
+ //# sourceMappingURL=instanceGateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instanceGateway.d.ts","sourceRoot":"","sources":["../../src/http/instanceGateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { InstanceGatewayRequestError } from './instanceGateway';
2
+ /**
3
+ * Client for the ForkLaunch model gateway, used from inside a managed
4
+ * instance.
5
+ *
6
+ * A managed instance calls platform-hosted AI models (Azure AI Foundry)
7
+ * without holding a provider key: each request is signed with the
8
+ * instance's own HMAC key, and the platform enforces the product's model
9
+ * allowlist, monthly token budget and rate limit. For a HIPAA product the
10
+ * platform only offers models covered by its BAA.
11
+ *
12
+ * The platform injects everything this needs into a hosted instance:
13
+ * `PLATFORM_GATEWAY_URL` (the platform's public base), `INSTANCE_ID` and
14
+ * `INSTANCE_HMAC_KEY`. Their absence means the instance is not hosted in
15
+ * managed mode, and the client refuses to be created rather than failing on
16
+ * the first call.
17
+ *
18
+ * @example
19
+ * const models = createModelGatewayClient();
20
+ * const reply = await models.chat.completions.create({
21
+ * model: 'terra',
22
+ * messages: [{ role: 'user', content: 'Summarize this intake form: …' }]
23
+ * });
24
+ * for await (const chunk of models.chat.completions.stream({ model: 'luna', messages })) {
25
+ * process.stdout.write(chunk.choices[0]?.delta?.content ?? '');
26
+ * }
27
+ */
28
+ export interface ModelGatewayClientOptions {
29
+ /** Platform base URL. Default: `PLATFORM_GATEWAY_URL`. */
30
+ gatewayUrl?: string;
31
+ /** This instance's id. Default: `INSTANCE_ID`. */
32
+ instanceId?: string;
33
+ /** This instance's HMAC key. Default: `INSTANCE_HMAC_KEY`. */
34
+ hmacKey?: string;
35
+ fetch?: typeof fetch;
36
+ }
37
+ /** An OpenAI-style chat message. */
38
+ export interface GatewayChatMessage {
39
+ role: 'system' | 'developer' | 'user' | 'assistant' | 'tool';
40
+ content: unknown;
41
+ [key: string]: unknown;
42
+ }
43
+ /** An OpenAI-compatible chat completions request; `model` is a catalog alias. */
44
+ export interface GatewayChatRequest {
45
+ model: string;
46
+ messages: GatewayChatMessage[];
47
+ temperature?: number;
48
+ top_p?: number;
49
+ max_tokens?: number;
50
+ max_completion_tokens?: number;
51
+ response_format?: unknown;
52
+ tools?: unknown[];
53
+ tool_choice?: unknown;
54
+ parallel_tool_calls?: boolean;
55
+ stop?: unknown;
56
+ seed?: number;
57
+ presence_penalty?: number;
58
+ frequency_penalty?: number;
59
+ reasoning_effort?: string;
60
+ }
61
+ export interface GatewayChatCompletion {
62
+ id: string;
63
+ object: string;
64
+ created: number;
65
+ model: string;
66
+ choices: {
67
+ index: number;
68
+ message: {
69
+ role: string;
70
+ content: string | null;
71
+ [key: string]: unknown;
72
+ };
73
+ finish_reason: string | null;
74
+ [key: string]: unknown;
75
+ }[];
76
+ usage?: {
77
+ prompt_tokens: number;
78
+ completion_tokens: number;
79
+ total_tokens: number;
80
+ };
81
+ [key: string]: unknown;
82
+ }
83
+ export interface GatewayChatChunk {
84
+ id: string;
85
+ object: string;
86
+ model: string;
87
+ choices: {
88
+ index: number;
89
+ delta: {
90
+ role?: string;
91
+ content?: string | null;
92
+ [key: string]: unknown;
93
+ };
94
+ finish_reason?: string | null;
95
+ }[];
96
+ usage?: GatewayChatCompletion['usage'];
97
+ [key: string]: unknown;
98
+ }
99
+ export interface GatewayModels {
100
+ models: {
101
+ id: string;
102
+ baa: boolean;
103
+ }[];
104
+ monthlyTokenBudget: number;
105
+ tokensUsedThisMonth: number;
106
+ requestsPerMinute: number;
107
+ withheldForHipaa?: string[];
108
+ }
109
+ /** A refusal or failure from the gateway, with the status it answered. */
110
+ export declare class ModelGatewayRequestError extends InstanceGatewayRequestError {
111
+ readonly name: 'ModelGatewayRequestError';
112
+ }
113
+ export interface ModelGatewayClient {
114
+ /** The models this instance may call, and where its monthly budget stands. */
115
+ models(): Promise<GatewayModels>;
116
+ chat: {
117
+ completions: {
118
+ create(request: GatewayChatRequest): Promise<GatewayChatCompletion>;
119
+ stream(request: GatewayChatRequest, options?: {
120
+ signal?: AbortSignal;
121
+ }): AsyncGenerator<GatewayChatChunk>;
122
+ };
123
+ };
124
+ }
125
+ export declare function createModelGatewayClient(options?: ModelGatewayClientOptions): ModelGatewayClient;
126
+ //# sourceMappingURL=modelGatewayClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelGatewayClient.d.ts","sourceRoot":"","sources":["../../src/http/modelGatewayClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import type Stripe from 'stripe';
2
+ import { InstanceGatewayRequestError, type InstanceGatewayOptions } from './instanceGateway';
3
+ /**
4
+ * Payments for a managed instance: Stripe Connect through the platform.
5
+ *
6
+ * The product's publisher runs the Stripe Connect platform, linked once to
7
+ * ForkLaunch. Each managed instance (a clinic, a studio) gets its OWN
8
+ * connected account and is the merchant of record: charges are direct
9
+ * charges on that account, and payouts go to the clinic's bank, never through
10
+ * the app. The app never holds a Stripe key:
11
+ *
12
+ * - `createPaymentsClient()` onboards the instance (a Stripe-hosted Account
13
+ * Link) and reports whether it can take payments yet;
14
+ * - `createStripeClient()` is the REAL Stripe SDK, pointed at the instance
15
+ * gateway. Every request is signed with the instance key, and the platform
16
+ * pins `Stripe-Account` to this instance's connected account, forwards
17
+ * only an allowlist of calls (customers, products and prices, checkout and
18
+ * billing-portal sessions, payment links, subscriptions, payment intents,
19
+ * refunds, invoices — never payouts, transfers, external accounts or
20
+ * account changes), adds the product's application fee, and refuses
21
+ * metadata that looks like protected data;
22
+ * - Stripe's events arrive as platform events (`/platform-events/payments`,
23
+ * type = the Stripe event type, id = the Stripe event id, data = the
24
+ * event's object), verified with `verifyPlatformEvent`.
25
+ *
26
+ * Outside managed mode `createStripeClient({ apiKey })` is `new Stripe(apiKey)`,
27
+ * so the same registration runs against a developer's own test account.
28
+ *
29
+ * @example
30
+ * const payments = createPaymentsClient();
31
+ * const { url } = await payments.onboardingLink({
32
+ * returnUrl: 'https://clinic.example.com/settings/payments?done=1',
33
+ * refreshUrl: 'https://clinic.example.com/settings/payments'
34
+ * });
35
+ * const stripe = createStripeClient({ Stripe });
36
+ * const session = await stripe.checkout.sessions.create({ mode: 'payment', … });
37
+ */
38
+ /** Where the gateway proxies Stripe's API, router-relative. */
39
+ export declare const STRIPE_GATEWAY_ROUTE = "/stripe";
40
+ export interface PaymentsStatus {
41
+ /** The connected account can take card payments. */
42
+ chargesEnabled: boolean;
43
+ /** Stripe can pay out to the clinic's bank account. */
44
+ payoutsEnabled: boolean;
45
+ /** What Stripe still needs (`individual.verification.document`, …). */
46
+ requirementsDue: string[];
47
+ }
48
+ export interface PaymentsClient {
49
+ /**
50
+ * A single-use Stripe-hosted onboarding link for this instance's connected
51
+ * account (created on first use). Send the clinic's owner to `url`; Stripe
52
+ * returns them to `returnUrl`, or to `refreshUrl` when the link expired.
53
+ */
54
+ onboardingLink(params: {
55
+ returnUrl: string;
56
+ refreshUrl: string;
57
+ }): Promise<{
58
+ url: string;
59
+ }>;
60
+ /** Whether the instance can take payments yet. */
61
+ status(): Promise<PaymentsStatus>;
62
+ }
63
+ /** A refusal or failure from the payments gateway. */
64
+ export declare class PaymentsRequestError extends InstanceGatewayRequestError {
65
+ readonly name: 'PaymentsRequestError';
66
+ }
67
+ export declare function createPaymentsClient(options?: InstanceGatewayOptions): PaymentsClient;
68
+ type StripeConstructor = typeof Stripe;
69
+ export interface StripeClientOptions extends InstanceGatewayOptions {
70
+ /**
71
+ * A Stripe secret key, for a service NOT running in managed mode (local
72
+ * development against your own test account, a self-hosted deployment).
73
+ * Ignored in managed mode, where the platform holds the key.
74
+ */
75
+ apiKey?: string;
76
+ /**
77
+ * The `Stripe` class to construct. Pass your own `import Stripe from
78
+ * 'stripe'` when the client is registered with `type: Stripe`: an ESM
79
+ * service and this package could otherwise load different builds of the
80
+ * SDK, and the registration's `instanceof` check would fail. Default: the
81
+ * `stripe` package, loaded on first use (it is an optional peer dependency).
82
+ */
83
+ Stripe?: StripeConstructor;
84
+ /** Extra SDK settings (apiVersion, maxNetworkRetries, timeout, appInfo). */
85
+ config?: Stripe.StripeConfig;
86
+ }
87
+ /**
88
+ * A fetch that sends Stripe SDK requests to the instance gateway, signed.
89
+ *
90
+ * The SDK builds `https://<host>:<port>/v1/...` from the `host`/`port`/
91
+ * `protocol` settings; this rewrites the path under
92
+ * `/instance-gateway/stripe` and adds the instance's HMAC `authorization`,
93
+ * replacing any bearer key. The signature covers the method, the
94
+ * router-relative path WITH its query string (`/stripe/v1/prices?active=true`,
95
+ * so a list filter cannot be altered in flight) and the body exactly as sent:
96
+ * Stripe's bodies are form-encoded, and the raw form string is signed
97
+ * verbatim (framework `createHmacToken` treats a string body as the wire
98
+ * bytes). An empty body signs as no body.
99
+ */
100
+ export declare function stripeGatewayFetch(settings: {
101
+ gatewayUrl: string;
102
+ instanceId: string;
103
+ hmacKey: string;
104
+ }, fetchImpl?: typeof fetch): typeof fetch;
105
+ /**
106
+ * The Stripe SDK for this service.
107
+ *
108
+ * In managed mode (gateway options given, or `PLATFORM_GATEWAY_URL`,
109
+ * `INSTANCE_ID` and `INSTANCE_HMAC_KEY` set) it is a real `Stripe` whose
110
+ * requests go to the platform's instance gateway, signed with the instance
111
+ * key; there is no Stripe key in the app. Otherwise it is `new
112
+ * Stripe(apiKey)`.
113
+ *
114
+ * Mechanism (stripe-node 22): `host`/`port`/`protocol` point the SDK at the
115
+ * gateway, `httpClient: Stripe.createFetchHttpClient(signedFetch)` rewrites
116
+ * each request under `/instance-gateway/stripe` and signs it (see
117
+ * `stripeGatewayFetch`), and a no-op `authenticator` stands in for the API
118
+ * key so no bearer credential is ever sent. Retries re-enter the fetch, so
119
+ * each attempt carries a fresh nonce.
120
+ */
121
+ export declare function createStripeClient(options?: StripeClientOptions): Stripe;
122
+ export {};
123
+ //# sourceMappingURL=paymentsClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymentsClient.d.ts","sourceRoot":"","sources":["../../src/http/paymentsClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAGL,2BAA2B,EAG3B,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,cAAc,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,cAAc,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,cAAc,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7B,kDAAkD;IAClD,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;CACnC;AAED,sDAAsD;AACtD,qBAAa,oBAAqB,SAAQ,2BAA2B;IACnE,SAAkB,IAAI,EAAG,sBAAsB,CAAU;CAC1D;AAED,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,sBAA2B,GACnC,cAAc,CAuChB;AAED,KAAK,iBAAiB,GAAG,OAAO,MAAM,CAAC;AAEvC,MAAM,WAAW,mBAAoB,SAAQ,sBAAsB;IACjE;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC;CAC9B;AAsBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACrE,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,KAAK,CAqDd;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAoC5E"}
@@ -0,0 +1,123 @@
1
+ import { InstanceGatewayRequestError, type InstanceGatewayOptions, type PlatformEvent } from './instanceGateway';
2
+ /**
3
+ * Client for platform-held SMS (AWS End User Messaging SMS), used from inside
4
+ * a managed instance.
5
+ *
6
+ * The instance never holds an AWS credential or a phone number. It signs each
7
+ * send with its own HMAC key; the platform checks the instance's monthly
8
+ * segment cap, its rate limit and its opt-out list, then sends from the
9
+ * product's origination pool under a configuration set named for the
10
+ * instance, so delivery receipts come back to this instance and no other.
11
+ *
12
+ * Events arrive at `POST /platform-events/sms` (verify them with
13
+ * `verifyPlatformEvent`): `sms.delivered`, `sms.failed`, `sms.received`
14
+ * (a reply) and `sms.opted_out` (the person texted STOP; further sends to that
15
+ * number are refused with 422).
16
+ *
17
+ * A text message is not a secure channel: carriers, the handset's lock screen
18
+ * and anyone holding the phone can read it. Never put protected data (a
19
+ * `.deanon` value, a diagnosis, a result) in `body`; send a link to sign in
20
+ * instead. `forklaunch score` flags it (`sms-protected-data`).
21
+ *
22
+ * Locally, run the gateway mock (`npx -p @forklaunch/core
23
+ * forklaunch-gateway-mock`, or the `gateway-mock` compose service that
24
+ * `forklaunch infra add <service> sms` wires) and point PLATFORM_GATEWAY_URL,
25
+ * INSTANCE_ID and INSTANCE_HMAC_KEY at it.
26
+ *
27
+ * @example
28
+ * const sms = createSmsClient();
29
+ * const { messageId, segments } = await sms.send({
30
+ * to: '+14155550123',
31
+ * body: 'Your appointment is confirmed. Sign in for details: https://…',
32
+ * purpose: 'transactional'
33
+ * });
34
+ */
35
+ export interface SmsClientOptions extends InstanceGatewayOptions {
36
+ /**
37
+ * Refuse on the first `send` rather than at creation when the service is
38
+ * not a managed instance. For dependency containers that build singletons
39
+ * at boot, so a local run without the gateway still starts.
40
+ */
41
+ deferRefusal?: boolean;
42
+ }
43
+ export type SmsPurpose = 'transactional' | 'promotional';
44
+ export interface SmsSendRequest {
45
+ /** E.164, e.g. `+14155550123`. */
46
+ to: string;
47
+ /** Plain text. At most `SMS_MAX_SEGMENTS` segments. */
48
+ body: string;
49
+ /** Default `transactional`. Promotional texts need prior marketing consent. */
50
+ purpose?: SmsPurpose;
51
+ }
52
+ export interface SmsSendResult {
53
+ /** The vendor's message id; delivery events carry it. */
54
+ messageId: string;
55
+ /** Billed segments (a long or non-GSM message is several). */
56
+ segments: number;
57
+ }
58
+ export interface SmsDeliveredData {
59
+ messageId: string;
60
+ to: string;
61
+ deliveredAt?: string;
62
+ }
63
+ export interface SmsFailedData {
64
+ messageId: string;
65
+ to: string;
66
+ reason: string;
67
+ }
68
+ export interface SmsReceivedData {
69
+ from: string;
70
+ body: string;
71
+ receivedAt: string;
72
+ /** The recognized keyword (STOP, HELP, START…), when the text was one. */
73
+ keyword?: string;
74
+ }
75
+ export interface SmsOptedOutData {
76
+ phone: string;
77
+ optedOutAt: string;
78
+ }
79
+ /** The events the platform delivers for SMS. */
80
+ export type SmsEvent = (PlatformEvent<SmsDeliveredData> & {
81
+ type: 'sms.delivered';
82
+ }) | (PlatformEvent<SmsFailedData> & {
83
+ type: 'sms.failed';
84
+ }) | (PlatformEvent<SmsReceivedData> & {
85
+ type: 'sms.received';
86
+ }) | (PlatformEvent<SmsOptedOutData> & {
87
+ type: 'sms.opted_out';
88
+ });
89
+ /** A refusal or failure from the SMS gateway, with the status it answered. */
90
+ export declare class SmsRequestError extends InstanceGatewayRequestError {
91
+ readonly name: 'SmsRequestError';
92
+ }
93
+ /** An input the client refuses before any network call. */
94
+ export declare class SmsValidationError extends Error {
95
+ readonly name: 'SmsValidationError';
96
+ }
97
+ export declare const SMS_MAX_SEGMENTS = 10;
98
+ export declare function isE164(phone: string): boolean;
99
+ /**
100
+ * How many segments a body is billed as: GSM-7 is 160 septets in one
101
+ * segment, 153 per segment when split; anything outside GSM-7 is UCS-2, 70
102
+ * characters in one, 67 per segment (UTF-16 code units).
103
+ */
104
+ export declare function smsSegments(body: string): {
105
+ encoding: 'GSM-7' | 'UCS-2';
106
+ units: number;
107
+ segments: number;
108
+ };
109
+ /** Check a send before it leaves the process; throws SmsValidationError. */
110
+ export declare function validateSmsSend(request: SmsSendRequest): void;
111
+ /**
112
+ * Sends texts through the platform. A class so a dependency container can
113
+ * register it by type (`type: SmsClient`); build it with `createSmsClient`.
114
+ */
115
+ export declare class SmsClient {
116
+ private readonly transport?;
117
+ constructor(options?: SmsClientOptions);
118
+ /** Whether sends can reach the gateway (false: every send refuses). */
119
+ get managed(): boolean;
120
+ send(request: SmsSendRequest): Promise<SmsSendResult>;
121
+ }
122
+ export declare function createSmsClient(options?: SmsClientOptions): SmsClient;
123
+ //# sourceMappingURL=smsClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smsClient.d.ts","sourceRoot":"","sources":["../../src/http/smsClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import { type InstanceGatewayOptions, InstanceGatewayRequestError } from './instanceGateway';
2
+ /**
3
+ * Client for platform-held voice calls (Amazon Connect), used from inside a
4
+ * managed instance.
5
+ *
6
+ * The instance never holds an AWS credential, a Connect instance id or a
7
+ * contact-flow ARN. It asks the platform to place a call with a FLOW NAME from
8
+ * the product's flow catalog (`appointment_reminder`, …); the platform maps it
9
+ * to the contact flow, dials from the phone number claimed for this instance,
10
+ * and enforces the instance's concurrent-call and monthly-minute limits.
11
+ *
12
+ * Call progress arrives as platform events on `/platform-events/voice`
13
+ * (`voice.call.started`, `voice.call.ended`, `voice.recording.ready`), signed
14
+ * with the instance key; `forklaunch infra add <service> voice` writes the
15
+ * route and a handler stub.
16
+ *
17
+ * Attributes are passed to the contact flow and are stored in Connect's
18
+ * contact records. Put identifiers in them (an appointment id the flow looks
19
+ * up), never health information: the `voice-protected-data` check flags a
20
+ * `.deanon` value flowing into them.
21
+ *
22
+ * Locally, `infra add` points the service at the gateway mock in
23
+ * docker-compose (flows from `MOCK_VOICE_FLOWS`, events delivered back to the
24
+ * service), so the same code runs with no AWS account.
25
+ *
26
+ * @example
27
+ * const voice = createVoiceClient();
28
+ * const { callId } = await voice.startOutboundCall({
29
+ * to: '+15551230000',
30
+ * flow: 'appointment_reminder',
31
+ * attributes: { appointmentId: appt.id }
32
+ * });
33
+ * const { status } = await voice.call(callId);
34
+ */
35
+ export type VoiceClientOptions = InstanceGatewayOptions;
36
+ /** Limits the gateway enforces on attributes; the client checks them first. */
37
+ export declare const VOICE_ATTRIBUTE_LIMITS: {
38
+ readonly maxKeys: 20;
39
+ readonly maxKeyLength: 64;
40
+ readonly maxValueLength: 256;
41
+ readonly maxTotalBytes: 4096;
42
+ /** Keys the platform reserves (it prefixes and adds its own under `fl_`). */
43
+ readonly reservedPrefix: 'fl_';
44
+ };
45
+ export interface StartOutboundCallRequest {
46
+ /** The number to call, E.164 (`+15551230000`). */
47
+ to: string;
48
+ /** A flow name from the product's catalog, e.g. `appointment_reminder`. */
49
+ flow: string;
50
+ /** String values the contact flow can read. No health information. */
51
+ attributes?: Record<string, string>;
52
+ }
53
+ export interface StartOutboundCallResult {
54
+ callId: string;
55
+ }
56
+ export type VoiceCallStatus = 'initiated' | 'in_progress' | 'ended';
57
+ export interface VoiceCall {
58
+ status: VoiceCallStatus;
59
+ startedAt: string;
60
+ endedAt?: string;
61
+ durationSeconds?: number;
62
+ /** Why it ended: `customer`, `agent`, `api`, `busy`, `no_answer`, … */
63
+ disconnectReason?: string;
64
+ }
65
+ /** Data of `voice.call.started`. */
66
+ export interface VoiceCallStartedEvent {
67
+ callId: string;
68
+ flow?: string;
69
+ }
70
+ /** Data of `voice.call.ended`. */
71
+ export interface VoiceCallEndedEvent {
72
+ callId: string;
73
+ durationSeconds: number;
74
+ disconnectReason: string;
75
+ }
76
+ /** Data of `voice.recording.ready`: the key in the instance's object store. */
77
+ export interface VoiceRecordingReadyEvent {
78
+ callId: string;
79
+ recordingKey: string;
80
+ }
81
+ /** A refusal or failure from the voice gateway, with its status. */
82
+ export declare class VoiceRequestError extends InstanceGatewayRequestError {
83
+ readonly name: 'VoiceRequestError';
84
+ }
85
+ /** Why a request would be refused, or undefined. Shared with the gateway. */
86
+ export declare function voiceRequestProblem(request: StartOutboundCallRequest): string | undefined;
87
+ /**
88
+ * The voice client. A class so a service's registrations.ts can declare it
89
+ * (`type: VoiceClient`); construct it with `createVoiceClient()`.
90
+ */
91
+ export declare class VoiceClient {
92
+ private readonly transport;
93
+ /** Throws when the process is not a managed instance (see instanceGatewaySettings). */
94
+ constructor(options?: VoiceClientOptions);
95
+ /** Place an outbound call; resolves once the platform accepted it. */
96
+ startOutboundCall(request: StartOutboundCallRequest): Promise<StartOutboundCallResult>;
97
+ /** Hang up a call this instance placed. */
98
+ endCall(callId: string): Promise<void>;
99
+ /** Where a call this instance placed stands. */
100
+ call(callId: string): Promise<VoiceCall>;
101
+ private send;
102
+ }
103
+ /** A voice client for this managed instance (settings from the environment). */
104
+ export declare function createVoiceClient(options?: VoiceClientOptions): VoiceClient;
105
+ //# sourceMappingURL=voiceClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voiceClient.d.ts","sourceRoot":"","sources":["../../src/http/voiceClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,2BAA2B,EAE5B,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,CAAC;AAExD,+EAA+E;AAC/E,eAAO,MAAM,sBAAsB;aACjC,OAAO,EAAE,EAAE;aACX,YAAY,EAAE,EAAE;aAChB,cAAc,EAAE,GAAG;aACnB,aAAa,EAAE,IAAI;IACnB,6EAA6E;aAC7E,cAAc,EAAE,KAAK;CACb,CAAC;AAEX,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,aAAa,GAAG,OAAO,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,+EAA+E;AAC/E,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,oEAAoE;AACpE,qBAAa,iBAAkB,SAAQ,2BAA2B;IAChE,SAAkB,IAAI,EAAG,mBAAmB,CAAU;CACvD;AAMD,6EAA6E;AAC7E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,wBAAwB,GAChC,MAAM,GAAG,SAAS,CAuCpB;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2B;IAErD,uFAAuF;IACvF,YAAY,OAAO,GAAE,kBAAuB,EAK3C;IAED,sEAAsE;IAChE,iBAAiB,CACrB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CAQlC;IAED,2CAA2C;IACrC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3C;IAED,gDAAgD;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAE7C;YAEa,IAAI;CAoBnB;AASD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAEb"}