Skip to content

feat: add teams resource (dhq teams list|show|create|update|delete)#33

Merged
facundofarias merged 4 commits into
mainfrom
feat/api-coverage-teams
Jul 14, 2026
Merged

feat: add teams resource (dhq teams list|show|create|update|delete)#33
facundofarias merged 4 commits into
mainfrom
feat/api-coverage-teams

Conversation

@MartaKar

@MartaKar MartaKar commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Closes out the last piece of DHQ-639 (API coverage). Teams are the account-level permission groups exposed by the DeployHQ API (teams_controller's valid_api_actions) that the CLI didn't cover yet — distinct from folders (project_categories), which organise projects for display.

What this PR does

Adds a dhq teams command tree and the SDK methods behind it, following the established resource pattern (agents, global-servers, …):

  • dhq teams list — table of teams (name, identifier, admin, member count, all-projects), with --json, quiet mode, and breadcrumbs.
  • dhq teams show <id> — full detail, including nested members, project assignments, and project exclusions.
  • dhq teams create <name> — scalar permission flags (--admin, --can-manage-users, --can-manage-billing, --can-manage-agents, --can-create-projects, --all-projects) plus --user-ids to seed membership.
  • dhq teams update <id> — partial update of any of the above, plus --clear-members.
  • dhq teams delete <id>.

SDK types + CRUD live in pkg/sdk/teams.go; the command tree in internal/commands/teams.go. Registered in root.go, agent_metadata.go (agent-facing flags), and the assist allowlist.

Contract details worth a look

The DeployHQ API wraps request bodies under the resource key ({"team": {...}}) but returns bare responses, and updates go over PATCH — matching the users/account/profile convention, not folders' PUT. Verified against the live backend.

Partial updates don't clobber — including membership

Update flags are pointers gated on cmd.Flags().Changed(...), so an unset flag is omitted from the PATCH rather than sent as a zero value that would wipe an existing permission.

Membership needed the same care, and it's the one subtle bit here. There are three distinct intents:

  • omitted → leave membership untouched
  • --user-ids 5,6 → sync to those users
  • --clear-members → remove all members

A plain []int with omitempty collapses the last two — an explicit empty list serialises to nothing, so "remove everyone" would silently no-op. For a permission group, silently failing to revoke access is the wrong default. So TeamUpdateRequest.UserIDs is a *[]int: nil omits the key, non-nil-but-empty sends "user_ids": [].

--clear-members exists as its own flag because cobra's IntSliceVar can't express an empty list from the command line (--user-ids "" fails to parse as an int slice). It's update-only and mutually exclusive with --user-ids.

Note on --admin

When --admin is set the server force-enables every other permission flag and grants all-projects access, regardless of what else is sent. The flag help and the SDK doc comment call this out; JSON output reflects the server's effective state.

Test plan

  • go build ./cmd/dhq/
  • go test ./... — full suite green (Teams: 12 SDK + 12 command tests)
  • golangci-lint run ./... — 0 issues
  • SDK tests assert the wrapped-request / bare-response / PATCH contract, partial-update omission, and the empty-user_ids clear-membership path
  • Error paths covered: 422 (blank/duplicate name), 403, 404; --user-ids/--clear-members conflict
  • Live smoke test against a local backend: list → create (with flags) → show → update (rename + flag, partial-update verified) → --clear-members → delete → list (cleanup confirmed)

Out of scope

Write support for project_assignments and excluded_project_ids is deferred — both are surfaced read-side in dhq teams show. First cut is scalar permission flags + --user-ids/--clear-members membership, which covers the common case.

Summary by CodeRabbit

  • New Features
    • Added dhq teams account-level commands to list, show, create, update, and delete teams.
    • Supports team permissions, per-project access, member synchronization, and JSON output; delete operations now include an explicit confirmation requirement.
    • Added SDK support for programmatic team management (CRUD).
  • Documentation
    • Expanded the embedded command documentation with “Account Resources” details for the dhq teams command set.
  • Tests
    • Added CLI help/guardrail and agent-metadata tests, plus SDK request/response and error-handling coverage.

MartaKar added 2 commits July 13, 2026 10:54
Adds account-level permission groups: SDK types + CRUD methods and a
`dhq teams` command tree, following the established resource pattern
(request bodies wrapped under `team`, bare responses, PATCH for update).

Membership syncs via --user-ids on create/update; the update request
uses *[]int so an explicit empty list clears all members while omitting
the flag leaves membership untouched. Scalar update flags use pointers
so partial updates don't clobber unset permissions.
The SDK models an empty membership list as a non-nil *[]int so it reaches
the server as "user_ids":[], but that empty case was unreachable from the
CLI: cobra's IntSliceVar rejects --user-ids "" at parse time (strconv.Atoi
on the empty string fails). Add a dedicated --clear-members flag (update
only) to express "remove all members", mutually exclusive with --user-ids.

