@12-apps/mcp 2.0.0 → 3.0.0

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/ADOPTING.md CHANGED
@@ -34,7 +34,7 @@ library updates, every host updates with **no app changes**. Same contract
34
34
  `enabled: false` authorize/token/jwks/discovery answer **404** — a probe cannot
35
35
  tell a disabled AS from an app that has none — while registration answers
36
36
  **403 `access_denied`**, because RFC 7591 has a code for "the endpoint is here,
37
- registration is closed". future-pay passes
37
+ registration is closed". The origin host passes
38
38
  `enabled: () => process.env.MCP_BEARER_ENABLED === 'true'`, so the surface stays
39
39
  OFF until an operator opts in.
40
40
  4. **No signing key, no tokens.** `signingKey` defaults to the env-backed provider
@@ -51,7 +51,7 @@ library updates, every host updates with **no app changes**. Same contract
51
51
  the internal origin rather than to an attacker's. Issuance and verification read
52
52
  the same resolver from the same request, which is what stops "minted for A,
53
53
  verified against B" from rejecting valid tokens.
54
- `trustedOriginsFromEnv('MCP_OAUTH_TRUSTED_ORIGINS')` keeps future-pay's wiring.
54
+ `trustedOriginsFromEnv('MCP_OAUTH_TRUSTED_ORIGINS')` keeps the origin host's wiring.
55
55
  6. **The stores are narrow ports; Prisma fills them in one line.**
56
56
  `createPrismaMcpStores(async () => prisma as unknown as McpOauthPrisma)`. A
57
57
  non-Prisma host implements `OAuthClientStore` / `RefreshTokenStore` /
@@ -104,7 +104,7 @@ library updates, every host updates with **no app changes**. Same contract
104
104
  default, and it is deliberately the inconvenient one.
105
105
  10. **Connections are per USER, not per tenant** — an MCP bearer is
106
106
  auth-passthrough. `connections.resolveUserId(email)` maps the token's email to
107
- the host's user id (future-pay resolves it by email because `session.user.id` is
107
+ the host's user id (the origin host resolves it by email because `session.user.id` is
108
108
  the OAuth `sub`); returning `null` records nothing. Recording is best-effort and
109
109
  FENCED: a failing directory can never turn a valid grant into a 500, and nothing
110
110
  about the attempt is logged, because the only values in hand are an email and a
@@ -211,7 +211,7 @@ Two things about the gates worth knowing before you adopt them:
211
211
  committed exclusions file the moment it adopted the package, so it needs its own
212
212
  burn-down).
213
213
 
214
- ## Phase B — adopting into a host that ALREADY has these tables (future-pay)
214
+ ## Phase B — adopting into a host that ALREADY has these tables (the origin host)
215
215
 
216
216
  **Nothing to baseline.** Every statement in the package migration is guarded
