@zackbart/connecta 0.8.0 → 0.9.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/CHANGELOG.md +128 -0
- package/README.md +31 -55
- package/SECURITY.md +5 -11
- package/dist/activity.d.ts +0 -8
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js +0 -1
- package/dist/activity.js.map +1 -1
- package/dist/auth/bearer.d.ts +1 -7
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +2 -23
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/clerk.d.ts +2 -11
- package/dist/auth/clerk.d.ts.map +1 -1
- package/dist/auth/clerk.js +31 -46
- package/dist/auth/clerk.js.map +1 -1
- package/dist/auth/downstream-oauth.d.ts +15 -6
- package/dist/auth/downstream-oauth.d.ts.map +1 -1
- package/dist/auth/downstream-oauth.js +60 -11
- package/dist/auth/downstream-oauth.js.map +1 -1
- package/dist/call-admission.d.ts.map +1 -1
- package/dist/call-admission.js +0 -1
- package/dist/call-admission.js.map +1 -1
- package/dist/catalog-service.d.ts +1 -2
- package/dist/catalog-service.d.ts.map +1 -1
- package/dist/catalog-service.js +12 -18
- package/dist/catalog-service.js.map +1 -1
- package/dist/catalog.d.ts +6 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +51 -0
- package/dist/catalog.js.map +1 -1
- package/dist/connectors/remote-mcp.d.ts +1 -1
- package/dist/connectors/remote-mcp.d.ts.map +1 -1
- package/dist/connectors/remote-mcp.js +73 -71
- package/dist/connectors/remote-mcp.js.map +1 -1
- package/dist/errors.d.ts +19 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +4 -9
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +41 -20
- package/dist/execute.js.map +1 -1
- package/dist/executor-result.js +1 -1
- package/dist/executor-result.js.map +1 -1
- package/dist/index.d.ts +3 -82
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -90
- package/dist/index.js.map +1 -1
- package/dist/invocation.d.ts +5 -0
- package/dist/invocation.d.ts.map +1 -1
- package/dist/invocation.js +46 -10
- package/dist/invocation.js.map +1 -1
- package/dist/meta-tools.d.ts +4 -12
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +119 -169
- package/dist/meta-tools.js.map +1 -1
- package/dist/operator-ui/generated.d.ts +2 -2
- package/dist/operator-ui/generated.d.ts.map +1 -1
- package/dist/operator-ui/generated.js +2 -2
- package/dist/operator-ui/generated.js.map +1 -1
- package/dist/operator-ui/model.d.ts +1 -22
- package/dist/operator-ui/model.d.ts.map +1 -1
- package/dist/operator-ui/model.js.map +1 -1
- package/dist/registry.d.ts +11 -178
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +52 -330
- package/dist/registry.js.map +1 -1
- package/dist/retired-toolkits.d.ts +3 -0
- package/dist/retired-toolkits.d.ts.map +1 -0
- package/dist/retired-toolkits.js +9 -0
- package/dist/retired-toolkits.js.map +1 -0
- package/dist/routes/activity.d.ts.map +1 -1
- package/dist/routes/activity.js +2 -5
- package/dist/routes/activity.js.map +1 -1
- package/dist/routes/credentials.d.ts.map +1 -1
- package/dist/routes/credentials.js +1 -12
- package/dist/routes/credentials.js.map +1 -1
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +94 -188
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/oauth.js +3 -8
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/shared.d.ts +9 -30
- package/dist/routes/shared.d.ts.map +1 -1
- package/dist/routes/shared.js +10 -69
- package/dist/routes/shared.js.map +1 -1
- package/dist/routes/ui.d.ts.map +1 -1
- package/dist/routes/ui.js +4 -10
- package/dist/routes/ui.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -31
- package/dist/server.js.map +1 -1
- package/dist/skills.d.ts +3 -6
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +9 -38
- package/dist/skills.js.map +1 -1
- package/dist/timeout.d.ts.map +1 -1
- package/dist/timeout.js +2 -4
- package/dist/timeout.js.map +1 -1
- package/dist/types.d.ts +8 -61
- package/dist/types.d.ts.map +1 -1
- package/dist/ui.d.ts +1 -2
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +5 -35
- package/dist/ui.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/src/activity.ts +0 -9
- package/src/auth/bearer.ts +3 -32
- package/src/auth/clerk.ts +35 -48
- package/src/auth/downstream-oauth.ts +106 -24
- package/src/call-admission.ts +0 -1
- package/src/catalog-service.ts +23 -23
- package/src/catalog.ts +55 -0
- package/src/connectors/remote-mcp.ts +106 -86
- package/src/errors.ts +22 -0
- package/src/execute.ts +43 -24
- package/src/executor-result.ts +1 -1
- package/src/index.ts +24 -208
- package/src/invocation.ts +63 -10
- package/src/meta-tools.ts +139 -187
- package/src/operator-ui/browser.css +1 -54
- package/src/operator-ui/browser.ts +16 -150
- package/src/operator-ui/generated.ts +2 -2
- package/src/operator-ui/model.ts +1 -23
- package/src/registry.ts +59 -429
- package/src/retired-toolkits.ts +14 -0
- package/src/routes/activity.ts +1 -6
- package/src/routes/credentials.ts +0 -12
- package/src/routes/mcp.ts +110 -230
- package/src/routes/oauth.ts +2 -8
- package/src/routes/shared.ts +10 -100
- package/src/routes/ui.ts +2 -12
- package/src/server.ts +1 -31
- package/src/skills.ts +9 -38
- package/src/timeout.ts +2 -4
- package/src/types.ts +11 -62
- package/src/ui.ts +9 -46
- package/src/version.ts +1 -1
- package/dist/credential-health.d.ts +0 -205
- package/dist/credential-health.d.ts.map +0 -1
- package/dist/credential-health.js +0 -610
- package/dist/credential-health.js.map +0 -1
- package/dist/toolkits.d.ts +0 -124
- package/dist/toolkits.d.ts.map +0 -1
- package/dist/toolkits.js +0 -322
- package/dist/toolkits.js.map +0 -1
- package/src/credential-health.ts +0 -835
- package/src/toolkits.ts +0 -461
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,134 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this package are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.9.0 — 2026-07-29
|
|
6
|
+
|
|
7
|
+
Connecta now speaks the 2026-07-28 MCP revision on both sides while retaining
|
|
8
|
+
its legacy compatibility floor (#176). Nothing breaks for deployments:
|
|
9
|
+
Connecta's exports, configuration, connector definitions, meta-tool surface,
|
|
10
|
+
and its own stateless `/mcp` behavior are unchanged. Deployments can ignore the
|
|
11
|
+
wire revision entirely unless they imported or pinned transitive MCP SDK
|
|
12
|
+
internals; those internals moved from the v1 monolith to the exact-pinned v2
|
|
13
|
+
client and server packages.
|
|
14
|
+
|
|
15
|
+
This is alignment and compatibility work, not a state-management rewrite. The
|
|
16
|
+
new spec arrived at Connecta's existing stateless server design. Modern clients
|
|
17
|
+
now negotiate without `initialize`, while legacy clients remain served.
|
|
18
|
+
Stateful legacy *downstreams* still require Connecta's explicit session DELETE:
|
|
19
|
+
tests confirm SDK v2 client close does not make it redundant.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Modern/legacy version negotiation and cache metadata.** Modern
|
|
24
|
+
`tools/list` results declare a one-hour private cache lifetime; the legacy
|
|
25
|
+
initialize path and session headers remain supported.
|
|
26
|
+
- **Issuer-bound downstream OAuth storage.** Registrations and tokens are
|
|
27
|
+
stored with the validated authorization-server issuer. A changed issuer
|
|
28
|
+
advances the existing generation fence before the SDK starts a fresh grant;
|
|
29
|
+
pre-upgrade credentials bind in place on their first validated read.
|
|
30
|
+
- **A complete in-repo disposition of the revision** in
|
|
31
|
+
[`documentation/mcp-2026-07-28.md`](./documentation/mcp-2026-07-28.md),
|
|
32
|
+
including the declined and gated surfaces.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **Downstream multi-round-trip results fail loudly instead of being
|
|
37
|
+
misread as complete.** `call_tool`, `batch_call`, and the `execute_code` host
|
|
38
|
+
boundary preserve the non-retryable `input_required_unsupported` code.
|
|
39
|
+
Passthrough remains gated until a real host and downstream establish the
|
|
40
|
+
resumed-call contract.
|
|
41
|
+
- **Browser CORS allows the modern `Mcp-Method` and `Mcp-Name` request
|
|
42
|
+
headers.**
|
|
43
|
+
- **JSON Schema 2020-12 compatibility is pinned by exotic-keyword discovery
|
|
44
|
+
and validation coverage.**
|
|
45
|
+
|
|
46
|
+
## 0.8.1 — 2026-07-29
|
|
47
|
+
|
|
48
|
+
0.8.1 hardens agent routing, response efficiency, and credential recovery while
|
|
49
|
+
making deployment boundaries the audience-scoping model. It removes toolkits
|
|
50
|
+
and proactive credential liveness probing: deployments still using either
|
|
51
|
+
retired configuration must migrate, and stale configuration fails at startup
|
|
52
|
+
instead of silently widening access. Deployments that use neither retired
|
|
53
|
+
feature need no configuration or storage migration; orphaned credential-health
|
|
54
|
+
records and old toolkit columns can remain unused.
|
|
55
|
+
|
|
56
|
+
Against the pre-0.8.1 release-audit baseline, all 21 task scenarios still pass,
|
|
57
|
+
discovery remains at 89.7% top-1 accuracy and 100% positive/default-page recall,
|
|
58
|
+
and discovery mean precision improves from 46.4% to 73.5%. The same 55 round
|
|
59
|
+
trips take 225.6 ms versus 228.4 ms of summed local-call latency (effectively
|
|
60
|
+
flat). Definition tokens move from 2,164 to 2,174 and request tokens from 1,144
|
|
61
|
+
to 1,145, while response tokens fall from 68,765 to 16,343 (-76.2%) and the
|
|
62
|
+
complete measured surface falls from 72,073 to 19,662 tokens (-72.7%).
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- **A current-version release audit and independently authored discovery
|
|
67
|
+
holdout** (#189). It exercises every meta-tool, destructive routing, OAuth
|
|
68
|
+
and static-credential recovery, result paging, client compatibility, and the
|
|
69
|
+
payload-free activity invariant on Node 20 and 22. Its evidence stays under
|
|
70
|
+
`eval/` and is excluded from the published package.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- **Lexical discovery ignores conservative conversational framing and defaults
|
|
75
|
+
to eight results instead of 25** (#190). Action terms such as `get`, `list`,
|
|
76
|
+
`search`, `find`, and `create` remain significant; cleanup that removes every
|
|
77
|
+
term falls back to the original query. Explicit `limit` still supports up to
|
|
78
|
+
100 results, and `total`, `hasMore`, and `nextOffset` preserve complete
|
|
79
|
+
pagination. On the holdout, mean results fall from 14.0 to 2.853 and negative
|
|
80
|
+
false positives from 80% to 20%, without losing positive or default-page
|
|
81
|
+
recall.
|
|
82
|
+
- **`execute_code` is advertised only with a configured live executor** (#193).
|
|
83
|
+
The existing capability boundary is now explicit in instructions,
|
|
84
|
+
documentation, and regression coverage: deployments without code mode expose
|
|
85
|
+
the nine base meta-tools; deployments with it expose ten.
|
|
86
|
+
- **The `usage` guide is slimmer and fetched on demand** (#194). The
|
|
87
|
+
`skills` meta-tool and per-connector guide delivery remain unchanged, while
|
|
88
|
+
the generic guide drops redundant examples and keeps only routing, probe,
|
|
89
|
+
recovery, and code-mode rules. Server instructions now recommend fetching it
|
|
90
|
+
when the routing workflow is unfamiliar instead of once per task.
|
|
91
|
+
- **Structured results now serialize compactly in text compatibility content**
|
|
92
|
+
(#191). `structuredContent` remains the canonical full-fidelity object and
|
|
93
|
+
`content` remains complete JSON for text-only clients, but indentation no
|
|
94
|
+
longer inflates discovery, call, paging, batch, authorization, or code-mode
|
|
95
|
+
responses. Replacing the compatibility copy with a summary remains deferred
|
|
96
|
+
until host-forwarding measurements justify departing from MCP's compatibility
|
|
97
|
+
guidance.
|
|
98
|
+
- **Credential recovery has one agent-facing route** (#192).
|
|
99
|
+
`auth_required` errors now name the connector, failed operation, recovery
|
|
100
|
+
class, `authorize_connector` call, operator handoff, and retry. Calling
|
|
101
|
+
`authorize_connector` returns `recovery: "oauth"`, `"operator_config"`, or
|
|
102
|
+
`"unavailable"`; static handoffs expose only declared field names and
|
|
103
|
+
guidance plus the Clerk-protected `/credentials` URL, never credential
|
|
104
|
+
values. A missing `credentials.encryptionKey` now boots with an explicit
|
|
105
|
+
unavailable recovery state instead of preventing the deployment from
|
|
106
|
+
explaining the problem.
|
|
107
|
+
- **Toolkits are removed** (#178). `ConnectaConfig.toolkits`, toolkit bindings
|
|
108
|
+
on `bearerToken` and `clerkAuth`, `?toolkit=` routing, scoped registries, and
|
|
109
|
+
the operator UI's toolkit projection no longer exist. Passing `toolkits` or
|
|
110
|
+
`unscoped` to any of those construction surfaces throws instead of silently
|
|
111
|
+
widening access, and an `/mcp` request still carrying `?toolkit=` — a URL
|
|
112
|
+
minted before the retirement — gets an explicit 404 naming #178, never a
|
|
113
|
+
silent widening to the full registry.
|
|
114
|
+
- **Activity events no longer carry `toolkitId`.** The Worker D1 example drops
|
|
115
|
+
its `toolkit_id` column; existing columns may be left in place unused.
|
|
116
|
+
- **Proactive credential liveness is removed** (#179), reverting the feature
|
|
117
|
+
introduced in #24. `credentials.health`, legacy `credentialHealth`,
|
|
118
|
+
`Connecta.checkCredentials`, scheduled sweep wiring, persisted verdict reads
|
|
119
|
+
and writes, and `credentialCheck` response/UI fields no longer exist.
|
|
120
|
+
Operator-triggered credential tests and local stored-shape drift detection
|
|
121
|
+
remain. A drifted connector now reports `auth_required` directly from the
|
|
122
|
+
drift check — `list_connectors` with `probe: true` and `/ui/data` no longer
|
|
123
|
+
live-probe a connector whose stored credential cannot be consumed anyway.
|
|
124
|
+
Existing `credhealth:*` KV records are harmless orphaned data: they are
|
|
125
|
+
never read or rewritten, and no cleanup migration runs.
|
|
126
|
+
|
|
127
|
+
### Fixed
|
|
128
|
+
|
|
129
|
+
- **Missing credential-vault configuration now fails at use with a typed,
|
|
130
|
+
actionable recovery envelope** (#192) instead of preventing the deployment
|
|
131
|
+
from starting before an agent or operator can diagnose it.
|
|
132
|
+
|
|
5
133
|
## 0.8.0 — 2026-07-28
|
|
6
134
|
|
|
7
135
|
0.8.0 is consolidation before capability growth (#157): the semantics that were
|
package/README.md
CHANGED
|
@@ -6,23 +6,16 @@ One MCP endpoint in front of every integration you've deliberately chosen.
|
|
|
6
6
|
Agents see a handful of meta-tools instead of hundreds of definitions, and each
|
|
7
7
|
client is configured once instead of once per integration.
|
|
8
8
|
|
|
9
|
-
## The problem
|
|
10
|
-
|
|
11
|
-
An agent connected to N MCP servers pays for all N before it does anything:
|
|
12
|
-
every server's full tool list lands in the context window at connect time,
|
|
13
|
-
nearly all of it irrelevant to the task at hand. The second cost is
|
|
14
|
-
configuration — every client has to be pointed at every server separately,
|
|
15
|
-
each with its own auth, and rotating one token means finding every place it
|
|
16
|
-
was pasted.
|
|
17
|
-
|
|
18
9
|
## What connecta is
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
An agent connected to N MCP servers pays for all N before it does anything:
|
|
12
|
+
every server's full tool list lands in the context window at connect time, and
|
|
13
|
+
every client is pointed at every server separately, each with its own auth.
|
|
14
|
+
Connecta is one endpoint you deploy instead — a Cloudflare Worker or a Node
|
|
15
|
+
process, same code either way — aggregating your connectors behind nine
|
|
16
|
+
meta-tools. A connector is a remote MCP server connecta proxies or a plain
|
|
17
|
+
HTTP API with hand-written tool definitions; both come out identical,
|
|
18
|
+
addressed as `<connectorId>.<toolName>`.
|
|
26
19
|
|
|
27
20
|
```
|
|
28
21
|
┌── remoteMcp("notion") → mcp.notion.com
|
|
@@ -31,30 +24,22 @@ Claude / Cursor ── MCP ──▶ connecta ───┼── remoteMcp("lin
|
|
|
31
24
|
└── api("internal") → fetch(...)
|
|
32
25
|
```
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
`
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
An optional tenth, `execute_code`, runs model-written JavaScript in a sandbox
|
|
44
|
-
with no network, filesystem, or environment access — only the explicitly
|
|
45
|
-
read-only tools as callable globals — turning a loop or a cross-connector join
|
|
46
|
-
into one round trip. Configure no executor and connecta is exactly the
|
|
47
|
-
nine-tool server.
|
|
27
|
+
The agent discovers instead of preloading: `search_tools` ranks matches,
|
|
28
|
+
`describe_tools` returns schemas for only the addresses about to be called,
|
|
29
|
+
`call_tool` / `batch_call` / `call_destructive_tool` invoke them, and
|
|
30
|
+
`list_connectors`, `authorize_connector`, `get_result`, and `skills` round out
|
|
31
|
+
the nine. An optional tenth, `execute_code`, runs model-written JavaScript in
|
|
32
|
+
a sandbox with no network, filesystem, or environment access — only the
|
|
33
|
+
read-only tools in scope. Context holds nine definitions whether ten tools sit
|
|
34
|
+
behind them or a thousand.
|
|
48
35
|
|
|
49
36
|
Three properties are load-bearing enough to name here; the rest live in the
|
|
50
|
-
[ethos](./ethos.md). **Read-only is fail-closed**:
|
|
51
|
-
annotated read-only
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
connector is an edit and a deploy — no registration API, no admin UI, one
|
|
57
|
-
small file you can review in a pull request.
|
|
37
|
+
[ethos](./ethos.md). **Read-only is fail-closed**: anything not explicitly
|
|
38
|
+
annotated read-only crosses `call_destructive_tool`, which is annotated so the
|
|
39
|
+
MCP host can ask a human. **Credentials stay server-side**: an encrypted
|
|
40
|
+
vault, rotated from an operator page, and no surface ever returns a secret.
|
|
41
|
+
**Config is code**: adding a connector is an edit and a deploy you can review
|
|
42
|
+
in a pull request.
|
|
58
43
|
|
|
59
44
|
## Getting started
|
|
60
45
|
|
|
@@ -97,18 +82,12 @@ Point an MCP client at `http://localhost:8787/mcp` with an
|
|
|
97
82
|
`search_tools`.
|
|
98
83
|
|
|
99
84
|
Runnable deployments live in
|
|
100
|
-
[`examples/`](https://github.com/zackbart/connecta/tree/main/examples):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
[`docker/`](https://github.com/zackbart/connecta/tree/main/examples/docker) is
|
|
107
|
-
a single-service compose stack. Anything beyond the core is installed only by
|
|
108
|
-
the deployments that use it — `@clerk/backend` and `quickjs-emscripten` are
|
|
109
|
-
optional peers behind the `/auth/clerk` and `/quickjs` subpaths — and connecta
|
|
110
|
-
ships no service-specific connectors: endpoint, credential, and tool choices
|
|
111
|
-
stay in your project, declared with `remoteMcp()` and `api()`.
|
|
85
|
+
[`examples/`](https://github.com/zackbart/connecta/tree/main/examples): a
|
|
86
|
+
free-tier-compatible Cloudflare Worker with KV and D1 adapters, a Node server
|
|
87
|
+
extending the one above, and a single-service Docker compose stack.
|
|
88
|
+
Heavyweight extras are optional peers behind subpaths (`/auth/clerk`,
|
|
89
|
+
`/quickjs`), and connecta ships no service-specific connectors — endpoint,
|
|
90
|
+
credential, and tool choices stay in your project.
|
|
112
91
|
|
|
113
92
|
A candid note on maturity: connecta is built for its author's deployments
|
|
114
93
|
first and published openly. Breaking changes are cheap and the version number
|
|
@@ -117,12 +96,9 @@ signals change, not stability — the [ethos](./ethos.md) says so on purpose.
|
|
|
117
96
|
## Learn more
|
|
118
97
|
|
|
119
98
|
- **[ethos.md](./ethos.md)** — what this is, what it refuses to be, the
|
|
120
|
-
decisions table, and the invariants
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
stubs: the old manual was retired during the phase-1 docs restructure and
|
|
124
|
-
each guide is being rewritten as the ideas settle; prior text lives in git
|
|
125
|
-
history.
|
|
99
|
+
decisions table, and the invariants. Read it before proposing anything.
|
|
100
|
+
- **[documentation/](./documentation/)** — per-subsystem guides (currently
|
|
101
|
+
stubs; the prior manual lives in git history).
|
|
126
102
|
- **[CHANGELOG](./CHANGELOG.md)** — what changed in each release.
|
|
127
103
|
- **[SECURITY](./SECURITY.md)** — supported versions and how to report a
|
|
128
104
|
vulnerability.
|
package/SECURITY.md
CHANGED
|
@@ -16,14 +16,8 @@ CI blocks moderate, high, and critical production dependency advisories. Lower
|
|
|
16
16
|
findings are reviewed for reachability and recorded when an upstream package has
|
|
17
17
|
not yet released a compatible fix.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`@hono/node-server` to 2.x through an `overrides` entry and keeps SDK 1.29.0.
|
|
25
|
-
|
|
26
|
-
Because npm only applies `overrides` to the root project, that pin governs this
|
|
27
|
-
repository's own installs rather than trees built by consumers of the published
|
|
28
|
-
package. The override is removed once the SDK declares `@hono/node-server` ^2
|
|
29
|
-
upstream.
|
|
19
|
+
The MCP TypeScript SDK 2.x packages are exact-pinned. The split client and
|
|
20
|
+
server packages no longer install Hono or `@hono/node-server`, so the temporary
|
|
21
|
+
root-project override used with SDK 1.x is gone. A dependency bump must pass
|
|
22
|
+
both `npm run release:check` and the Node/Workers runtime suites before the pin
|
|
23
|
+
moves.
|
package/dist/activity.d.ts
CHANGED
|
@@ -40,12 +40,6 @@ export interface ToolCallActivityEvent {
|
|
|
40
40
|
serverName: string;
|
|
41
41
|
serverVersion: string;
|
|
42
42
|
deploymentId?: string;
|
|
43
|
-
/**
|
|
44
|
-
* Name of the toolkit this connection selected with `?toolkit=`, when it
|
|
45
|
-
* selected one. Calls are recorded the same way with or without it; this only
|
|
46
|
-
* says which scoped view the call came through.
|
|
47
|
-
*/
|
|
48
|
-
toolkitId?: string;
|
|
49
43
|
}
|
|
50
44
|
export interface ActivityPage {
|
|
51
45
|
events: ToolCallActivityEvent[];
|
|
@@ -92,8 +86,6 @@ export interface ActivityRequestContext {
|
|
|
92
86
|
version: string;
|
|
93
87
|
};
|
|
94
88
|
deploymentId?: string;
|
|
95
|
-
/** Toolkit this connection is scoped to, when `?toolkit=` selected one. */
|
|
96
|
-
toolkitId?: string;
|
|
97
89
|
defer?: (promise: Promise<unknown>) => void;
|
|
98
90
|
logger: Logger;
|
|
99
91
|
}
|
package/dist/activity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,uBAAuB,GACvB,YAAY,GACZ,cAAc,CAAC;AAEnB,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,OAAO,GACP,SAAS,GACT,WAAW,CAAC;AAEhB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,CAAC,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,uBAAuB,GACvB,YAAY,GACZ,cAAc,CAAC;AAEnB,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,OAAO,GACP,SAAS,GACT,WAAW,CAAC;AAEhB;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,CAAC,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,eAAe,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,qBAAqB,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC,GAAG;IACrE,KAAK,EAAE,iBAAiB,CAAC;CAC1B,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,iFAAiF;AACjF,qBAAa,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,SAAgC;;CAK9C;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,aAAa,KACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,qBAAqB,EACnB,aAAa,GACb,UAAU,GACV,SAAS,GACT,QAAQ,GACR,SAAS,GACT,YAAY,GACZ,UAAU,GACV,WAAW,CACd,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,sBAAsB,GAAG,SAAS,EAC3C,KAAK,EAAE,kBAAkB,GACxB,IAAI,CAkCN"}
|
package/dist/activity.js
CHANGED
|
@@ -32,7 +32,6 @@ export function recordToolActivity(context, input) {
|
|
|
32
32
|
...(context.deploymentId
|
|
33
33
|
? { deploymentId: context.deploymentId }
|
|
34
34
|
: {}),
|
|
35
|
-
...(context.toolkitId ? { toolkitId: context.toolkitId } : {}),
|
|
36
35
|
};
|
|
37
36
|
try {
|
|
38
37
|
const result = context.sink.record(event);
|
package/dist/activity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAyFA,iFAAiF;AACjF,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,GAAG,4BAA4B,CAAC;IAE7C;QACE,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACnC,CAAC;CACF;AA6BD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA2C,EAC3C,KAAyB;IAEzB,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,KAAK,GAA0B;QACnC,aAAa,EAAE,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;QACvB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrD,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjD,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI;QACnC,aAAa,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO;QACzC,GAAG,CAAC,OAAO,CAAC,YAAY;YACtB,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAQ,MAA2B,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACvE,OAAO;QACT,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACtD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;AACH,CAAC"}
|
package/dist/auth/bearer.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { type ToolkitBindingOptions } from "../toolkits.js";
|
|
2
1
|
import type { InboundAuth } from "../types.js";
|
|
3
|
-
export interface BearerTokenOptions
|
|
2
|
+
export interface BearerTokenOptions {
|
|
4
3
|
/** Stable identity for this credential, used on activity events. */
|
|
5
4
|
subjectId?: string;
|
|
6
5
|
}
|
|
@@ -8,11 +7,6 @@ export interface BearerTokenOptions extends ToolkitBindingOptions {
|
|
|
8
7
|
* Static bearer-token inbound auth. Constant-time compares the Bearer token
|
|
9
8
|
* against `secret`. Checked BEFORE the Clerk gate in the server; a mismatch
|
|
10
9
|
* falls through so a co-configured Clerk provider can still admit the request.
|
|
11
|
-
*
|
|
12
|
-
* `toolkits` binds the token to named toolkits (documentation/toolkits.md): one
|
|
13
|
-
* `bearerToken(...)` per team credential, each naming the view that team may
|
|
14
|
-
* open. Omit it and the token stays unbound — every declared toolkit plus the
|
|
15
|
-
* full registry.
|
|
16
10
|
*/
|
|
17
11
|
export declare function bearerToken(secret: string, options?: BearerTokenOptions): InboundAuth;
|
|
18
12
|
//# sourceMappingURL=bearer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAiB3D,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CA6Bb"}
|
package/dist/auth/bearer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { assertNoRetiredToolkitOptions } from "../retired-toolkits.js";
|
|
2
2
|
const encoder = new TextEncoder();
|
|
3
3
|
/** Constant-time byte comparison. Differing lengths still iterate to reduce leak. */
|
|
4
4
|
function timingSafeEqual(a, b) {
|
|
@@ -18,33 +18,12 @@ function timingSafeEqual(a, b) {
|
|
|
18
18
|
* Static bearer-token inbound auth. Constant-time compares the Bearer token
|
|
19
19
|
* against `secret`. Checked BEFORE the Clerk gate in the server; a mismatch
|
|
20
20
|
* falls through so a co-configured Clerk provider can still admit the request.
|
|
21
|
-
*
|
|
22
|
-
* `toolkits` binds the token to named toolkits (documentation/toolkits.md): one
|
|
23
|
-
* `bearerToken(...)` per team credential, each naming the view that team may
|
|
24
|
-
* open. Omit it and the token stays unbound — every declared toolkit plus the
|
|
25
|
-
* full registry.
|
|
26
21
|
*/
|
|
27
22
|
export function bearerToken(secret, options = {}) {
|
|
23
|
+
assertNoRetiredToolkitOptions("bearerToken", options);
|
|
28
24
|
const secretBytes = encoder.encode(secret);
|
|
29
|
-
const toolkitBinding = resolveToolkitBinding(options.subjectId
|
|
30
|
-
? `bearerToken (subjectId "${options.subjectId}")`
|
|
31
|
-
: "bearerToken", options);
|
|
32
|
-
if (toolkitBinding && !options.subjectId) {
|
|
33
|
-
// A bound token stands for one team, and both surfaces that report on it —
|
|
34
|
-
// the 403 refusal log (documentation/toolkits.md) and activity events
|
|
35
|
-
// (documentation/operator-ui.md) — can only say "bearer" without a subjectId. With
|
|
36
|
-
// several bound tokens that makes an operator unable to tell which
|
|
37
|
-
// credential was refused, or whose call succeeded. console.warn (as the
|
|
38
|
-
// Clerk adapter does) because an adapter is constructed before
|
|
39
|
-
// `createConnecta` has a logger to hand it.
|
|
40
|
-
console.warn("[connecta] bearerToken is bound to toolkits " +
|
|
41
|
-
`(${toolkitBinding.toolkits.join(", ") || "unscoped only"}) but has no ` +
|
|
42
|
-
"subjectId: refusal logs and activity events cannot say which " +
|
|
43
|
-
"credential they came from. Pass { subjectId: \"<team>\" }.");
|
|
44
|
-
}
|
|
45
25
|
return {
|
|
46
26
|
kind: "bearer",
|
|
47
|
-
...(toolkitBinding ? { toolkitBinding } : {}),
|
|
48
27
|
authorize(request) {
|
|
49
28
|
const header = request.headers.get("authorization") ?? "";
|
|
50
29
|
const match = /^Bearer\s+(.+)$/i.exec(header);
|
package/dist/auth/bearer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAGvE,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,qFAAqF;AACrF,SAAS,eAAe,CAAC,CAAa,EAAE,CAAa;IACnD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,UAA8B,EAAE;IAEhC,6BAA6B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,SAAS,CAAC,OAAO;YACf,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9C,IAAI,KAAK,IAAI,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC;gBACpE,OAAO;oBACL,EAAE,EAAE,IAAI;oBACR,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC/D,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,QAAQ,EAAE,IAAI,QAAQ,CACpB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EACzC;oBACE,MAAM,EAAE,GAAG;oBACX,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,kBAAkB,EAAE,QAAQ;qBAC7B;iBACF,CACF;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/auth/clerk.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createClerkClient } from "@clerk/backend";
|
|
2
|
-
import { type ToolkitBindingOptions } from "../toolkits.js";
|
|
3
2
|
import type { InboundAuth } from "../types.js";
|
|
4
3
|
type ClerkClient = ReturnType<typeof createClerkClient>;
|
|
5
|
-
export interface ClerkAuthOptions
|
|
4
|
+
export interface ClerkAuthOptions {
|
|
6
5
|
publishableKey: string;
|
|
7
6
|
secretKey: string;
|
|
8
7
|
/** Public base URL of this deployment. Defaults to the request origin. */
|
|
@@ -31,15 +30,7 @@ export interface ClerkAuthOptions extends ToolkitBindingOptions {
|
|
|
31
30
|
/**
|
|
32
31
|
* Clerk inbound auth.
|
|
33
32
|
*
|
|
34
|
-
* `allowedDomains` and `gate` decide
|
|
35
|
-
* `toolkits` decides WHICH view the admitted user gets.
|
|
36
|
-
*
|
|
37
|
-
* `toolkits` binds every user this provider admits to those toolkits
|
|
38
|
-
* (documentation/toolkits.md). For a per-team split, configure one `clerkAuth(...)` per
|
|
39
|
-
* team — the same keys, a `gate` naming that team's users, and that team's
|
|
40
|
-
* `toolkits`. The server tries providers in order and the first that admits the
|
|
41
|
-
* user supplies the binding, so a user one gate rejects falls through to the
|
|
42
|
-
* next.
|
|
33
|
+
* `allowedDomains` and `gate` decide who is admitted; both must pass.
|
|
43
34
|
*/
|
|
44
35
|
export declare function clerkAuth(opts: ClerkAuthOptions): InboundAuth;
|
|
45
36
|
export {};
|
package/dist/auth/clerk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clerk.d.ts","sourceRoot":"","sources":["../../src/auth/clerk.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"clerk.d.ts","sourceRoot":"","sources":["../../src/auth/clerk.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAGxD,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,8EAA8E;IAC9E,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsMD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAyT7D"}
|
package/dist/auth/clerk.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Single tenant, no tenant-tag requirement, optional allowedDomains/gate() with
|
|
3
3
|
// ~60s identity caching.
|
|
4
4
|
import { createClerkClient } from "@clerk/backend";
|
|
5
|
-
import {
|
|
5
|
+
import { assertNoRetiredToolkitOptions } from "../retired-toolkits.js";
|
|
6
6
|
const CORS_HEADERS = {
|
|
7
7
|
"Access-Control-Allow-Origin": "*",
|
|
8
8
|
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
@@ -38,6 +38,25 @@ const ACTIVITY_LABEL_MAX_IN_FLIGHT = 8;
|
|
|
38
38
|
// identities define the isolate's lifetime memory footprint.
|
|
39
39
|
const GATE_CACHE_MAX_IDENTITIES = 1_024;
|
|
40
40
|
const ACTIVITY_LABEL_MAX_LENGTH = 160;
|
|
41
|
+
function readIdentityCache(cache, key) {
|
|
42
|
+
const hit = cache.get(key);
|
|
43
|
+
if (!hit)
|
|
44
|
+
return undefined;
|
|
45
|
+
cache.delete(key);
|
|
46
|
+
if (Date.now() >= hit.exp)
|
|
47
|
+
return undefined;
|
|
48
|
+
cache.set(key, hit);
|
|
49
|
+
return hit;
|
|
50
|
+
}
|
|
51
|
+
function writeIdentityCache(cache, key, value) {
|
|
52
|
+
cache.delete(key);
|
|
53
|
+
cache.set(key, value);
|
|
54
|
+
if (cache.size <= GATE_CACHE_MAX_IDENTITIES)
|
|
55
|
+
return;
|
|
56
|
+
const oldest = cache.keys().next();
|
|
57
|
+
if (!oldest.done)
|
|
58
|
+
cache.delete(oldest.value);
|
|
59
|
+
}
|
|
41
60
|
function cleanActivityLabel(value) {
|
|
42
61
|
if (!value)
|
|
43
62
|
return undefined;
|
|
@@ -119,7 +138,7 @@ function normalizeAllowedDomains(value) {
|
|
|
119
138
|
}
|
|
120
139
|
/**
|
|
121
140
|
* Bounded, escaped form of the denied domain for the operator log — the same
|
|
122
|
-
* treatment
|
|
141
|
+
* treatment server logs give other caller-controlled values. An email domain is
|
|
123
142
|
* caller-influenced (anyone who controls a mailbox controls its domain): the
|
|
124
143
|
* bound is what a 253-byte domain needs, and the escaping — JSON.stringify plus
|
|
125
144
|
* the hand-rolled U+2028/U+2029 pass it leaves raw — is defense in depth behind
|
|
@@ -152,22 +171,14 @@ function emailDomain(email) {
|
|
|
152
171
|
/**
|
|
153
172
|
* Clerk inbound auth.
|
|
154
173
|
*
|
|
155
|
-
* `allowedDomains` and `gate` decide
|
|
156
|
-
* `toolkits` decides WHICH view the admitted user gets.
|
|
157
|
-
*
|
|
158
|
-
* `toolkits` binds every user this provider admits to those toolkits
|
|
159
|
-
* (documentation/toolkits.md). For a per-team split, configure one `clerkAuth(...)` per
|
|
160
|
-
* team — the same keys, a `gate` naming that team's users, and that team's
|
|
161
|
-
* `toolkits`. The server tries providers in order and the first that admits the
|
|
162
|
-
* user supplies the binding, so a user one gate rejects falls through to the
|
|
163
|
-
* next.
|
|
174
|
+
* `allowedDomains` and `gate` decide who is admitted; both must pass.
|
|
164
175
|
*/
|
|
165
176
|
export function clerkAuth(opts) {
|
|
177
|
+
assertNoRetiredToolkitOptions("clerkAuth", opts);
|
|
166
178
|
const clerk = createClerkClient({
|
|
167
179
|
secretKey: opts.secretKey,
|
|
168
180
|
publishableKey: opts.publishableKey,
|
|
169
181
|
});
|
|
170
|
-
const toolkitBinding = resolveToolkitBinding("clerkAuth", opts);
|
|
171
182
|
const allowedDomains = normalizeAllowedDomains(opts.allowedDomains);
|
|
172
183
|
const scopes = opts.scopes ?? ["openid", "profile", "email"];
|
|
173
184
|
const gateCache = new Map();
|
|
@@ -177,28 +188,16 @@ export function clerkAuth(opts) {
|
|
|
177
188
|
let activeActivityLabelLookups = 0;
|
|
178
189
|
const resolveBase = (baseUrl) => opts.publicUrl ?? baseUrl;
|
|
179
190
|
const cacheActivityLabel = (userId, label) => {
|
|
180
|
-
activityLabelCache
|
|
181
|
-
activityLabelCache.set(userId, {
|
|
191
|
+
writeIdentityCache(activityLabelCache, userId, {
|
|
182
192
|
...(label ? { label } : {}),
|
|
183
193
|
exp: Date.now() +
|
|
184
194
|
(label ? ACTIVITY_LABEL_TTL_MS : ACTIVITY_LABEL_MISS_TTL_MS),
|
|
185
195
|
});
|
|
186
|
-
if (activityLabelCache.size > GATE_CACHE_MAX_IDENTITIES) {
|
|
187
|
-
const oldest = activityLabelCache.keys().next();
|
|
188
|
-
if (!oldest.done)
|
|
189
|
-
activityLabelCache.delete(oldest.value);
|
|
190
|
-
}
|
|
191
196
|
};
|
|
192
197
|
const resolveActivityLabel = async (userId) => {
|
|
193
|
-
const cached = activityLabelCache
|
|
194
|
-
if (cached)
|
|
195
|
-
|
|
196
|
-
activityLabelCache.delete(userId);
|
|
197
|
-
activityLabelCache.set(userId, cached);
|
|
198
|
-
return cached.label;
|
|
199
|
-
}
|
|
200
|
-
activityLabelCache.delete(userId);
|
|
201
|
-
}
|
|
198
|
+
const cached = readIdentityCache(activityLabelCache, userId);
|
|
199
|
+
if (cached)
|
|
200
|
+
return cached.label;
|
|
202
201
|
const existing = pendingActivityLabels.get(userId);
|
|
203
202
|
if (existing)
|
|
204
203
|
return existing;
|
|
@@ -309,17 +308,9 @@ export function clerkAuth(opts) {
|
|
|
309
308
|
const checkGate = async (userId) => {
|
|
310
309
|
if (!opts.gate && !allowedDomains)
|
|
311
310
|
return true;
|
|
312
|
-
const hit = gateCache
|
|
313
|
-
if (hit)
|
|
314
|
-
|
|
315
|
-
// Map iteration order is the LRU order. Refreshing a valid hit keeps a
|
|
316
|
-
// small active identity set resident when one-off identities churn.
|
|
317
|
-
gateCache.delete(userId);
|
|
318
|
-
gateCache.set(userId, hit);
|
|
319
|
-
return hit.allowed;
|
|
320
|
-
}
|
|
321
|
-
gateCache.delete(userId);
|
|
322
|
-
}
|
|
311
|
+
const hit = readIdentityCache(gateCache, userId);
|
|
312
|
+
if (hit)
|
|
313
|
+
return hit.allowed;
|
|
323
314
|
let allowed = false;
|
|
324
315
|
try {
|
|
325
316
|
allowed =
|
|
@@ -329,22 +320,16 @@ export function clerkAuth(opts) {
|
|
|
329
320
|
catch {
|
|
330
321
|
allowed = false;
|
|
331
322
|
}
|
|
332
|
-
gateCache
|
|
323
|
+
writeIdentityCache(gateCache, userId, {
|
|
333
324
|
allowed,
|
|
334
325
|
exp: Date.now() +
|
|
335
326
|
(allowed ? GATE_ALLOWED_TTL_MS : GATE_FORBIDDEN_TTL_MS),
|
|
336
327
|
});
|
|
337
|
-
if (gateCache.size > GATE_CACHE_MAX_IDENTITIES) {
|
|
338
|
-
const oldest = gateCache.keys().next();
|
|
339
|
-
if (!oldest.done)
|
|
340
|
-
gateCache.delete(oldest.value);
|
|
341
|
-
}
|
|
342
328
|
return allowed;
|
|
343
329
|
};
|
|
344
330
|
return {
|
|
345
331
|
kind: "clerk",
|
|
346
332
|
activityActorNamespace: fapiUrl(opts.publishableKey),
|
|
347
|
-
...(toolkitBinding ? { toolkitBinding } : {}),
|
|
348
333
|
activityActorLabel: resolveActivityLabel,
|
|
349
334
|
uiAuth: {
|
|
350
335
|
kind: "clerk",
|