Repository navigation
Summary
3.4.0 serves input schemas the Anthropic Messages API accepts on every surface, can ask a person its questions in Spanish, follows GitLab.com's move of the Orbit routes, and tightens HTTP mode's authentication budgets, its listener and the configuration it starts with.
- No tool carries
allOf,anyOf,oneOf,not,if,thenorelseat the root of its input schema (#1509). The Anthropic Messages API refuses a whole request whose tool list holds one, and 3.3.0 served one on several individual tools and on every meta tool in thecompactandfullparameter-schema modes. Each rule stays in the catalog, whichgitlab_find_actionandgitlab://toolsread, and the handler enforces it before anything is sent. GITLAB_MCP_LANGUAGE=es(or--language=es) serves the texts a person reads directly in Spanish: the questions and field titles of the guided flows, the confirmation of a destructive action and the progress messages (#1577 to #1581, ADR-0027). What the model reads stays in English, and a server that sets nothing, oren, serves the same texts as 3.3.0.- Orbit (#1585, #1593): GitLab.com removed five of the six REST routes the Orbit tools read on 27 and 28 October, and
orbit.status,orbit.schema,orbit.tools,orbit.dslandorbit.graph_statusnow read GitLab's GraphQL API and its Orbit MCP endpoint, under the same action IDs, tool names and parameters. Since Orbit's general availability on 29 October, GitLab.com serves a namespace's index and queries only for a top-level group with theorbit_promoadd-on or an Orbit trial;orbit.graph_statuspublishes such a group's Orbitaccessandtrialto a token with the Owner role there, and answers a group without access with them rather than with an error. - HTTP mode: the authentication budgets key an IPv6 address by its /64 and bound each /48, and
unixin--trusted-proxieslets a proxy on a unix socket name its callers through--trusted-proxy-header(#1481). The two server cards and the RFC 9728 metadata are rate-limited per client address, at 20 requests a second with a burst of 200 by default (--discovery-rate-limit-rps,--discovery-rate-limit-burst,0to turn it off) (#1483). A listener off loopback that serves plain HTTP warns at startup, andGITLAB_MCP_ALLOW_PLAINTEXT_HTTP=false(or--allow-plaintext-http=false) refuses one (#1561). A session refused because it is not open for the presented credential is no longer described as belonging to another credential, which was false of one that idled out or did not survive a restart (#1484). - Configuration (#1519 to #1524): a zero means off wherever it has a meaning, through the flag and the variable alike, and
0sreads as0; a value the server cannot use refuses the start on both transports instead of being replaced or ignored (see Breaking changes). A stdio server no longer reads the settings only HTTP mode has, and names any it finds set, and it now honorsGITLAB_MCP_SESSION_REVALIDATE_INTERVAL.--max-listen-streamssets the listen ceiling as a flag. gitlab_find_actionranks the action a plural noun names first, solist issuesanswersissue.list(#1470). A string parameter GitLab checks (an email address, a URL, a commit SHA, a cron expression, a semantic version and others) declares its format or pattern, and find's example call fills it with a value of that form (#1504). Every text block of a result is annotated with the priority the output format reference documents, 0.4 for a list, 0.6 for a read and 0.8 for a write, where 3.3.0 annotated most with 0.7 (#1499).- New parameters: client-go v3.30.0 (#1460), with
member_role_idon the access levels of project and group protected branches (Ultimate); anavatarongroup.create,project.create,project.create_for_user,user.create,user.modify,admin.topic_createandadmin.topic_update,remove_avatarongroup.update,project.updateandadmin.topic_update, and 39 moreoverride_paramskeys onproject.import_from_file(#1640);hide_backlog_listandhide_closed_listongroup.group_board_update(#1510);archivedonproject.label_list, andrefonsearch.commitsandsearch.wikifor a project search (#1635). The board listings name every column with a work-in-progress limit (#1512),mr_review.changes_getpublishes its pagination (#1584), andsecurity_scan_profile.attachtakes thebusiness_logic(GitLab 19.5) andskillguard(GitLab 19.6) default profiles by name (#1585). - Fixes:
- An inline comment or draft note on a file past the first page of a merge request's diff is no longer refused as outside the diff, and the five prompts that read a merge request's changed files say when they read only the first page (#1584, from #1517 by Nikita Turchaninov).
access.approve_projectandaccess.approve_grouprefuse a level the project or group does not grant, where0used to grant Developer and another level left the request pending while it was reported as approved; every membership access level parameter offers only the levels its route accepts (#1567).- On the meta and dynamic surfaces, a protected environment approval rule given a count and no grantee was sent as a rule for Maintainers, and an update of a rule by its
idmoved its grantee to Maintainers; the dynamic surface also turned a top-levelrequired_approval_countinto such a rule. Both are now refused before a request on every surface (#1503). merge_request.cancel_auto_mergefalls back to the deprecated route when GitLab 19.5 or later answerscancel_auto_mergewith 404, as a node can during a rolling upgrade (#1594).- A 405 for a project named by a path it no longer has says to retry with the project's ID, instead of reading as a refusal of the merge request, file or token the call was about (#1496).
job.traceremoves the timestamp a runner writes in front of each line and joins a line the runner wrote in pieces, sotail_linescounts the lines the job printed (#1498).- The external status check create and delete name the Maintainer role on the 403 GitLab 19.5 answers a caller without it (#1463), and the safe-mode preview names both spellings that turn safe mode off (#1497).
- Release and project: the image is built on Alpine 3.24.3 (#1554), and its packages are held to Trivy's vulnerability database before anything is pushed (#1553). Every release binary is rebuilt from its tag and compared byte for byte, binaries from this release on are stamped with the full commit, and
scripts/install.shhonorsDESTDIR(#1557). Each release opens with a written summary (#1555), and the PyPI wheels carry PEP 740 publish attestations (#1551). The telemetry guide has a worked OpenTelemetry collector example (#1471), the repository states its governance, review standard and roadmap (#1556) and a security policy that describes what happens (#1560), and every commit is signed off under the Developer Certificate of Origin (#1562).
Breaking changes
Configurations that started under 3.3.0 with a value the server ignored or replaced now refuse to start, naming the setting:
- A unix-socket
--http-addrwhose--trusted-proxiesnames addresses and notunix, which used to start with--trusted-proxy-headerignored, so every caller on the socket shared one budget (#1481). --oauth-cache-ttlat0or below, in either authentication mode, asGITLAB_MCP_OAUTH_CACHE_TTLalready was (#1519).- A negative
--session-timeout,--revalidate-intervalor--pool-idle-timeout(#1520). - In HTTP mode, an upload size (
--upload-max-file-size,GITLAB_MCP_UPLOAD_MAX_FILE_SIZE) that does not parse, is not positive or lies above 1 TB, as stdio already refused; on both transports, a size whose byte count does not fit in 64 bits, such as17179869185GB(#1524). - With telemetry on, an identity policy the server does not know, or, with no key configured, a key rotation that does not parse or lies outside 0 to 720h (#1523).
HTTP mode's budgets are shared differently (#1481): every address of one IPv6 /64 spends one fast budget and one distinct-credential budget, as the callers behind one IPv4 NAT share an address's, and ten /64s of one /48 that had a credential refused inside --auth-distinct-token-window block the whole /48 for every credential the deployment does not already serve. --auth-failure-window=0 no longer turns the distinct-credential budget off, and GITLAB_MCP_SESSION_TIMEOUT=0 turns the idle timeout off instead of refusing the start (#1519).
The Orbit outputs no longer carry what GitLab.com stopped sending (#1585): the status's user, system, timestamp and formatted_text, and each component's replicas and metrics; the schema's schema_version, each domain's description and each node's incoming and outgoing edges; and the index's formatted_text, last_started_at, last_duration_ms and last_error. response_format on the status and the index is accepted and changes nothing, and orbit.query refuses a query sent as a JSON object, since GitLab.com removed the JSON query DSL on 27 October.
Withdrawn, as the versioning policy allows in a minor release for what a tool could never honor:
pagination,page_tokenandorder_byongroup.service_account_pat_listandproject.service_account_pat_list, whose routes answer every keyset request with 405 and read noorder_by;sorttakes the eight orders the routes document in place ofascanddesc(#1573).new_epiconuser.notification_project_update, which the project route does not declare (#1570).repository_checksum_failedandwiki_checksum_failedonproject.list,project.list_forks,project.list_user_projects,project.list_user_starredandproject.list_user_contributed, which no route reads, so a list asked for them answered every project (#1570).access_level_descriptionon the approval rules ofenvironment.protected_protect,environment.protected_update,group.protected_env_protectandgroup.protected_env_update, which no route declares (#1503).- The
name,path,namespace_id,default_branchandlfs_enabledkeys ofoverride_paramsonproject.import_from_file, which the import drops (#1640). - Below the tier GitLab needs for them, the parameters GitLab drops or refuses there (#1569, #1570):
- Premium: on
group.update,file_template_project_id,ip_restriction_ranges,allowed_email_domains_list,prevent_forking_outside_group,only_allow_merge_if_pipeline_succeeds,allow_merge_on_skipped_pipelineandonly_allow_merge_if_all_discussions_are_resolved;wiki_access_levelongroup.createandgroup.update;repository_storageongroup.listandgroup.subgroups;approver_idsonmerge_request.list,merge_request.list_globalandmerge_request.list_group;new_epiconuser.notification_global_updateanduser.notification_group_update; onproject.createandproject.create_for_user,external_authorization_classification_label,use_custom_template,template_project_id,group_with_project_templates_id,mirrorandmirror_trigger_builds; and onproject.update,external_authorization_classification_label,allow_pipeline_trigger_approve_deployment,ci_restrict_pipeline_cancellation_role,issues_template,merge_requests_template,import_url,mirror,mirror_trigger_builds,mirror_user_id,only_mirror_protected_branches,mirror_overwrites_diverged_branchesandmirror_branch_regex. - Ultimate:
with_security_reportsongroup.projects;member_role_idonproject.member_add,group.group_member_add,group.ldap_link_addandgroup.saml_link_add; andprevent_merge_without_jira_issueonproject.update.
- Premium: on
Refused before a request, where GitLab refused the call or did something other than it asked (#1502, #1503, #1567):
group.ldap_link_addandgroup.ldap_link_deletewith both or neither ofcnandfilter.- On
environment.protected_protect,environment.protected_update,group.protected_env_protectandgroup.protected_env_update: a protect with no deploy access level, a deploy access level naming other than exactly one ofaccess_level,user_idandgroup_id, an approval rule naming none of the three unless_destroyis true, anaccess_levelother than 20, 30, 40 or 60, and a top-levelrequired_approval_countabove 0, which GitLab refuses as deprecated. access.approve_projectandaccess.approve_groupat a level the project or group does not grant,0included, which used to grant Developer.
Upgrading
- A unix-socket deployment that lists proxies in
--trusted-proxiesaddsunixto the list. - Remove an
--oauth-cache-ttlof0or below, which ran an oauth deployment at the 15-minute default and was never read in legacy mode, and turn a negative--session-timeout,--revalidate-intervalor--pool-idle-timeoutinto0, which is what the server made of it. - Correct the upload size the server names at startup: in HTTP mode it ran under
2GB, or under the 1 TB ceiling for a size above it, and on either transport a size whose byte count does not fit in 64 bits ran as a much smaller or an unlimited one. - With telemetry on, correct the identity policy (
none,pseudonymousorfull) or the key rotation the server names at startup; while it was wrong, the server recorded nothing about callers. - A listener off loopback that serves plain HTTP behind a proxy that terminates TLS sets
GITLAB_MCP_ALLOW_PLAINTEXT_HTTP=true(or--allow-plaintext-http) to say so, which logs the line at INFO instead of warning. A container that keeps the image's command sets the variable, since an argument after the image name replaces the command. - Send
orbit.queryits query as GQL text. - Leave a withdrawn parameter out of a call. An imported project takes its name, path and namespace from the import's own
name,pathandnamespace, and its default branch and LFS setting from aproject.updateafter it; the service account token lists are ordered with one of the eightsortvalues, such ascreated_desc, rather than withorder_byandascordesc. - Approve an access request at Developer by leaving
access_levelout, rather than sending0. - Name the grantee of every protected environment approval rule (
access_level: 40for Maintainers), which the meta and dynamic surfaces used to fill in, and send a required count as the rule'srequired_approvalsrather than as a top-levelrequired_approval_count.
Security
- Fixes GHSA-rxjw-584q-hxjr (medium, CVSS 4.7, CWE-23, CWE-20): a tool argument placed into the path of a request to GitLab was not checked for path separators or dot segments, so a crafted value, such as one a model fills in under prompt injection, could make the server build a request path that, once a front layer or GitLab resolves the dot segments, names a different GitLab API endpoint than the action intends, under the configured token and past the server's per-action controls. Every release from 1.0.0 through 3.3.0 is affected: the job artifact, template, model registry download and pipeline schedule variable actions, and any action whose escaped path argument is
.or..as a whole, from 1.0.0, the system hook URL-variable actions from 2.0.2, and the group hook URL-variable, custom-header and test actions from 2.3.0. A standard GitLab install does not serve such a request (400by default from GitLab 18.2,404before it); a front layer that resolves dot segments before forwarding lets it through. 3.4.0 fixes it: the transport refuses to send any request whose path carries a.or..segment, as given or once percent-decoded; the sixteen actions the advisory names also refuse such an argument before building the request, naming the parameter; and the handlers of the routes that placed an argument into the path unescaped now escape it, so a%in those arguments is sent as%25. The 1.x and 2.x module paths carry no patched release, so upgrading to 3.4.0 is the remedy. - Dependencies: Go 1.27.3 (#1455), a security release of
crypto/x509, fixes GO-2026-6809 (CVE-2026-111943), which the 3.3.0 binaries carry, andgolang.org/x/netv0.62.0 (#1564) fixes GO-2026-6860 and GO-2026-6866 inx/net/html. The image moves to Alpine 3.24.3 (#1554), which fixes CVE-2026-85091 in zlib and CVE-2026-107891 in musl, both in the 3.3.0 image. - Hardening without an advisory, in HTTP mode:
- An IPv6 caller that changed its address inside its /64 was given a fresh fast budget and a fresh distinct-credential budget on every request; the budgets now key the /64 and count the refused /64s of each /48 (#1481).
- Behind
--trusted-proxy-header, the transport-source budget kept a record of every (source, key) pair it charged, both chosen by the caller, until its five-minute sweep, including for sources its limiter never recorded; it now keeps a pair only for a failure its limiter counted, and at most 500 for one source (#1482).
Changelog
✨ Features
- 05cdb35: feat(http)!: key the authentication budgets on the IPv6 /64, bound the /48 and name the unix-socket peer (#1481) (@jmrplens)
- d4b958b: feat(http): warn on a plaintext listener off loopback, and refuse it in a hardened mode (#1561) (@jmrplens)
- 1e4e1e1: feat(tools): offer every param the option struct an action sends already models, and declare the ones GitLab drops (R-PARAM) (#1640) (@jmrplens)
🐛 Bug Fixes
- d4e6ec0: fix(externalstatuschecks): hint the Maintainer role on the 403 a create or delete gets from 19.5 (#1463) (@jmrplens)
- 9c467c7: fix(graphql): stop selecting crashState, and hold every document to the schema of GitLab 19.5 (#1647) (@jmrplens)
- fffe119: fix(groupboards): send the Open and Closed list switches on the group board update (#1510) (@jmrplens)
- 1fc9bad: fix(mergerequests): retry the deprecated cancel route after a 404 (#1594) (@KashifManzer)
- a82c704: fix(orbit): read the Orbit status, schema, tools, query language and index from the sources GitLab.com still serves (#1585) (@jmrplens)
- f486238: fix: answer the review of the best practices stack, update every dependency and regenerate the testing reference (#1564) (@jmrplens)
📚 Documentation
- 251d071: docs(security): make the policy describe what happens, and publish an assurance case (#1560) (@jmrplens)
- 8a54699: docs(security): record the October 2026 security review, and check the documentation site's headers after each deploy (#1559) (@jmrplens)
- 21e93d0: docs(upstream-bugs): keep row 78's merge request to severities and leave row 79 to GitLab's existing issue (#1487) (@jmrplens)
- 4ac0119: docs(upstream-bugs): name the client-go!3063 commits by their current hashes (#1454) (@jmrplens)
- f114a89: docs(upstream-bugs): name the merge request that sends row 6 again (#1476) (@jmrplens)
- 2419d1c: docs(upstream-bugs): record client-go's joint merge request closed and split (#1457) (@jmrplens)
- c5c42c4: docs(upstream-bugs): record row 53's merge and the rows that moved since 2026-10-19 (#1490) (@jmrplens)
- ed18d7d: docs(upstream-bugs): record row 55's merge and the rows that moved since 2026-10-22 (#1495) (@jmrplens)
- 6bc5d1d: docs: move the long-form references out of CLAUDE.md (#1453) (@jmrplens)
- 6c9066a: docs: say that web commits are signed off now that the repository requires it (#1566) (@jmrplens)
- e237441: docs: stop describing row 34's joint merge request as open (#1458) (@jmrplens)
- b6c94ed: docs: write down governance, roles, continuity, code review and a roadmap, and show the OpenSSF Best Practices badge (#1556) (@jmrplens)
🚧 Maintenance
- fc6486e: Add a gate that refuses a closed httptest server whose address is still used (#1473) (@jmrplens)
- d52ad65: Add a worked OpenTelemetry collector example, held to the server by the collector module (#1471) (@jmrplens)
- e846186: Add the person-facing message catalog and the GITLAB_MCP_LANGUAGE setting, English only (#1577) (@jmrplens)
- 96b4413: Answer the group settings, custom role and group variable rows of issue 1240 from GitLab's source (#1569) (@jmrplens)
- 1b31f66: Answer the issue, merge request, notification, push mirror and project rows of issue 1240 from GitLab's source (#1570) (@jmrplens)
- fcf6ea0: Bound the transport-source budget's record of the pairs it charged (#1482) (@jmrplens)
- 9146b5f: Check inline comment positions past the first page of a merge request's diff, publish the pagination of mr_review.changes_get, and say when a prompt read only the first page of changed files (#1584) (@jmrplens)
- ffa14bc: Derive every action's content kind in the catalog, so a list, a read and a write carry 0.4, 0.6 and 0.8 (#1499) (@jmrplens)
- d6f108b: Describe the live record's keyset half and R-PAGE's, cover the token lists end to end, and regenerate the stack's artifacts (#1575) (@jmrplens)
- 3a5f984: Document the language setting, record ADR-0027, and close #1547 (#1581) (@jmrplens)
- 5b8d57f: Gate package and exported-symbol doc comments, and fix what the audit reports (#1478) (@jmrplens)
- f085317: Give each limit's zero one meaning, and write its default once (#1519) (@jmrplens)
- dbd1b4a: Give tests a dead endpoint that keeps its port, and move the sixteen closed-server sites onto it (#1472) (@jmrplens)
- d4a08c9: Hold protected environment entries to GitLab's rules before they are sent (#1503) (@jmrplens)
- 431e25d: Hold the Go commands a credentialed job runs to this module, retire what nothing needed, and declare every script that is not Go (#1550) (@jmrplens)
- 2a331bf: Leave no mutant lived, uncovered or timed out in the md-escaping and action-ids gates (#1488) (@jmrplens)
- d450c30: Make the stdio pin of register row 11 tell its two failures apart (#1469) (@jmrplens)
- 39b7093: Merge commit from fork (@jmrplens)
- 08263e3: Mirror to GitLab over IPv4, retry the push and leave Dependabot out, like every other repository (#1493) (@jmrplens)
- 22e6603: Name both safe-mode spellings in the preview hint (#1497) (@jmrplens)
- ef06f1d: Name each limited board column, its ceilings and its metric in the project and group board listings (#1512) (@jmrplens)
- 1ee10c3: Offer Ko-fi beside GitHub Sponsors in the sponsor button and the npm funding field (#1489) (@jmrplens)
- 1376e58: Offer no keyset pagination or order_by on the service account token lists, and publish the eight sort orders they document (#1573) (@jmrplens)
- cd0861e: Offer only the access levels each GitLab route accepts, and stop reporting a pending access request as approved (#1567) (@jmrplens)
- b95d8bb: Probe what GitLab 19.5 counts against an invalid token, and state the distinct-credential budget's reason from it (#1480) (@jmrplens)
- de493dc: Publish the form GitLab checks on a string and fill find's example with it (#1504) (@jmrplens)
- b2bf38b: Rank the action a plural noun names first in gitlab_find_action (#1470) (@jmrplens)
- 491eb0a: Rate-limit the discovery documents per client address (#1483) (@jmrplens)
- 0fd65b6: Read a timestamped job log as GitLab's viewer does: no header, and a line written in pieces whole again (#1498) (@jmrplens)
- e5d4a81: Read group boards through client-go and the captured answer instead of requests of their own (#1511) (@jmrplens)
- 4d3b622: Read no HTTP-only setting on stdio, honor the revalidation interval there, and refuse negative duration flags (#1520) (@jmrplens)
- ae420eb: Read the answers to the edition tier audit's parameter findings from a declaration table, and answer the seven Minimal access rows (#1568) (@jmrplens)
- 04937dc: Read the twelve settings issue 957 found around the configuration package through it, and give the listen ceiling its flag (#1522) (@jmrplens)
- 9f1eae6: Record the malformed values issue 957 keeps, and hold every GITLAB_MCP_ read outside the configuration rule (#1521) (@jmrplens)
- 779d7cb: Record the zeros issue 958 decided, the capacity rule and why each fixed value is fixed (#1518) (@jmrplens)
- 3be10e4: Record which routes can page by keyset at schema 5, and hold page_token to them in R-PAGE (#1574) (@jmrplens)
- 2d35ffc: Refuse a malformed or oversized upload size in HTTP mode as stdio does, and state it on RQB-007 (#1524) (@jmrplens)
- f72d514: Refuse a start whose telemetry identity setting cannot be used, and say what a malformed value of each setting does (#1523) (@jmrplens)
- b6a6eb0: Refuse an ended session in words true of it (#1484) (@jmrplens)
- a3fb213: Require exactly one of cn or filter on the LDAP group link add and delete (#1502) (@jmrplens)
- a066752: Run OpenSSF Scorecard on main, hold a container action's image to its digest, and group the README badges (#1552) (@jmrplens)
- e420540: Say what a 405 for a moved project's old path means, so the caller retries with the ID (#1496) (@jmrplens)
- 7a50406: Scan the image's Alpine packages with Trivy before the push, and refuse Aqua's Trivy actions in a credentialed job (#1553) (@jmrplens)
- 59a2143: Serve no combinator at the root of a tool's input schema, which the Anthropic Messages API refuses (#1509) (@jmrplens)
- 9199b1a: Serve the person-facing texts in Spanish with GITLAB_MCP_LANGUAGE=es (#1580) (@jmrplens)
- 4e6a848: Serve the texts a person reads from the message catalog, with English unchanged (#1579) (@jmrplens)
- a0e4e6c: Share the scaffolding the source gates had copied, in goprogram and a new sourcegate package (#1479) (@jmrplens)
- 430de90: Skip the Orbit live tests only on GitLab's own answer that Orbit is not served, hold the live tier test to the fixture group's plan, and say that a shortest path names its relationship types (#1593) (@jmrplens)
- b8846b9: Take Alpine 3.24.3 for zlib and musl, and expressive-code 0.44.3 for postcss-selector-parser (#1554) (@jmrplens)
- f1ab52b: Teach the Markdown escaping audit the message catalog and add the person-facing text gate (#1578) (@jmrplens)
- ff18ee5: The GitLab release sync waits for the mirror push (#1494) (@jmrplens)
- c077123: Wire the closed-server gate into make analyze and CI, and document netfixture (#1474) (@jmrplens)
- 1debc22: audit(1to1): adjudicate the routes no action reaches and gate on them (#1642) (@jmrplens)
- 703f46f: audit(1to1): compare nested objects both ways and pair the converters toolutil declares (#1643) (@jmrplens)
- 031ba7e: audit(1to1): give every workaround waiting on client-go a predicate the pinned SDK is held to (#1636) (@jmrplens)
- 567ec29: audit(1to1): hold an id-or-path identifier to an input that accepts both (#1638) (@jmrplens)
- 44fd2b9: audit(1to1): hold every live route to an action or a reason (R-ROUTE) (#1641) (@jmrplens)
- adb1afd: audit(1to1): hold every option struct a call sends to an input, and a copy between two to every field they share (#1635) (@jmrplens)
- 00a2cee: audit(1to1): report a captured key the client-go struct beside it already models (#1637) (@jmrplens)
- ca54e00: audit(1to1): report every param a reached route declares that nothing here sends (R-PARAM) (#1639) (@jmrplens)
- 1974696: chore(deps): bump client-go to v3.30.0 and take the custom role on protected branch access levels (#1460) (@jmrplens)
- b9c5512: chore(deps): dependency sweep of 20 October (#1455) (@jmrplens)
- 0e6334b: chore(release): move VERSION to 3.4.0, with its release notes (#1648) (@jmrplens)
- 0b20816: chore: carry a copyright line and SPDX-License-Identifier: MIT in every source file (#1563) (@jmrplens)
- 2f8021c: chore: index R-PARAM and R-ROUTE beside the other audit dimensions and regenerate the artifacts at the top of the auditor stack (#1644) (@jmrplens)
- 56758fb: chore: regenerate the artifacts at the top of the access level and edition tier stack (#1571) (@jmrplens)
- 958c651: chore: regenerate the artifacts at the top of the localization stack (#1582) (@jmrplens)
- 59e16d7: chore: regenerate the artifacts the exactly-one, list-item and format schemas move (#1505) (@jmrplens)
- 8e959c3: chore: regenerate the artifacts the group board layers move (#1513) (@jmrplens)
- e9389a0: chore: regenerate the artifacts the job trace usage line and the stack's tests move (#1500) (@jmrplens)
- fb60a22: chore: regenerate the artifacts the status check usage line moves (#1466) (@jmrplens)
- 6fbaf20: chore: regenerate the testing reference at the top of the authentication-budget stack (#1485) (@jmrplens)
- e3e09d2: chore: regenerate the testing reference at the top of the configuration stack (#1525) (@jmrplens)
- e5b0357: chore: update manifests for v3.3.0 (@jmrplens)
- 7bab2ea: ci(release): open every release with a written summary, and refuse a tag without one (#1555) (@jmrplens)
- 450f926: ci(release): prove each release binary rebuilds bit for bit, and honor DESTDIR in install.sh (#1557) (@jmrplens)
- d6a58ea: ci(release): publish to PyPI with steps of our own, from a hash-pinned lock, under the trusted publisher (#1551) (@jmrplens)
- 3da05d1: ci: adopt the Developer Certificate of Origin (#1562) (@jmrplens)
- 2512c41: ci: fuzz weekly, measure the tree's branch and condition coverage, and date the linter count (#1558) (@jmrplens)
- 3f25d21: test(e2e): commit the suite's pipeline configurations with the skip marker, and gate it (#1462) (@jmrplens)
- 0506a76: test(e2e): keep one surface's description edit from resolving the next surface's to-do (#1464) (@jmrplens)
- e920d95: test(e2e): run the throttle probe last on the complete CE run's stack, and fix a branch-commit flake (#1646) (@jmrplens)
- a691865: test(e2e): wait for the scheduled storage move to end before cleanup (#1465) (@jmrplens)
- 8f339f4: test(orbit): move the fixtures into the jmrp-oss open source group and re-record the Orbit routes (#1532) (@jmrplens)
- 6049193: test(orbit): use the renamed fixture group and re-record the Orbit routes before GA (#1529) (@jmrplens)
- 276918c: test(server): give the parked listing a registration's bound under the race detector (#1649) (@jmrplens)
Full changelog: v3.3.0...v3.4.0
Verify the assets
All binaries are listed in checksums.txt, signed keylessly with cosign:
cosign verify-blob \
--bundle checksums.txt.sigstore.json \
--certificate-identity "https://github.com/jmrplens/gitlab-mcp-server/.github/workflows/release.yml@refs/tags/v3.4.0" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
checksums.txt
sha256sum --check --ignore-missing checksums.txt