Found by live smoke-testing the command against a real backend; the SDK
unit test passed because it builds the request struct directly, bypassing
flag parsing.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fa768ebe-6535-4b41-8390-0b024c1b7045

📥 Commits

Reviewing files that changed from the base of the PR and between 967ab5b and 4b4783b.

📒 Files selected for processing (2)
  • internal/commands/teams.go
  • internal/commands/teams_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/commands/teams.go
  • internal/commands/teams_test.go

Walkthrough

Changes

Teams resource support

Layer / File(s) Summary
Team SDK contract and API
pkg/sdk/teams.go, pkg/sdk/teams_test.go
Adds team models, CRUD client methods, partial-update membership semantics, JSON payload handling, and HTTP/error tests.
Teams CLI commands and mutation semantics
internal/commands/teams.go
Adds list, show, create, update, and delete commands with table, quiet, and JSON output plus permission and membership flags.
CLI registration, metadata, and validation
internal/commands/root.go, internal/commands/agent_metadata.go, internal/assist/prompt.go, internal/commands/teams_test.go
Registers the command, documents it, assigns agent metadata, and tests help output, flag validation, wiring, and metadata.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TeamsCommand
  participant SDKClient
  participant TeamsAPI
  participant CLIOutput
  User->>TeamsCommand: Run a teams command
  TeamsCommand->>SDKClient: Invoke the matching team operation
  SDKClient->>TeamsAPI: Send the team API request
  TeamsAPI-->>SDKClient: Return team data or an error
  SDKClient-->>TeamsCommand: Return the decoded result
  TeamsCommand->>CLIOutput: Render JSON, table, quiet, or status output
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding the teams resource and its CLI subcommands.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/api-coverage-teams

Comment @coderabbitai help to get the list of available commands.

@MartaKar MartaKar self-assigned this Jul 13, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/commands/teams.go`:
- Around line 251-280: Validate an explicitly provided empty name in
newTeamsUpdateCmd before constructing or sending the update request, matching
the existing teams create validation behavior and returning the same user-facing
error. Keep omitted --name behavior unchanged so updates can leave the existing
team name intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16de2242-125c-45c5-bc12-af1663bba8a9

📥 Commits

Reviewing files that changed from the base of the PR and between 00822d6 and 967ab5b.

📒 Files selected for processing (7)
  • internal/assist/prompt.go
  • internal/commands/agent_metadata.go
  • internal/commands/root.go
  • internal/commands/teams.go
  • internal/commands/teams_test.go
  • pkg/sdk/teams.go
  • pkg/sdk/teams_test.go

Comment thread internal/commands/teams.go
Match `teams create`, which rejects a blank name before the API call.
Previously `teams update --name ""` passed the Changed() check and sent
"name":"" to the server, relying on a round-trip 422 rather than failing
fast. Addresses CodeRabbit feedback on PR #33.

@thdurante thdurante left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

# Conflicts:
#	internal/assist/prompt.go
#	internal/commands/agent_metadata.go
@facundofarias
facundofarias merged commit 4968051 into main Jul 14, 2026
2 checks passed
@facundofarias
facundofarias deleted the feat/api-coverage-teams branch July 14, 2026 08:36
facundofarias added a commit that referenced this pull request Jul 14, 2026
First CHANGELOG.md for the CLI. Documents the API-coverage expansion
(#31, #32, #33) and the breaking pkg/sdk changes in #32 under an
explicit "Breaking (SDK)" section.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants