@every-app/sdk 0.2.0 → 0.3.0-rc.10

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 (189) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +609 -3
  3. package/dist/cloudflare/catalogSettings.generated.d.ts +81 -0
  4. package/dist/cloudflare/catalogSettings.generated.d.ts.map +1 -0
  5. package/dist/cloudflare/catalogSettings.generated.js +174 -0
  6. package/dist/cloudflare/index.d.ts +23 -0
  7. package/dist/cloudflare/index.d.ts.map +1 -0
  8. package/dist/cloudflare/index.js +24 -0
  9. package/dist/cloudflare/sentinel.d.ts +127 -0
  10. package/dist/cloudflare/sentinel.d.ts.map +1 -0
  11. package/dist/cloudflare/sentinel.js +85 -0
  12. package/dist/cloudflare/worker.d.ts +805 -0
  13. package/dist/cloudflare/worker.d.ts.map +1 -0
  14. package/dist/cloudflare/worker.js +997 -0
  15. package/dist/dev/index.d.ts +8 -0
  16. package/dist/dev/index.d.ts.map +1 -0
  17. package/dist/dev/index.js +7 -0
  18. package/dist/dev/keypair.d.ts +26 -0
  19. package/dist/dev/keypair.d.ts.map +1 -0
  20. package/dist/dev/keypair.js +62 -0
  21. package/dist/index.d.ts +6 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +5 -0
  24. package/dist/internal/aiDefault.d.ts +204 -0
  25. package/dist/internal/aiDefault.d.ts.map +1 -0
  26. package/dist/internal/aiDefault.js +334 -0
  27. package/dist/internal/aiProviders.d.ts +72 -0
  28. package/dist/internal/aiProviders.d.ts.map +1 -0
  29. package/dist/internal/aiProviders.js +233 -0
  30. package/dist/internal/appSettings.d.ts +315 -0
  31. package/dist/internal/appSettings.d.ts.map +1 -0
  32. package/dist/internal/appSettings.js +549 -0
  33. package/dist/internal/audit.d.ts +108 -0
  34. package/dist/internal/audit.d.ts.map +1 -0
  35. package/dist/internal/audit.js +235 -0
  36. package/dist/internal/capabilities.d.ts +3174 -0
  37. package/dist/internal/capabilities.d.ts.map +1 -0
  38. package/dist/internal/capabilities.js +1110 -0
  39. package/dist/internal/catalog/commerce.d.ts +394 -0
  40. package/dist/internal/catalog/commerce.d.ts.map +1 -0
  41. package/dist/internal/catalog/commerce.js +477 -0
  42. package/dist/internal/catalog/comms.d.ts +375 -0
  43. package/dist/internal/catalog/comms.d.ts.map +1 -0
  44. package/dist/internal/catalog/comms.js +520 -0
  45. package/dist/internal/catalog/index.d.ts +1973 -0
  46. package/dist/internal/catalog/index.d.ts.map +1 -0
  47. package/dist/internal/catalog/index.js +19 -0
  48. package/dist/internal/catalog/inference.d.ts +393 -0
  49. package/dist/internal/catalog/inference.d.ts.map +1 -0
  50. package/dist/internal/catalog/inference.js +460 -0
  51. package/dist/internal/catalog/infra.d.ts +423 -0
  52. package/dist/internal/catalog/infra.d.ts.map +1 -0
  53. package/dist/internal/catalog/infra.js +543 -0
  54. package/dist/internal/catalog/search.d.ts +400 -0
  55. package/dist/internal/catalog/search.d.ts.map +1 -0
  56. package/dist/internal/catalog/search.js +463 -0
  57. package/dist/internal/devProviders.d.ts +49 -0
  58. package/dist/internal/devProviders.d.ts.map +1 -0
  59. package/dist/internal/devProviders.js +80 -0
  60. package/dist/internal/email.d.ts +280 -0
  61. package/dist/internal/email.d.ts.map +1 -0
  62. package/dist/internal/email.js +613 -0
  63. package/dist/internal/events.d.ts +193 -0
  64. package/dist/internal/events.d.ts.map +1 -0
  65. package/dist/internal/events.js +367 -0
  66. package/dist/internal/gatewaySettings.d.ts +83 -0
  67. package/dist/internal/gatewaySettings.d.ts.map +1 -0
  68. package/dist/internal/gatewaySettings.js +215 -0
  69. package/dist/internal/identity.d.ts +57 -5
  70. package/dist/internal/identity.d.ts.map +1 -1
  71. package/dist/internal/identity.js +99 -22
  72. package/dist/internal/index.d.ts +22 -1
  73. package/dist/internal/index.d.ts.map +1 -1
  74. package/dist/internal/index.js +22 -1
  75. package/dist/internal/members.d.ts +36 -0
  76. package/dist/internal/members.d.ts.map +1 -0
  77. package/dist/internal/members.js +7 -0
  78. package/dist/internal/oauthClient.d.ts +61 -0
  79. package/dist/internal/oauthClient.d.ts.map +1 -0
  80. package/dist/internal/oauthClient.js +133 -0
  81. package/dist/internal/oauthPresets.d.ts +33 -0
  82. package/dist/internal/oauthPresets.d.ts.map +1 -0
  83. package/dist/internal/oauthPresets.js +1064 -0
  84. package/dist/internal/oauthScopes.d.ts +172 -0
  85. package/dist/internal/oauthScopes.d.ts.map +1 -0
  86. package/dist/internal/oauthScopes.js +510 -0
  87. package/dist/internal/oauthSpec.d.ts +102 -0
  88. package/dist/internal/oauthSpec.d.ts.map +1 -0
  89. package/dist/internal/oauthSpec.js +789 -0
  90. package/dist/internal/organizationName.d.ts +18 -0
  91. package/dist/internal/organizationName.d.ts.map +1 -0
  92. package/dist/internal/organizationName.js +24 -0
  93. package/dist/internal/protocol.d.ts +150 -3
  94. package/dist/internal/protocol.d.ts.map +1 -1
  95. package/dist/internal/protocol.js +163 -2
  96. package/dist/internal/providerApps.d.ts +75 -0
  97. package/dist/internal/providerApps.d.ts.map +1 -0
  98. package/dist/internal/providerApps.js +59 -0
  99. package/dist/internal/providerRegistry.d.ts +218 -0
  100. package/dist/internal/providerRegistry.d.ts.map +1 -0
  101. package/dist/internal/providerRegistry.js +432 -0
  102. package/dist/internal/providerSpec.d.ts +66 -0
  103. package/dist/internal/providerSpec.d.ts.map +1 -0
  104. package/dist/internal/providerSpec.js +1154 -0
  105. package/dist/internal/remoteMcp.d.ts +188 -0
  106. package/dist/internal/remoteMcp.d.ts.map +1 -0
  107. package/dist/internal/remoteMcp.js +543 -0
  108. package/dist/internal/signInProviders.d.ts +104 -0
  109. package/dist/internal/signInProviders.d.ts.map +1 -0
  110. package/dist/internal/signInProviders.js +245 -0
  111. package/dist/internal/tools.d.ts +115 -0
  112. package/dist/internal/tools.d.ts.map +1 -0
  113. package/dist/internal/tools.js +80 -0
  114. package/dist/manifest.d.ts +238 -0
  115. package/dist/manifest.d.ts.map +1 -0
  116. package/dist/manifest.js +30 -0
  117. package/dist/server/ai.d.ts +111 -0
  118. package/dist/server/ai.d.ts.map +1 -0
  119. package/dist/server/ai.js +145 -0
  120. package/dist/server/aiBinding.d.ts +68 -0
  121. package/dist/server/aiBinding.d.ts.map +1 -0
  122. package/dist/server/aiBinding.js +294 -0
  123. package/dist/server/attribution.d.ts +43 -0
  124. package/dist/server/attribution.d.ts.map +1 -0
  125. package/dist/server/attribution.js +75 -0
  126. package/dist/server/authorizeUrl.d.ts +43 -0
  127. package/dist/server/authorizeUrl.d.ts.map +1 -0
  128. package/dist/server/authorizeUrl.js +106 -0
  129. package/dist/server/connectUrl.d.ts +21 -0
  130. package/dist/server/connectUrl.d.ts.map +1 -0
  131. package/dist/server/connectUrl.js +37 -0
  132. package/dist/server/context.d.ts +68 -0
  133. package/dist/server/context.d.ts.map +1 -0
  134. package/dist/server/context.js +117 -0
  135. package/dist/server/emailBinding.d.ts +72 -0
  136. package/dist/server/emailBinding.d.ts.map +1 -0
  137. package/dist/server/emailBinding.js +124 -0
  138. package/dist/server/emit.d.ts +63 -0
  139. package/dist/server/emit.d.ts.map +1 -0
  140. package/dist/server/emit.js +101 -0
  141. package/dist/server/env.d.ts +44 -0
  142. package/dist/server/env.d.ts.map +1 -0
  143. package/dist/server/env.js +1 -0
  144. package/dist/server/everyApp.d.ts +65 -19
  145. package/dist/server/everyApp.d.ts.map +1 -1
  146. package/dist/server/everyApp.js +195 -30
  147. package/dist/server/fromMcpTools.d.ts +89 -0
  148. package/dist/server/fromMcpTools.d.ts.map +1 -0
  149. package/dist/server/fromMcpTools.js +192 -0
  150. package/dist/server/gatewayFetch.d.ts +54 -14
  151. package/dist/server/gatewayFetch.d.ts.map +1 -1
  152. package/dist/server/gatewayFetch.js +201 -37
  153. package/dist/server/gatewayUrl.d.ts +13 -0
  154. package/dist/server/gatewayUrl.d.ts.map +1 -0
  155. package/dist/server/gatewayUrl.js +34 -0
  156. package/dist/server/index.d.ts +23 -3
  157. package/dist/server/index.d.ts.map +1 -1
  158. package/dist/server/index.js +19 -2
  159. package/dist/server/integrationFetch.d.ts +162 -0
  160. package/dist/server/integrationFetch.d.ts.map +1 -0
  161. package/dist/server/integrationFetch.js +688 -0
  162. package/dist/server/listMembers.d.ts +32 -0
  163. package/dist/server/listMembers.d.ts.map +1 -0
  164. package/dist/server/listMembers.js +71 -0
  165. package/dist/server/nodeServer.d.ts +48 -0
  166. package/dist/server/nodeServer.d.ts.map +1 -0
  167. package/dist/server/nodeServer.js +45 -0
  168. package/dist/server/refusal.d.ts +55 -0
  169. package/dist/server/refusal.d.ts.map +1 -0
  170. package/dist/server/refusal.js +193 -0
  171. package/dist/server/sendEmail.d.ts +39 -0
  172. package/dist/server/sendEmail.d.ts.map +1 -0
  173. package/dist/server/sendEmail.js +114 -0
  174. package/dist/server/tools.d.ts +184 -0
  175. package/dist/server/tools.d.ts.map +1 -0
  176. package/dist/server/tools.js +347 -0
  177. package/dist/server/toolsEndpoint.d.ts +32 -0
  178. package/dist/server/toolsEndpoint.d.ts.map +1 -0
  179. package/dist/server/toolsEndpoint.js +237 -0
  180. package/dist/tanstack-start/index.d.ts +9 -0
  181. package/dist/tanstack-start/index.d.ts.map +1 -0
  182. package/dist/tanstack-start/index.js +29 -0
  183. package/dist/testing/index.d.ts +93 -0
  184. package/dist/testing/index.d.ts.map +1 -0
  185. package/dist/testing/index.js +156 -0
  186. package/package.json +42 -8
  187. package/dist/server/mcp.d.ts +0 -66
  188. package/dist/server/mcp.d.ts.map +0 -1
  189. package/dist/server/mcp.js +0 -147