217
217
  (`CREATE TABLE IF NOT EXISTS`, `CREATE [UNIQUE] INDEX IF NOT EXISTS`, `ADD COLUMN
@@ -223,8 +223,8 @@ a host that already has `oauth_clients` / `oauth_refresh_tokens` /
223
223
  Deliberate deltas to reconcile:
224
224
 
225
225
  - **The FK from `mcp_connections.user_id` to `users` is not in the package
226
- migration** — host vocabulary. future-pay keeps its `ON DELETE CASCADE`.
227
- - **`onboarding_states` is not here.** future-pay's migration created it beside
226
+ migration** — host vocabulary. The origin host keeps its `ON DELETE CASCADE`.
227
+ - **`onboarding_states` is not here.** The origin host's migration created it beside
228
228
  `mcp_connections`; it belongs to `@12-apps/onboarding` (12-23).
229
229
  - The host's `lib/mcp/oauth/**` (~1.5k LOC) and its four route files are replaced
230
230
  by the mount plus, where a coverage gate forces the file to exist, a one-line
@@ -242,7 +242,7 @@ Deliberate deltas to reconcile:
242
242
  and redactions, is the host's catalogue. The package generates, dispatches and
243
243
  gates it.
244
244
  - **`mcp:lint`, `mcp:parity`, `mcp:smoke`, `mcp:test-coverage`** — the remaining
245
- future-pay MCP scripts. Only the two the reusable CI workflows shell out to moved
245
+ the origin host MCP scripts. Only the two the reusable CI workflows shell out to moved
246
246
  (12-23's scope).
247
247
  - **Authorization codes as rows.** They are stateless signed blobs, so there is no
248
248
  table and nothing to sweep — only the replay store (rule 8).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/mcp",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "type": "module",
5
5
  "description": "App-agnostic MCP server core: generate one MCP tool per OpenAPI operation and proxy each call carrying the caller's bearer token (permission passthrough). Also ships the OAuth 2.1 authorization server (./oauth, ./hono: register/authorize/token, JWKS and both .well-known documents), the package-owned Prisma partial + migration for its three tables, the mcp:generate/mcp:check (./generate) and mcp:coverage (./coverage) gates, and the reusable AI-connect onboarding UI (./react).",
6
6
  "exports": {
@@ -23,9 +23,9 @@
23
23
  "prisma:sync:check": "node scripts/sync-mcp-schema.mjs --check"
24
24
  },
25
25
  "dependencies": {
26
- "@12-apps/onboarding": "^1.20.0",
27
- "@12-apps/rbac": "^3.0.0",
28
- "@12-apps/ui": "^4.1.0",
26
+ "@12-apps/onboarding": "^2.0.0",
27
+ "@12-apps/rbac": "^4.0.0",
28
+ "@12-apps/ui": "^5.0.0",
29
29
  "@mui/icons-material": "^6.5.0",
30
30
  "jose": "^6.1.3",
31
31
  "react": "^19.2.0"
package/prisma/mcp.prisma CHANGED
@@ -11,7 +11,7 @@
11
11
  //
12
12
  // Host-agnostic by design (the entity-lifecycle / rbac doctrine): `user_id` is a
13
13
  // by-value scalar with NO relation, because this package cannot know the name of
14
- // the host's user model. The host's own migration may add the FK (future-pay's
14
+ // the host's user model. The host's own migration may add the FK (the origin host's
15
15
  // is ON DELETE CASCADE). Note there is deliberately no `oauth_codes` table:
16
16
  // authorization codes are STATELESS signed blobs, so there is nothing to store
17
17
  // and nothing to sweep.
@@ -18,13 +18,13 @@
18
18
  -- Authorization codes are deliberately absent: they are STATELESS signed blobs,
19
19
  -- so there is no table to create and nothing to sweep.
20
20
  --
21
- -- The columns, defaults, indexes and CHECK are future-pay's
21
+ -- The columns, defaults, indexes and CHECK are the origin host's
22
22
  -- `20260713120000_add_oauth_client_refresh`,
23
23
  -- `20260715180000_add_onboarding_state_mcp_connection` (the mcp_connections half
24
24
  -- — the onboarding half belongs to @12-apps/onboarding) and
25
25
  -- `20260720120000_add_mcp_connection_host` verbatim, minus the FK to `users`:
26
26
  -- this package cannot know the name of a host's user table, and a host that has
27
- -- one keeps its own constraint (future-pay's is ON DELETE CASCADE).
27
+ -- one keeps its own constraint (the origin host's is ON DELETE CASCADE).
28
28
  --
29
29
  -- EVERY statement is guarded (`IF NOT EXISTS`, and a conrelid-scoped DO block for
30
30
  -- the CHECK, which has no IF NOT EXISTS form). That is what makes adoption by a
@@ -35,7 +35,7 @@
35
35
  -- the difference bites exactly the host this file is written for: `CREATE TABLE IF
36
36
  -- NOT EXISTS` skips the whole table, columns included, so a host holding an OLDER
37
37
  -- shape of one of these tables silently keeps it. Each table below is therefore
38
- -- followed by a guarded `ADD COLUMN` for every column that reached future-pay in a
38
+ -- followed by a guarded `ADD COLUMN` for every column that reached the origin host in a
39
39
  -- LATER migration than its own CREATE. The full audit: `oauth_refresh_tokens
40
40
  -- .user_sub` (`20260713150000_add_oauth_refresh_user_sub`) and `mcp_connections
41
41
  -- .host` (`20260720120000_add_mcp_connection_host`). `oauth_clients` needs none —
@@ -112,10 +112,10 @@ CREATE INDEX IF NOT EXISTS "oauth_refresh_tokens_user_email_client_id_idx"
112
112
  -- `CREATE TABLE IF NOT EXISTS` skips the WHOLE table, so a host that already holds
113
113
  -- `oauth_refresh_tokens` in an OLDER SHAPE gets none of the columns declared above
114
114
  -- — statement-level guarding is not the same as column-level guarding. That is
115
- -- precisely how future-pay's own history ran: `user_sub` arrived in a SECOND
115
+ -- precisely how the origin host's own history ran: `user_sub` arrived in a SECOND
116
116
  -- migration (FUT-105, `20260713150000_add_oauth_refresh_user_sub`), so a host
117
117
  -- frozen before it would adopt this file, skip the CREATE, never get the column,
118
- -- and then fail on every refresh the package serves. Mirror future-pay's pair
118
+ -- and then fail on every refresh the package serves. Mirror the origin host's pair
119
119
  -- verbatim — guarded add with a backfill default to satisfy NOT NULL, then drop
120
120
  -- the default so the column matches the Prisma schema (`String`, no default).
121
121
  -- Both statements are no-ops on a fresh host and on a replay.
@@ -147,6 +147,6 @@ CREATE INDEX IF NOT EXISTS "mcp_connections_last_active_at_idx"
147
147
  ON "mcp_connections"("last_active_at");
148
148
 
149
149
  -- A host adopting this migration where `mcp_connections` predates the `host`
150
- -- column (future-pay added it in a later migration) gets it here; a fresh host
150
+ -- column (the origin host added it in a later migration) gets it here; a fresh host
151
151
  -- already has it from the CREATE above, so the guard makes both cases a no-op.
152
152
  ALTER TABLE "mcp_connections" ADD COLUMN IF NOT EXISTS "host" TEXT;
@@ -14,14 +14,14 @@
14
14
  *
15
15
  * Only the schema partial. MIGRATIONS ARE NOT HANDLED HERE — the host
16
16
  * discovers and copies them structurally, by looking for a `prisma/migrations`
17
- * directory inside every installed `@12-apps/*` package (see future-pay's
17
+ * directory inside every installed `@12-apps/*` package (see the origin host's
18
18
  * packages/prisma/scripts/sync-prisma-plugins.mjs).
19
19
  *
20
20
  * The host package that owns the schema folder MUST also declare this package
21
21
  * as a dependency, so the source of the copy is present in every build
22
22
  * context.
23
23
  *
24
- * Default host path follows the future-pay layout
24
+ * Default host path follows the origin host layout
25
25
  * (`packages/prisma/prisma/schema/`); another repo passes its own schema
26
26
  * folder as the positional argument, or sets MCP_HOST_SCHEMA_DIR.
27
27
  */
@@ -6,7 +6,7 @@ import { collectRouteMethods } from "./route-methods";
6
6
 
7
7
  /**
8
8
  * `@12-apps/mcp/coverage` — the MCP route/action coverage gate (12-23), moved out
9
- * of future-pay's `apps/web/scripts/mcp/coverage.ts` so a host's own script is a
9
+ * of the origin host's `apps/web/scripts/mcp/coverage.ts` so a host's own script is a
10
10
  * one-line re-export and the CI workflow that shells out to the consumer's
11
11
  * `mcp:coverage` package script (`12-apps/ci`'s `mcp-contract.yml`) keeps working
12
12
  * unchanged.
@@ -11,7 +11,7 @@ import { exportedNamesOf, urlPathOf, walkRouteFiles } from "@12-apps/rbac/covera
11
11
  * walk (`walkRouteFiles`), the URL mapping (`urlPathOf`) AND the export-head
12
12
  * parser (`exportedNamesOf`) — and that is deliberate: both gates assert a
13
13
  * COMPLETENESS property over the same two surfaces (`app/**` route files and
14
- * `*actions.ts` modules), and future-pay's own comment on the shared scanner says
14
+ * `*actions.ts` modules), and the origin host's own comment on the shared scanner says
15
15
  * why they must share it — "so the two gates can never disagree about what the
16
16
  * surface is". Two copies would agree on the day they were written and drift
17
17
  * silently after, in the direction of not looking. What is left here is the one
@@ -13,7 +13,7 @@ import type { ToolManifest } from "../types";
13
13
 
14
14
  /**
15
15
  * `@12-apps/mcp/generate` — the `mcp:generate` / `mcp:check` gate (12-23), moved
16
- * out of future-pay's `apps/web/scripts/mcp/generate.ts` so a host's own script is
16
+ * out of the origin host's `apps/web/scripts/mcp/generate.ts` so a host's own script is
17
17
  * a one-line call and `12-apps/ci`'s `mcp-contract.yml`, which shells out to the
18
18
  * consumer's `mcp:check` package script, keeps working unchanged.
19
19
  *
@@ -4,7 +4,7 @@ import { issuer, resourceAudience, DEFAULT_MCP_RESOURCE_PATH, type McpScope } fr
4
4
  import { SIGNING_ALG, type McpSigningKeyProvider } from "./keys";
5
5
 
6
6
  /**
7
- * JWT access-token issuer + verifier (12-23, ported from future-pay's
7
+ * JWT access-token issuer + verifier (12-23, ported from the origin host's
8
8
  * `lib/mcp/oauth/jwt.ts` — behaviour unchanged; the signing key arrives through a
9
9
  * provider and the resource path is config).
10
10
  *
@@ -4,7 +4,7 @@ import { issuer } from "./config";
4
4
  import { SIGNING_ALG, type McpSigningKeyProvider } from "./keys";
5
5
 
6
6
  /**
7
- * Stateless authorization-code mint/verify (12-23, ported from future-pay's
7
+ * Stateless authorization-code mint/verify (12-23, ported from the origin host's
8
8
  * `lib/mcp/oauth/authorization-code.ts` — behaviour unchanged; the signing key
9
9
  * arrives through a provider instead of an env read).
10
10
  *
@@ -6,7 +6,7 @@ import type { StoredOAuthClient } from "./stores";
6
6
 
7
7
  /**
8
8
  * The OAuth 2.1 Authorization Code + PKCE authorization endpoint (12-23, ported
9
- * from future-pay's `app/api/oauth/authorize/route.ts`).
9
+ * from the origin host's `app/api/oauth/authorize/route.ts`).
10
10
  *
11
11
  * It renders no UI: it authenticates the caller against the host's cookie session
12
12
  * (through `resolveSession`), validates the request, and either 302-redirects an
@@ -8,7 +8,7 @@ import type {
8
8
 
9
9
  /**
10
10
  * Client registration and the open-redirect guard (12-23, ported from
11
- * future-pay's `lib/mcp/oauth/clients.ts`).
11
+ * the origin host's `lib/mcp/oauth/clients.ts`).
12
12
  *
13
13
  * A registered client is an external host (a Claude.ai / ChatGPT connector) from
14
14
  * RFC 7591 dynamic client registration, or a static registration an operator
@@ -122,7 +122,7 @@ export interface ProviderAttributionRule {
122
122
  provider: string;
123
123
  }
124
124
 
125
- /** future-pay's rules, and a sane default for any host talking to the same two. */
125
+ /** The origin host's rules, and a sane default for any host talking to the same two. */
126
126
  export const DEFAULT_PROVIDER_ROOTS: readonly ProviderAttributionRule[] = [
127
127
  { roots: ["claude.ai", "anthropic.com"], provider: "claude" },
128
128
  { roots: ["chatgpt.com", "openai.com"], provider: "chatgpt" },
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Single-use guard for the stateless authorization codes (12-23, ported from
3
- * future-pay's `lib/mcp/oauth/token-replay.ts`).
3
+ * the origin host's `lib/mcp/oauth/token-replay.ts`).
4
4
  *
5
5
  * A code is a signed blob with a `jti`, so "already redeemed" has to be remembered
6
6
  * somewhere. The in-process option remembers it IN THIS PROCESS: a small map of
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The OAuth 2.1 authorization-server foundation: the shared scope source, the
3
3
  * issuer/audience derivation, and the trusted-origin resolver every URL in the
4
- * surface is built from (12-23, ported from future-pay's
4
+ * surface is built from (12-23, ported from the origin host's
5
5
  * `lib/mcp/oauth/config.ts`).
6
6
  *
7
7
  * Keeping the scopes and the origin resolution in ONE place is what stops the
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * What was env-reading in the host is CONFIG here (the package must not learn a
13
13
  * host's variable names); `trustedOriginsFromEnv` is the one-line helper that
14
- * keeps future-pay's wiring identical.
14
+ * keeps the origin host's wiring identical.
15
15
  */
16
16
 
17
17
  /** Scopes advertised by both discovery documents. `mcp:write` gates mutating tools. */
@@ -66,7 +66,7 @@ function normalizeOrigins(origins: readonly string[]): string[] {
66
66
  }
67
67
 
68
68
  /**
69
- * Read a comma-separated allowlist out of an environment variable — future-pay
69
+ * Read a comma-separated allowlist out of an environment variable — the origin host
70
70
  * passes `trustedOriginsFromEnv('MCP_OAUTH_TRUSTED_ORIGINS')`, so the behaviour
71
71
  * is identical while the variable's NAME stays the host's.
72
72
  */
@@ -25,7 +25,7 @@ import type { McpOauthStores, StoredOAuthClient } from "./stores";
25
25
  /** The identity an authorize request binds a code to. From the SESSION only. */
26
26
  export interface McpOauthSession {
27
27
  /**
28
- * The OAuth subject (future-pay passes the Google `sub`, falling back to the
28
+ * The OAuth subject (the origin host passes the Google `sub`, falling back to the
29
29
  * email). Carried through every rotation so a refreshed token keeps the same
30
30
  * stable `sub`.
31
31
  */
@@ -45,7 +45,7 @@ export interface McpOauthPaths {
45
45
  }
46
46
 
47
47
  export const DEFAULT_OAUTH_PATHS: McpOauthPaths = {
48
- // future-pay's paths, and the ones the RFC 8414 document has always advertised.
48
+ // the origin host's paths, and the ones the RFC 8414 document has always advertised.
49
49
  authorize: "/api/oauth/authorize",
50
50
  token: "/api/oauth/token",
51
51
  register: "/api/oauth/register",
@@ -78,12 +78,12 @@ export interface McpOauthConfig {
78
78
  resolveSession: (request: Request) => Promise<McpOauthSession | null> | McpOauthSession | null;
79
79
  /**
80
80
  * The operator gate. `false` makes the whole surface inert — authorize/token/jwks
81
- * answer 404 and registration answers 403 — which is how future-pay ships it OFF
81
+ * answer 404 and registration answers 403 — which is how the origin host ships it OFF
82
82
  * by default (`MCP_BEARER_ENABLED`). Default: enabled (mounting is the opt-in).
83
83
  */
84
84
  enabled?: boolean | (() => boolean);
85
85
  /**
86
- * Signing material. Default: the env-backed provider with future-pay's variable
86
+ * Signing material. Default: the env-backed provider with the origin host's variable
87
87
  * names. `null` from the provider means "not provisioned": nothing is minted and
88
88
  * the JWKS answers 503 rather than falling back to a weaker mode.
89
89
  */
@@ -216,7 +216,7 @@ export function resolveMcpOauthConfig(config: McpOauthConfig): McpOauthContext {
216
216
  stores: config.stores,
217
217
  resolveSession: config.resolveSession,
218
218
  // Mounting is the opt-in, so the gate defaults to ON; a host that ships the
219
- // surface dark passes its own flag (future-pay: `MCP_BEARER_ENABLED`).
219
+ // surface dark passes its own flag (the origin host: `MCP_BEARER_ENABLED`).
220
220
  enabled: typeof enabled === "function" ? enabled : () => enabled,
221
221
  // `null` from the provider means "not provisioned": nothing is minted and the
222
222
  // JWKS answers 503 rather than falling back to a weaker mode.
package/src/oauth/keys.ts CHANGED
@@ -2,7 +2,7 @@ import { exportJWK, importPKCS8, type CryptoKey, type JWK } from "jose";
2
2
 
3
3
  /**
4
4
  * Signing-key / JWK loading for the OAuth authorization server (12-23, ported
5
- * from future-pay's `lib/mcp/oauth/keys.ts`).
5
+ * from the origin host's `lib/mcp/oauth/keys.ts`).
6
6
  *
7
7
  * ES256 (P-256) from PEM material, the published public JWK (with `kid` for
8
8
  * rotation), and a safe-by-default absence signal (`null`) when no key is
@@ -10,7 +10,7 @@ import { exportJWK, importPKCS8, type CryptoKey, type JWK } from "jose";
10
10
  * rather than falling back to a weaker mode while the surface is mounted.
11
11
  *
12
12
  * WHERE the PEM comes from is the host's business: `loadSigningKeyFromEnv` keeps
13
- * future-pay's env-var wiring, and any other provider (a secrets manager, a KMS
13
+ * the origin host's env-var wiring, and any other provider (a secrets manager, a KMS
14
14
  * export) satisfies the same `McpSigningKeyProvider` shape.
15
15
  */
16
16
 
@@ -87,13 +87,13 @@ export function signingKeyProvider(
87
87
  };
88
88
  }
89
89
 
90
- /** Env var carrying the ES256 private key as a PKCS#8 PEM (future-pay's name). */
90
+ /** Env var carrying the ES256 private key as a PKCS#8 PEM (the origin host's name). */
91
91
  export const DEFAULT_SIGNING_KEY_ENV = "MCP_OAUTH_SIGNING_KEY";
92
92
  /** Env var carrying the key id (`kid`) used to select the key during rotation. */
93
93
  export const DEFAULT_SIGNING_KEY_ID_ENV = "MCP_OAUTH_SIGNING_KEY_ID";
94
94
 
95
95
  /**
96
- * The env-backed provider — future-pay's wiring, kept identical, with the
96
+ * The env-backed provider — the origin host's wiring, kept identical, with the
97
97
  * variable names as arguments so the package states no host's vocabulary.
98
98
  */
99
99
  export function loadSigningKeyFromEnv(
package/src/oauth/pkce.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * PKCE (RFC 7636) S256 challenge helpers for the OAuth authorization server
3
- * (12-23, ported verbatim from future-pay's `lib/mcp/oauth/pkce.ts`).
3
+ * (12-23, ported verbatim from the origin host's `lib/mcp/oauth/pkce.ts`).
4
4
  *
5
5
  * OAuth 2.1 mandates the `S256` code-challenge method and forbids `plain`, so
6
6
  * this module computes `BASE64URL(SHA-256(code_verifier))` and compares it to
@@ -3,7 +3,7 @@ import { createHash, randomBytes } from "node:crypto";
3
3
  import type { NewRefreshToken, RefreshTokenStore, StoredRefreshToken } from "./stores";
4
4
 
5
5
  /**
6
- * Refresh-token issue + rotation (12-23, ported from future-pay's
6
+ * Refresh-token issue + rotation (12-23, ported from the origin host's
7
7
  * `lib/mcp/oauth/refresh.ts` — behaviour unchanged; Prisma calls became the
8
8
  * `RefreshTokenStore` port).
9
9
  *
@@ -3,7 +3,7 @@ import type { McpOauthContext } from "./context";
3
3
  import type { TokenEndpointAuthMethod } from "./stores";
4
4
 
5
5
  /**
6
- * RFC 7591 Dynamic Client Registration (12-23, ported from future-pay's
6
+ * RFC 7591 Dynamic Client Registration (12-23, ported from the origin host's
7
7
  * `app/api/oauth/register/route.ts`).
8
8
  *
9
9
  * An external host (a Claude.ai / ChatGPT connector) self-registers by POSTing RFC
@@ -19,7 +19,7 @@ import {
19
19
  } from "./token-response";
20
20
 
21
21
  /**
22
- * The two grant handlers of the token endpoint (12-23, ported from future-pay's
22
+ * The two grant handlers of the token endpoint (12-23, ported from the origin host's
23
23
  * `lib/mcp/oauth/token-grants.ts`).
24
24
  *
25
25
  * Security invariants enforced here, unchanged:
@@ -123,7 +123,7 @@ function readAuthorizationCodeParams(form: URLSearchParams): AuthorizationCodePa
123
123
  /**
124
124
  * Redeem a presented code, or refuse.
125
125
  *
126
- * The ORDER is the security contract, and it is the order future-pay established:
126
+ * The ORDER is the security contract, and it is the order the origin host established:
127
127
  * verify the code's signature, authenticate the presenting client against the
128
128
  * client the code was bound to, check the bound `redirect_uri`, check PKCE — and
129
129
  * only THEN consume the single-use `jti`. Consuming earlier would let a failed
@@ -5,7 +5,7 @@ import type { OAuthClientStore } from "./stores";
5
5
  /**
6
6
  * The token endpoint's wire helpers: the RFC 6749 §5.1/§5.2 bodies and client
7
7
  * authentication (12-23, split out of the grant handlers so each file stays under
8
- * the size gate — the same split future-pay made).
8
+ * the size gate — the same split the origin host made).
9
9
  *
10
10
  * These bodies are NOT the house `{ data }` envelope, deliberately: they are read
11
11
  * by OAuth clients that expect the RFC shapes at the top level, and `Cache-Control:
@@ -11,7 +11,7 @@ import type { GeneratedTool, ToolManifest } from "../types";
11
11
  export interface BuildManifestOptions {
12
12
  /** Bumped intentionally on any tool-shape change (mirrors the golden catalog). */
13
13
  version: number;
14
- /** Human label for the spec, e.g. "future-pay web @ openapi.json". */
14
+ /** Human label for the spec, e.g. "acme web @ openapi.json". */
15
15
  source: string;
16
16
  }
17
17
 
@@ -16,7 +16,7 @@ import type { GeneratedTool } from "../types";
16
16
  * ask again: a tool that shipped stays invisible to every ALREADY CONNECTED
17
17
  * client for as long as that connection lives.
18
18
  *
19
- * That is not a hypothetical. In `future-pay` a new tool reached production,
19
+ * That is not a hypothetical. In the origin host a new tool reached production,
20
20
  * answered on its route, and did not appear in a live connector — behind a
21
21
  * `serverInfo.version` frozen at its initial value while ~280 tools were added
22
22
  * underneath it. Nothing was broken; the only thing asking anyone to bump it was