@greatwait/contracts 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/authority.d.ts +217 -0
- package/dist/authority.js +261 -0
- package/dist/callback-ownership.d.ts +58 -0
- package/dist/callback-ownership.js +71 -0
- package/dist/callback-safety.d.ts +38 -0
- package/dist/callback-safety.js +403 -0
- package/dist/compatibility.d.ts +82 -0
- package/dist/compatibility.js +115 -0
- package/dist/delivery.d.ts +401 -0
- package/dist/delivery.js +311 -0
- package/dist/endpoints.d.ts +305 -0
- package/dist/endpoints.js +179 -0
- package/dist/events.d.ts +62 -0
- package/dist/events.js +38 -0
- package/dist/first-value-journey.d.ts +305 -0
- package/dist/first-value-journey.js +466 -0
- package/dist/forecast.d.ts +443 -0
- package/dist/forecast.js +729 -0
- package/dist/identifiers.d.ts +109 -0
- package/dist/identifiers.js +131 -0
- package/dist/identity.d.ts +196 -0
- package/dist/identity.js +182 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mcp.d.ts +51 -0
- package/dist/mcp.js +56 -0
- package/dist/oauth.d.ts +796 -0
- package/dist/oauth.js +708 -0
- package/dist/operations.d.ts +3985 -0
- package/dist/operations.js +1837 -0
- package/dist/partition.d.ts +771 -0
- package/dist/partition.js +206 -0
- package/dist/policy.d.ts +93 -0
- package/dist/policy.js +180 -0
- package/dist/problems.d.ts +158 -0
- package/dist/problems.js +104 -0
- package/dist/protocol.d.ts +308 -0
- package/dist/protocol.js +515 -0
- package/dist/scheduling-records.d.ts +395 -0
- package/dist/scheduling-records.js +284 -0
- package/dist/scheduling.d.ts +1098 -0
- package/dist/scheduling.js +1116 -0
- package/dist/secrets.d.ts +383 -0
- package/dist/secrets.js +272 -0
- package/dist/signatures.d.ts +704 -0
- package/dist/signatures.js +867 -0
- package/dist/tenancy.d.ts +178 -0
- package/dist/tenancy.js +145 -0
- package/dist/test-sink.d.ts +986 -0
- package/dist/test-sink.js +755 -0
- package/dist/time.d.ts +45 -0
- package/dist/time.js +128 -0
- package/dist/usage.d.ts +121 -0
- package/dist/usage.js +200 -0
- package/dist/webhooks.d.ts +116 -0
- package/dist/webhooks.js +161 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.js +59 -0
- package/generated/v1/callback-delivery-signature.json +467 -0
- package/generated/v1/callback-endpoint-verification.json +59 -0
- package/generated/v1/callback-receiver.json +241 -0
- package/generated/v1/examples/attempts.list.response.json +24 -0
- package/generated/v1/examples/attempts.read.response.json +20 -0
- package/generated/v1/examples/credentials.create.request.json +5 -0
- package/generated/v1/examples/credentials.create.response.json +10 -0
- package/generated/v1/examples/credentials.list.response.json +17 -0
- package/generated/v1/examples/credentials.revoke.response.json +11 -0
- package/generated/v1/examples/credentials.rotate.request.json +3 -0
- package/generated/v1/examples/credentials.rotate.response.json +22 -0
- package/generated/v1/examples/endpoints.create.request.json +3 -0
- package/generated/v1/examples/endpoints.create.response.json +16 -0
- package/generated/v1/examples/endpoints.disable.response.json +15 -0
- package/generated/v1/examples/endpoints.list.response.json +21 -0
- package/generated/v1/examples/endpoints.read.response.json +14 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.request.json +3 -0
- package/generated/v1/examples/endpoints.rotateSigningKey.response.json +23 -0
- package/generated/v1/examples/endpoints.update.request.json +3 -0
- package/generated/v1/examples/endpoints.update.response.json +13 -0
- package/generated/v1/examples/endpoints.verify.response.json +15 -0
- package/generated/v1/examples/forecast.read.response.json +28 -0
- package/generated/v1/examples/forecast.windows.response.json +21 -0
- package/generated/v1/examples/grants.list.response.json +17 -0
- package/generated/v1/examples/grants.revoke.response.json +16 -0
- package/generated/v1/examples/meta.scaffold.response.json +5 -0
- package/generated/v1/examples/meta.version.response.json +5 -0
- package/generated/v1/examples/occurrences.list.response.json +17 -0
- package/generated/v1/examples/occurrences.read.response.json +15 -0
- package/generated/v1/examples/occurrences.redeliver.response.json +16 -0
- package/generated/v1/examples/projects.create.request.json +3 -0
- package/generated/v1/examples/projects.create.response.json +5 -0
- package/generated/v1/examples/projects.list.response.json +9 -0
- package/generated/v1/examples/schedules.archive.response.json +25 -0
- package/generated/v1/examples/schedules.cancel.response.json +24 -0
- package/generated/v1/examples/schedules.create.request.json +9 -0
- package/generated/v1/examples/schedules.create.response.json +25 -0
- package/generated/v1/examples/schedules.list.response.json +23 -0
- package/generated/v1/examples/schedules.pause.response.json +23 -0
- package/generated/v1/examples/schedules.read.response.json +25 -0
- package/generated/v1/examples/schedules.replace.request.json +8 -0
- package/generated/v1/examples/schedules.replace.response.json +25 -0
- package/generated/v1/examples/schedules.resume.response.json +23 -0
- package/generated/v1/examples/sinkdeliveries.list.response.json +19 -0
- package/generated/v1/examples/sinkdeliveries.read.response.json +16 -0
- package/generated/v1/examples/testsinks.configure.request.json +3 -0
- package/generated/v1/examples/testsinks.configure.response.json +13 -0
- package/generated/v1/examples/testsinks.create.request.json +8 -0
- package/generated/v1/examples/testsinks.create.response.json +13 -0
- package/generated/v1/examples/testsinks.delete.response.json +13 -0
- package/generated/v1/examples/testsinks.list.response.json +20 -0
- package/generated/v1/examples/testsinks.read.response.json +14 -0
- package/generated/v1/examples/usage.read.response.json +20 -0
- package/generated/v1/first-value-journey.json +436 -0
- package/generated/v1/manifest.json +1037 -0
- package/generated/v1/openapi.json +23665 -0
- package/generated/v1/policy-matrix.json +305 -0
- package/generated/v1/schemas/attempts.list.query.json +16 -0
- package/generated/v1/schemas/attempts.list.response.json +175 -0
- package/generated/v1/schemas/attempts.read.response.json +168 -0
- package/generated/v1/schemas/credentials.create.request.json +39 -0
- package/generated/v1/schemas/credentials.create.response.json +88 -0
- package/generated/v1/schemas/credentials.list.query.json +16 -0
- package/generated/v1/schemas/credentials.list.response.json +124 -0
- package/generated/v1/schemas/credentials.revoke.response.json +84 -0
- package/generated/v1/schemas/credentials.rotate.request.json +11 -0
- package/generated/v1/schemas/credentials.rotate.response.json +171 -0
- package/generated/v1/schemas/endpoints.create.request.json +12 -0
- package/generated/v1/schemas/endpoints.create.response.json +115 -0
- package/generated/v1/schemas/endpoints.disable.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.disable.response.json +100 -0
- package/generated/v1/schemas/endpoints.list.query.json +16 -0
- package/generated/v1/schemas/endpoints.list.response.json +146 -0
- package/generated/v1/schemas/endpoints.read.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.read.response.json +100 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.request.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +118 -0
- package/generated/v1/schemas/endpoints.update.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.update.request.json +12 -0
- package/generated/v1/schemas/endpoints.update.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.update.response.json +100 -0
- package/generated/v1/schemas/endpoints.verify.request-headers.json +10 -0
- package/generated/v1/schemas/endpoints.verify.response-headers.json +11 -0
- package/generated/v1/schemas/endpoints.verify.response.json +100 -0
- package/generated/v1/schemas/forecast.read.query.json +26 -0
- package/generated/v1/schemas/forecast.read.response.json +100 -0
- package/generated/v1/schemas/forecast.windows.query.json +26 -0
- package/generated/v1/schemas/forecast.windows.response.json +94 -0
- package/generated/v1/schemas/grants.list.response.json +98 -0
- package/generated/v1/schemas/grants.revoke.response.json +95 -0
- package/generated/v1/schemas/meta.scaffold.response.json +36 -0
- package/generated/v1/schemas/meta.version.response.json +19 -0
- package/generated/v1/schemas/occurrences.list.query.json +16 -0
- package/generated/v1/schemas/occurrences.list.response.json +83 -0
- package/generated/v1/schemas/occurrences.read.response.json +76 -0
- package/generated/v1/schemas/occurrences.redeliver.request-headers.json +13 -0
- package/generated/v1/schemas/occurrences.redeliver.response-headers.json +10 -0
- package/generated/v1/schemas/occurrences.redeliver.response.json +168 -0
- package/generated/v1/schemas/projects.create.request.json +12 -0
- package/generated/v1/schemas/projects.create.response.json +25 -0
- package/generated/v1/schemas/projects.list.response.json +35 -0
- package/generated/v1/schemas/schedules.archive.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.archive.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.archive.response.json +189 -0
- package/generated/v1/schemas/schedules.cancel.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.cancel.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.cancel.response.json +189 -0
- package/generated/v1/schemas/schedules.create.request-headers.json +12 -0
- package/generated/v1/schemas/schedules.create.request.json +99 -0
- package/generated/v1/schemas/schedules.create.response-headers.json +15 -0
- package/generated/v1/schemas/schedules.create.response.json +189 -0
- package/generated/v1/schemas/schedules.list.query.json +16 -0
- package/generated/v1/schemas/schedules.list.response.json +170 -0
- package/generated/v1/schemas/schedules.pause.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.pause.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.pause.response.json +189 -0
- package/generated/v1/schemas/schedules.read.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.read.response.json +189 -0
- package/generated/v1/schemas/schedules.replace.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.replace.request.json +99 -0
- package/generated/v1/schemas/schedules.replace.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.replace.response.json +189 -0
- package/generated/v1/schemas/schedules.resume.request-headers.json +10 -0
- package/generated/v1/schemas/schedules.resume.response-headers.json +11 -0
- package/generated/v1/schemas/schedules.resume.response.json +189 -0
- package/generated/v1/schemas/sinkdeliveries.list.query.json +16 -0
- package/generated/v1/schemas/sinkdeliveries.list.response.json +126 -0
- package/generated/v1/schemas/sinkdeliveries.read.response.json +98 -0
- package/generated/v1/schemas/testsinks.configure.request.json +66 -0
- package/generated/v1/schemas/testsinks.configure.response.json +115 -0
- package/generated/v1/schemas/testsinks.create.request.json +76 -0
- package/generated/v1/schemas/testsinks.create.response.json +115 -0
- package/generated/v1/schemas/testsinks.delete.response.json +115 -0
- package/generated/v1/schemas/testsinks.list.query.json +16 -0
- package/generated/v1/schemas/testsinks.list.response.json +161 -0
- package/generated/v1/schemas/testsinks.read.response.json +115 -0
- package/generated/v1/schemas/usage.read.query.json +15 -0
- package/generated/v1/schemas/usage.read.response.json +71 -0
- package/generated/v1/snippets/attempts.list.json +5 -0
- package/generated/v1/snippets/attempts.read.json +5 -0
- package/generated/v1/snippets/credentials.create.json +5 -0
- package/generated/v1/snippets/credentials.list.json +5 -0
- package/generated/v1/snippets/credentials.revoke.json +5 -0
- package/generated/v1/snippets/credentials.rotate.json +5 -0
- package/generated/v1/snippets/endpoints.create.json +5 -0
- package/generated/v1/snippets/endpoints.disable.json +5 -0
- package/generated/v1/snippets/endpoints.list.json +5 -0
- package/generated/v1/snippets/endpoints.read.json +5 -0
- package/generated/v1/snippets/endpoints.rotateSigningKey.json +5 -0
- package/generated/v1/snippets/endpoints.update.json +5 -0
- package/generated/v1/snippets/endpoints.verify.json +5 -0
- package/generated/v1/snippets/forecast.read.json +5 -0
- package/generated/v1/snippets/forecast.windows.json +5 -0
- package/generated/v1/snippets/grants.list.json +5 -0
- package/generated/v1/snippets/grants.revoke.json +5 -0
- package/generated/v1/snippets/meta.scaffold.json +5 -0
- package/generated/v1/snippets/meta.version.json +5 -0
- package/generated/v1/snippets/occurrences.list.json +5 -0
- package/generated/v1/snippets/occurrences.read.json +5 -0
- package/generated/v1/snippets/occurrences.redeliver.json +5 -0
- package/generated/v1/snippets/projects.create.json +5 -0
- package/generated/v1/snippets/projects.list.json +5 -0
- package/generated/v1/snippets/schedules.archive.json +5 -0
- package/generated/v1/snippets/schedules.cancel.json +5 -0
- package/generated/v1/snippets/schedules.create.json +5 -0
- package/generated/v1/snippets/schedules.list.json +5 -0
- package/generated/v1/snippets/schedules.pause.json +5 -0
- package/generated/v1/snippets/schedules.read.json +5 -0
- package/generated/v1/snippets/schedules.replace.json +5 -0
- package/generated/v1/snippets/schedules.resume.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.list.json +5 -0
- package/generated/v1/snippets/sinkdeliveries.read.json +5 -0
- package/generated/v1/snippets/testsinks.configure.json +5 -0
- package/generated/v1/snippets/testsinks.create.json +5 -0
- package/generated/v1/snippets/testsinks.delete.json +5 -0
- package/generated/v1/snippets/testsinks.list.json +5 -0
- package/generated/v1/snippets/testsinks.read.json +5 -0
- package/generated/v1/snippets/usage.read.json +5 -0
- package/package.json +153 -0
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type Scope } from "./authority.js";
|
|
3
|
+
/**
|
|
4
|
+
* The delegated-authorization vocabulary: OAuth 2.1 as this product speaks it.
|
|
5
|
+
*
|
|
6
|
+
* Two things make this file worth reading before the routes that use it.
|
|
7
|
+
*
|
|
8
|
+
* **OAuth's wire shapes are not this product's wire shapes.** Everything on
|
|
9
|
+
* `/v1` answers `application/problem+json` with a `code` from `PROBLEM_CODES`;
|
|
10
|
+
* an OAuth endpoint answers `{"error": "invalid_grant"}` because RFC 6749 §5.2
|
|
11
|
+
* says so and every client in existence parses that. The two taxonomies are kept
|
|
12
|
+
* apart deliberately rather than reconciled — a client library that has to
|
|
13
|
+
* branch on which envelope it got back is a client library that will get it
|
|
14
|
+
* wrong. `OAUTH_ERRORS` below is the OAuth half, and it is closed for the same
|
|
15
|
+
* reason `PROBLEM_CODES` is.
|
|
16
|
+
*
|
|
17
|
+
* **The scope vocabulary is shared, and that is the whole point.** An OAuth
|
|
18
|
+
* grant carries `Scope` values from `authority.ts` — the same nine an API
|
|
19
|
+
* credential carries, capped by the same `capScopesToRole`. There is no
|
|
20
|
+
* OAuth-only scope and no OAuth-only operation, so a token cannot reach anything
|
|
21
|
+
* a key cannot, which is what architecture section 8 means by "API key and Clerk
|
|
22
|
+
* role mappings share one policy package".
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Where each OAuth endpoint lives.
|
|
26
|
+
*
|
|
27
|
+
* Stated once because two readers must agree: the router that serves them and
|
|
28
|
+
* the discovery documents that advertise them. A client fetches the metadata and
|
|
29
|
+
* then uses exactly the URLs it found there, so a path that drifts from its
|
|
30
|
+
* advertisement is not a 404 in one place — it is a client that cannot
|
|
31
|
+
* authenticate and cannot say why.
|
|
32
|
+
*
|
|
33
|
+
* Outside `/v1` on purpose, following the convention `CLERK_WEBHOOK_PATH` set.
|
|
34
|
+
* The `/v1` surface is the product's operation registry: every entry is
|
|
35
|
+
* projected into OpenAPI, the SDK, an MCP tool and the contract mock, and W1-07
|
|
36
|
+
* enforces parity across all of them. None of that is true of an OAuth endpoint,
|
|
37
|
+
* whose shape is fixed by a standard rather than by us, and one of which
|
|
38
|
+
* (`/oauth/token`) must never become an agent-callable tool.
|
|
39
|
+
*/
|
|
40
|
+
export declare const OAUTH_ROUTES: {
|
|
41
|
+
/** RFC 8414 authorization server metadata. */
|
|
42
|
+
readonly authorizationServerMetadata: "/.well-known/oauth-authorization-server";
|
|
43
|
+
/** The browser-facing start of the flow. */
|
|
44
|
+
readonly authorize: "/oauth/authorize";
|
|
45
|
+
/** What the consent screen reads to render itself. Session-authenticated. */
|
|
46
|
+
readonly authorizationRequest: "/oauth/authorization-requests/:authorizationRequestId";
|
|
47
|
+
/** Where the consent screen posts approve or deny. Session-authenticated. */
|
|
48
|
+
readonly consent: "/oauth/authorization-requests/:authorizationRequestId/consent";
|
|
49
|
+
/** RFC 9728 protected resource metadata, which is how MCP clients start. */
|
|
50
|
+
readonly protectedResourceMetadata: "/.well-known/oauth-protected-resource";
|
|
51
|
+
/** RFC 7591 dynamic client registration. */
|
|
52
|
+
readonly register: "/oauth/register";
|
|
53
|
+
/** RFC 7009 token revocation. */
|
|
54
|
+
readonly revoke: "/oauth/revoke";
|
|
55
|
+
/** RFC 6749 token endpoint. */
|
|
56
|
+
readonly token: "/oauth/token";
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Every error this authorization server emits, and nothing else.
|
|
60
|
+
*
|
|
61
|
+
* Closed rather than open because an `error` value is what a client branches on,
|
|
62
|
+
* exactly like a problem `code`. RFC 6749 §4.1.2.1 and §5.2 define most of
|
|
63
|
+
* these; `invalid_target` is RFC 8707's, for a `resource` naming something this
|
|
64
|
+
* server does not protect.
|
|
65
|
+
*
|
|
66
|
+
* Note what is *not* here: there is no error meaning "your membership was
|
|
67
|
+
* downgraded" and none meaning "that grant was revoked". Both are `invalid_grant`
|
|
68
|
+
* at the token endpoint, because RFC 6749 gives one code for "the grant is no
|
|
69
|
+
* longer usable" and inventing a second would tell a client which of the two
|
|
70
|
+
* happened — which is information about the account, delivered to whoever holds
|
|
71
|
+
* a dead token.
|
|
72
|
+
*/
|
|
73
|
+
export declare const OAUTH_ERRORS: readonly ["access_denied", "invalid_client", "invalid_client_metadata", "invalid_grant", "invalid_redirect_uri", "invalid_request", "invalid_scope", "invalid_target", "server_error", "temporarily_unavailable", "unauthorized_client", "unsupported_grant_type", "unsupported_response_type"];
|
|
74
|
+
export declare const oauthErrorCodeSchema: z.ZodEnum<{
|
|
75
|
+
invalid_request: "invalid_request";
|
|
76
|
+
access_denied: "access_denied";
|
|
77
|
+
invalid_client: "invalid_client";
|
|
78
|
+
invalid_client_metadata: "invalid_client_metadata";
|
|
79
|
+
invalid_grant: "invalid_grant";
|
|
80
|
+
invalid_redirect_uri: "invalid_redirect_uri";
|
|
81
|
+
invalid_scope: "invalid_scope";
|
|
82
|
+
invalid_target: "invalid_target";
|
|
83
|
+
server_error: "server_error";
|
|
84
|
+
temporarily_unavailable: "temporarily_unavailable";
|
|
85
|
+
unauthorized_client: "unauthorized_client";
|
|
86
|
+
unsupported_grant_type: "unsupported_grant_type";
|
|
87
|
+
unsupported_response_type: "unsupported_response_type";
|
|
88
|
+
}>;
|
|
89
|
+
export type OAuthErrorCode = z.infer<typeof oauthErrorCodeSchema>;
|
|
90
|
+
/**
|
|
91
|
+
* The error body, RFC 6749 §5.2.
|
|
92
|
+
*
|
|
93
|
+
* `error_description` is human-readable and must stay that way: it is displayed
|
|
94
|
+
* to developers and never parsed. FXO-1368 is the record of what happens when
|
|
95
|
+
* a caller does parse it — reconciliation that matched a provider's
|
|
96
|
+
* human-readable string broke when the wording changed. Anything a client needs
|
|
97
|
+
* to act on belongs in `error`.
|
|
98
|
+
*/
|
|
99
|
+
export declare const oauthErrorSchema: z.ZodObject<{
|
|
100
|
+
error: z.ZodEnum<{
|
|
101
|
+
invalid_request: "invalid_request";
|
|
102
|
+
access_denied: "access_denied";
|
|
103
|
+
invalid_client: "invalid_client";
|
|
104
|
+
invalid_client_metadata: "invalid_client_metadata";
|
|
105
|
+
invalid_grant: "invalid_grant";
|
|
106
|
+
invalid_redirect_uri: "invalid_redirect_uri";
|
|
107
|
+
invalid_scope: "invalid_scope";
|
|
108
|
+
invalid_target: "invalid_target";
|
|
109
|
+
server_error: "server_error";
|
|
110
|
+
temporarily_unavailable: "temporarily_unavailable";
|
|
111
|
+
unauthorized_client: "unauthorized_client";
|
|
112
|
+
unsupported_grant_type: "unsupported_grant_type";
|
|
113
|
+
unsupported_response_type: "unsupported_response_type";
|
|
114
|
+
}>;
|
|
115
|
+
error_description: z.ZodOptional<z.ZodString>;
|
|
116
|
+
error_uri: z.ZodOptional<z.ZodURL>;
|
|
117
|
+
}, z.core.$strip>;
|
|
118
|
+
export type OAuthErrorBody = z.infer<typeof oauthErrorSchema>;
|
|
119
|
+
/**
|
|
120
|
+
* HTTP status for each error, so a route cannot pair a code with the wrong one.
|
|
121
|
+
*
|
|
122
|
+
* `invalid_client` is 401 because RFC 6749 §5.2 says so, and the difference is
|
|
123
|
+
* load-bearing: a client that cannot authenticate must not be told to fix its
|
|
124
|
+
* request. Everything else on the token endpoint is 400 — including
|
|
125
|
+
* `invalid_grant`, which is the code a revoked, replayed or expired grant
|
|
126
|
+
* produces, and which is deliberately *not* 401. A 401 invites a client to
|
|
127
|
+
* re-present the same dead credential.
|
|
128
|
+
*/
|
|
129
|
+
export declare const OAUTH_ERROR_STATUS: Readonly<Record<OAuthErrorCode, 400 | 401 | 500 | 503>>;
|
|
130
|
+
/**
|
|
131
|
+
* Build an error body. The status comes from the table above rather than from
|
|
132
|
+
* the caller, so the two cannot contradict each other — the same argument
|
|
133
|
+
* `problem()` makes for `PROBLEM_CODES`.
|
|
134
|
+
*/
|
|
135
|
+
export declare function oauthError(error: OAuthErrorCode, description?: string): {
|
|
136
|
+
readonly body: OAuthErrorBody;
|
|
137
|
+
readonly status: 400 | 401 | 500 | 503;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The only grant types this server issues against.
|
|
141
|
+
*
|
|
142
|
+
* No implicit grant, no resource owner password credentials, no client
|
|
143
|
+
* credentials. The first two are removed by OAuth 2.1; the third would be a
|
|
144
|
+
* client acting with no human behind it, which is what an API credential already
|
|
145
|
+
* is and what `capScopesToRole` has no role to cap against.
|
|
146
|
+
*/
|
|
147
|
+
export declare const OAUTH_GRANT_TYPES: readonly ["authorization_code", "refresh_token"];
|
|
148
|
+
export declare const oauthGrantTypeSchema: z.ZodEnum<{
|
|
149
|
+
authorization_code: "authorization_code";
|
|
150
|
+
refresh_token: "refresh_token";
|
|
151
|
+
}>;
|
|
152
|
+
export type OAuthGrantType = z.infer<typeof oauthGrantTypeSchema>;
|
|
153
|
+
/** Authorization code is the only response type. See above. */
|
|
154
|
+
export declare const OAUTH_RESPONSE_TYPES: readonly ["code"];
|
|
155
|
+
/**
|
|
156
|
+
* PKCE challenge methods, and `plain` is not one.
|
|
157
|
+
*
|
|
158
|
+
* OAuth 2.1 removes it, and the reason is worth stating where the constant is:
|
|
159
|
+
* `plain` sends the verifier as the challenge, so anyone who can read the
|
|
160
|
+
* authorization request can complete the exchange — which is the entire attack
|
|
161
|
+
* PKCE exists to stop. A client asking for `plain` is refused rather than
|
|
162
|
+
* downgraded to it.
|
|
163
|
+
*/
|
|
164
|
+
export declare const PKCE_METHODS: readonly ["S256"];
|
|
165
|
+
export declare const pkceMethodSchema: z.ZodEnum<{
|
|
166
|
+
S256: "S256";
|
|
167
|
+
}>;
|
|
168
|
+
/**
|
|
169
|
+
* RFC 7636 §4.1: 43–128 characters from an unreserved alphabet. The floor is
|
|
170
|
+
* what makes the verifier unguessable, so it is enforced rather than assumed.
|
|
171
|
+
*/
|
|
172
|
+
export declare const PKCE_VERIFIER_PATTERN: RegExp;
|
|
173
|
+
/** The base64url SHA-256 of a verifier: 43 characters, no padding. */
|
|
174
|
+
export declare const PKCE_CHALLENGE_PATTERN: RegExp;
|
|
175
|
+
/**
|
|
176
|
+
* Client authentication methods this server accepts, which is one: none.
|
|
177
|
+
*
|
|
178
|
+
* **Every client here is a public client.** An MCP client is a desktop
|
|
179
|
+
* application, a CLI, or a browser extension; it cannot keep a secret, and RFC
|
|
180
|
+
* 7591 registration hands a `client_secret` to whoever asked for one without
|
|
181
|
+
* ever authenticating them. Issuing a secret to an unauthenticated registrant
|
|
182
|
+
* and then treating it as proof of identity is a confidence trick played on
|
|
183
|
+
* ourselves.
|
|
184
|
+
*
|
|
185
|
+
* What replaces it is PKCE, which is mandatory here, plus exact redirect
|
|
186
|
+
* matching — together those bind an authorization code to the software instance
|
|
187
|
+
* that started the flow, which is the property a client secret is usually
|
|
188
|
+
* pressed into providing. A confidential-client flow can be added later without
|
|
189
|
+
* a contract break; adding it now would be surface with no consumer.
|
|
190
|
+
*/
|
|
191
|
+
export declare const TOKEN_ENDPOINT_AUTH_METHODS: readonly ["none"];
|
|
192
|
+
/**
|
|
193
|
+
* How long a member has to finish consenting before the request expires.
|
|
194
|
+
*
|
|
195
|
+
* Short because a pending authorization request is a live intent to grant
|
|
196
|
+
* access, and a long-lived one is something an attacker can hope a member
|
|
197
|
+
* approves absent-mindedly later. Ten minutes is enough to sign in to Clerk from
|
|
198
|
+
* a cold browser and read the screen.
|
|
199
|
+
*/
|
|
200
|
+
export declare const AUTHORIZATION_REQUEST_TTL_SECONDS = 600;
|
|
201
|
+
/**
|
|
202
|
+
* How long an issued authorization code may be exchanged.
|
|
203
|
+
*
|
|
204
|
+
* RFC 6749 §4.1.2 recommends a maximum of ten minutes; this is deliberately much
|
|
205
|
+
* shorter, because the code travels through the user's browser — a redirect
|
|
206
|
+
* chain, an address bar, a browser history entry, and whatever referrer policy
|
|
207
|
+
* the client's own page carries. Sixty seconds is more than a token exchange
|
|
208
|
+
* needs and less than a leak is useful for.
|
|
209
|
+
*/
|
|
210
|
+
export declare const AUTHORIZATION_CODE_TTL_SECONDS = 60;
|
|
211
|
+
/**
|
|
212
|
+
* How long an access token is valid.
|
|
213
|
+
*
|
|
214
|
+
* The number that decides how stale a revocation may be *in the worst case where
|
|
215
|
+
* the token check is skipped* — which, on this server, is never: every request
|
|
216
|
+
* loads the grant and re-checks membership, so a revoked grant fails on its next
|
|
217
|
+
* use rather than at the end of this window. The lifetime is short anyway,
|
|
218
|
+
* because a token this cheap to refresh has no reason to be long-lived.
|
|
219
|
+
*/
|
|
220
|
+
export declare const ACCESS_TOKEN_TTL_SECONDS = 3600;
|
|
221
|
+
/**
|
|
222
|
+
* How long a refresh token is valid, absent rotation.
|
|
223
|
+
*
|
|
224
|
+
* Rotation resets it, so an actively used grant survives indefinitely and an
|
|
225
|
+
* abandoned one stops working after thirty days. That is the behaviour a member
|
|
226
|
+
* expects from "apps I have connected": the ones they use keep working, and the
|
|
227
|
+
* ones they forgot about do not accumulate forever.
|
|
228
|
+
*/
|
|
229
|
+
export declare const REFRESH_TOKEN_TTL_SECONDS = 2592000;
|
|
230
|
+
/**
|
|
231
|
+
* Token shapes.
|
|
232
|
+
*
|
|
233
|
+
* The same prefix-plus-secret construction API credentials use, for the same
|
|
234
|
+
* reason: a presented token is found by its non-secret leading segment before
|
|
235
|
+
* anything is compared, so verification never scans. The environment is in the
|
|
236
|
+
* prefix because a token that cannot be told apart from a live one at a glance
|
|
237
|
+
* is one somebody will paste into the wrong place.
|
|
238
|
+
*
|
|
239
|
+
* Three separate prefixes rather than one, because they are three different
|
|
240
|
+
* things with three different lifetimes, and a store that accepted a refresh
|
|
241
|
+
* token where an access token belonged would be one type confusion away from
|
|
242
|
+
* making the short lifetime meaningless.
|
|
243
|
+
*/
|
|
244
|
+
/** `oat_live_` and friends: four characters, the environment, two separators. */
|
|
245
|
+
export declare const OAUTH_TOKEN_NAMESPACE_LENGTH = 9;
|
|
246
|
+
/**
|
|
247
|
+
* Random characters after the namespace. Forty-eight of a 32-symbol alphabet is
|
|
248
|
+
* 240 bits — deliberately more than a credential's 160, because these are minted
|
|
249
|
+
* by machines at machine rates and nobody ever has to type one.
|
|
250
|
+
*/
|
|
251
|
+
export declare const OAUTH_TOKEN_SECRET_LENGTH = 48;
|
|
252
|
+
export declare const ACCESS_TOKEN_PATTERN: RegExp;
|
|
253
|
+
export declare const REFRESH_TOKEN_PATTERN: RegExp;
|
|
254
|
+
export declare const AUTHORIZATION_CODE_PATTERN: RegExp;
|
|
255
|
+
/** Any of the three, for the one place that has to tell ours from anything else. */
|
|
256
|
+
export declare const OAUTH_SECRET_PATTERN: RegExp;
|
|
257
|
+
export declare const redirectUriSchema: z.ZodString;
|
|
258
|
+
/** Whether a redirect URI names a loopback listener. Exported for the store. */
|
|
259
|
+
export declare function isLoopbackRedirect(value: string): boolean;
|
|
260
|
+
/** The most redirect URIs one client may register. */
|
|
261
|
+
export declare const MAX_REDIRECT_URIS = 8;
|
|
262
|
+
/**
|
|
263
|
+
* RFC 7591 dynamic client registration.
|
|
264
|
+
*
|
|
265
|
+
* Registration is open — no credential is required to call it — and that is a
|
|
266
|
+
* deliberate, bounded decision rather than an oversight. An MCP client
|
|
267
|
+
* discovers this server, registers itself, and only then asks a human to
|
|
268
|
+
* approve it; requiring a credential first would mean every client had to be
|
|
269
|
+
* provisioned by hand before anyone could try it, which is the friction dynamic
|
|
270
|
+
* registration exists to remove.
|
|
271
|
+
*
|
|
272
|
+
* What makes it safe is that **a registered client holds no authority at all**.
|
|
273
|
+
* It cannot read, write, or name anything until a signed-in member approves a
|
|
274
|
+
* grant, and that grant is capped by the member's own role. The worst a
|
|
275
|
+
* registration flood achieves is rows in a table, which is a rate-limiting
|
|
276
|
+
* problem — W7-03's, and named there rather than solved here with an unmeasured
|
|
277
|
+
* limit.
|
|
278
|
+
*
|
|
279
|
+
* Unknown fields are dropped rather than refused. RFC 7591 §2 lets a client send
|
|
280
|
+
* metadata a server does not implement, and says the server returns what it
|
|
281
|
+
* actually registered — so a client sending `logo_uri` gets a registration back
|
|
282
|
+
* without one, not a 400.
|
|
283
|
+
*/
|
|
284
|
+
/**
|
|
285
|
+
* A URL the consent screen may put in front of a human.
|
|
286
|
+
*
|
|
287
|
+
* `https` and nothing else. The scheme check is the whole guard: `javascript:`
|
|
288
|
+
* and `data:` are the ones that execute, and `http:` is the one an intermediary
|
|
289
|
+
* can rewrite — on the page where what the human sees *is* the decision.
|
|
290
|
+
*/
|
|
291
|
+
export declare const httpsUriSchema: z.ZodURL;
|
|
292
|
+
export declare const clientRegistrationRequestSchema: z.ZodObject<{
|
|
293
|
+
client_name: z.ZodString;
|
|
294
|
+
client_uri: z.ZodOptional<z.ZodURL>;
|
|
295
|
+
grant_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
296
|
+
authorization_code: "authorization_code";
|
|
297
|
+
refresh_token: "refresh_token";
|
|
298
|
+
}>>>;
|
|
299
|
+
logo_uri: z.ZodOptional<z.ZodURL>;
|
|
300
|
+
policy_uri: z.ZodOptional<z.ZodURL>;
|
|
301
|
+
redirect_uris: z.ZodArray<z.ZodString>;
|
|
302
|
+
response_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
303
|
+
code: "code";
|
|
304
|
+
}>>>;
|
|
305
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
306
|
+
token_endpoint_auth_method: z.ZodOptional<z.ZodEnum<{
|
|
307
|
+
none: "none";
|
|
308
|
+
}>>;
|
|
309
|
+
tos_uri: z.ZodOptional<z.ZodURL>;
|
|
310
|
+
}, z.core.$strip>;
|
|
311
|
+
export type ClientRegistrationRequest = z.infer<typeof clientRegistrationRequestSchema>;
|
|
312
|
+
/**
|
|
313
|
+
* What registration answers with, RFC 7591 §3.2.1.
|
|
314
|
+
*
|
|
315
|
+
* No `client_secret`, and no `client_secret_expires_at` either — RFC 7591 says
|
|
316
|
+
* the latter is required *when a secret is issued*, and emitting it as `0`
|
|
317
|
+
* alongside no secret is how a client concludes it has a non-expiring one.
|
|
318
|
+
*/
|
|
319
|
+
export declare const clientRegistrationSchema: z.ZodObject<{
|
|
320
|
+
client_id: z.ZodString;
|
|
321
|
+
client_id_issued_at: z.ZodNumber;
|
|
322
|
+
client_name: z.ZodString;
|
|
323
|
+
client_uri: z.ZodOptional<z.ZodString>;
|
|
324
|
+
grant_types: z.ZodArray<z.ZodEnum<{
|
|
325
|
+
authorization_code: "authorization_code";
|
|
326
|
+
refresh_token: "refresh_token";
|
|
327
|
+
}>>;
|
|
328
|
+
logo_uri: z.ZodOptional<z.ZodString>;
|
|
329
|
+
policy_uri: z.ZodOptional<z.ZodString>;
|
|
330
|
+
redirect_uris: z.ZodArray<z.ZodString>;
|
|
331
|
+
response_types: z.ZodArray<z.ZodEnum<{
|
|
332
|
+
code: "code";
|
|
333
|
+
}>>;
|
|
334
|
+
scope: z.ZodString;
|
|
335
|
+
token_endpoint_auth_method: z.ZodEnum<{
|
|
336
|
+
none: "none";
|
|
337
|
+
}>;
|
|
338
|
+
tos_uri: z.ZodOptional<z.ZodString>;
|
|
339
|
+
}, z.core.$strip>;
|
|
340
|
+
export type ClientRegistration = z.infer<typeof clientRegistrationSchema>;
|
|
341
|
+
/**
|
|
342
|
+
* Scopes on the wire are one space-delimited string, RFC 6749 §3.3.
|
|
343
|
+
*
|
|
344
|
+
* Parsing drops anything not in `SCOPES` rather than refusing the request. The
|
|
345
|
+
* choice matters and follows `capScopesToRole`: a client asking for a scope this
|
|
346
|
+
* server does not know is asking for less than it thought, and the consent
|
|
347
|
+
* screen shows what it will actually get. Refusing outright would break every
|
|
348
|
+
* client that sends a scope some other server understood.
|
|
349
|
+
*
|
|
350
|
+
* A request whose scopes *all* fall away is a different case and is refused as
|
|
351
|
+
* `invalid_scope` by the caller — asking for nothing this server can grant is a
|
|
352
|
+
* mistake worth reporting.
|
|
353
|
+
*/
|
|
354
|
+
export declare function parseScopeString(value: string | undefined): readonly Scope[];
|
|
355
|
+
/** The inverse. Ordered by `SCOPES` so one grant has exactly one spelling. */
|
|
356
|
+
export declare function formatScopeString(scopes: readonly Scope[]): string;
|
|
357
|
+
/**
|
|
358
|
+
* The authorization request, as it arrives on the query string.
|
|
359
|
+
*
|
|
360
|
+
* Everything is a string because a query string has no other type, and the
|
|
361
|
+
* coercions happen here rather than in the route. `state` is opaque and echoed
|
|
362
|
+
* back untouched — it is the client's CSRF defence and this server has no
|
|
363
|
+
* business interpreting it.
|
|
364
|
+
*
|
|
365
|
+
* `resource` is RFC 8707's, and MCP's authorization specification requires
|
|
366
|
+
* clients to send it. It is validated against this server's own resource
|
|
367
|
+
* identifier rather than merely recorded: a token minted for one audience and
|
|
368
|
+
* accepted by another is the confused-deputy problem RFC 8707 exists to close.
|
|
369
|
+
*/
|
|
370
|
+
export declare const authorizationParametersSchema: z.ZodObject<{
|
|
371
|
+
client_id: z.ZodString;
|
|
372
|
+
code_challenge: z.ZodString;
|
|
373
|
+
code_challenge_method: z.ZodEnum<{
|
|
374
|
+
S256: "S256";
|
|
375
|
+
}>;
|
|
376
|
+
redirect_uri: z.ZodString;
|
|
377
|
+
resource: z.ZodOptional<z.ZodString>;
|
|
378
|
+
response_type: z.ZodEnum<{
|
|
379
|
+
code: "code";
|
|
380
|
+
}>;
|
|
381
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
382
|
+
state: z.ZodOptional<z.ZodString>;
|
|
383
|
+
}, z.core.$strip>;
|
|
384
|
+
export type AuthorizationParameters = z.infer<typeof authorizationParametersSchema>;
|
|
385
|
+
/**
|
|
386
|
+
* What the consent screen is given to render.
|
|
387
|
+
*
|
|
388
|
+
* It names the client, the scopes, and the projects the member may grant
|
|
389
|
+
* within — architecture section 8 requires consent to name project, environment
|
|
390
|
+
* and scopes, and a screen that cannot show them cannot obtain that consent.
|
|
391
|
+
*
|
|
392
|
+
* `scopes` here is already capped to the member's current role, so the screen
|
|
393
|
+
* never displays a permission that would not actually be granted. A member who
|
|
394
|
+
* asked for `credentials:write` and holds `member` sees the reduced list, which
|
|
395
|
+
* is the honest thing to show and is also what will be recorded.
|
|
396
|
+
*/
|
|
397
|
+
export declare const consentPromptSchema: z.ZodObject<{
|
|
398
|
+
client: z.ZodObject<{
|
|
399
|
+
id: z.ZodString;
|
|
400
|
+
logoUri: z.ZodOptional<z.ZodString>;
|
|
401
|
+
name: z.ZodString;
|
|
402
|
+
policyUri: z.ZodOptional<z.ZodString>;
|
|
403
|
+
termsUri: z.ZodOptional<z.ZodString>;
|
|
404
|
+
uri: z.ZodOptional<z.ZodString>;
|
|
405
|
+
}, z.core.$strip>;
|
|
406
|
+
environmentKinds: z.ZodArray<z.ZodEnum<{
|
|
407
|
+
test: "test";
|
|
408
|
+
live: "live";
|
|
409
|
+
}>>;
|
|
410
|
+
expiresAt: z.ZodString;
|
|
411
|
+
redirectUri: z.ZodString;
|
|
412
|
+
projects: z.ZodArray<z.ZodObject<{
|
|
413
|
+
id: z.ZodString;
|
|
414
|
+
name: z.ZodString;
|
|
415
|
+
}, z.core.$strip>>;
|
|
416
|
+
scopes: z.ZodArray<z.ZodEnum<{
|
|
417
|
+
"credentials:administer": "credentials:administer";
|
|
418
|
+
"credentials:read": "credentials:read";
|
|
419
|
+
"credentials:write": "credentials:write";
|
|
420
|
+
"endpoints:read": "endpoints:read";
|
|
421
|
+
"endpoints:write": "endpoints:write";
|
|
422
|
+
"forecast:read": "forecast:read";
|
|
423
|
+
"grants:read": "grants:read";
|
|
424
|
+
"grants:write": "grants:write";
|
|
425
|
+
"occurrences:read": "occurrences:read";
|
|
426
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
427
|
+
"projects:read": "projects:read";
|
|
428
|
+
"projects:write": "projects:write";
|
|
429
|
+
"schedules:read": "schedules:read";
|
|
430
|
+
"schedules:write": "schedules:write";
|
|
431
|
+
"usage:read": "usage:read";
|
|
432
|
+
}>>;
|
|
433
|
+
}, z.core.$strip>;
|
|
434
|
+
export type ConsentPrompt = z.infer<typeof consentPromptSchema>;
|
|
435
|
+
/**
|
|
436
|
+
* The member's decision.
|
|
437
|
+
*
|
|
438
|
+
* `scopes` is the member's own narrowing — a consent screen that only offered
|
|
439
|
+
* all-or-nothing would train people to click through. It is intersected with
|
|
440
|
+
* what was requested and with the role ceiling, so it can only ever reduce.
|
|
441
|
+
*
|
|
442
|
+
* `project` and `environmentKind` are the *authority* the grant will carry, and
|
|
443
|
+
* they are chosen here rather than requested by the client. A client that could
|
|
444
|
+
* name a project would be selecting a tenant, which the `/v1` conventions forbid
|
|
445
|
+
* outright and which is no less forbidden because the request arrived through a
|
|
446
|
+
* browser.
|
|
447
|
+
*/
|
|
448
|
+
export declare const consentDecisionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
449
|
+
decision: z.ZodLiteral<"approve">;
|
|
450
|
+
environmentKind: z.ZodEnum<{
|
|
451
|
+
test: "test";
|
|
452
|
+
live: "live";
|
|
453
|
+
}>;
|
|
454
|
+
project: z.ZodString;
|
|
455
|
+
scopes: z.ZodArray<z.ZodEnum<{
|
|
456
|
+
"credentials:administer": "credentials:administer";
|
|
457
|
+
"credentials:read": "credentials:read";
|
|
458
|
+
"credentials:write": "credentials:write";
|
|
459
|
+
"endpoints:read": "endpoints:read";
|
|
460
|
+
"endpoints:write": "endpoints:write";
|
|
461
|
+
"forecast:read": "forecast:read";
|
|
462
|
+
"grants:read": "grants:read";
|
|
463
|
+
"grants:write": "grants:write";
|
|
464
|
+
"occurrences:read": "occurrences:read";
|
|
465
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
466
|
+
"projects:read": "projects:read";
|
|
467
|
+
"projects:write": "projects:write";
|
|
468
|
+
"schedules:read": "schedules:read";
|
|
469
|
+
"schedules:write": "schedules:write";
|
|
470
|
+
"usage:read": "usage:read";
|
|
471
|
+
}>>;
|
|
472
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
473
|
+
decision: z.ZodLiteral<"deny">;
|
|
474
|
+
}, z.core.$strip>], "decision">;
|
|
475
|
+
export type ConsentDecision = z.infer<typeof consentDecisionSchema>;
|
|
476
|
+
/**
|
|
477
|
+
* Where to send the browser next.
|
|
478
|
+
*
|
|
479
|
+
* Returned as a body rather than served as a 302, because the caller is the
|
|
480
|
+
* consent screen's `fetch` rather than the browser itself — a redirect answered
|
|
481
|
+
* to `fetch` would be followed by the client, delivering the code to the
|
|
482
|
+
* consent screen's own JavaScript instead of to the client's redirect URI.
|
|
483
|
+
*/
|
|
484
|
+
export declare const consentOutcomeSchema: z.ZodObject<{
|
|
485
|
+
redirectTo: z.ZodString;
|
|
486
|
+
}, z.core.$strip>;
|
|
487
|
+
export type ConsentOutcome = z.infer<typeof consentOutcomeSchema>;
|
|
488
|
+
/** RFC 6749 §5.1. `expires_in` is seconds, and relative, as the standard says. */
|
|
489
|
+
export declare const tokenResponseSchema: z.ZodObject<{
|
|
490
|
+
access_token: z.ZodString;
|
|
491
|
+
expires_in: z.ZodNumber;
|
|
492
|
+
refresh_token: z.ZodString;
|
|
493
|
+
scope: z.ZodString;
|
|
494
|
+
token_type: z.ZodLiteral<"Bearer">;
|
|
495
|
+
}, z.core.$strip>;
|
|
496
|
+
export type TokenResponse = z.infer<typeof tokenResponseSchema>;
|
|
497
|
+
/**
|
|
498
|
+
* The token request, form-encoded per RFC 6749 §4.1.3 and §6.
|
|
499
|
+
*
|
|
500
|
+
* A discriminated union on `grant_type` so the two exchanges cannot borrow each
|
|
501
|
+
* other's fields: an authorization-code request without a `code_verifier` is
|
|
502
|
+
* refused by the shape rather than by a check somebody has to remember, which is
|
|
503
|
+
* what makes "PKCE is mandatory" a property of the contract.
|
|
504
|
+
*/
|
|
505
|
+
export declare const tokenRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
506
|
+
client_id: z.ZodString;
|
|
507
|
+
code: z.ZodString;
|
|
508
|
+
code_verifier: z.ZodString;
|
|
509
|
+
grant_type: z.ZodLiteral<"authorization_code">;
|
|
510
|
+
redirect_uri: z.ZodString;
|
|
511
|
+
resource: z.ZodOptional<z.ZodString>;
|
|
512
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
513
|
+
client_id: z.ZodString;
|
|
514
|
+
grant_type: z.ZodLiteral<"refresh_token">;
|
|
515
|
+
refresh_token: z.ZodString;
|
|
516
|
+
resource: z.ZodOptional<z.ZodString>;
|
|
517
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
518
|
+
}, z.core.$strip>], "grant_type">;
|
|
519
|
+
export type TokenRequest = z.infer<typeof tokenRequestSchema>;
|
|
520
|
+
/** RFC 7009 §2.1. The hint is advisory and this server ignores it. */
|
|
521
|
+
export declare const revocationRequestSchema: z.ZodObject<{
|
|
522
|
+
client_id: z.ZodString;
|
|
523
|
+
token: z.ZodString;
|
|
524
|
+
token_type_hint: z.ZodOptional<z.ZodEnum<{
|
|
525
|
+
refresh_token: "refresh_token";
|
|
526
|
+
access_token: "access_token";
|
|
527
|
+
}>>;
|
|
528
|
+
}, z.core.$strip>;
|
|
529
|
+
export type RevocationRequest = z.infer<typeof revocationRequestSchema>;
|
|
530
|
+
/**
|
|
531
|
+
* What became of a grant.
|
|
532
|
+
*
|
|
533
|
+
* `revoked` is terminal and covers every way a grant dies — the member revoked
|
|
534
|
+
* it, a code or refresh token was replayed, or the client revoked its own token.
|
|
535
|
+
* There is no `expired` state: a grant whose refresh token lapsed is still a
|
|
536
|
+
* grant the member may want to see and revoke, and collapsing it into `revoked`
|
|
537
|
+
* would say somebody decided something when nobody did.
|
|
538
|
+
*/
|
|
539
|
+
export declare const OAUTH_GRANT_STATUSES: readonly ["active", "revoked"];
|
|
540
|
+
export declare const oauthGrantStatusSchema: z.ZodEnum<{
|
|
541
|
+
active: "active";
|
|
542
|
+
revoked: "revoked";
|
|
543
|
+
}>;
|
|
544
|
+
export type OAuthGrantStatus = z.infer<typeof oauthGrantStatusSchema>;
|
|
545
|
+
/**
|
|
546
|
+
* Why a grant became terminal.
|
|
547
|
+
*
|
|
548
|
+
* Recorded because "my integration stopped working" is a support question, and
|
|
549
|
+
* the four answers are genuinely different: somebody revoked it deliberately,
|
|
550
|
+
* the client revoked its own token, or one of the two replay defences fired.
|
|
551
|
+
* The last two are security events and the first two are not, and an audit trail
|
|
552
|
+
* that cannot tell them apart cannot answer either question.
|
|
553
|
+
*/
|
|
554
|
+
export declare const OAUTH_REVOCATION_REASONS: readonly ["authorization-code-replayed", "client-revoked", "member-revoked", "refresh-token-replayed"];
|
|
555
|
+
export declare const oauthRevocationReasonSchema: z.ZodEnum<{
|
|
556
|
+
"authorization-code-replayed": "authorization-code-replayed";
|
|
557
|
+
"client-revoked": "client-revoked";
|
|
558
|
+
"member-revoked": "member-revoked";
|
|
559
|
+
"refresh-token-replayed": "refresh-token-replayed";
|
|
560
|
+
}>;
|
|
561
|
+
export type OAuthRevocationReason = z.infer<typeof oauthRevocationReasonSchema>;
|
|
562
|
+
/**
|
|
563
|
+
* A grant as the member sees it. No token material, present or past.
|
|
564
|
+
*
|
|
565
|
+
* This is the shape architecture section 8's "user-visible grant revocation"
|
|
566
|
+
* needs: enough to recognise which application this is and decide whether to
|
|
567
|
+
* keep it, and nothing that would let a reader of the list use it.
|
|
568
|
+
*/
|
|
569
|
+
export declare const oauthGrantSchema: z.ZodObject<{
|
|
570
|
+
client: z.ZodObject<{
|
|
571
|
+
id: z.ZodString;
|
|
572
|
+
name: z.ZodString;
|
|
573
|
+
}, z.core.$strip>;
|
|
574
|
+
createdAt: z.ZodString;
|
|
575
|
+
environmentKind: z.ZodEnum<{
|
|
576
|
+
test: "test";
|
|
577
|
+
live: "live";
|
|
578
|
+
}>;
|
|
579
|
+
id: z.ZodString;
|
|
580
|
+
lastUsedAt: z.ZodOptional<z.ZodString>;
|
|
581
|
+
project: z.ZodString;
|
|
582
|
+
revocationReason: z.ZodOptional<z.ZodEnum<{
|
|
583
|
+
"authorization-code-replayed": "authorization-code-replayed";
|
|
584
|
+
"client-revoked": "client-revoked";
|
|
585
|
+
"member-revoked": "member-revoked";
|
|
586
|
+
"refresh-token-replayed": "refresh-token-replayed";
|
|
587
|
+
}>>;
|
|
588
|
+
revokedAt: z.ZodOptional<z.ZodString>;
|
|
589
|
+
scopes: z.ZodArray<z.ZodEnum<{
|
|
590
|
+
"credentials:administer": "credentials:administer";
|
|
591
|
+
"credentials:read": "credentials:read";
|
|
592
|
+
"credentials:write": "credentials:write";
|
|
593
|
+
"endpoints:read": "endpoints:read";
|
|
594
|
+
"endpoints:write": "endpoints:write";
|
|
595
|
+
"forecast:read": "forecast:read";
|
|
596
|
+
"grants:read": "grants:read";
|
|
597
|
+
"grants:write": "grants:write";
|
|
598
|
+
"occurrences:read": "occurrences:read";
|
|
599
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
600
|
+
"projects:read": "projects:read";
|
|
601
|
+
"projects:write": "projects:write";
|
|
602
|
+
"schedules:read": "schedules:read";
|
|
603
|
+
"schedules:write": "schedules:write";
|
|
604
|
+
"usage:read": "usage:read";
|
|
605
|
+
}>>;
|
|
606
|
+
status: z.ZodEnum<{
|
|
607
|
+
active: "active";
|
|
608
|
+
revoked: "revoked";
|
|
609
|
+
}>;
|
|
610
|
+
}, z.core.$strip>;
|
|
611
|
+
export type OAuthGrant = z.infer<typeof oauthGrantSchema>;
|
|
612
|
+
export declare const oauthGrantListSchema: z.ZodObject<{
|
|
613
|
+
data: z.ZodArray<z.ZodObject<{
|
|
614
|
+
client: z.ZodObject<{
|
|
615
|
+
id: z.ZodString;
|
|
616
|
+
name: z.ZodString;
|
|
617
|
+
}, z.core.$strip>;
|
|
618
|
+
createdAt: z.ZodString;
|
|
619
|
+
environmentKind: z.ZodEnum<{
|
|
620
|
+
test: "test";
|
|
621
|
+
live: "live";
|
|
622
|
+
}>;
|
|
623
|
+
id: z.ZodString;
|
|
624
|
+
lastUsedAt: z.ZodOptional<z.ZodString>;
|
|
625
|
+
project: z.ZodString;
|
|
626
|
+
revocationReason: z.ZodOptional<z.ZodEnum<{
|
|
627
|
+
"authorization-code-replayed": "authorization-code-replayed";
|
|
628
|
+
"client-revoked": "client-revoked";
|
|
629
|
+
"member-revoked": "member-revoked";
|
|
630
|
+
"refresh-token-replayed": "refresh-token-replayed";
|
|
631
|
+
}>>;
|
|
632
|
+
revokedAt: z.ZodOptional<z.ZodString>;
|
|
633
|
+
scopes: z.ZodArray<z.ZodEnum<{
|
|
634
|
+
"credentials:administer": "credentials:administer";
|
|
635
|
+
"credentials:read": "credentials:read";
|
|
636
|
+
"credentials:write": "credentials:write";
|
|
637
|
+
"endpoints:read": "endpoints:read";
|
|
638
|
+
"endpoints:write": "endpoints:write";
|
|
639
|
+
"forecast:read": "forecast:read";
|
|
640
|
+
"grants:read": "grants:read";
|
|
641
|
+
"grants:write": "grants:write";
|
|
642
|
+
"occurrences:read": "occurrences:read";
|
|
643
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
644
|
+
"projects:read": "projects:read";
|
|
645
|
+
"projects:write": "projects:write";
|
|
646
|
+
"schedules:read": "schedules:read";
|
|
647
|
+
"schedules:write": "schedules:write";
|
|
648
|
+
"usage:read": "usage:read";
|
|
649
|
+
}>>;
|
|
650
|
+
status: z.ZodEnum<{
|
|
651
|
+
active: "active";
|
|
652
|
+
revoked: "revoked";
|
|
653
|
+
}>;
|
|
654
|
+
}, z.core.$strip>>;
|
|
655
|
+
}, z.core.$strip>;
|
|
656
|
+
export type OAuthGrantList = z.infer<typeof oauthGrantListSchema>;
|
|
657
|
+
/**
|
|
658
|
+
* What disconnecting answers with.
|
|
659
|
+
*
|
|
660
|
+
* The grant rather than an empty body, for the reason `credentialRevokedSchema`
|
|
661
|
+
* gives: a member who clicked disconnect wants to see *which* connection stopped
|
|
662
|
+
* and when, and a 204 makes them ask for that separately.
|
|
663
|
+
*/
|
|
664
|
+
export declare const oauthGrantRevokedSchema: z.ZodObject<{
|
|
665
|
+
grant: z.ZodObject<{
|
|
666
|
+
client: z.ZodObject<{
|
|
667
|
+
id: z.ZodString;
|
|
668
|
+
name: z.ZodString;
|
|
669
|
+
}, z.core.$strip>;
|
|
670
|
+
createdAt: z.ZodString;
|
|
671
|
+
environmentKind: z.ZodEnum<{
|
|
672
|
+
test: "test";
|
|
673
|
+
live: "live";
|
|
674
|
+
}>;
|
|
675
|
+
id: z.ZodString;
|
|
676
|
+
lastUsedAt: z.ZodOptional<z.ZodString>;
|
|
677
|
+
project: z.ZodString;
|
|
678
|
+
revocationReason: z.ZodOptional<z.ZodEnum<{
|
|
679
|
+
"authorization-code-replayed": "authorization-code-replayed";
|
|
680
|
+
"client-revoked": "client-revoked";
|
|
681
|
+
"member-revoked": "member-revoked";
|
|
682
|
+
"refresh-token-replayed": "refresh-token-replayed";
|
|
683
|
+
}>>;
|
|
684
|
+
revokedAt: z.ZodOptional<z.ZodString>;
|
|
685
|
+
scopes: z.ZodArray<z.ZodEnum<{
|
|
686
|
+
"credentials:administer": "credentials:administer";
|
|
687
|
+
"credentials:read": "credentials:read";
|
|
688
|
+
"credentials:write": "credentials:write";
|
|
689
|
+
"endpoints:read": "endpoints:read";
|
|
690
|
+
"endpoints:write": "endpoints:write";
|
|
691
|
+
"forecast:read": "forecast:read";
|
|
692
|
+
"grants:read": "grants:read";
|
|
693
|
+
"grants:write": "grants:write";
|
|
694
|
+
"occurrences:read": "occurrences:read";
|
|
695
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
696
|
+
"projects:read": "projects:read";
|
|
697
|
+
"projects:write": "projects:write";
|
|
698
|
+
"schedules:read": "schedules:read";
|
|
699
|
+
"schedules:write": "schedules:write";
|
|
700
|
+
"usage:read": "usage:read";
|
|
701
|
+
}>>;
|
|
702
|
+
status: z.ZodEnum<{
|
|
703
|
+
active: "active";
|
|
704
|
+
revoked: "revoked";
|
|
705
|
+
}>;
|
|
706
|
+
}, z.core.$strip>;
|
|
707
|
+
}, z.core.$strip>;
|
|
708
|
+
export type OAuthGrantRevoked = z.infer<typeof oauthGrantRevokedSchema>;
|
|
709
|
+
/**
|
|
710
|
+
* RFC 8414 authorization server metadata.
|
|
711
|
+
*
|
|
712
|
+
* Only the fields a client uses are advertised. Two are worth noting for what
|
|
713
|
+
* they refuse rather than what they offer: `code_challenge_methods_supported` is
|
|
714
|
+
* `["S256"]`, which tells a conforming client that `plain` will be rejected
|
|
715
|
+
* before it tries; and `grant_types_supported` omits everything OAuth 2.1
|
|
716
|
+
* removed, so a client cannot conclude from silence that implicit is available.
|
|
717
|
+
*/
|
|
718
|
+
export declare const authorizationServerMetadataSchema: z.ZodObject<{
|
|
719
|
+
authorization_endpoint: z.ZodURL;
|
|
720
|
+
code_challenge_methods_supported: z.ZodArray<z.ZodEnum<{
|
|
721
|
+
S256: "S256";
|
|
722
|
+
}>>;
|
|
723
|
+
grant_types_supported: z.ZodArray<z.ZodEnum<{
|
|
724
|
+
authorization_code: "authorization_code";
|
|
725
|
+
refresh_token: "refresh_token";
|
|
726
|
+
}>>;
|
|
727
|
+
issuer: z.ZodURL;
|
|
728
|
+
registration_endpoint: z.ZodURL;
|
|
729
|
+
response_modes_supported: z.ZodArray<z.ZodLiteral<"query">>;
|
|
730
|
+
response_types_supported: z.ZodArray<z.ZodEnum<{
|
|
731
|
+
code: "code";
|
|
732
|
+
}>>;
|
|
733
|
+
revocation_endpoint: z.ZodURL;
|
|
734
|
+
scopes_supported: z.ZodArray<z.ZodEnum<{
|
|
735
|
+
"credentials:administer": "credentials:administer";
|
|
736
|
+
"credentials:read": "credentials:read";
|
|
737
|
+
"credentials:write": "credentials:write";
|
|
738
|
+
"endpoints:read": "endpoints:read";
|
|
739
|
+
"endpoints:write": "endpoints:write";
|
|
740
|
+
"forecast:read": "forecast:read";
|
|
741
|
+
"grants:read": "grants:read";
|
|
742
|
+
"grants:write": "grants:write";
|
|
743
|
+
"occurrences:read": "occurrences:read";
|
|
744
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
745
|
+
"projects:read": "projects:read";
|
|
746
|
+
"projects:write": "projects:write";
|
|
747
|
+
"schedules:read": "schedules:read";
|
|
748
|
+
"schedules:write": "schedules:write";
|
|
749
|
+
"usage:read": "usage:read";
|
|
750
|
+
}>>;
|
|
751
|
+
token_endpoint: z.ZodURL;
|
|
752
|
+
token_endpoint_auth_methods_supported: z.ZodArray<z.ZodEnum<{
|
|
753
|
+
none: "none";
|
|
754
|
+
}>>;
|
|
755
|
+
}, z.core.$strip>;
|
|
756
|
+
export type AuthorizationServerMetadata = z.infer<typeof authorizationServerMetadataSchema>;
|
|
757
|
+
/**
|
|
758
|
+
* RFC 9728 protected resource metadata.
|
|
759
|
+
*
|
|
760
|
+
* This is where an MCP client's discovery actually begins: it calls a protected
|
|
761
|
+
* endpoint, receives 401 with `WWW-Authenticate: Bearer resource_metadata=…`,
|
|
762
|
+
* fetches this document, and learns which authorization server to talk to. A
|
|
763
|
+
* server that serves the RFC 8414 document but not this one is discoverable only
|
|
764
|
+
* by clients that already knew where to look.
|
|
765
|
+
*/
|
|
766
|
+
export declare const protectedResourceMetadataSchema: z.ZodObject<{
|
|
767
|
+
authorization_servers: z.ZodArray<z.ZodURL>;
|
|
768
|
+
bearer_methods_supported: z.ZodArray<z.ZodLiteral<"header">>;
|
|
769
|
+
resource: z.ZodURL;
|
|
770
|
+
scopes_supported: z.ZodArray<z.ZodEnum<{
|
|
771
|
+
"credentials:administer": "credentials:administer";
|
|
772
|
+
"credentials:read": "credentials:read";
|
|
773
|
+
"credentials:write": "credentials:write";
|
|
774
|
+
"endpoints:read": "endpoints:read";
|
|
775
|
+
"endpoints:write": "endpoints:write";
|
|
776
|
+
"forecast:read": "forecast:read";
|
|
777
|
+
"grants:read": "grants:read";
|
|
778
|
+
"grants:write": "grants:write";
|
|
779
|
+
"occurrences:read": "occurrences:read";
|
|
780
|
+
"occurrences:redeliver": "occurrences:redeliver";
|
|
781
|
+
"projects:read": "projects:read";
|
|
782
|
+
"projects:write": "projects:write";
|
|
783
|
+
"schedules:read": "schedules:read";
|
|
784
|
+
"schedules:write": "schedules:write";
|
|
785
|
+
"usage:read": "usage:read";
|
|
786
|
+
}>>;
|
|
787
|
+
}, z.core.$strip>;
|
|
788
|
+
export type ProtectedResourceMetadata = z.infer<typeof protectedResourceMetadataSchema>;
|
|
789
|
+
/**
|
|
790
|
+
* The `WWW-Authenticate` value a protected endpoint returns on 401.
|
|
791
|
+
*
|
|
792
|
+
* RFC 9728 §5.1. The `resource_metadata` parameter is the whole mechanism —
|
|
793
|
+
* without it a client that receives a 401 knows only that it is unauthenticated,
|
|
794
|
+
* and has nowhere to go next.
|
|
795
|
+
*/
|
|
796
|
+
export declare function bearerChallenge(resourceMetadataUrl: string): string;
|