@anchrd/intel-api 0.17.0 → 0.18.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/README.md +18 -4
- package/dist/intel/intel.js +26 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -348,10 +348,24 @@ both, every silent sign-in is refused and the Tools area shows "No access to the
|
|
|
348
348
|
correct behaviour for somebody outside every policy, and a misleading one for a deployment that
|
|
349
349
|
simply never enabled the setting.
|
|
350
350
|
|
|
351
|
-
⚠️ **
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
351
|
+
⚠️ **Somebody who carries the Gate capability `mcp.connect` at no service at all is not sent into
|
|
352
|
+
that sign-in.** Gate answers that question service-wide, Intel asks it before the first redirect,
|
|
353
|
+
and the person stays here reading a sentence that says whom to ask — rather than landing on the
|
|
354
|
+
portal's own error page, outside Intel, with no way back but the browser's back button
|
|
355
|
+
(anchrd/intel#434). Grant `mcp.connect` alongside the Intel capabilities to everyone who should
|
|
356
|
+
reach Tools.
|
|
357
|
+
|
|
358
|
+
Two things that guard deliberately does not do. It **names no server**: the answer is one bit, so
|
|
359
|
+
somebody who may reach a different product's MCP server walks on and sees what the portal offers
|
|
360
|
+
them. And it **promises nothing** — this is the part worth knowing before you grant: the portal
|
|
361
|
+
decides on the `mcp` claim frozen into the ID token, and a running Cloudflare Access session carries
|
|
362
|
+
the old claim for up to 24 hours. ⚠️ **Inside that window the old dead end is still open.** Somebody
|
|
363
|
+
who was granted `mcp.connect` a minute ago is not refused here, walks on, and Access then decides on
|
|
364
|
+
the claim state that produced the error page in the first place. The guard closes the trip that is
|
|
365
|
+
certainly pointless; it does not close this one. The way out is the same as before — sign out of
|
|
366
|
+
Access and in again, so a new ID token carries the new claim. (Not measured against a running
|
|
367
|
+
installation; the claim lifetime is the documented one.) Against a Gate too old to answer the
|
|
368
|
+
question at all, nobody is refused here.
|
|
355
369
|
|
|
356
370
|
The Tools screen distinguishes four situations rather than calling all of them "no access": a
|
|
357
371
|
refusal that really came back, an expired connection, a sign-in that broke, and a sign-in that was
|
package/dist/intel/intel.js
CHANGED
|
@@ -50,7 +50,32 @@ export function createIntel(deps) {
|
|
|
50
50
|
if (!authorization) {
|
|
51
51
|
return context.redirect(`/auth/login?returnTo=${connectReturnTo}`);
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
// ⚠️ Two questions, and both are answered BEFORE the first redirect leaves Intel (#434).
|
|
54
|
+
// `tools:read` is Intel's own door. `mcpPortalRefused()` is Gate's answer to a question Intel
|
|
55
|
+
// cannot ask itself: does this person carry `mcp.connect` at ANY service? Measured against the
|
|
56
|
+
// running installation, somebody without it was sent to `mcp.anchrd.sh/servers-callback` and
|
|
57
|
+
// landed on a white page saying "No allowed servers available, check your Zero trust policies"
|
|
58
|
+
// — a sentence written for an administrator, on a foreign domain, with not one clickable
|
|
59
|
+
// element on it.
|
|
60
|
+
//
|
|
61
|
+
// ⚠️ The helper, never the raw `mcpConnectAnywhere` beside it. The field has THREE states, and
|
|
62
|
+
// `undefined` means "this Gate is older than the question" (anchrd/gate#277), not "nowhere".
|
|
63
|
+
// `if (!authorization.mcpConnectAnywhere)` passes `tsc --noEmit` and `biome check` alike and
|
|
64
|
+
// would turn every reader of such an installation away without a word — the difference is a
|
|
65
|
+
// value, not a type, so nothing but this line prevents it (anchrd/gate#288).
|
|
66
|
+
//
|
|
67
|
+
// ⚠️ And it is deliberately NOT `can("mcp", "connect")`, which is what this guard was first
|
|
68
|
+
// built as: Gate trims `rules` to the ASKING service (GATE-64, least privilege), so that asks
|
|
69
|
+
// `intel.mcp.connect`. The portal is a door onto every server — somebody carrying
|
|
70
|
+
// `dwh.mcp.connect` reaches it and sees the dwh tools, and that spelling would have locked
|
|
71
|
+
// them out. The bit knows no service names, on purpose; it is one bit and carries no more.
|
|
72
|
+
//
|
|
73
|
+
// ⚠️ It spares the certainly wasted trip and promises no successful one: the portal decides
|
|
74
|
+
// on the `mcp` claim frozen into the ID token, and a running Access session carries the old
|
|
75
|
+
// claim for up to 24 hours. Somebody granted a minute ago is NOT refused here, walks on, and
|
|
76
|
+
// meets Access deciding on the very claim state this ticket is about — inside that window the
|
|
77
|
+
// old dead end is still open, and this guard does not close it. It closes the certain one.
|
|
78
|
+
if (!authorization.can("tools", "read") || authorization.mcpPortalRefused()) {
|
|
54
79
|
return context.redirect("/tools?connectError=permission_required");
|
|
55
80
|
}
|
|
56
81
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anchrd/intel-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"typecheck": "tsc --noEmit"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@anchrd/gate-sdk": "^0.
|
|
45
|
+
"@anchrd/gate-sdk": "^0.15.0",
|
|
46
46
|
"@anchrd/intel-contract": "^0.15.0",
|
|
47
47
|
"@cfworker/json-schema": "^4.1.1",
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.30.0",
|