@every-app/sdk 0.1.14 → 0.3.0-rc.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/README.md +608 -2
- package/dist/cloudflare/index.d.ts +21 -1
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +21 -1
- package/dist/cloudflare/sentinel.d.ts +69 -0
- package/dist/cloudflare/sentinel.d.ts.map +1 -0
- package/dist/cloudflare/sentinel.js +50 -0
- package/dist/cloudflare/worker.d.ts +511 -0
- package/dist/cloudflare/worker.d.ts.map +1 -0
- package/dist/cloudflare/worker.js +738 -0
- package/dist/dev/index.d.ts +8 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +7 -0
- package/dist/dev/keypair.d.ts +24 -0
- package/dist/dev/keypair.d.ts.map +1 -0
- package/dist/dev/keypair.js +60 -0
- package/dist/internal/aiProviders.d.ts +67 -0
- package/dist/internal/aiProviders.d.ts.map +1 -0
- package/dist/internal/aiProviders.js +220 -0
- package/dist/internal/appSettings.d.ts +237 -0
- package/dist/internal/appSettings.d.ts.map +1 -0
- package/dist/internal/appSettings.js +374 -0
- package/dist/internal/capabilities.d.ts +1344 -0
- package/dist/internal/capabilities.d.ts.map +1 -0
- package/dist/internal/capabilities.js +1521 -0
- package/dist/internal/devProviders.d.ts +49 -0
- package/dist/internal/devProviders.d.ts.map +1 -0
- package/dist/internal/devProviders.js +62 -0
- package/dist/internal/email.d.ts +280 -0
- package/dist/internal/email.d.ts.map +1 -0
- package/dist/internal/email.js +613 -0
- package/dist/internal/events.d.ts +182 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +324 -0
- package/dist/internal/gatewaySettings.d.ts +82 -0
- package/dist/internal/gatewaySettings.d.ts.map +1 -0
- package/dist/internal/gatewaySettings.js +209 -0
- package/dist/internal/identity.d.ts +88 -0
- package/dist/internal/identity.d.ts.map +1 -0
- package/dist/internal/identity.js +231 -0
- package/dist/internal/index.d.ts +19 -0
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +18 -0
- package/dist/internal/members.d.ts +35 -0
- package/dist/internal/members.d.ts.map +1 -0
- package/dist/internal/members.js +7 -0
- package/dist/internal/oauthClient.d.ts +63 -0
- package/dist/internal/oauthClient.d.ts.map +1 -0
- package/dist/internal/oauthClient.js +194 -0
- package/dist/internal/oauthScopes.d.ts +117 -0
- package/dist/internal/oauthScopes.d.ts.map +1 -0
- package/dist/internal/oauthScopes.js +416 -0
- package/dist/internal/organizationName.d.ts +18 -0
- package/dist/internal/organizationName.d.ts.map +1 -0
- package/dist/internal/organizationName.js +24 -0
- package/dist/internal/protocol.d.ts +195 -0
- package/dist/internal/protocol.d.ts.map +1 -0
- package/dist/internal/protocol.js +250 -0
- package/dist/internal/providerApps.d.ts +75 -0
- package/dist/internal/providerApps.d.ts.map +1 -0
- package/dist/internal/providerApps.js +59 -0
- package/dist/internal/providerRegistry.d.ts +147 -0
- package/dist/internal/providerRegistry.d.ts.map +1 -0
- package/dist/internal/providerRegistry.js +262 -0
- package/dist/internal/providerSpec.d.ts +55 -0
- package/dist/internal/providerSpec.d.ts.map +1 -0
- package/dist/internal/providerSpec.js +746 -0
- package/dist/internal/remoteMcp.d.ts +188 -0
- package/dist/internal/remoteMcp.d.ts.map +1 -0
- package/dist/internal/remoteMcp.js +543 -0
- package/dist/internal/tools.d.ts +115 -0
- package/dist/internal/tools.d.ts.map +1 -0
- package/dist/internal/tools.js +80 -0
- package/dist/server/attribution.d.ts +39 -0
- package/dist/server/attribution.d.ts.map +1 -0
- package/dist/server/attribution.js +67 -0
- package/dist/server/authorizeUrl.d.ts +43 -0
- package/dist/server/authorizeUrl.d.ts.map +1 -0
- package/dist/server/authorizeUrl.js +110 -0
- package/dist/server/emit.d.ts +63 -0
- package/dist/server/emit.d.ts.map +1 -0
- package/dist/server/emit.js +101 -0
- package/dist/server/everyApp.d.ts +81 -0
- package/dist/server/everyApp.d.ts.map +1 -0
- package/dist/server/everyApp.js +185 -0
- package/dist/server/gatewayFetch.d.ts +37 -0
- package/dist/server/gatewayFetch.d.ts.map +1 -0
- package/dist/server/gatewayFetch.js +115 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +15 -0
- package/dist/server/integrationFetch.d.ts +131 -0
- package/dist/server/integrationFetch.d.ts.map +1 -0
- package/dist/server/integrationFetch.js +526 -0
- package/dist/server/listMembers.d.ts +32 -0
- package/dist/server/listMembers.d.ts.map +1 -0
- package/dist/server/listMembers.js +74 -0
- package/dist/server/nodeServer.d.ts +48 -0
- package/dist/server/nodeServer.d.ts.map +1 -0
- package/dist/server/nodeServer.js +45 -0
- package/dist/server/sendEmail.d.ts +39 -0
- package/dist/server/sendEmail.d.ts.map +1 -0
- package/dist/server/sendEmail.js +114 -0
- package/dist/server/tools.d.ts +184 -0
- package/dist/server/tools.d.ts.map +1 -0
- package/dist/server/tools.js +347 -0
- package/dist/server/toolsEndpoint.d.ts +32 -0
- package/dist/server/toolsEndpoint.d.ts.map +1 -0
- package/dist/server/toolsEndpoint.js +231 -0
- package/package.json +21 -31
- package/dist/cloudflare/getLocalD1Url.d.ts +0 -2
- package/dist/cloudflare/getLocalD1Url.d.ts.map +0 -1
- package/dist/cloudflare/getLocalD1Url.js +0 -40
- package/dist/cloudflare/lazyInit.d.ts +0 -22
- package/dist/cloudflare/lazyInit.d.ts.map +0 -1
- package/dist/cloudflare/lazyInit.js +0 -65
- package/dist/cloudflare/server/gateway.d.ts +0 -29
- package/dist/cloudflare/server/gateway.d.ts.map +0 -1
- package/dist/cloudflare/server/gateway.js +0 -69
- package/dist/cloudflare/server/index.d.ts +0 -3
- package/dist/cloudflare/server/index.d.ts.map +0 -1
- package/dist/cloudflare/server/index.js +0 -2
- package/dist/core/authenticatedFetch.d.ts +0 -9
- package/dist/core/authenticatedFetch.d.ts.map +0 -1
- package/dist/core/authenticatedFetch.js +0 -31
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -2
- package/dist/core/sessionManager.d.ts +0 -58
- package/dist/core/sessionManager.d.ts.map +0 -1
- package/dist/core/sessionManager.js +0 -357
- package/dist/shared/bypassGatewayLocalOnly.d.ts +0 -15
- package/dist/shared/bypassGatewayLocalOnly.d.ts.map +0 -1
- package/dist/shared/bypassGatewayLocalOnly.js +0 -45
- package/dist/shared/parseMessagePayload.d.ts +0 -3
- package/dist/shared/parseMessagePayload.d.ts.map +0 -1
- package/dist/shared/parseMessagePayload.js +0 -18
- package/dist/tanstack/EmbeddedAppProvider.d.ts +0 -30
- package/dist/tanstack/EmbeddedAppProvider.d.ts.map +0 -1
- package/dist/tanstack/EmbeddedAppProvider.js +0 -57
- package/dist/tanstack/GatewayRequiredError.d.ts +0 -20
- package/dist/tanstack/GatewayRequiredError.d.ts.map +0 -1
- package/dist/tanstack/GatewayRequiredError.js +0 -91
- package/dist/tanstack/_internal/useEveryAppSession.d.ts +0 -18
- package/dist/tanstack/_internal/useEveryAppSession.d.ts.map +0 -1
- package/dist/tanstack/_internal/useEveryAppSession.js +0 -47
- package/dist/tanstack/index.d.ts +0 -4
- package/dist/tanstack/index.d.ts.map +0 -1
- package/dist/tanstack/index.js +0 -3
- package/dist/tanstack/server/authConfig.d.ts +0 -3
- package/dist/tanstack/server/authConfig.d.ts.map +0 -1
- package/dist/tanstack/server/authConfig.js +0 -13
- package/dist/tanstack/server/authenticateRequest.d.ts +0 -31
- package/dist/tanstack/server/authenticateRequest.d.ts.map +0 -1
- package/dist/tanstack/server/authenticateRequest.js +0 -154
- package/dist/tanstack/server/index.d.ts +0 -4
- package/dist/tanstack/server/index.d.ts.map +0 -1
- package/dist/tanstack/server/index.js +0 -2
- package/dist/tanstack/server/types.d.ts +0 -5
- package/dist/tanstack/server/types.d.ts.map +0 -1
- package/dist/tanstack/server/types.js +0 -1
- package/dist/tanstack/useEveryAppRouter.d.ts +0 -7
- package/dist/tanstack/useEveryAppRouter.d.ts.map +0 -1
- package/dist/tanstack/useEveryAppRouter.js +0 -66
- package/dist/tanstack/useSessionTokenClientMiddleware.d.ts +0 -2
- package/dist/tanstack/useSessionTokenClientMiddleware.d.ts.map +0 -1
- package/dist/tanstack/useSessionTokenClientMiddleware.js +0 -29
|
@@ -0,0 +1,209 @@
|
|
|
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 { CAPABILITIES, CAPABILITY_IDS, capabilitySettings, } 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 const INSTALL_OWNED_GATEWAY_SETTINGS = [
|
|
21
|
+
"GATEWAY_URL",
|
|
22
|
+
"APP_BASE_DOMAIN",
|
|
23
|
+
"BETTER_AUTH_SECRET",
|
|
24
|
+
"JWT_PRIVATE_KEY",
|
|
25
|
+
"JWT_PUBLIC_KEY",
|
|
26
|
+
"GATEWAY_DEPLOYMENT_MODE",
|
|
27
|
+
"CLOUDFLARE_ACCOUNT_ID",
|
|
28
|
+
"THIRD_PARTY_DEPLOYS",
|
|
29
|
+
];
|
|
30
|
+
const INSTALL_OWNED = new Set(INSTALL_OWNED_GATEWAY_SETTINGS);
|
|
31
|
+
export function isInstallOwnedGatewaySetting(name) {
|
|
32
|
+
return INSTALL_OWNED.has(name);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The settings the catalog's providers read (the AI providers' keys, the
|
|
36
|
+
* API-key providers' keys, the OAuth clients and the Mastodon instance's
|
|
37
|
+
* URL), in catalog order, the install's own left out: what `everyapp
|
|
38
|
+
* secret set` accepts because a provider reads it. A gateway's registered
|
|
39
|
+
* rows add theirs at run time (providerRegistry.settingNames()).
|
|
40
|
+
*/
|
|
41
|
+
const PROVIDER_GATEWAY_SETTINGS = [
|
|
42
|
+
...new Set(CAPABILITY_IDS.flatMap((id) => {
|
|
43
|
+
const capability = CAPABILITIES[id];
|
|
44
|
+
return capability.mode === "service"
|
|
45
|
+
? []
|
|
46
|
+
: capabilitySettings(capability);
|
|
47
|
+
})),
|
|
48
|
+
].filter((name) => !INSTALL_OWNED.has(name));
|
|
49
|
+
/** The Gateway's own optional settings `everyapp secret set` changes: nothing a provider reads. */
|
|
50
|
+
export const GATEWAY_OWN_SETTINGS = [
|
|
51
|
+
"AI_PROXY_EXTRA_ROUTES",
|
|
52
|
+
// Email's providers: Cloudflare's REST token, Resend's key, the choice.
|
|
53
|
+
"EMAIL_REST_API_TOKEN",
|
|
54
|
+
"RESEND_API_KEY",
|
|
55
|
+
"EMAIL_PROVIDER",
|
|
56
|
+
"EMAIL_FROM",
|
|
57
|
+
"EMAIL_FROM_NAME",
|
|
58
|
+
"MCP_OAUTH_ENABLED",
|
|
59
|
+
"MCP_DCR_ENABLED",
|
|
60
|
+
"MCP_ALLOWED_ORIGINS",
|
|
61
|
+
"MCP_AUDIT_RETENTION_DAYS",
|
|
62
|
+
"CLOUDFLARE_ACCESS_OIDC_ISSUER",
|
|
63
|
+
"CLOUDFLARE_ACCESS_OIDC_CLIENT_ID",
|
|
64
|
+
"CLOUDFLARE_ACCESS_OIDC_CLIENT_SECRET",
|
|
65
|
+
"CLOUDFLARE_ACCESS_OIDC_LABEL",
|
|
66
|
+
"CLOUDFLARE_ACCESS_TEAM_DOMAIN",
|
|
67
|
+
"CLOUDFLARE_ACCESS_AUD",
|
|
68
|
+
"CLOUDFLARE_ACCESS_APPS_AUD",
|
|
69
|
+
"CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS",
|
|
70
|
+
"CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN",
|
|
71
|
+
"EMAIL_PASSWORD_SIGN_IN",
|
|
72
|
+
// "false" keeps the hosted gateway's sign-up invite-only.
|
|
73
|
+
"HOSTED_OPEN_SIGNUP",
|
|
74
|
+
// Release deployers and the hosted third-party domain. The hosted launch
|
|
75
|
+
// gate, THIRD_PARTY_DEPLOYS, is never set from here: it is opened by
|
|
76
|
+
// hand once the launch checks pass (docs/runbooks/hosted-install.md).
|
|
77
|
+
"CF_DEPLOY_TOKEN",
|
|
78
|
+
// Self-hosted browser installs are on by default; "off" opts out.
|
|
79
|
+
"BROWSER_APP_INSTALLS",
|
|
80
|
+
"DISPATCH_NAMESPACE",
|
|
81
|
+
"THIRD_PARTY_DOMAIN",
|
|
82
|
+
// "true" lets event webhooks target http: and private hosts (self-host only).
|
|
83
|
+
"EVENTS_ALLOW_PRIVATE_TARGETS",
|
|
84
|
+
];
|
|
85
|
+
/**
|
|
86
|
+
* The Gateway's optional settings `everyapp secret set` changes: every
|
|
87
|
+
* setting a catalog provider reads, then the Gateway's own.
|
|
88
|
+
*/
|
|
89
|
+
export const SETTABLE_GATEWAY_SETTINGS = [
|
|
90
|
+
...PROVIDER_GATEWAY_SETTINGS,
|
|
91
|
+
...GATEWAY_OWN_SETTINGS,
|
|
92
|
+
];
|
|
93
|
+
const SETTABLE = new Set(SETTABLE_GATEWAY_SETTINGS);
|
|
94
|
+
/**
|
|
95
|
+
* The credential names of remote MCP apps (`everyapp mcp add <url>`,
|
|
96
|
+
* ./remoteMcp.ts): `<ID>_MCP_TOKEN` by default, any name ending in
|
|
97
|
+
* `_MCP_TOKEN` by choice. A family rather than a list, so the names a
|
|
98
|
+
* registry row declares at run time route to the Gateway like the fixed
|
|
99
|
+
* names (`everyapp secret set` reads no registry to decide), an app's own
|
|
100
|
+
* secret can never take one (the manifest validator refuses the family),
|
|
101
|
+
* and a remote server can never be given a fixed provider key.
|
|
102
|
+
*/
|
|
103
|
+
export const REMOTE_MCP_SECRET_PATTERN = /^[A-Z][A-Z0-9_]*_MCP_TOKEN$/;
|
|
104
|
+
/** Whether `name` is a remote MCP app's credential name (`TREG_MCP_TOKEN`). */
|
|
105
|
+
export function isRemoteMcpSecretName(name) {
|
|
106
|
+
return REMOTE_MCP_SECRET_PATTERN.test(name);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Whether `everyapp secret set <name>` changes the Gateway: one of the
|
|
110
|
+
* fixed settings, or a remote MCP app's credential name.
|
|
111
|
+
*/
|
|
112
|
+
export function isSettableGatewaySetting(name) {
|
|
113
|
+
return SETTABLE.has(name) || isRemoteMcpSecretName(name);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Settable Gateway settings whose value is a plain word, address, list
|
|
117
|
+
* or switch rather than a credential: a sender, a provider choice, a
|
|
118
|
+
* URL, an audience, a flag. `everyapp secret set` may show these as they
|
|
119
|
+
* are typed and check their shape; anything else is a credential and
|
|
120
|
+
* stays hidden.
|
|
121
|
+
*/
|
|
122
|
+
export const PLAIN_GATEWAY_SETTINGS = [
|
|
123
|
+
"EMAIL_FROM",
|
|
124
|
+
"EMAIL_FROM_NAME",
|
|
125
|
+
"EMAIL_PROVIDER",
|
|
126
|
+
"EMAIL_PASSWORD_SIGN_IN",
|
|
127
|
+
"MASTODON_URL",
|
|
128
|
+
"AI_PROXY_EXTRA_ROUTES",
|
|
129
|
+
"MCP_OAUTH_ENABLED",
|
|
130
|
+
"MCP_DCR_ENABLED",
|
|
131
|
+
"MCP_ALLOWED_ORIGINS",
|
|
132
|
+
"MCP_AUDIT_RETENTION_DAYS",
|
|
133
|
+
"CLOUDFLARE_ACCESS_OIDC_ISSUER",
|
|
134
|
+
"CLOUDFLARE_ACCESS_OIDC_CLIENT_ID",
|
|
135
|
+
"CLOUDFLARE_ACCESS_OIDC_LABEL",
|
|
136
|
+
"CLOUDFLARE_ACCESS_TEAM_DOMAIN",
|
|
137
|
+
"CLOUDFLARE_ACCESS_AUD",
|
|
138
|
+
"CLOUDFLARE_ACCESS_APPS_AUD",
|
|
139
|
+
"CLOUDFLARE_ACCESS_AUTO_JOIN_DOMAINS",
|
|
140
|
+
"CLOUDFLARE_ACCESS_OUTER_RING_AUTO_JOIN",
|
|
141
|
+
"HOSTED_OPEN_SIGNUP",
|
|
142
|
+
"BROWSER_APP_INSTALLS",
|
|
143
|
+
"DISPATCH_NAMESPACE",
|
|
144
|
+
"THIRD_PARTY_DOMAIN",
|
|
145
|
+
"EVENTS_ALLOW_PRIVATE_TARGETS",
|
|
146
|
+
];
|
|
147
|
+
const PLAIN = new Set(PLAIN_GATEWAY_SETTINGS);
|
|
148
|
+
/** Whether a settable Gateway setting's value is a plain value, not a credential. */
|
|
149
|
+
export function isPlainGatewaySetting(name) {
|
|
150
|
+
return PLAIN.has(name);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Settable Gateway settings only the hosted gateway reads: a self-hosted
|
|
154
|
+
* install never needs them, so `secret list` leaves them out there.
|
|
155
|
+
*/
|
|
156
|
+
export const HOSTED_ONLY_GATEWAY_SETTINGS = [
|
|
157
|
+
"HOSTED_OPEN_SIGNUP",
|
|
158
|
+
"DISPATCH_NAMESPACE",
|
|
159
|
+
"THIRD_PARTY_DOMAIN",
|
|
160
|
+
];
|
|
161
|
+
const HOSTED_ONLY = new Set(HOSTED_ONLY_GATEWAY_SETTINGS);
|
|
162
|
+
export function isHostedOnlyGatewaySetting(name) {
|
|
163
|
+
return HOSTED_ONLY.has(name);
|
|
164
|
+
}
|
|
165
|
+
/** Gateway settings for local testing only, set in the gateway's `.dev.vars`, never deployed. */
|
|
166
|
+
export const DEV_ONLY_GATEWAY_SETTINGS = [
|
|
167
|
+
"MCP_ACCESS_TOKEN_TTL",
|
|
168
|
+
// "true" sends the DataForSEO provider app's calls to the free sandbox.
|
|
169
|
+
"DATAFORSEO_SANDBOX",
|
|
170
|
+
];
|
|
171
|
+
export function isDevOnlyGatewaySetting(name) {
|
|
172
|
+
return DEV_ONLY_GATEWAY_SETTINGS.includes(name);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Names an app's own secret can't take: the deploy sets GATEWAY_URL on
|
|
176
|
+
* every Worker and builds in the identity settings, the gateway binding
|
|
177
|
+
* and the platform's own namespaces. Checked without regard to case. The
|
|
178
|
+
* SDK's `everyAppWorker()` keeps the same rule as a regex (its config
|
|
179
|
+
* module can't import this one); a test keeps them in step.
|
|
180
|
+
*/
|
|
181
|
+
const RESERVED_APP_SECRET_NAMES = new Set([
|
|
182
|
+
"GATEWAY_URL",
|
|
183
|
+
"CF_VERSION_METADATA",
|
|
184
|
+
]);
|
|
185
|
+
const RESERVED_APP_SECRET_PREFIXES = [
|
|
186
|
+
"EVERYAPP_",
|
|
187
|
+
"EVERY_APP_",
|
|
188
|
+
"APP__",
|
|
189
|
+
];
|
|
190
|
+
/** What the reserved names are, for messages. */
|
|
191
|
+
export const RESERVED_APP_SECRET_NAMES_TEXT = "GATEWAY_URL, CF_VERSION_METADATA and the EVERYAPP_*, EVERY_APP_* and APP__* names";
|
|
192
|
+
export function isReservedAppSecretName(name) {
|
|
193
|
+
const upper = name.toUpperCase();
|
|
194
|
+
return (RESERVED_APP_SECRET_NAMES.has(upper) ||
|
|
195
|
+
RESERVED_APP_SECRET_PREFIXES.some((prefix) => upper.startsWith(prefix)));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* The AI provider or capability a Gateway setting belongs to: what to list
|
|
199
|
+
* in a manifest instead of holding the key as the app's own.
|
|
200
|
+
*/
|
|
201
|
+
export function gatewaySettingOwner(name) {
|
|
202
|
+
for (const id of CAPABILITY_IDS) {
|
|
203
|
+
const capability = CAPABILITIES[id];
|
|
204
|
+
if (capabilitySettings(capability).includes(name)) {
|
|
205
|
+
return { kind: capability.mode === "ai" ? "provider" : "capability", id };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, type SystemClaims, type SystemTokenPurpose } from "./protocol.js";
|
|
2
|
+
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, type EveryAppUser, type IdentityChannel, };
|
|
3
|
+
export declare class IdentityError extends Error {
|
|
4
|
+
readonly status = 401;
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class ConfigurationError extends Error {
|
|
8
|
+
readonly status = 500;
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse the public key set from an env var value. Accepts a JSON array of PEM
|
|
13
|
+
* strings, or a single PEM string. Returns at least one key or throws.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parsePublicKeys(envValue: string | undefined | null): string[];
|
|
16
|
+
export interface VerifyOptions {
|
|
17
|
+
/** SPKI PEM public keys (current + next). */
|
|
18
|
+
publicKeys: string[];
|
|
19
|
+
/** Expected `aud` — this app's id. */
|
|
20
|
+
audience: string;
|
|
21
|
+
/** Expected issuer (the gateway URL). Required for user identities. */
|
|
22
|
+
issuer?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Accept the dev identity kid ({@link IDENTITY_DEV_KEY_ID}). Set ONLY in
|
|
25
|
+
* local dev (driven by the {@link DEV_ENV} worker env var). Never true in
|
|
26
|
+
* production. Requires `issuer` to be {@link DEV_ISSUER}.
|
|
27
|
+
*/
|
|
28
|
+
allowDevIdentities?: boolean;
|
|
29
|
+
/** Override for tests. */
|
|
30
|
+
now?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verify an identity JWT fail-closed. Throws {@link IdentityError} on any
|
|
34
|
+
* problem (bad alg/kid, `none`, wrong key, expired, wrong audience, missing
|
|
35
|
+
* claims).
|
|
36
|
+
*/
|
|
37
|
+
export declare function verifyIdentityJwt(token: string, options: VerifyOptions): Promise<EveryAppUser>;
|
|
38
|
+
/**
|
|
39
|
+
* Verify the gateway's system token (the value of `x-everyapp-system`)
|
|
40
|
+
* fail-closed, for exactly one purpose. A user identity or public marker is
|
|
41
|
+
* never a system token, and a system token is never an identity.
|
|
42
|
+
*/
|
|
43
|
+
export declare function verifySystemJwt(token: string, options: VerifyOptions & {
|
|
44
|
+
purpose: SystemTokenPurpose;
|
|
45
|
+
}): Promise<SystemClaims>;
|
|
46
|
+
/**
|
|
47
|
+
* Verify a public-route marker (the value of `x-everyapp-public`). The marker
|
|
48
|
+
* is a gateway-signed, app-scoped JWT with `pub: true` and `typ: "public"` —
|
|
49
|
+
* a bare header is NEVER a trust source, so a re-exposed app worker cannot be
|
|
50
|
+
* flipped into public mode by anyone who can type a header. Throws on any
|
|
51
|
+
* problem.
|
|
52
|
+
*/
|
|
53
|
+
export declare function verifyPublicMarkerJwt(token: string, options: VerifyOptions): Promise<void>;
|
|
54
|
+
export interface IdentityResult {
|
|
55
|
+
/** The verified user, or null for a declared public route. */
|
|
56
|
+
user: EveryAppUser | null;
|
|
57
|
+
/** True when the gateway marked this request as a public route. */
|
|
58
|
+
isPublic: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface RequestIdentityOptions {
|
|
61
|
+
audience: string;
|
|
62
|
+
/** Provide keys directly, or let {@link getIdentityFromRequest} read env. */
|
|
63
|
+
publicKeys?: string[];
|
|
64
|
+
/** Env bag to read {@link PUBLIC_KEYS_ENV} / {@link DEV_ENV} from. */
|
|
65
|
+
env?: Record<string, unknown>;
|
|
66
|
+
keysEnvVar?: string;
|
|
67
|
+
issuer?: string;
|
|
68
|
+
/** Force dev-kid acceptance. Defaults to reading {@link DEV_ENV} from env. */
|
|
69
|
+
allowDevIdentities?: boolean;
|
|
70
|
+
now?: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The verification options for a request: keys from options or env, the
|
|
74
|
+
* expected issuer, and the dev-kid opt-in. Throws {@link ConfigurationError}
|
|
75
|
+
* when no key set is configured, or when the dev opt-in meets an issuer other
|
|
76
|
+
* than {@link DEV_ISSUER}.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveVerifyOptions(options: RequestIdentityOptions): VerifyOptions;
|
|
79
|
+
/**
|
|
80
|
+
* Resolve identity for an incoming proxied request. Public routes carry a
|
|
81
|
+
* gateway-SIGNED marker in `x-everyapp-public` and resolve to
|
|
82
|
+
* `{ user: null, isPublic: true }` only after the marker verifies. Everything
|
|
83
|
+
* else requires a valid identity JWT. Throws {@link IdentityError} on any
|
|
84
|
+
* problem — including a bare/forged public header — so a re-exposed worker
|
|
85
|
+
* fails closed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getIdentityFromRequest(request: Request, options: RequestIdentityOptions): Promise<IdentityResult>;
|
|
88
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/internal/identity.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,UAAU,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EAKjB,KAAK,YAAY,EACjB,KAAK,eAAe,EAEpB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,UAAU,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,CAAC;AAEF,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,OAAO;gBACV,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,OAAO;gBACV,OAAO,EAAE,MAAM;CAI5B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,EAAE,CA8B7E;AAYD,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,0BAA0B;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAeD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAUvB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GAAG;IAAE,OAAO,EAAE,kBAAkB,CAAA;CAAE,GACvD,OAAO,CAAC,YAAY,CAAC,CAUvB;AAoED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,sBAAsB,GAC9B,aAAa,CAwBf;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAiBzB"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every App identity JWT verification (the app side of the trust boundary).
|
|
3
|
+
*
|
|
4
|
+
* The gateway injects a short-lived RS256 JWT as `x-everyapp-identity`. This
|
|
5
|
+
* module verifies it **fail-closed**: the algorithm and key id are pinned,
|
|
6
|
+
* `none` is rejected, the audience must equal this app, and the verification
|
|
7
|
+
* key set arrives from an env var (current + next public keys) — never a
|
|
8
|
+
* runtime JWKS fetch. A bare header is never a trust source; only a token that
|
|
9
|
+
* survives verification produces a user.
|
|
10
|
+
*/
|
|
11
|
+
import { importSPKI, jwtVerify, decodeProtectedHeader, } from "jose";
|
|
12
|
+
import { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, assertPublicMarkerClaims, assertSystemClaims, identityClaimsToEveryAppUser, ProtocolClaimsError, } from "./protocol.js";
|
|
13
|
+
export { APP_ID_ENV, DEV_ENV, DEV_ISSUER, IDENTITY_ALG, IDENTITY_DEV_KEY_ID, IDENTITY_HEADER, IDENTITY_KEY_ID, ISSUER_ENV, PUBLIC_HEADER, PUBLIC_KEYS_ENV, PUBLIC_MARKER_SUB, };
|
|
14
|
+
export class IdentityError extends Error {
|
|
15
|
+
status = 401;
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "IdentityError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class ConfigurationError extends Error {
|
|
22
|
+
status = 500;
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "ConfigurationError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parse the public key set from an env var value. Accepts a JSON array of PEM
|
|
30
|
+
* strings, or a single PEM string. Returns at least one key or throws.
|
|
31
|
+
*/
|
|
32
|
+
export function parsePublicKeys(envValue) {
|
|
33
|
+
if (!envValue || envValue.trim().length === 0) {
|
|
34
|
+
throw new ConfigurationError(`${PUBLIC_KEYS_ENV} is not set — the gateway must inject the identity public key set.`);
|
|
35
|
+
}
|
|
36
|
+
const trimmed = envValue.trim();
|
|
37
|
+
let keys;
|
|
38
|
+
if (trimmed.startsWith("[")) {
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(trimmed);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new ConfigurationError(`${PUBLIC_KEYS_ENV} must be a JSON array of PEM strings: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(parsed) || parsed.some((k) => typeof k !== "string")) {
|
|
47
|
+
throw new ConfigurationError(`${PUBLIC_KEYS_ENV} must be a JSON array of PEM strings.`);
|
|
48
|
+
}
|
|
49
|
+
keys = parsed.map((k) => k.replace(/\\n/g, "\n"));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
keys = [trimmed.replace(/\\n/g, "\n")];
|
|
53
|
+
}
|
|
54
|
+
if (keys.length === 0) {
|
|
55
|
+
throw new ConfigurationError(`${PUBLIC_KEYS_ENV} contained no keys.`);
|
|
56
|
+
}
|
|
57
|
+
return keys;
|
|
58
|
+
}
|
|
59
|
+
const keyCache = new Map();
|
|
60
|
+
function importKey(pem) {
|
|
61
|
+
let cached = keyCache.get(pem);
|
|
62
|
+
if (!cached) {
|
|
63
|
+
cached = importSPKI(pem, IDENTITY_ALG);
|
|
64
|
+
keyCache.set(pem, cached);
|
|
65
|
+
}
|
|
66
|
+
return cached;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The dev keypair is public (`@every-app/sdk/dev`), so the dev opt-in holds
|
|
70
|
+
* only for the dev issuer: a dev-kid token that names a real gateway as its
|
|
71
|
+
* issuer never verifies, whatever the env says.
|
|
72
|
+
*/
|
|
73
|
+
function assertDevIssuer(options) {
|
|
74
|
+
if (options.allowDevIdentities && options.issuer !== DEV_ISSUER) {
|
|
75
|
+
throw new ConfigurationError(`Dev identities are accepted only from the dev issuer ${DEV_ISSUER}, not ${options.issuer ? `"${options.issuer}"` : "an unset issuer"}. ${DEV_ENV} is for \`everyapp dev\` alone.`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verify an identity JWT fail-closed. Throws {@link IdentityError} on any
|
|
80
|
+
* problem (bad alg/kid, `none`, wrong key, expired, wrong audience, missing
|
|
81
|
+
* claims).
|
|
82
|
+
*/
|
|
83
|
+
export async function verifyIdentityJwt(token, options) {
|
|
84
|
+
const payload = await verifyPinnedJwt(token, options, "user");
|
|
85
|
+
try {
|
|
86
|
+
return identityClaimsToEveryAppUser(payload);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error instanceof ProtocolClaimsError) {
|
|
90
|
+
throw new IdentityError(error.message);
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Verify the gateway's system token (the value of `x-everyapp-system`)
|
|
97
|
+
* fail-closed, for exactly one purpose. A user identity or public marker is
|
|
98
|
+
* never a system token, and a system token is never an identity.
|
|
99
|
+
*/
|
|
100
|
+
export async function verifySystemJwt(token, options) {
|
|
101
|
+
const payload = await verifyPinnedJwt(token, options, "system");
|
|
102
|
+
try {
|
|
103
|
+
return assertSystemClaims(payload, options.purpose);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof ProtocolClaimsError) {
|
|
107
|
+
throw new IdentityError(error.message);
|
|
108
|
+
}
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The shared fail-closed verification core: pinned alg/kid, `none` rejected,
|
|
114
|
+
* `aud` checked, multi-key (current + next). Returns the verified payload.
|
|
115
|
+
*/
|
|
116
|
+
async function verifyPinnedJwt(token, options, expectedTyp) {
|
|
117
|
+
assertDevIssuer(options);
|
|
118
|
+
if (!token)
|
|
119
|
+
throw new IdentityError("no identity token");
|
|
120
|
+
// Pin the header BEFORE attempting any signature work. This is what defeats
|
|
121
|
+
// `alg: none` and algorithm-confusion (e.g. an HS256 token forged with the
|
|
122
|
+
// public key as the HMAC secret).
|
|
123
|
+
let header;
|
|
124
|
+
try {
|
|
125
|
+
header = decodeProtectedHeader(token);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
throw new IdentityError("malformed identity token");
|
|
129
|
+
}
|
|
130
|
+
if (header.alg !== IDENTITY_ALG) {
|
|
131
|
+
throw new IdentityError(`unexpected alg "${header.alg}" (expected ${IDENTITY_ALG})`);
|
|
132
|
+
}
|
|
133
|
+
const allowedKids = options.allowDevIdentities
|
|
134
|
+
? [IDENTITY_KEY_ID, IDENTITY_DEV_KEY_ID]
|
|
135
|
+
: [IDENTITY_KEY_ID];
|
|
136
|
+
if (!header.kid || !allowedKids.includes(header.kid)) {
|
|
137
|
+
throw new IdentityError(`unexpected kid "${header.kid}"`);
|
|
138
|
+
}
|
|
139
|
+
if (expectedTyp !== "public" && !options.issuer) {
|
|
140
|
+
throw new IdentityError(`${ISSUER_ENV} not configured — deploy with the Every App CLI or provide an explicit issuer.`);
|
|
141
|
+
}
|
|
142
|
+
const verifyOpts = {
|
|
143
|
+
algorithms: [IDENTITY_ALG],
|
|
144
|
+
audience: options.audience,
|
|
145
|
+
requiredClaims: expectedTyp === "system" ? ["exp", "iat"] : ["exp"],
|
|
146
|
+
...(options.issuer ? { issuer: options.issuer } : {}),
|
|
147
|
+
...(options.now ? { currentDate: new Date(options.now) } : {}),
|
|
148
|
+
};
|
|
149
|
+
let lastErr;
|
|
150
|
+
for (const pem of options.publicKeys) {
|
|
151
|
+
try {
|
|
152
|
+
const key = await importKey(pem);
|
|
153
|
+
const { payload } = await jwtVerify(token, key, verifyOpts);
|
|
154
|
+
if (payload.typ !== expectedTyp) {
|
|
155
|
+
throw new IdentityError(`unexpected token typ "${payload.typ}" (expected ${expectedTyp})`);
|
|
156
|
+
}
|
|
157
|
+
return payload;
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
lastErr = err;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
throw new IdentityError(`identity verification failed: ${lastErr?.message ?? "no matching key"}`);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Verify a public-route marker (the value of `x-everyapp-public`). The marker
|
|
167
|
+
* is a gateway-signed, app-scoped JWT with `pub: true` and `typ: "public"` —
|
|
168
|
+
* a bare header is NEVER a trust source, so a re-exposed app worker cannot be
|
|
169
|
+
* flipped into public mode by anyone who can type a header. Throws on any
|
|
170
|
+
* problem.
|
|
171
|
+
*/
|
|
172
|
+
export async function verifyPublicMarkerJwt(token, options) {
|
|
173
|
+
const payload = await verifyPinnedJwt(token, options, "public");
|
|
174
|
+
try {
|
|
175
|
+
assertPublicMarkerClaims(payload);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error instanceof ProtocolClaimsError) {
|
|
179
|
+
throw new IdentityError(error.message);
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The verification options for a request: keys from options or env, the
|
|
186
|
+
* expected issuer, and the dev-kid opt-in. Throws {@link ConfigurationError}
|
|
187
|
+
* when no key set is configured, or when the dev opt-in meets an issuer other
|
|
188
|
+
* than {@link DEV_ISSUER}.
|
|
189
|
+
*/
|
|
190
|
+
export function resolveVerifyOptions(options) {
|
|
191
|
+
const publicKeys = options.publicKeys ??
|
|
192
|
+
parsePublicKeys(options.env?.[options.keysEnvVar ?? PUBLIC_KEYS_ENV] ?? null);
|
|
193
|
+
// Dev identities are accepted only when the worker env opts in
|
|
194
|
+
// (everyAppWorker() sets EVERYAPP_DEV in development). A deploy never does.
|
|
195
|
+
const devEnv = options.env?.[DEV_ENV];
|
|
196
|
+
const allowDevIdentities = options.allowDevIdentities ??
|
|
197
|
+
(typeof devEnv === "string" &&
|
|
198
|
+
(devEnv === "1" || devEnv.toLowerCase() === "true"));
|
|
199
|
+
const resolved = {
|
|
200
|
+
publicKeys,
|
|
201
|
+
audience: options.audience,
|
|
202
|
+
issuer: options.issuer ??
|
|
203
|
+
(options.env?.[ISSUER_ENV] || undefined),
|
|
204
|
+
allowDevIdentities,
|
|
205
|
+
now: options.now,
|
|
206
|
+
};
|
|
207
|
+
assertDevIssuer(resolved);
|
|
208
|
+
return resolved;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Resolve identity for an incoming proxied request. Public routes carry a
|
|
212
|
+
* gateway-SIGNED marker in `x-everyapp-public` and resolve to
|
|
213
|
+
* `{ user: null, isPublic: true }` only after the marker verifies. Everything
|
|
214
|
+
* else requires a valid identity JWT. Throws {@link IdentityError} on any
|
|
215
|
+
* problem — including a bare/forged public header — so a re-exposed worker
|
|
216
|
+
* fails closed.
|
|
217
|
+
*/
|
|
218
|
+
export async function getIdentityFromRequest(request, options) {
|
|
219
|
+
const verifyOptions = resolveVerifyOptions(options);
|
|
220
|
+
const publicMarker = request.headers.get(PUBLIC_HEADER);
|
|
221
|
+
if (publicMarker) {
|
|
222
|
+
await verifyPublicMarkerJwt(publicMarker, verifyOptions);
|
|
223
|
+
return { user: null, isPublic: true };
|
|
224
|
+
}
|
|
225
|
+
const token = request.headers.get(IDENTITY_HEADER);
|
|
226
|
+
if (!token) {
|
|
227
|
+
throw new IdentityError("request reached the app without an identity token (not proxied through the gateway?)");
|
|
228
|
+
}
|
|
229
|
+
const user = await verifyIdentityJwt(token, verifyOptions);
|
|
230
|
+
return { user, isPublic: false };
|
|
231
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from "./protocol.js";
|
|
2
|
+
export * from "./tools.js";
|
|
3
|
+
export * from "./capabilities.js";
|
|
4
|
+
export * from "./aiProviders.js";
|
|
5
|
+
export * from "./gatewaySettings.js";
|
|
6
|
+
export * from "./appSettings.js";
|
|
7
|
+
export * from "./email.js";
|
|
8
|
+
export * from "./members.js";
|
|
9
|
+
export * from "./organizationName.js";
|
|
10
|
+
export * from "./oauthClient.js";
|
|
11
|
+
export * from "./oauthScopes.js";
|
|
12
|
+
export * from "./providerApps.js";
|
|
13
|
+
export * from "./events.js";
|
|
14
|
+
export * from "./providerSpec.js";
|
|
15
|
+
export * from "./providerRegistry.js";
|
|
16
|
+
export * from "./remoteMcp.js";
|
|
17
|
+
export * from "./devProviders.js";
|
|
18
|
+
export { ConfigurationError, IdentityError, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, type IdentityResult, type RequestIdentityOptions, type VerifyOptions, } from "./identity.js";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,GACnB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export * from "./protocol.js";
|
|
2
|
+
export * from "./tools.js";
|
|
3
|
+
export * from "./capabilities.js";
|
|
4
|
+
export * from "./aiProviders.js";
|
|
5
|
+
export * from "./gatewaySettings.js";
|
|
6
|
+
export * from "./appSettings.js";
|
|
7
|
+
export * from "./email.js";
|
|
8
|
+
export * from "./members.js";
|
|
9
|
+
export * from "./organizationName.js";
|
|
10
|
+
export * from "./oauthClient.js";
|
|
11
|
+
export * from "./oauthScopes.js";
|
|
12
|
+
export * from "./providerApps.js";
|
|
13
|
+
export * from "./events.js";
|
|
14
|
+
export * from "./providerSpec.js";
|
|
15
|
+
export * from "./providerRegistry.js";
|
|
16
|
+
export * from "./remoteMcp.js";
|
|
17
|
+
export * from "./devProviders.js";
|
|
18
|
+
export { ConfigurationError, IdentityError, getIdentityFromRequest, parsePublicKeys, resolveVerifyOptions, verifyIdentityJwt, verifyPublicMarkerJwt, verifySystemJwt, } from "./identity.js";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `members` capability's wire contract (docs/capabilities.md "Gateway
|
|
3
|
+
* services"): what `GET /api/integrations/members/list` answers. The
|
|
4
|
+
* gateway builds it, the SDK's `listMembers()` returns it, and its local-dev
|
|
5
|
+
* fallback answers in the same shape. Types only.
|
|
6
|
+
*/
|
|
7
|
+
/** A member's role in the organization. */
|
|
8
|
+
export type OrganizationMemberRole = "owner" | "admin" | "member";
|
|
9
|
+
/**
|
|
10
|
+
* One member of the organization who can open the app: not deactivated,
|
|
11
|
+
* and, for an organization's own app, granted it.
|
|
12
|
+
*/
|
|
13
|
+
export interface OrganizationMember {
|
|
14
|
+
/** The user id, the identity's `sub` (`getEveryAppUser().id`). */
|
|
15
|
+
id: string;
|
|
16
|
+
email: string;
|
|
17
|
+
/** The display name; empty when the person set none. */
|
|
18
|
+
name: string;
|
|
19
|
+
role: OrganizationMemberRole;
|
|
20
|
+
}
|
|
21
|
+
/** What a list answers. */
|
|
22
|
+
export interface ListMembersResult {
|
|
23
|
+
members: OrganizationMember[];
|
|
24
|
+
}
|
|
25
|
+
/** `GET /api/integrations/members`: whether the app may list members. */
|
|
26
|
+
export interface MembersCapabilityStatus {
|
|
27
|
+
capability: "members";
|
|
28
|
+
/** The app's manifest lists `members`. */
|
|
29
|
+
requested: boolean;
|
|
30
|
+
/** Always true: the gateway needs no setting to list its own members. */
|
|
31
|
+
configured: true;
|
|
32
|
+
/** Lists would go through. */
|
|
33
|
+
ready: boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=members.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../src/internal/members.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,sBAAsB,CAAC;CAC9B;AAED,2BAA2B;AAC3B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,SAAS,CAAC;IACtB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,UAAU,EAAE,IAAI,CAAC;IACjB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAC;CAChB"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `members` capability's wire contract (docs/capabilities.md "Gateway
|
|
3
|
+
* services"): what `GET /api/integrations/members/list` answers. The
|
|
4
|
+
* gateway builds it, the SDK's `listMembers()` returns it, and its local-dev
|
|
5
|
+
* fallback answers in the same shape. Types only.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|