Skip to content
This repository was archived by the owner on May 25, 2026. It is now read-only.

feat(schemas): schema-driven slim fields on get_merge_request (DOT-557) - #109

Merged
ichoosetoaccept merged 1 commit into
detailobsessedfrom
port/dot-557-slim-fields-mr
May 15, 2026
Merged

feat(schemas): schema-driven slim fields on get_merge_request (DOT-557)#109
ichoosetoaccept merged 1 commit into
detailobsessedfrom
port/dot-557-slim-fields-mr

Conversation

@ichoosetoaccept

@ichoosetoaccept ichoosetoaccept commented May 15, 2026

Copy link
Copy Markdown
Member

Phase 2 of the response-schema initiative (DOT-555). Wires field
projection into get_merge_request and migrates list_merge_requests onto
a schema-derived single source of truth for slim defaults.

Mechanism — reuses the existing fields/fieldsParam pattern (already on
every list endpoint and documented in README's "Field Projection"
section) rather than introducing a parallel verbose: boolean flag.
Schemas from Phase 1 become the source of truth for which fields are
slim defaults, via .pick().

Changes:

  • src/schemas/merge-requests.ts: add MergeRequestSlimShape (the source
    of truth), GitLabMergeRequestSlimSchema (the .pick() view), and
    MERGE_REQUEST_SLIM_FIELDS (the field-name allow-list consumed by
    projectField / projectFields).
  • src/utils/projection.ts: add projectField (singular) wrapper.
  • src/tools/merge-requests.ts: drop the hand-maintained
    LIST_MERGE_REQUESTS_DEFAULT_FIELDS; add fields: fieldsParam("merge
    request") to get_merge_request's input; apply projectField on both
    the iid and branch_name handler paths; migrate list_merge_requests
    to consume MERGE_REQUEST_SLIM_FIELDS.
  • src/schemas/parse.ts: update Phase-2 stub comment to reflect the
    chosen fields-pattern direction.
  • README.md: extend the "Field Projection" section to include singular
    endpoints with a concrete get_merge_request example.
  • Tests: slim-schema parse, projectField allow-list, token-budget
    regression, and handler tests for default / fields:"all" / custom
    pick / branch_name path.

Out of scope (Phase 3 / DOT-558): replicate the same pattern across
the other Phase-1 endpoints (issues, commits, pipelines, projects,
repositories, users).

Note

Add schema-driven slim field projection to get_merge_request

  • Adds MergeRequestSlimShape, GitLabMergeRequestSlimSchema, and MERGE_REQUEST_SLIM_FIELDS to src/schemas/merge-requests.ts as a single source of truth for the default field set (17 fields: id, iid, title, state, draft, labels, branches, author, assignees, reviewers, milestone, web_url, timestamps, merge status).
  • Extends get_merge_request with an optional fields parameter (via existing fieldsParam() pattern) and applies projectField projection on both the iid and branch_name lookup paths, replacing the previous full-payload return.
  • Adds a projectField helper to src/utils/projection.ts for single-resource projection, mirroring the existing projectFields list utility.
  • Migrates list_merge_requests off the hand-maintained LIST_MERGE_REQUESTS_DEFAULT_FIELDS constant to the schema-derived MERGE_REQUEST_SLIM_FIELDS.
  • Behavioral Change: get_merge_request now returns a slim subset of fields by default; callers must pass fields: "all" to get the full payload. list_merge_requests default fields may also differ if the old constant diverged from the new schema-derived list.

🖇️ Linked Issues

Completes DOT-557, the Phase 2 sub-task of the DOT-555 Zod response schema initiative. This establishes the pattern for Phase 3 (DOT-558), which will extend schema-driven slimming to the remaining endpoints.

Macroscope summarized aa57fea.

Phase 2 of the response-schema initiative (DOT-555). Wires field
projection into get_merge_request and migrates list_merge_requests onto
a schema-derived single source of truth for slim defaults.

Mechanism — reuses the existing fields/fieldsParam pattern (already on
every list endpoint and documented in README's "Field Projection"
section) rather than introducing a parallel `verbose: boolean` flag.
Schemas from Phase 1 become the source of truth for which fields are
slim defaults, via `.pick()`.

Changes:
- src/schemas/merge-requests.ts: add MergeRequestSlimShape (the source
  of truth), GitLabMergeRequestSlimSchema (the .pick() view), and
  MERGE_REQUEST_SLIM_FIELDS (the field-name allow-list consumed by
  projectField / projectFields).
- src/utils/projection.ts: add projectField (singular) wrapper.
- src/tools/merge-requests.ts: drop the hand-maintained
  LIST_MERGE_REQUESTS_DEFAULT_FIELDS; add fields: fieldsParam("merge
  request") to get_merge_request's input; apply projectField on both
  the iid and branch_name handler paths; migrate list_merge_requests
  to consume MERGE_REQUEST_SLIM_FIELDS.
- src/schemas/parse.ts: update Phase-2 stub comment to reflect the
  chosen fields-pattern direction.
- README.md: extend the "Field Projection" section to include singular
  endpoints with a concrete get_merge_request example.
- Tests: slim-schema parse, projectField allow-list, token-budget
  regression, and handler tests for default / fields:"all" / custom
  pick / branch_name path.

Out of scope (Phase 3 / DOT-558): replicate the same pattern across
the other Phase-1 endpoints (issues, commits, pipelines, projects,
repositories, users).
@ichoosetoaccept

Copy link
Copy Markdown
Member Author

This change is part of the following stack:

Change managed by git-spice.

@linear-code

linear-code Bot commented May 15, 2026

Copy link
Copy Markdown

DOT-557

@macroscopeapp

macroscopeapp Bot commented May 15, 2026

Copy link
Copy Markdown

Approvability

Verdict: Approved

Extends existing field projection pattern to get_merge_request endpoint. Changes are mechanical - moving field definitions to schemas and applying the same slimming logic already used by list_merge_requests. Backwards-compatible with fields: 'all' opt-out, well-tested.

You can customize Macroscope's approvability policy. Learn more.

@ichoosetoaccept
ichoosetoaccept merged commit 585e7d9 into detailobsessed May 15, 2026
4 checks passed
@ichoosetoaccept
ichoosetoaccept deleted the port/dot-557-slim-fields-mr branch May 15, 2026 13:13
github-actions Bot pushed a commit that referenced this pull request May 15, 2026
# [2.30.0](v2.29.0...v2.30.0) (2026-05-15)

### Features

* **schemas:** schema-driven slim fields on get_merge_request (DOT-557) ([#109](#109)) ([585e7d9](585e7d9))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.30.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

ichoosetoaccept added a commit that referenced this pull request May 15, 2026
* feat(schemas): schema-driven slim fields on commits (DOT-558)

Phase 3 of the response-schema initiative (DOT-555), replicating the
merge-request pattern (PR #109) on the commits domain.

- src/schemas/commits.ts: export CommitSlimShape (source of truth),
  GitLabCommitSlimSchema (.pick view), COMMIT_SLIM_FIELDS (allow-list).
- src/tools/commits.ts: drop hand-maintained LIST_COMMITS_DEFAULT_FIELDS;
  list_commits now consumes COMMIT_SLIM_FIELDS; get_commit gains a fields
  param + parseGitLabResponse + projectField call. get_commit_diff is
  out of scope (diff shape, not a resource).
- Tests: slim-schema parse, projectField allow-list, token-budget
  regression, and handler tests for get_commit default / fields:'all' /
  custom pick.

* feat(schemas): schema-driven slim fields on issues (DOT-558)

Same recipe as the commits commit on this branch.

- src/schemas/issues.ts: export IssueSlimShape, GitLabIssueSlimSchema,
  ISSUE_SLIM_FIELDS.
- src/tools/issues.ts: drop LIST_ISSUES_DEFAULT_FIELDS; list_issues and
  my_issues now consume ISSUE_SLIM_FIELDS; get_issue gains a fields
  param + projectField call (it already parsed via GitLabIssueSchema).
- Tests: slim-schema parse + token-budget regression + handler tests
  for get_issue.

* feat(schemas): schema-driven slim fields on pipelines (DOT-558)

Same recipe as the prior commits.

- src/schemas/pipelines.ts: export PipelineSlimShape,
  GitLabPipelineSlimSchema, PIPELINE_SLIM_FIELDS.
- src/tools/pipelines.ts: drop LIST_PIPELINES_DEFAULT_FIELDS;
  list_pipelines now consumes PIPELINE_SLIM_FIELDS; get_pipeline gains
  a fields param + parseGitLabResponse + projectField call (Phase 1
  hadn't wrapped its response in parseGitLabResponse either, so this
  brings it in line with the get_issue / get_merge_request pattern).
- Tests: slim-schema parse + token-budget regression + handler tests
  for get_pipeline.

* feat(schemas): schema-driven slim fields on projects (DOT-558)

Same recipe as the prior commits, with one extra wrinkle: get_project
has an existing include_secrets flag that gates runners_token. The
slim default never includes runners_token; redaction still runs before
projection; include_secrets: true implies fields: 'all' (the existing
list-endpoint behavior) so callers actually see the token they asked
for unless they pass an explicit fields override.

- src/schemas/projects.ts: export ProjectSlimShape (no runners_token —
  privacy guardrail asserted in tests), GitLabProjectSlimSchema,
  PROJECT_SLIM_FIELDS.
- src/tools/projects.ts: drop LIST_PROJECTS_DEFAULT_FIELDS;
  list_projects + list_group_projects + get_project all consume
  PROJECT_SLIM_FIELDS. get_project now also parses via
  GitLabProjectSchema before redact-then-project.
- Tests: slim-schema parse, projectField allow-list with privacy
  guardrail (PROJECT_SLIM_FIELDS does NOT contain runners_token),
  token-budget regression, and handler tests for get_project covering
  default / fields:'all' / include_secrets:true / custom pick (the
  include_secrets test verifies the secret is actually visible).

* docs(readme): list new singular get_* endpoints under Field Projection (DOT-558)

Extends the Field Projection section's currently-applied list to
include get_project, get_issue, get_pipeline, get_commit alongside
get_merge_request (added in Phase 2).
github-actions Bot pushed a commit that referenced this pull request May 15, 2026
# [2.31.0](v2.30.0...v2.31.0) (2026-05-15)

### Features

* **schemas:** schema-driven slim fields on commits (DOT-558) ([#110](#110)) ([c912b64](c912b64)), closes [#109](#109)
ichoosetoaccept added a commit that referenced this pull request May 15, 2026
…#111)

Sibling of DOT-558 (Phase 3a). Extends the schema-driven slim-fields
pattern (canonical: PR #109, PR #110) to the users domain — the one
piece Phase 3a deferred because the slim shape needed a privacy-aware
design pass.

Slim shape: identity-only — id, username, name, state, avatar_url,
web_url, bot. Seven fields. Always safe to expose for any user.
Privacy-sensitive fields (email, last_sign_in_at, is_admin,
two_factor_enabled, confirmed_at, current_sign_in_at, private_profile,
last_activity_on, theme_id, color_scheme_id, projects_limit, external)
are excluded by default; opt back in via fields:'all' or explicit pick.
A dedicated test pins the privacy guardrail so future expansions of
UserSlimShape can't accidentally leak those fields.

Phase-1 gaps closed along the way:
- src/schemas/users.ts: GitLabUserListSchema didn't exist; add it.
- src/tools/users.ts: get_users and search_users were never wrapped
  with parseGitLabResponse; wrap them now (a prerequisite for typed
  slim defaults to project from).

Wires four user-returning tools with fields + projection:
- get_current_user (already parse-wrapped, just adds fields+project)
- get_user (already parse-wrapped, just adds fields+project)
- get_users (newly parse-wrapped, per-username map slimmed element-wise)
- search_users (newly parse-wrapped, list slimmed)

Out of scope: list_events, get_project_events, upload_markdown,
download_attachment, health_check — they live in users.ts for
organizational convenience but don't return user-shaped data.

Tests:
- tests/schemas/users.test.ts: slim-schema parse, USER_SLIM_FIELDS
  allow-list invariant, projectField allow-list at runtime,
  **privacy guardrail** (USER_SLIM_FIELDS does NOT contain email /
  is_admin / two_factor_enabled / etc.), separate test that
  projectField actually drops those fields on a populated current-user
  fixture, GitLabUserListSchema parse, token-budget regression.
- tests/users.test.ts: default / fields:'all' / custom-pick handler
  tests for each of the four tools (12+ cases). get_current_user and
  get_user tests specifically verify privacy fields absent by default
  and present under fields:'all'. search_users test confirms `fields`
  is not forwarded to GitLab as a query string.

README "Field Projection" section extended to list the four user
endpoints.
github-actions Bot pushed a commit that referenced this pull request May 15, 2026
# [2.32.0](v2.31.0...v2.32.0) (2026-05-15)

### Features

* **schemas:** schema-driven slim fields on users (Phase 3b, DOT-560) ([#111](#111)) ([6ea1953](6ea1953)), closes [#109](#109) [#110](#110)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant