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 users (Phase 3b, DOT-560)#111

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

feat(schemas): schema-driven slim fields on users (Phase 3b, DOT-560)#111
ichoosetoaccept merged 1 commit into
detailobsessedfrom
port/dot-560-slim-fields-users

Conversation

@ichoosetoaccept

@ichoosetoaccept ichoosetoaccept commented May 15, 2026

Copy link
Copy Markdown
Member

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.

Note

Add schema-driven slim field projection to all four user-returning tools

  • Adds UserSlimShape, GitLabUserSlimSchema, USER_SLIM_FIELDS, and GitLabUserListSchema to src/schemas/users.ts, exporting a privacy-aware 7-field identity shape (id, username, name, state, avatar_url, web_url, bot).
  • Wires fields: fieldsParam("user").optional() and projectField/projectFields into get_current_user, get_user, get_users, and search_users; all four now return the slim shape by default.
  • Wraps get_users and search_users with parseGitLabResponse(GitLabUserListSchema, ...) for the first time, closing a Phase-1 gap.
  • Privacy-sensitive fields (email, is_admin, two_factor_enabled, last_sign_in_at, etc.) are excluded from the default output and only returned when fields="all" or explicitly requested.
  • Behavioral Change: all four user tools now return a reduced field set by default; callers relying on full payloads must pass fields="all".

🖇️ Linked Issues

Completes DOT-560, which tracks Phase 3b of the response-schema initiative for the users domain. Part of the broader DOT-555 initiative to introduce Zod response schemas as a token-efficiency primitive.

Macroscope summarized f10b61c.

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.
@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-560

@macroscopeapp

macroscopeapp Bot commented May 15, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

This PR changes the default response shape of 4 user endpoints to return fewer fields (excluding privacy-sensitive data). While backwards-compatible via fields: 'all', this runtime behavior change affecting multiple endpoints warrants human verification that downstream consumers are prepared for the modified defaults.

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

@ichoosetoaccept ichoosetoaccept merged commit 6ea1953 into detailobsessed May 15, 2026
4 checks passed
@ichoosetoaccept ichoosetoaccept deleted the port/dot-560-slim-fields-users branch May 15, 2026 15:33
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)
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.32.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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