@@ -0,0 +1,193 @@
1
+ /**
2
+ * The event bus's shared contract (docs/design/2026-10-events-out.md): the
3
+ * catalogue of types the gateway emits, the pattern a subscription matches
4
+ * them by, the shape and size an app's own event may have, the headers a
5
+ * delivery carries, and every limit, in one place the gateway, the CLI
6
+ * (`everyapp events`), the SDK (`emit`) and the docs drift test read.
7
+ *
8
+ * The gateway builds each type's `data` and summary in
9
+ * apps/every-app-gateway/src/server/events/catalogue.ts; this module knows
10
+ * the names, versions and one-line descriptions only.
11
+ */
12
+ export type EventGroup = "member" | "organization" | "app" | "cap" | "group" | "tool" | "connection" | "token" | "access" | "signin_provider" | "mcp_app" | "provider" | "subscription" | "ai" | "ping";
13
+ export interface EventTypeInfo {
14
+ /** `member.joined`, `cap.reached`, … */
15
+ readonly type: string;
16
+ /** Bumped when the type's `data` changes shape; the old one stays documented. */
17
+ readonly version: number;
18
+ /** One line, for `everyapp events types`, the Add dialog and the docs. */
19
+ readonly description: string;
20
+ readonly group: EventGroup;
21
+ }
22
+ /**
23
+ * Every type the gateway itself emits, in the order the docs list them.
24
+ * An app's own events (`app.<id>.<name>`, {@link appEventType}) are a
25
+ * pattern, not entries here. Reserved entries are emitted by sibling
26
+ * features (remote MCP apps, the provider registry) through the same bus.
27
+ */
28
+ export declare const EVENT_TYPES: readonly EventTypeInfo[];
29
+ /** The catalogue entry for a type, or undefined for an app's own event. */
30
+ export declare function eventTypeInfo(type: string): EventTypeInfo | undefined;
31
+ /** The prefix every app's own event carries: `app.<app id>.<name>`. */
32
+ export declare const APP_EVENT_PREFIX = "app.";
33
+ /** An app's event name: `invoice.paid`, `todo_completed`; lowercase, dotted. */
34
+ export declare const APP_EVENT_NAME_PATTERN: RegExp;
35
+ export declare const APP_EVENT_NAME_MAX = 64;
36
+ /** The type an app's event is delivered as. */
37
+ export declare function appEventType(appId: string, name: string): string;
38
+ /**
39
+ * Whether `type` is an app's own event (`app.<id>.<name>`) rather than one
40
+ * of the gateway's `app.*` entries, which have exactly one segment after
41
+ * the prefix.
42
+ */
43
+ export declare function isAppOwnEventType(type: string): boolean;
44
+ /** What is wrong with an app event's name, or null. */
45
+ export declare function appEventNameProblem(name: unknown): string | null;
46
+ /** Bytes of `data` an app's event may carry, serialized. */
47
+ export declare const APP_EVENT_DATA_MAX_BYTES: number;
48
+ /** Bytes of `data` any event row may carry (the gateway's own included). */
49
+ export declare const EVENT_DATA_MAX_BYTES: number;
50
+ /** How deep `data` may nest. */
51
+ export declare const EVENT_DATA_MAX_DEPTH = 8;
52
+ /** Emits per app per hour (`rate_limit_counters`). */
53
+ export declare const APP_EVENT_RATE_PER_HOUR = 600;
54
+ /** Subscriptions per organization. */
55
+ export declare const EVENT_SUBSCRIPTIONS_MAX = 25;
56
+ /** A webhook signing secret's length. */
57
+ export declare const EVENT_SECRET_MIN_LENGTH = 16;
58
+ export declare const EVENT_SECRET_MAX_LENGTH = 128;
59
+ /**
60
+ * Deliveries (the queue and its log) are kept this long. Events themselves
61
+ * are the audit log and live longer ({@link AUDIT_RETENTION_DAYS}).
62
+ */
63
+ export declare const EVENT_RETENTION_DAYS = 30;
64
+ /**
65
+ * Events are kept this long: Admin → Activity → Audit, `everyapp workspace
66
+ * audit` and `everyapp_workspace_audit` read them back. A constant, not a
67
+ * setting.
68
+ */
69
+ export declare const AUDIT_RETENTION_DAYS = 90;
70
+ /** The most audit rows one page carries, on every surface. */
71
+ export declare const AUDIT_PAGE_MAX = 200;
72
+ /** A subscription's URL. */
73
+ export declare const EVENT_URL_MAX_LENGTH = 2048;
74
+ /** A subscription's name. */
75
+ export declare const EVENT_SUBSCRIPTION_NAME_MAX = 100;
76
+ /**
77
+ * The wait after attempt n fails (n from 1): the first attempt is right
78
+ * after the event; the seventh failure is dead (about 35 hours in all).
79
+ */
80
+ export declare const EVENT_RETRY_DELAYS_MS: readonly number[];
81
+ export declare const EVENT_DELIVERY_MAX_ATTEMPTS: number;
82
+ /** A webhook's answer is awaited this long. */
83
+ export declare const EVENT_DELIVERY_TIMEOUT_MS = 10000;
84
+ /** How much of a failed answer's body is read, and how much is kept. */
85
+ export declare const EVENT_RESPONSE_READ_MAX_BYTES = 1024;
86
+ export declare const EVENT_RESPONSE_KEEP_CHARS = 200;
87
+ /** The age of a signature's timestamp a receiver should accept. */
88
+ export declare const EVENT_SIGNATURE_TOLERANCE_SECONDS = 300;
89
+ /** The app-to-gateway route an app emits on (over the EVERY_APP_GATEWAY binding). */
90
+ export declare const EVENTS_EMIT_PATH = "/api/events/emit";
91
+ /** The headers every webhook delivery carries. */
92
+ export declare const EVENT_HEADERS: {
93
+ readonly event: "x-everyapp-event";
94
+ readonly eventId: "x-everyapp-event-id";
95
+ readonly delivery: "x-everyapp-delivery";
96
+ readonly attempt: "x-everyapp-attempt";
97
+ readonly signature: "x-everyapp-signature";
98
+ };
99
+ /** The Gateway setting that lets http: and private hosts be targets. */
100
+ export declare const EVENTS_ALLOW_PRIVATE_TARGETS_SETTING = "EVENTS_ALLOW_PRIVATE_TARGETS";
101
+ /**
102
+ * Name suffixes (and exact names) that mean a local or private machine: a
103
+ * webhook target under one is refused unless EVENTS_ALLOW_PRIVATE_TARGETS
104
+ * is "true". One list for the gateway (which checks a URL before every
105
+ * attempt) and the CLI (which checks it when `everyapp events add` writes
106
+ * the subscription), so the two never drift.
107
+ */
108
+ export declare const EVENT_PRIVATE_NAME_SUFFIXES: readonly string[];
109
+ /**
110
+ * Whether a normalized hostname (lowercase, no trailing dot) is a local or
111
+ * private name: one of {@link EVENT_PRIVATE_NAME_SUFFIXES}, a name under
112
+ * one (`n8n.lan`, `hooks.acme.corp`), or a bare label (`n8n`), which only
113
+ * a private resolver answers.
114
+ */
115
+ export declare function isPrivateEventTargetName(host: string): boolean;
116
+ /** The sinks a subscription delivers to. */
117
+ export declare const EVENT_SINKS: readonly ["webhook", "email"];
118
+ export type EventSink = (typeof EVENT_SINKS)[number];
119
+ /** Whom the email sink mails: the organization's owners, or owners and admins. */
120
+ export declare const EVENT_EMAIL_RECIPIENTS: readonly ["owners", "admins"];
121
+ export type EventEmailRecipients = (typeof EVENT_EMAIL_RECIPIENTS)[number];
122
+ /**
123
+ * A subscription pattern: `*` (everything but ping), an exact type, or a
124
+ * prefix with `.*` (`member.*`, `app.*`, `app.crm.*`). `app.*` matches the
125
+ * gateway's app events and every app's own.
126
+ */
127
+ export declare function eventPatternMatches(pattern: string, type: string): boolean;
128
+ /** Whether any of a subscription's patterns matches the type. */
129
+ export declare function eventSubscribed(patterns: readonly string[], type: string): boolean;
130
+ /**
131
+ * What is wrong with a pattern someone typed, or null: a known type, a
132
+ * prefix of known types (`member.*`), an app's own events (`app.crm.*`,
133
+ * `app.crm.invoice.paid`), or `*`.
134
+ */
135
+ export declare function eventPatternProblem(pattern: string): string | null;
136
+ /**
137
+ * A key that reads like a credential. An event's `data` is refused when any
138
+ * key, at any depth, matches: a payload can't carry a secret by accident,
139
+ * whether an app's own or the gateway's (the catalogue's builders are
140
+ * checked by the same rule).
141
+ */
142
+ export declare const CREDENTIAL_KEY_PATTERN: RegExp;
143
+ export type EventDataProblem = {
144
+ code: "event_data_invalid";
145
+ message: string;
146
+ } | {
147
+ code: "event_data_too_large";
148
+ message: string;
149
+ bytes: number;
150
+ } | {
151
+ code: "event_data_refused";
152
+ message: string;
153
+ key: string;
154
+ };
155
+ export type EventDataCheck = {
156
+ ok: true;
157
+ bytes: number;
158
+ } | ({
159
+ ok: false;
160
+ } & EventDataProblem);
161
+ /**
162
+ * Check an event's `data`: a JSON object (not an array, not a scalar), at
163
+ * most `maxBytes` serialized, nested at most {@link EVENT_DATA_MAX_DEPTH}
164
+ * deep, with no key named like a credential. Functions, bigints, dates and
165
+ * the like must already be plain JSON: the caller serializes what it got.
166
+ */
167
+ export declare function checkEventData(data: unknown, maxBytes?: number): EventDataCheck;
168
+ /** What `POST /api/events/emit` takes from an app. */
169
+ export interface EmitEventRequest {
170
+ /** The app's own name for the event (`invoice.paid`). */
171
+ event: string;
172
+ data: Record<string, unknown>;
173
+ }
174
+ /** What it answers. */
175
+ export interface EmitEventResult {
176
+ /** The event's id (`evt_…`), or `dev-…` under `everyapp dev`. */
177
+ id: string;
178
+ /** The delivered type: `app.<app id>.<event>`. */
179
+ type: string;
180
+ }
181
+ /**
182
+ * The string a webhook delivery is signed over: the timestamp (seconds
183
+ * since the epoch), a dot, the exact body.
184
+ */
185
+ export declare function eventSigningInput(timestamp: number, body: string): string;
186
+ /** `t=<seconds>,v1=<hex>`, as the signature header carries it. */
187
+ export declare function formatEventSignature(timestamp: number, hexDigest: string): string;
188
+ /** The parts of a signature header, or null when it isn't one. */
189
+ export declare function parseEventSignature(header: string | null | undefined): {
190
+ timestamp: number;
191
+ v1: string[];
192
+ } | null;
193
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/internal/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,367 @@
1
+ /**
2
+ * The event bus's shared contract (docs/design/2026-10-events-out.md): the
3
+ * catalogue of types the gateway emits, the pattern a subscription matches
4
+ * them by, the shape and size an app's own event may have, the headers a
5
+ * delivery carries, and every limit, in one place the gateway, the CLI
6
+ * (`everyapp events`), the SDK (`emit`) and the docs drift test read.
7
+ *
8
+ * The gateway builds each type's `data` and summary in
9
+ * apps/every-app-gateway/src/server/events/catalogue.ts; this module knows
10
+ * the names, versions and one-line descriptions only.
11
+ */
12
+ const entry = (group, type, description, version = 1) => ({ type, version, description, group });
13
+ /**
14
+ * Every type the gateway itself emits, in the order the docs list them.
15
+ * An app's own events (`app.<id>.<name>`, {@link appEventType}) are a
16
+ * pattern, not entries here. Reserved entries are emitted by sibling
17
+ * features (remote MCP apps, the provider registry) through the same bus.
18
+ */
19
+ export const EVENT_TYPES = [
20
+ entry("member", "member.invited", "Someone was invited to the workspace"),
21
+ entry("member", "member.joined", "Someone joined the workspace"),
22
+ entry("member", "member.role_changed", "A member's role changed"),
23
+ entry("member", "member.deactivated", "A member was deactivated"),
24
+ entry("member", "member.reactivated", "A member was reactivated"),
25
+ entry("member", "member.removed", "A member was removed"),
26
+ entry("member", "member.password_reset", "A member reset their password"),
27
+ entry("member", "member.invitation_cancelled", "A pending invitation was cancelled"),
28
+ entry("organization", "organization.renamed", "The workspace was renamed"),
29
+ entry("organization", "organization.linked_dev_changed", "Linked dev (everyapp dev against this Gateway) was turned on or off"),
30
+ entry("app", "app.installed", "An app was installed on the Gateway"),
31
+ entry("app", "app.updated", "An app was redeployed"),
32
+ entry("app", "app.live", "An app went live on the Gateway"),
33
+ entry("app", "app.removed", "An app was removed from the Gateway"),
34
+ entry("app", "app.needs_setup", "An app needs a setting before it opens"),
35
+ entry("app", "app.ready", "An app has every setting it needs"),
36
+ entry("app", "app.paused_cap", "An app is paused: its monthly cap is reached"),
37
+ entry("app", "app.tools_changed", "An app's AI tools changed"),
38
+ entry("app", "app.renamed", "An app's name or description changed"),
39
+ entry("app", "app.settings_changed", "An app's settings were set or unset (names only)"),
40
+ entry("app", "app.access_changed", "Who can open an app changed"),
41
+ entry("app", "app.email_changed", "An app's email senders or inbound changed"),
42
+ entry("cap", "cap.warning", "An app is at 80% of its monthly cap"),
43
+ entry("cap", "cap.reached", "An app reached its monthly cap"),
44
+ entry("cap", "cap.raised", "An app's monthly cap, or the workspace default, was raised or removed"),
45
+ entry("cap", "cap.changed", "An app's monthly cap, or the workspace default, was set or lowered"),
46
+ entry("group", "group.created", "A group was created"),
47
+ entry("group", "group.updated", "A group was renamed or described"),
48
+ entry("group", "group.removed", "A group was removed"),
49
+ entry("group", "group.members_changed", "A group's members changed"),
50
+ entry("group", "group.apps_changed", "The apps a group opens changed"),
51
+ entry("tool", "tool.blocked", "An AI client's tool call was blocked"),
52
+ entry("tool", "tool.error", "An AI client's tool call failed"),
53
+ entry("connection", "connection.created", "An AI app was connected"),
54
+ entry("connection", "connection.revoked", "An AI app connection was revoked"),
55
+ entry("connection", "connection.used", "Linked dev used the Gateway's services (first call of the day)"),
56
+ entry("token", "token.created", "A personal access token was created"),
57
+ entry("token", "token.revoked", "A personal access token was revoked"),
58
+ entry("access", "access.changed", "Cloudflare Access was turned on or off"),
59
+ entry("signin_provider", "signin_provider.added", "A sign-in provider (Continue with Google, …) was turned on"),
60
+ entry("signin_provider", "signin_provider.removed", "A sign-in provider was turned off"),
61
+ entry("mcp_app", "mcp_app.added", "An MCP app was added"),
62
+ entry("mcp_app", "mcp_app.removed", "An MCP app was removed"),
63
+ entry("mcp_app", "mcp_app.enabled", "An MCP app is being served again"),
64
+ entry("mcp_app", "mcp_app.disabled", "An MCP app stopped being served"),
65
+ entry("mcp_app", "mcp_app.updated", "An MCP app's risk default, name or description changed"),
66
+ entry("mcp_app", "mcp_app.tool_changed", "One tool of an MCP app was overridden: its risk, or on/off"),
67
+ entry("provider", "provider.added", "A provider was registered"),
68
+ entry("provider", "provider.removed", "A provider was removed"),
69
+ entry("provider", "provider.updated", "A provider's spec or OAuth client was replaced"),
70
+ entry("provider", "provider.connected", "Someone connected an account at an OAuth provider"),
71
+ entry("provider", "provider.disconnected", "An OAuth provider account was disconnected"),
72
+ entry("provider", "provider.connection_expired", "An OAuth provider refused to refresh a connection; it needs reconnecting"),
73
+ entry("subscription", "subscription.created", "An event subscription was added"),
74
+ entry("subscription", "subscription.updated", "An event subscription was changed, paused or resumed"),
75
+ entry("subscription", "subscription.removed", "An event subscription was removed"),
76
+ entry("subscription", "subscription.redelivered", "A delivery was queued again by hand"),
77
+ entry("ai", "ai.default_changed", "The default model provider changed"),
78
+ entry("ai", "ai.model_changed", "A provider's default model changed"),
79
+ entry("ping", "ping", "A test event, sent to one subscription on request"),
80
+ ];
81
+ const typesByName = new Map(EVENT_TYPES.map((info) => [info.type, info]));
82
+ /** The catalogue entry for a type, or undefined for an app's own event. */
83
+ export function eventTypeInfo(type) {
84
+ return typesByName.get(type);
85
+ }
86
+ /** The prefix every app's own event carries: `app.<app id>.<name>`. */
87
+ export const APP_EVENT_PREFIX = "app.";
88
+ /** An app's event name: `invoice.paid`, `todo_completed`; lowercase, dotted. */
89
+ export const APP_EVENT_NAME_PATTERN = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/;
90
+ export const APP_EVENT_NAME_MAX = 64;
91
+ /** The type an app's event is delivered as. */
92
+ export function appEventType(appId, name) {
93
+ return `${APP_EVENT_PREFIX}${appId}.${name}`;
94
+ }
95
+ /**
96
+ * Whether `type` is an app's own event (`app.<id>.<name>`) rather than one
97
+ * of the gateway's `app.*` entries, which have exactly one segment after
98
+ * the prefix.
99
+ */
100
+ export function isAppOwnEventType(type) {
101
+ return (type.startsWith(APP_EVENT_PREFIX) &&
102
+ !typesByName.has(type) &&
103
+ type.slice(APP_EVENT_PREFIX.length).includes("."));
104
+ }
105
+ /** What is wrong with an app event's name, or null. */
106
+ export function appEventNameProblem(name) {
107
+ if (typeof name !== "string" || name.length === 0) {
108
+ return "event is required: a name like invoice.paid";
109
+ }
110
+ if (name.length > APP_EVENT_NAME_MAX) {
111
+ return `event is at most ${APP_EVENT_NAME_MAX} characters`;
112
+ }
113
+ if (!APP_EVENT_NAME_PATTERN.test(name)) {
114
+ return "event is lowercase letters, digits and underscores, in segments joined by dots (invoice.paid)";
115
+ }
116
+ return null;
117
+ }
118
+ /** Bytes of `data` an app's event may carry, serialized. */
119
+ export const APP_EVENT_DATA_MAX_BYTES = 8 * 1024;
120
+ /** Bytes of `data` any event row may carry (the gateway's own included). */
121
+ export const EVENT_DATA_MAX_BYTES = 16 * 1024;
122
+ /** How deep `data` may nest. */
123
+ export const EVENT_DATA_MAX_DEPTH = 8;
124
+ /** Emits per app per hour (`rate_limit_counters`). */
125
+ export const APP_EVENT_RATE_PER_HOUR = 600;
126
+ /** Subscriptions per organization. */
127
+ export const EVENT_SUBSCRIPTIONS_MAX = 25;
128
+ /** A webhook signing secret's length. */
129
+ export const EVENT_SECRET_MIN_LENGTH = 16;
130
+ export const EVENT_SECRET_MAX_LENGTH = 128;
131
+ /**
132
+ * Deliveries (the queue and its log) are kept this long. Events themselves
133
+ * are the audit log and live longer ({@link AUDIT_RETENTION_DAYS}).
134
+ */
135
+ export const EVENT_RETENTION_DAYS = 30;
136
+ /**
137
+ * Events are kept this long: Admin → Activity → Audit, `everyapp workspace
138
+ * audit` and `everyapp_workspace_audit` read them back. A constant, not a
139
+ * setting.
140
+ */
141
+ export const AUDIT_RETENTION_DAYS = 90;
142
+ /** The most audit rows one page carries, on every surface. */
143
+ export const AUDIT_PAGE_MAX = 200;
144
+ /** A subscription's URL. */
145
+ export const EVENT_URL_MAX_LENGTH = 2048;
146
+ /** A subscription's name. */
147
+ export const EVENT_SUBSCRIPTION_NAME_MAX = 100;
148
+ /**
149
+ * The wait after attempt n fails (n from 1): the first attempt is right
150
+ * after the event; the seventh failure is dead (about 35 hours in all).
151
+ */
152
+ export const EVENT_RETRY_DELAYS_MS = [
153
+ 60_000, 300_000, 1_800_000, 7_200_000, 28_800_000, 86_400_000,
154
+ ];
155
+ export const EVENT_DELIVERY_MAX_ATTEMPTS = EVENT_RETRY_DELAYS_MS.length + 1;
156
+ /** A webhook's answer is awaited this long. */
157
+ export const EVENT_DELIVERY_TIMEOUT_MS = 10_000;
158
+ /** How much of a failed answer's body is read, and how much is kept. */
159
+ export const EVENT_RESPONSE_READ_MAX_BYTES = 1024;
160
+ export const EVENT_RESPONSE_KEEP_CHARS = 200;
161
+ /** The age of a signature's timestamp a receiver should accept. */
162
+ export const EVENT_SIGNATURE_TOLERANCE_SECONDS = 300;
163
+ /** The app-to-gateway route an app emits on (over the EVERY_APP_GATEWAY binding). */
164
+ export const EVENTS_EMIT_PATH = "/api/events/emit";
165
+ /** The headers every webhook delivery carries. */
166
+ export const EVENT_HEADERS = {
167
+ event: "x-everyapp-event",
168
+ eventId: "x-everyapp-event-id",
169
+ delivery: "x-everyapp-delivery",
170
+ attempt: "x-everyapp-attempt",
171
+ signature: "x-everyapp-signature",
172
+ };
173
+ /** The Gateway setting that lets http: and private hosts be targets. */
174
+ export const EVENTS_ALLOW_PRIVATE_TARGETS_SETTING = "EVENTS_ALLOW_PRIVATE_TARGETS";
175
+ /**
176
+ * Name suffixes (and exact names) that mean a local or private machine: a
177
+ * webhook target under one is refused unless EVENTS_ALLOW_PRIVATE_TARGETS
178
+ * is "true". One list for the gateway (which checks a URL before every
179
+ * attempt) and the CLI (which checks it when `everyapp events add` writes
180
+ * the subscription), so the two never drift.
181
+ */
182
+ export const EVENT_PRIVATE_NAME_SUFFIXES = [
183
+ "localhost",
184
+ "local",
185
+ "localdomain",
186
+ "internal",
187
+ "intranet",
188
+ "lan",
189
+ "corp",
190
+ "private",
191
+ "home.arpa",
192
+ "onion",
193
+ ];
194
+ /**
195
+ * Whether a normalized hostname (lowercase, no trailing dot) is a local or
196
+ * private name: one of {@link EVENT_PRIVATE_NAME_SUFFIXES}, a name under
197
+ * one (`n8n.lan`, `hooks.acme.corp`), or a bare label (`n8n`), which only
198
+ * a private resolver answers.
199
+ */
200
+ export function isPrivateEventTargetName(host) {
201
+ if (!host.includes("."))
202
+ return true;
203
+ return EVENT_PRIVATE_NAME_SUFFIXES.some((suffix) => host === suffix || host.endsWith(`.${suffix}`));
204
+ }
205
+ /** The sinks a subscription delivers to. */
206
+ export const EVENT_SINKS = ["webhook", "email"];
207
+ /** Whom the email sink mails: the organization's owners, or owners and admins. */
208
+ export const EVENT_EMAIL_RECIPIENTS = ["owners", "admins"];
209
+ /**
210
+ * A subscription pattern: `*` (everything but ping), an exact type, or a
211
+ * prefix with `.*` (`member.*`, `app.*`, `app.crm.*`). `app.*` matches the
212
+ * gateway's app events and every app's own.
213
+ */
214
+ export function eventPatternMatches(pattern, type) {
215
+ // Everything but a test ping and the bus's own housekeeping: a webhook
216
+ // hears about subscriptions only when it names `subscription.*`, so a
217
+ // catch-all's first delivery is the event it was made for, not itself.
218
+ if (pattern === "*")
219
+ return type !== "ping" && !type.startsWith("subscription.");
220
+ if (pattern.endsWith(".*")) {
221
+ return type.startsWith(pattern.slice(0, -1));
222
+ }
223
+ return pattern === type;
224
+ }
225
+ /** Whether any of a subscription's patterns matches the type. */
226
+ export function eventSubscribed(patterns, type) {
227
+ return patterns.some((pattern) => eventPatternMatches(pattern, type));
228
+ }
229
+ const PATTERN_SHAPE = /^(\*|[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*(\.\*)?)$/;
230
+ /**
231
+ * What is wrong with a pattern someone typed, or null: a known type, a
232
+ * prefix of known types (`member.*`), an app's own events (`app.crm.*`,
233
+ * `app.crm.invoice.paid`), or `*`.
234
+ */
235
+ export function eventPatternProblem(pattern) {
236
+ if (!PATTERN_SHAPE.test(pattern) || pattern.length > APP_EVENT_NAME_MAX + 8) {
237
+ return `"${pattern}" isn't an event type or pattern (member.joined, member.*, app.crm.*, *)`;
238
+ }
239
+ if (pattern === "*" || typesByName.has(pattern))
240
+ return null;
241
+ if (pattern.endsWith(".*")) {
242
+ const prefix = pattern.slice(0, -1);
243
+ if (EVENT_TYPES.some((info) => info.type.startsWith(prefix)))
244
+ return null;
245
+ if (pattern.startsWith(APP_EVENT_PREFIX))
246
+ return null; // app.<id>.*
247
+ return `"${pattern}" matches no event type (everyapp events types lists them)`;
248
+ }
249
+ if (isAppOwnEventType(pattern))
250
+ return null;
251
+ return `"${pattern}" isn't an event type (everyapp events types lists them)`;
252
+ }
253
+ /**
254
+ * A key that reads like a credential. An event's `data` is refused when any
255
+ * key, at any depth, matches: a payload can't carry a secret by accident,
256
+ * whether an app's own or the gateway's (the catalogue's builders are
257
+ * checked by the same rule).
258
+ */
259
+ export const CREDENTIAL_KEY_PATTERN = /secret|token|password|passwd|authorization|api[_-]?key|private[_-]?key|credential|cookie|session/i;
260
+ function findCredentialKey(value, depth) {
261
+ if (depth > EVENT_DATA_MAX_DEPTH)
262
+ return "\0depth";
263
+ if (Array.isArray(value)) {
264
+ for (const item of value) {
265
+ const found = findCredentialKey(item, depth + 1);
266
+ if (found)
267
+ return found;
268
+ }
269
+ return null;
270
+ }
271
+ if (value && typeof value === "object") {
272
+ for (const [key, inner] of Object.entries(value)) {
273
+ if (CREDENTIAL_KEY_PATTERN.test(key))
274
+ return key;
275
+ const found = findCredentialKey(inner, depth + 1);
276
+ if (found)
277
+ return found;
278
+ }
279
+ }
280
+ return null;
281
+ }
282
+ /**
283
+ * Check an event's `data`: a JSON object (not an array, not a scalar), at
284
+ * most `maxBytes` serialized, nested at most {@link EVENT_DATA_MAX_DEPTH}
285
+ * deep, with no key named like a credential. Functions, bigints, dates and
286
+ * the like must already be plain JSON: the caller serializes what it got.
287
+ */
288
+ export function checkEventData(data, maxBytes = APP_EVENT_DATA_MAX_BYTES) {
289
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
290
+ return {
291
+ ok: false,
292
+ code: "event_data_invalid",
293
+ message: "data is a JSON object",
294
+ };
295
+ }
296
+ let serialized;
297
+ try {
298
+ serialized = JSON.stringify(data);
299
+ }
300
+ catch {
301
+ return {
302
+ ok: false,
303
+ code: "event_data_invalid",
304
+ message: "data must serialize as JSON",
305
+ };
306
+ }
307
+ if (serialized === undefined) {
308
+ return {
309
+ ok: false,
310
+ code: "event_data_invalid",
311
+ message: "data is a JSON object",
312
+ };
313
+ }
314
+ const bytes = new TextEncoder().encode(serialized).length;
315
+ if (bytes > maxBytes) {
316
+ return {
317
+ ok: false,
318
+ code: "event_data_too_large",
319
+ message: `data is at most ${maxBytes.toLocaleString("en-US")} bytes as JSON (this is ${bytes.toLocaleString("en-US")})`,
320
+ bytes,
321
+ };
322
+ }
323
+ const key = findCredentialKey(JSON.parse(serialized), 1);
324
+ if (key === "\0depth") {
325
+ return {
326
+ ok: false,
327
+ code: "event_data_invalid",
328
+ message: `data nests at most ${EVENT_DATA_MAX_DEPTH} levels deep`,
329
+ };
330
+ }
331
+ if (key) {
332
+ return {
333
+ ok: false,
334
+ code: "event_data_refused",
335
+ message: `data must not carry a credential: the key "${key}" reads like one (secret, token, password, authorization, api key, private key, credential, cookie, session)`,
336
+ key,
337
+ };
338
+ }
339
+ return { ok: true, bytes };
340
+ }
341
+ /**
342
+ * The string a webhook delivery is signed over: the timestamp (seconds
343
+ * since the epoch), a dot, the exact body.
344
+ */
345
+ export function eventSigningInput(timestamp, body) {
346
+ return `${timestamp}.${body}`;
347
+ }
348
+ /** `t=<seconds>,v1=<hex>`, as the signature header carries it. */
349
+ export function formatEventSignature(timestamp, hexDigest) {
350
+ return `t=${timestamp},v1=${hexDigest}`;
351
+ }
352
+ /** The parts of a signature header, or null when it isn't one. */
353
+ export function parseEventSignature(header) {
354
+ if (!header)
355
+ return null;
356
+ let timestamp = null;
357
+ const v1 = [];
358
+ for (const part of header.split(",")) {
359
+ const [key, value] = part.trim().split("=", 2);
360
+ if (key === "t" && value && /^\d+$/.test(value))
361
+ timestamp = Number(value);
362
+ else if (key === "v1" && value && /^[0-9a-f]{64}$/i.test(value)) {
363
+ v1.push(value.toLowerCase());
364
+ }
365
+ }
366
+ return timestamp !== null && v1.length > 0 ? { timestamp, v1 } : null;
367
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The Gateway's settings and the app's own secrets, by name: the Gateway
3
+ * settings an operator changes with `everyapp secret set <NAME>` (plain
4
+ * secrets on the Gateway Worker, read on its next request), the ones the
5
+ * install writes once, and the names an app's own secret can never take.
6
+ * What an app's manifest needs of them is appSettings.ts. One registry serves
7
+ * the CLI (a Gateway name goes to the Gateway, any other to the app in the
8
+ * current directory), the manifest validator (an app's `secrets` may not
9
+ * take a Gateway name, since the app reaches those through `providers` and
10
+ * `capabilities`) and the Gateway's dev config, which a test keeps
11
+ * declaring every settable one.
12
+ */
13
+ import { type CapabilitySecret } from "./capabilities.js";
14
+ /**
15
+ * The Gateway's own settings: the install writes them once (`everyapp
16
+ * setup`), or an operator by hand (THIRD_PARTY_DEPLOYS), and `everyapp
17
+ * secret set` never changes them. An app's own Worker may still have a
18
+ * secret of the same name (OpenSEO's BETTER_AUTH_SECRET): the two never meet.
19
+ */
20
+ export declare const INSTALL_OWNED_GATEWAY_SETTINGS: readonly ["GATEWAY_URL", "APP_BASE_DOMAIN", "BETTER_AUTH_SECRET", "JWT_PRIVATE_KEY", "JWT_PUBLIC_KEY", "GATEWAY_DEPLOYMENT_MODE", "CLOUDFLARE_ACCOUNT_ID", "THIRD_PARTY_DEPLOYS"];
21
+ export declare function isInstallOwnedGatewaySetting(name: string): boolean;
22
+ /** The Gateway's own optional settings `everyapp secret set` changes: nothing a provider reads. */
23
+ export declare const GATEWAY_OWN_SETTINGS: readonly ["AI_PROXY_EXTRA_ROUTES", "EMAIL_REST_API_TOKEN", "RESEND_API_KEY", "EMAIL_PROVIDER", "EMAIL_FROM", "EMAIL_FROM_NAME", "MCP_OAUTH_ENABLED", "MCP_DCR_ENABLED", "MCP_ALLOWED_ORIGINS", "MCP_AUDIT_RETENTION_DAYS", "CLOUDFLARE_ACCESS_OIDC_ISSUER", "CLOUDFLARE_ACCESS_OIDC_CLIENT_ID", "CLOUDFLARE_ACCESS_OIDC_CLIENT_SECRET", "CLOUDFLARE_ACCESS_OIDC_LABEL", "CLOUDFLARE_ACCESS_TEAM_DOMAIN", "CLOUDFLARE_ACCESS_AUD", "CLOUDFLARE_ACCESS_APPS_AUD", "CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS", "CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN", "EMAIL_PASSWORD_SIGN_IN", "HOSTED_OPEN_SIGNUP", "CF_DEPLOY_TOKEN", "BROWSER_APP_INSTALLS", "DISPATCH_NAMESPACE", "THIRD_PARTY_DOMAIN", "EVENTS_ALLOW_PRIVATE_TARGETS"];
24
+ export type SettableGatewaySetting = Exclude<CapabilitySecret, (typeof INSTALL_OWNED_GATEWAY_SETTINGS)[number]> | (typeof GATEWAY_OWN_SETTINGS)[number];
25
+ /**
26
+ * The Gateway's optional settings `everyapp secret set` changes: every
27
+ * setting a catalog provider reads, the Gateway's own, then the sign-in
28
+ * providers' (`<ID>_SIGNIN_<FIELD>`, ./signInProviders.ts).
29
+ */
30
+ export declare const SETTABLE_GATEWAY_SETTINGS: readonly SettableGatewaySetting[];
31
+ /**
32
+ * The credential names of remote MCP apps (`everyapp mcp add <url>`,
33
+ * ./remoteMcp.ts): `<ID>_MCP_TOKEN` by default, any name ending in
34
+ * `_MCP_TOKEN` by choice. A family rather than a list, so the names a
35
+ * registry row declares at run time route to the Gateway like the fixed
36
+ * names (`everyapp secret set` reads no registry to decide), an app's own
37
+ * secret can never take one (the manifest validator refuses the family),
38
+ * and a remote server can never be given a fixed provider key.
39
+ */
40
+ export declare const REMOTE_MCP_SECRET_PATTERN: RegExp;
41
+ /** Whether `name` is a remote MCP app's credential name (`TREG_MCP_TOKEN`). */
42
+ export declare function isRemoteMcpSecretName(name: string): boolean;
43
+ /**
44
+ * Whether `everyapp secret set <name>` changes the Gateway: one of the
45
+ * fixed settings, or a remote MCP app's credential name.
46
+ */
47
+ export declare function isSettableGatewaySetting(name: string): boolean;
48
+ /**
49
+ * Settable Gateway settings whose value is a plain word, address, list
50
+ * or switch rather than a credential: a sender, a provider choice, a
51
+ * URL, an audience, a flag. `everyapp secret set` may show these as they
52
+ * are typed and check their shape; anything else is a credential and
53
+ * stays hidden.
54
+ */
55
+ export declare const PLAIN_GATEWAY_SETTINGS: readonly ["EMAIL_FROM", "EMAIL_FROM_NAME", "EMAIL_PROVIDER", "EMAIL_PASSWORD_SIGN_IN", "AI_PROXY_EXTRA_ROUTES", "MCP_OAUTH_ENABLED", "MCP_DCR_ENABLED", "MCP_ALLOWED_ORIGINS", "MCP_AUDIT_RETENTION_DAYS", "CLOUDFLARE_ACCESS_OIDC_ISSUER", "CLOUDFLARE_ACCESS_OIDC_CLIENT_ID", "CLOUDFLARE_ACCESS_OIDC_LABEL", "CLOUDFLARE_ACCESS_TEAM_DOMAIN", "CLOUDFLARE_ACCESS_AUD", "CLOUDFLARE_ACCESS_APPS_AUD", "CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS", "CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN", "HOSTED_OPEN_SIGNUP", "BROWSER_APP_INSTALLS", "DISPATCH_NAMESPACE", "THIRD_PARTY_DOMAIN", "EVENTS_ALLOW_PRIVATE_TARGETS"];
56
+ /** Whether a settable Gateway setting's value is a plain value, not a credential. */
57
+ export declare function isPlainGatewaySetting(name: string): boolean;
58
+ /**
59
+ * Settable Gateway settings only the hosted gateway reads: a self-hosted
60
+ * install never needs them, so `secret list` leaves them out there.
61
+ */
62
+ export declare const HOSTED_ONLY_GATEWAY_SETTINGS: readonly ["HOSTED_OPEN_SIGNUP", "DISPATCH_NAMESPACE", "THIRD_PARTY_DOMAIN"];
63
+ export declare function isHostedOnlyGatewaySetting(name: string): boolean;
64
+ /** Gateway settings for local testing only, set in the gateway's `.dev.vars`, never deployed. */
65
+ export declare const DEV_ONLY_GATEWAY_SETTINGS: readonly ["MCP_ACCESS_TOKEN_TTL", "DATAFORSEO_SANDBOX"];
66
+ export declare function isDevOnlyGatewaySetting(name: string): boolean;
67
+ /** What the reserved names are, for messages. */
68
+ export declare const RESERVED_APP_SECRET_NAMES_TEXT = "GATEWAY_URL, CF_VERSION_METADATA and the EVERYAPP_*, EVERY_APP_* and APP__* names";
69
+ export declare function isReservedAppSecretName(name: string): boolean;
70
+ /** Which AI provider or capability reads a Gateway setting, if any does. */
71
+ export type GatewaySettingOwner = {
72
+ kind: "provider";
73
+ id: string;
74
+ } | {
75
+ kind: "capability";
76
+ id: string;
77
+ };
78
+ /**
79
+ * The AI provider or capability a Gateway setting belongs to: what to list
80
+ * in a manifest instead of holding the key as the app's own.
81
+ */
82
+ export declare function gatewaySettingOwner(name: string): GatewaySettingOwner | null;
83
+ //# sourceMappingURL=gatewaySettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gatewaySettings.d.ts","sourceRoot":"","sources":["../../src/internal/gatewaySettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAM3B;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,mLASjC,CAAC;AAMX,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElE;AAmBD,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,yrBAkCvB,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,EAAE,CAAC,OAAO,8BAA8B,CAAC,CAAC,MAAM,CAAC,CAAC,GAC1E,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,sBAAsB,EAItE,CAAC;AAIF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,QAAgC,CAAC;AAEvE,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,olBAuBmB,CAAC;AASvD,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,6EAIa,CAAC;AAIvD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,yDAI5B,CAAC;AAEX,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAmBD,iDAAiD;AACjD,eAAO,MAAM,8BAA8B,sFAC0C,CAAC;AAEtF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAQ5E"}