@zereight/mcp-gitlab 2.1.70 → 2.2.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.ko.md +3 -1
- package/README.md +6 -2
- package/README.pt-BR.md +1 -1
- package/README.zh-CN.md +3 -1
- package/build/config.js +12 -4
- package/build/deprecated-env.js +47 -0
- package/build/index.js +369 -184
- package/build/oauth-device-flow.js +80 -0
- package/build/oauth.js +135 -18
- package/build/schemas.js +1 -1
- package/build/server/remote-http-stack.js +39 -0
- package/build/tools/discover-activation.js +38 -0
- package/build/tools/exposed-tools.js +35 -0
- package/build/tools/listed-tools.js +76 -0
- package/build/tools/registry.js +226 -57
- package/build/tools/tool-profile.js +66 -0
- package/build/utils/compact-tool-allowlist.js +14 -0
- package/build/utils/logger.js +34 -12
- package/package.json +3 -3
- package/build/scripts/check-skill-sync.js +0 -143
- package/build/scripts/generate-server-card.js +0 -39
- package/build/scripts/generate-tool-coverage.js +0 -58
- package/build/scripts/generate-tool-docs.js +0 -430
- package/build/scripts/tool-coverage/coverage.js +0 -341
- package/build/scripts/tool-coverage/coverage.test.js +0 -142
- package/build/test/callback-proxy-tests.js +0 -321
- package/build/test/cli/args.test.js +0 -175
- package/build/test/cli/boolean-flags.test.js +0 -106
- package/build/test/cli/compact-mcp-result.test.js +0 -93
- package/build/test/cli/credentials.test.js +0 -153
- package/build/test/cli/exposure.test.js +0 -104
- package/build/test/cli/load-config-snapshot.js +0 -5
- package/build/test/cli/output.test.js +0 -74
- package/build/test/cli/replay-command.test.js +0 -37
- package/build/test/cli/router.test.js +0 -183
- package/build/test/client-pool-test.js +0 -109
- package/build/test/clients/client.js +0 -34
- package/build/test/clients/custom-header-client.js +0 -122
- package/build/test/clients/sse-client.js +0 -95
- package/build/test/clients/stdio-client.js +0 -113
- package/build/test/clients/streamable-http-client.js +0 -95
- package/build/test/config-allowed-groups.test.js +0 -97
- package/build/test/create-commit-actions.test.js +0 -102
- package/build/test/draft-note-schema.test.js +0 -44
- package/build/test/dynamic-api-url-allowlist.test.js +0 -121
- package/build/test/dynamic-api-url-test.js +0 -304
- package/build/test/dynamic-routing-tests.js +0 -495
- package/build/test/get-merge-request-discussion-schema.test.js +0 -30
- package/build/test/gitlab-api-tool-errors.test.js +0 -112
- package/build/test/gitlab-artifact-entry-schema.test.js +0 -44
- package/build/test/gitlab-diff-schema.test.js +0 -36
- package/build/test/gitlab-pipeline-schedule-schema.test.js +0 -32
- package/build/test/gitlab-tag-schema.test.js +0 -51
- package/build/test/group-milestone-schema.test.js +0 -45
- package/build/test/mcp-oauth-tests.js +0 -905
- package/build/test/mcp-server-name.test.js +0 -87
- package/build/test/merge-merge-request-schema.test.js +0 -75
- package/build/test/multi-server-test.js +0 -190
- package/build/test/no-proxy-integration-test.js +0 -183
- package/build/test/no-proxy-test.js +0 -149
- package/build/test/nullable-gitlab-response-fields.test.js +0 -37
- package/build/test/nullish-tool-arguments-schema.test.js +0 -118
- package/build/test/oauth-device-flow-tests.js +0 -450
- package/build/test/oauth-download-url.test.js +0 -157
- package/build/test/oauth-startup.test.js +0 -204
- package/build/test/oauth-tests.js +0 -428
- package/build/test/path-segment-encoding.test.js +0 -98
- package/build/test/remote-auth-simple-test.js +0 -277
- package/build/test/remote-auth-tests.js +0 -314
- package/build/test/response-masking.test.js +0 -445
- package/build/test/schema-tests.js +0 -1679
- package/build/test/server/metrics.test.js +0 -47
- package/build/test/server/request-helpers.test.js +0 -48
- package/build/test/server/version.test.js +0 -13
- package/build/test/sse-auth-guard.test.js +0 -96
- package/build/test/sse-session-limits.test.js +0 -273
- package/build/test/stateless/callback-proxy.test.js +0 -510
- package/build/test/stateless/client-id.test.js +0 -177
- package/build/test/stateless/codec.test.js +0 -328
- package/build/test/stateless/config-ttl.test.js +0 -149
- package/build/test/stateless/consumed-proxy-code-cache.test.js +0 -150
- package/build/test/stateless/session-id-integration.test.js +0 -675
- package/build/test/stateless/session-id.test.js +0 -157
- package/build/test/streamable-http-concurrent-session.test.js +0 -171
- package/build/test/streamable-http-dns-rebinding.test.js +0 -185
- package/build/test/streamable-http-sse-stream.test.js +0 -350
- package/build/test/streamable-http-static-token-auth.test.js +0 -157
- package/build/test/streamable-http-unauthenticated-discovery.test.js +0 -207
- package/build/test/test-all-transport-server.js +0 -255
- package/build/test/test-auth-retry.js +0 -195
- package/build/test/test-blank-filters.js +0 -156
- package/build/test/test-ci-catalog.js +0 -177
- package/build/test/test-ci-lint.js +0 -191
- package/build/test/test-ci-variables.js +0 -309
- package/build/test/test-create-repository.js +0 -120
- package/build/test/test-dependency-proxy.js +0 -195
- package/build/test/test-deployment-tools.js +0 -463
- package/build/test/test-download-attachment.js +0 -190
- package/build/test/test-dynamic-project-scope.js +0 -524
- package/build/test/test-empty-toolsets.js +0 -535
- package/build/test/test-get-file-blame.js +0 -145
- package/build/test/test-get-file-contents.js +0 -128
- package/build/test/test-geteffectiveprojectid.js +0 -804
- package/build/test/test-health-check.js +0 -115
- package/build/test/test-issue-description-patch.js +0 -256
- package/build/test/test-job-artifacts.js +0 -275
- package/build/test/test-json-schema.js +0 -166
- package/build/test/test-list-group-members.js +0 -150
- package/build/test/test-list-group-merge-requests.js +0 -165
- package/build/test/test-list-issues.js +0 -170
- package/build/test/test-list-merge-requests.js +0 -201
- package/build/test/test-list-milestones.js +0 -145
- package/build/test/test-list-project-members.js +0 -132
- package/build/test/test-merge-request-approval-state-tools.js +0 -213
- package/build/test/test-merge-request-approvals.js +0 -187
- package/build/test/test-merge-request-pipelines.js +0 -106
- package/build/test/test-mr-diffs-filter.js +0 -132
- package/build/test/test-mr-file-diffs.js +0 -251
- package/build/test/test-oauth-proxy-rate-limit.js +0 -133
- package/build/test/test-orbit.js +0 -155
- package/build/test/test-permission-mode.js +0 -424
- package/build/test/test-pipeline-schedules.js +0 -484
- package/build/test/test-protected-branches.js +0 -174
- package/build/test/test-remote-downloads.js +0 -510
- package/build/test/test-search-code.js +0 -275
- package/build/test/test-snippets.js +0 -735
- package/build/test/test-tags.js +0 -220
- package/build/test/test-todos.js +0 -195
- package/build/test/test-token-optimizations.js +0 -691
- package/build/test/test-toolset-filtering.js +0 -499
- package/build/test/test-update-issue-slim.js +0 -141
- package/build/test/test-update-project.js +0 -112
- package/build/test/test-upload-markdown.js +0 -206
- package/build/test/test-vulnerabilities.js +0 -399
- package/build/test/test-webhooks.js +0 -218
- package/build/test/tool-description-quality.test.js +0 -50
- package/build/test/utils/bulk-publish-options.test.js +0 -32
- package/build/test/utils/download-token.test.js +0 -35
- package/build/test/utils/forwarded-public-base-url.test.js +0 -46
- package/build/test/utils/gitlab-instance-version.test.js +0 -32
- package/build/test/utils/gitlab-version-gate.test.js +0 -74
- package/build/test/utils/graphql-query.test.js +0 -168
- package/build/test/utils/helpers-path.test.js +0 -104
- package/build/test/utils/jmespath-tool-result.test.js +0 -91
- package/build/test/utils/masking.test.js +0 -384
- package/build/test/utils/merge-request-position.test.js +0 -57
- package/build/test/utils/mock-gitlab-server.js +0 -614
- package/build/test/utils/proxy-client-ip.test.js +0 -28
- package/build/test/utils/redact-sensitive.test.js +0 -32
- package/build/test/utils/safe-redirect-fetch.test.js +0 -463
- package/build/test/utils/server-launcher.js +0 -231
- package/build/test/utils/tool-args.test.js +0 -210
- package/build/test/utils/url.test.js +0 -141
- package/build/test/utils/version-check.test.js +0 -239
- package/build/test/utils/wiki-title.test.js +0 -21
- package/build/test-note.js +0 -54
- package/build/test-resolve-issue-note.js +0 -127
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for ConsumedProxyCodeCache — TTL-aware replay prevention.
|
|
3
|
-
*
|
|
4
|
-
* Expectation (CWE-294): consumed hashes remain rejected until the configured
|
|
5
|
-
* code TTL expires; the cache never LRU-evicts early; inserts fail closed when
|
|
6
|
-
* still-valid entries fill capacity.
|
|
7
|
-
*/
|
|
8
|
-
import assert from "node:assert/strict";
|
|
9
|
-
import { describe, test } from "node:test";
|
|
10
|
-
import { ConsumedProxyCodeCache, PROXY_CODE_CACHE_FULL, } from "../../stateless/consumed-proxy-code-cache.js";
|
|
11
|
-
function reserveId(cache, key, ttlSeconds) {
|
|
12
|
-
const result = cache.tryReserve(key, ttlSeconds);
|
|
13
|
-
assert.equal(result.ok, true);
|
|
14
|
-
if (!result.ok) {
|
|
15
|
-
throw new Error("expected reservation to succeed");
|
|
16
|
-
}
|
|
17
|
-
return result.reservationId;
|
|
18
|
-
}
|
|
19
|
-
describe("ConsumedProxyCodeCache", () => {
|
|
20
|
-
test("rejects replay of a committed hash for the full configured TTL", () => {
|
|
21
|
-
let now = 1_000_000;
|
|
22
|
-
const cache = new ConsumedProxyCodeCache(10, () => now);
|
|
23
|
-
const ttlSeconds = 120;
|
|
24
|
-
const id = reserveId(cache, "hash-a", ttlSeconds);
|
|
25
|
-
cache.commit("hash-a", id);
|
|
26
|
-
// Still within TTL — must reject as consumed.
|
|
27
|
-
now += (ttlSeconds - 1) * 1000;
|
|
28
|
-
assert.deepEqual(cache.tryReserve("hash-a", ttlSeconds), {
|
|
29
|
-
ok: false,
|
|
30
|
-
reason: "consumed",
|
|
31
|
-
});
|
|
32
|
-
// Exactly at expiry boundary — still rejected while expiresAt > now.
|
|
33
|
-
now += 999;
|
|
34
|
-
assert.deepEqual(cache.tryReserve("hash-a", ttlSeconds), {
|
|
35
|
-
ok: false,
|
|
36
|
-
reason: "consumed",
|
|
37
|
-
});
|
|
38
|
-
// After TTL — purged; a new reservation is allowed (sealed code itself
|
|
39
|
-
// would also be expired by openStoredTokensCode at this point).
|
|
40
|
-
now += 1;
|
|
41
|
-
assert.equal(cache.tryReserve("hash-a", ttlSeconds).ok, true);
|
|
42
|
-
});
|
|
43
|
-
test("never LRU-evicts a live entry; fails closed when full", () => {
|
|
44
|
-
const now = 5_000_000;
|
|
45
|
-
const maxSize = 3;
|
|
46
|
-
const cache = new ConsumedProxyCodeCache(maxSize, () => now);
|
|
47
|
-
const ttlSeconds = 600;
|
|
48
|
-
cache.commit("h1", reserveId(cache, "h1", ttlSeconds));
|
|
49
|
-
cache.commit("h2", reserveId(cache, "h2", ttlSeconds));
|
|
50
|
-
cache.commit("h3", reserveId(cache, "h3", ttlSeconds));
|
|
51
|
-
assert.equal(cache.size, 3);
|
|
52
|
-
// A fourth insert must fail closed — not silently drop h1.
|
|
53
|
-
assert.throws(() => cache.tryReserve("h4", ttlSeconds), (err) => {
|
|
54
|
-
return err.message === PROXY_CODE_CACHE_FULL;
|
|
55
|
-
});
|
|
56
|
-
// Original consumed hashes are still covered through the TTL window.
|
|
57
|
-
assert.deepEqual(cache.tryReserve("h1", ttlSeconds), {
|
|
58
|
-
ok: false,
|
|
59
|
-
reason: "consumed",
|
|
60
|
-
});
|
|
61
|
-
assert.deepEqual(cache.tryReserve("h2", ttlSeconds), {
|
|
62
|
-
ok: false,
|
|
63
|
-
reason: "consumed",
|
|
64
|
-
});
|
|
65
|
-
assert.deepEqual(cache.tryReserve("h3", ttlSeconds), {
|
|
66
|
-
ok: false,
|
|
67
|
-
reason: "consumed",
|
|
68
|
-
});
|
|
69
|
-
assert.equal(cache.size, 3);
|
|
70
|
-
});
|
|
71
|
-
test("purge of expired entries frees capacity without reopening live replays", () => {
|
|
72
|
-
let now = 9_000_000;
|
|
73
|
-
const cache = new ConsumedProxyCodeCache(2, () => now);
|
|
74
|
-
cache.commit("old", reserveId(cache, "old", 10));
|
|
75
|
-
cache.commit("live", reserveId(cache, "live", 600));
|
|
76
|
-
assert.equal(cache.size, 2);
|
|
77
|
-
// Expire only "old" so a new insert can reclaim that slot.
|
|
78
|
-
now += 10_000;
|
|
79
|
-
cache.commit("fresh", reserveId(cache, "fresh", 600));
|
|
80
|
-
assert.equal(cache.size, 2);
|
|
81
|
-
// Still-valid "live" hash must remain rejected through its TTL.
|
|
82
|
-
assert.deepEqual(cache.tryReserve("live", 600), {
|
|
83
|
-
ok: false,
|
|
84
|
-
reason: "consumed",
|
|
85
|
-
});
|
|
86
|
-
// Cache is full of non-expired entries — fail closed, do not LRU-evict.
|
|
87
|
-
assert.throws(() => cache.tryReserve("another", 600), (err) => {
|
|
88
|
-
return err.message === PROXY_CODE_CACHE_FULL;
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
test("release drops pending reservation but not committed entries", () => {
|
|
92
|
-
const now = 2_000_000;
|
|
93
|
-
const cache = new ConsumedProxyCodeCache(10, () => now);
|
|
94
|
-
const pendingId = reserveId(cache, "pending", 60);
|
|
95
|
-
cache.release("pending", pendingId);
|
|
96
|
-
assert.equal(cache.size, 0);
|
|
97
|
-
const retryId = reserveId(cache, "pending", 60);
|
|
98
|
-
cache.commit("pending", retryId);
|
|
99
|
-
cache.release("pending", retryId);
|
|
100
|
-
assert.equal(cache.size, 1);
|
|
101
|
-
assert.deepEqual(cache.tryReserve("pending", 60), {
|
|
102
|
-
ok: false,
|
|
103
|
-
reason: "consumed",
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
test("pending reservation also blocks concurrent replay attempts", () => {
|
|
107
|
-
const cache = new ConsumedProxyCodeCache(10, () => 3_000_000);
|
|
108
|
-
assert.equal(cache.tryReserve("in-flight", 120).ok, true);
|
|
109
|
-
assert.deepEqual(cache.tryReserve("in-flight", 120), {
|
|
110
|
-
ok: false,
|
|
111
|
-
reason: "pending",
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
test("non-finite TTL still blocks a second reservation for the same key", () => {
|
|
115
|
-
const cache = new ConsumedProxyCodeCache(10, () => 4_000_000);
|
|
116
|
-
assert.equal(cache.tryReserve("nan-ttl", Number.NaN).ok, true);
|
|
117
|
-
assert.deepEqual(cache.tryReserve("nan-ttl", Number.NaN), {
|
|
118
|
-
ok: false,
|
|
119
|
-
reason: "pending",
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
test("extreme finite TTL keeps expiresAt finite and evictable", () => {
|
|
123
|
-
let now = 1_000_000;
|
|
124
|
-
const cache = new ConsumedProxyCodeCache(10, () => now);
|
|
125
|
-
cache.commit("max-ttl", reserveId(cache, "max-ttl", Number.MAX_VALUE));
|
|
126
|
-
assert.deepEqual(cache.tryReserve("max-ttl", Number.MAX_VALUE), {
|
|
127
|
-
ok: false,
|
|
128
|
-
reason: "consumed",
|
|
129
|
-
});
|
|
130
|
-
// Advance past the capped expiry so purgeExpired can reclaim the slot.
|
|
131
|
-
now += Math.floor(Number.MAX_SAFE_INTEGER / 1000) * 1000 + 1;
|
|
132
|
-
assert.equal(cache.tryReserve("max-ttl", 60).ok, true);
|
|
133
|
-
});
|
|
134
|
-
test("stale reservation id cannot release or commit a newer reservation", () => {
|
|
135
|
-
let now = 1_000_000;
|
|
136
|
-
const cache = new ConsumedProxyCodeCache(10, () => now);
|
|
137
|
-
const ttlSeconds = 10;
|
|
138
|
-
const staleId = reserveId(cache, "key", ttlSeconds);
|
|
139
|
-
now += 11_000;
|
|
140
|
-
const liveId = reserveId(cache, "key", ttlSeconds);
|
|
141
|
-
cache.release("key", staleId);
|
|
142
|
-
assert.deepEqual(cache.tryReserve("key", ttlSeconds), {
|
|
143
|
-
ok: false,
|
|
144
|
-
reason: "pending",
|
|
145
|
-
});
|
|
146
|
-
cache.commit("key", staleId);
|
|
147
|
-
cache.release("key", liveId);
|
|
148
|
-
assert.equal(cache.tryReserve("key", ttlSeconds).ok, true);
|
|
149
|
-
});
|
|
150
|
-
});
|