Skip to content

Add team assignment checks to APIs that do label association#37246

Merged
lucasmrod merged 11 commits intomainfrom
37104-add-assignment-labels-check
Dec 15, 2025
Merged

Add team assignment checks to APIs that do label association#37246
lucasmrod merged 11 commits intomainfrom
37104-add-assignment-labels-check

Conversation

@lucasmrod
Copy link
Copy Markdown
Member

@lucasmrod lucasmrod commented Dec 14, 2025

Resolves #37104

Testing

Summary by CodeRabbit

  • New Features

    • Label validation now enforces team-context constraints for policies, queries, and MDM profiles.
    • Global policies now verify label validity before creation.
  • Bug Fixes

    • Improved label association verification in team-specific configurations.
  • Tests

    • Added comprehensive test coverage for team label associations, including label scoping validation and team deletion scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@lucasmrod lucasmrod requested a review from a team as a code owner December 14, 2025 22:59
Base automatically changed from 36781-team-labels-backend to main December 14, 2025 23:02
@lucasmrod
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 14, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 14, 2025

Walkthrough

This PR adds team-aware label validation to prevent mismatched label-entity associations. It introduces a teamID parameter to label validation functions, adds checks in policy/query creation and software management endpoints, and ensures labels belong to the correct team scope.

Changes

Cohort / File(s) Summary
Label validation infrastructure
server/service/labels_util.go, server/service/labels.go
Adds new helper functions loadLabelsFromNames and verifyLabelsToAssociate to enforce team/global label constraints. Updates BatchValidateLabels signature to include teamID parameter and calls verification logic.
Interface and mock updates
server/fleet/service.go, server/mock/service/service_mock.go
Updates BatchValidateLabels interface method signature in Service to include teamID *uint parameter; updates mock implementation and function type.
Policy validation
server/service/global_policies.go, server/service/team_policies.go
Adds verifyLabelsToAssociate pre-checks during policy creation and modification for both global and team policies.
Query validation
server/service/queries.go
Adds pre-creation and pre-modification checks calling verifyLabelsToAssociate with query team context.
Software and VPP management
ee/server/service/maintained_apps.go, ee/server/service/software_installers.go, ee/server/service/vpp.go
Updates call sites to pass teamID parameter to ValidateSoftwareLabels; updates function signature to include team context.
MDM profile validation
server/service/mdm.go, server/service/apple_mdm.go, server/service/windows_mdm_profiles.go
Adds teamID parameter to profile label validation functions (batchValidateProfileLabels, validateProfileLabels); threads team context through validation.
Test mock enhancements
cmd/fleetctl/fleetctl/gitops_test.go, cmd/fleetctl/integrationtest/gitops/software_test.go, server/service/mdm_test.go, server/service/labels_test.go
Adds or enhances LabelsByNameFunc mock implementations to return label objects, complementing existing ID-based label resolution.
Software installer tests
server/service/software_installers_test.go
Updates test calls to ValidateSoftwareLabels to pass new teamID parameter.
Integration test
server/service/integration_mdm_test.go
Adds comprehensive TestTeamLabelsAssociationsCheck covering multi-team label associations, policy/query/profile label binding, and team deletion cleanup.
Test utilities
server/service/testing_client.go
Updates cleanup to also clear vpp_apps and in_house_apps tables during teardown.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Verification of call site consistency: Ensure all ValidateSoftwareLabels, BatchValidateLabels, and profile validation calls pass the new teamID parameter correctly across 23+ affected files.
  • Team scoping logic in verifyLabelsToAssociate: Verify that global vs. team-scoped label constraints are correctly enforced (nil/0 entityTeamID → global labels only; non-global → same-team or global labels).
  • Integration test comprehensiveness: Review TestTeamLabelsAssociationsCheck for correctness of multi-team scenarios, label associations, policy/query/profile interactions, and team deletion edge cases.

Possibly related PRs

Suggested reviewers

  • iansltx
  • JordanMontgomery

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is mostly incomplete, missing several required checklist items including changes file, validation checks, backward compatibility verification, and database migration confirmations. Complete the PR description by addressing all unchecked items or explicitly confirming they are not applicable, particularly regarding changes files and database migrations.
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main objective of the PR: adding team assignment checks to APIs that perform label association.
Linked Issues check ✅ Passed The PR implements team assignment checks across multiple APIs (policies, queries, software installers, VPP apps, profiles) to ensure labels belong to the same team as the entity being configured, directly fulfilling issue #37104 requirements.
Out of Scope Changes check ✅ Passed The PR includes a comprehensive test (TestTeamLabelsAssociationsCheck) verifying label association logic across teams, plus updates to mock implementations and utility functions. All changes directly support the core objective of adding team assignment checks.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 37104-add-assignment-labels-check

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/service/testing_client.go (1)

143-161: Teardown cleanup scope/comment mismatch: unscoped DELETEs for in_house_apps/vpp_apps.

If the intent is to clean only “No team”, mirror the global_or_team_id = 0 pattern (if those tables have it). If the intent is “wipe all”, please update the comment to avoid misleading future changes.

-	// Clean software installers in "No team" (the others are deleted in ts.ds.DeleteTeam above).
+	// Clean "No team" software installers; also cleanup app tables for test isolation.
🧹 Nitpick comments (8)
server/fleet/service.go (1)

278-285: Clarify teamID semantics (nil vs 0) in the interface docstring.
verifyLabelsToAssociate treats both nil (global) and 0 (“no team”) as “labels must be global”, but that nuance isn’t obvious from “belong to the given teamID.” Consider documenting the nil/0 behavior explicitly.

server/service/labels_util.go (1)

24-72: Team/global/no-team association rules are enforced as intended; add targeted mismatch tests.
The entityTeamID == nil || *entityTeamID == 0 branch + “same-team or global” rule for team entities matches the stated constraints; I’d add a small set of unit tests covering the negative paths to lock behavior.

server/service/labels.go (1)

683-720: Good: BatchValidateLabels now enforces team-aware association after existence validation.
Authz precondition is preserved, and the new verifyLabelsToAssociate step aligns with the PR goal. (Optional micro-optimization: pass uniqueNames instead of labelNames, since verifyLabelsToAssociate dedupes anyway.)

server/service/labels_test.go (1)

378-387: Tests are correctly updated to account for team-aware validation (new LabelsByNameFunc mock).
Consider extending TestBatchValidateLabels with cases where teamID is non-nil and a label has a different TeamID, and where teamID is nil/0 and a label has a non-nil TeamID (expect error).

Also applies to: 416-430, 482-483

server/service/integration_mdm_test.go (3)

19264-19269: Minor inconsistency: globalLabel omits explicit type fields.

For consistency with the other label creations in this test (and hunk 1), consider adding the explicit LabelType and LabelMembershipType fields. While it works correctly due to Go's zero-value defaults matching the iota definitions, explicit fields improve readability.

 	globalLabel, err := s.ds.NewLabel(t.Context(), &fleet.Label{
-		Name:   "global",
-		Query:  "SELECT global;",
-		TeamID: nil,
+		Name:                "global",
+		Query:               "SELECT global;",
+		TeamID:              nil,
+		LabelType:           fleet.LabelTypeRegular,
+		LabelMembershipType: fleet.LabelMembershipTypeDynamic,
 	})

19408-19450: Fix comment numbering inconsistencies in "No team" policy section.

The comments in this section use incorrect subsection numbers:

  • Line 19408: "1.B.2" should be "1.C.2"
  • Line 19422: "1.B.3" should be "1.C.3"
  • Line 19437: "1.B.3" should be "1.C.4" and "team policy" should be "No team policy"
-		// 1.B.2 Attempt to create a "No team" policy with a global label (should succeed).
+		// 1.C.2 Attempt to create a "No team" policy with a global label (should succeed).
 		tpResp = teamPolicyResponse{}
 		s.DoJSON("POST", "/api/latest/fleet/teams/0/policies", teamPolicyRequest{
-		// 1.B.3 Attempt to edit a "No team" policy with a team policy that references l2t2 (should fail).
+		// 1.C.3 Attempt to edit a "No team" policy with labels that reference l2t2 (should fail).
 		mtplr = modifyTeamPolicyResponse{}
-		// 1.B.3 Attempt to edit a team policy with a team policy that references a global label (should succeed).
+		// 1.C.4 Attempt to edit a "No team" policy with a global label (should succeed).
 		mtplr = modifyTeamPolicyResponse{}

19510-19526: Fix misleading variable name and comment numbering.

  1. Variable team1LabelID stores a query ID, not a label ID - rename to team1QueryID for clarity.
  2. Comments on lines 19512 and 19520 use "2.A.x" numbering but should use "2.B.x" since they're in the team query subsection.
 		s.DoJSON("POST", "/api/latest/fleet/queries", reqQuery, http.StatusOK, &createQueryResp)
-		team1LabelID := createQueryResp.Query.ID
+		team1QueryID := createQueryResp.Query.ID

-		// 2.A.3 Attempt to edit a team query with a label of another team (should fail).
+		// 2.B.3 Attempt to edit a team query with a label of another team (should fail).
 		modifyQueryResp = modifyQueryResponse{}
-		s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", team1LabelID), modifyQueryRequest{
+		s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", team1QueryID), modifyQueryRequest{
 			QueryPayload: fleet.QueryPayload{
 				LabelsIncludeAny: []string{l2t2.Name, globalLabel.Name},
 			},
 		}, http.StatusBadRequest, &modifyQueryResp)

-		// 2.A.4 Attempt to edit team query with a label of the same team (should succeed).
+		// 2.B.4 Attempt to edit team query with a label of the same team (should succeed).
 		modifyQueryResp = modifyQueryResponse{}
-		s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", team1LabelID), modifyQueryRequest{
+		s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/queries/%d", team1QueryID), modifyQueryRequest{
server/service/software_installers_test.go (1)

213-342: Consider adding test coverage for team-specific label validation.

The tests correctly pass nil for the new teamID parameter, covering the global/no-team scenario. However, given that the PR objective is to add "team assignment checks" to enforce team consistency and prevent cross-team label assignment, consider adding tests that verify:

  1. Labels from a specific team can be successfully validated when the correct teamID is provided
  2. Labels from team A are rejected when attempting to associate with an entity in team B
  3. Global labels (teamID=nil) behavior when used with team entities
  4. Appropriate error messages are returned for team mismatches

This would ensure the security feature works as intended and provide regression protection.

Generate a test case example:

t.Run("reject labels from different team", func(t *testing.T) {
	teamID := uint(1)
	teamLabels := map[string]uint{
		"team1-label": 10,
	}
	
	ds.LabelIDsByNameFunc = func(ctx context.Context, names []string) (map[string]uint, error) {
		// Return the labels but they should be rejected due to team mismatch
		return teamLabels, nil
	}
	
	// Attempt to validate team 1 labels for team 2 entity
	differentTeamID := uint(2)
	_, err := eeservice.ValidateSoftwareLabels(ctx, svc, &differentTeamID, []string{"team1-label"}, nil)
	require.Error(t, err)
	require.Contains(t, err.Error(), "team") // or whatever the expected error message is
})
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78b926d and 3b1971f.

📒 Files selected for processing (20)
  • cmd/fleetctl/fleetctl/gitops_test.go (1 hunks)
  • cmd/fleetctl/integrationtest/gitops/software_test.go (2 hunks)
  • ee/server/service/maintained_apps.go (1 hunks)
  • ee/server/service/software_installers.go (5 hunks)
  • ee/server/service/vpp.go (3 hunks)
  • server/fleet/service.go (1 hunks)
  • server/mock/service/service_mock.go (2 hunks)
  • server/service/apple_mdm.go (1 hunks)
  • server/service/global_policies.go (1 hunks)
  • server/service/integration_mdm_test.go (2 hunks)
  • server/service/labels.go (2 hunks)
  • server/service/labels_test.go (3 hunks)
  • server/service/labels_util.go (1 hunks)
  • server/service/mdm.go (6 hunks)
  • server/service/mdm_test.go (1 hunks)
  • server/service/queries.go (2 hunks)
  • server/service/software_installers_test.go (2 hunks)
  • server/service/team_policies.go (2 hunks)
  • server/service/testing_client.go (1 hunks)
  • server/service/windows_mdm_profiles.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

⚙️ CodeRabbit configuration file

When reviewing SQL queries that are added or modified, ensure that appropriate filtering criteria are applied—especially when a query is intended to return data for a specific entity (e.g., a single host). Check for missing WHERE clauses or incorrect filtering that could lead to incorrect or non-deterministic results (e.g., returning the first row instead of the correct one). Flag any queries that may return unintended results due to lack of precise scoping.

Files:

  • server/service/testing_client.go
  • server/service/integration_mdm_test.go
  • server/service/windows_mdm_profiles.go
  • server/service/labels_util.go
  • server/service/team_policies.go
  • server/service/queries.go
  • ee/server/service/maintained_apps.go
  • ee/server/service/software_installers.go
  • server/mock/service/service_mock.go
  • server/service/global_policies.go
  • server/fleet/service.go
  • ee/server/service/vpp.go
  • cmd/fleetctl/integrationtest/gitops/software_test.go
  • server/service/apple_mdm.go
  • server/service/labels_test.go
  • server/service/software_installers_test.go
  • server/service/labels.go
  • server/service/mdm.go
  • server/service/mdm_test.go
  • cmd/fleetctl/fleetctl/gitops_test.go
🧠 Learnings (6)
📚 Learning: 2025-08-13T18:20:42.136Z
Learnt from: titanous
Repo: fleetdm/fleet PR: 31075
File: tools/redis-tests/elasticache/iam_auth.go:4-10
Timestamp: 2025-08-13T18:20:42.136Z
Learning: For test harnesses and CLI tools in the Fleet codebase, resource cleanup on error paths (like closing connections before log.Fatalf) may not be necessary since the OS handles cleanup when the process exits. These tools prioritize simplicity over defensive programming patterns used in production code.

Applied to files:

  • server/service/testing_client.go
📚 Learning: 2025-10-03T18:16:11.482Z
Learnt from: MagnusHJensen
Repo: fleetdm/fleet PR: 33805
File: server/service/integration_mdm_test.go:1248-1251
Timestamp: 2025-10-03T18:16:11.482Z
Learning: In server/service/integration_mdm_test.go, the helper createAppleMobileHostThenEnrollMDM(platform string) is exclusively for iOS/iPadOS hosts (mobile). Do not flag macOS model/behavior issues based on changes within this helper; macOS provisioning uses different helpers such as createHostThenEnrollMDM.

Applied to files:

  • server/service/integration_mdm_test.go
  • server/service/apple_mdm.go
📚 Learning: 2025-08-08T07:40:05.301Z
Learnt from: getvictor
Repo: fleetdm/fleet PR: 31726
File: server/datastore/mysql/labels_test.go:2031-2031
Timestamp: 2025-08-08T07:40:05.301Z
Learning: In fleetdm/fleet repository tests (server/datastore/mysql/labels_test.go and similar), using testing.T.Context() is valid because the project targets a recent Go version where testing.T.Context() exists. Do not suggest replacing t.Context() with context.Background() in this codebase.

Applied to files:

  • server/service/integration_mdm_test.go
  • server/service/labels_test.go
  • server/service/software_installers_test.go
  • cmd/fleetctl/fleetctl/gitops_test.go
📚 Learning: 2025-08-08T08:32:31.529Z
Learnt from: getvictor
Repo: fleetdm/fleet PR: 31695
File: server/datastore/mysql/apple_mdm_test.go:132-132
Timestamp: 2025-08-08T08:32:31.529Z
Learning: Datastore.NewMDMWindowsConfigProfile signature is: NewMDMWindowsConfigProfile(ctx context.Context, cp fleet.MDMWindowsConfigProfile, usesFleetVars []string) (*fleet.MDMWindowsConfigProfile, error). Passing nil for usesFleetVars in tests denotes “no Fleet variables referenced” and is used consistently across the repo.

Applied to files:

  • server/service/windows_mdm_profiles.go
  • server/service/apple_mdm.go
  • server/service/mdm.go
📚 Learning: 2025-08-08T07:40:05.301Z
Learnt from: getvictor
Repo: fleetdm/fleet PR: 31726
File: server/datastore/mysql/labels_test.go:2031-2031
Timestamp: 2025-08-08T07:40:05.301Z
Learning: In fleetdm/fleet, tests may validly use testing.T.Context() when the module/toolchain targets Go 1.24+. Do not flag t.Context() usage in this codebase if go.mod/toolchain indicates Go >= 1.24.

Applied to files:

  • server/service/labels_test.go
📚 Learning: 2025-08-08T07:40:05.301Z
Learnt from: getvictor
Repo: fleetdm/fleet PR: 31726
File: server/datastore/mysql/labels_test.go:2031-2031
Timestamp: 2025-08-08T07:40:05.301Z
Learning: Fleet repo targets Go 1.24.5 (root go.mod), which supports testing.T.Context(). Do not flag usage of t.Context() or suggest replacing it with context.Background() in tests (e.g., server/datastore/mysql/labels_test.go Line 2031 and similar).

Applied to files:

  • server/service/labels_test.go
  • cmd/fleetctl/fleetctl/gitops_test.go
🧬 Code graph analysis (16)
server/service/integration_mdm_test.go (2)
server/fleet/labels.go (2)
  • LabelTypeRegular (65-65)
  • LabelMembershipTypeDynamic (100-100)
server/fleet/software_installer.go (1)
  • UploadSoftwareInstallerPayload (489-525)
server/service/labels_util.go (1)
server/contexts/ctxerr/ctxerr.go (1)
  • Wrap (199-202)
server/service/team_policies.go (2)
server/fleet/mdm.go (2)
  • LabelsIncludeAny (868-868)
  • LabelsExcludeAny (869-869)
server/contexts/ctxerr/ctxerr.go (1)
  • Wrap (199-202)
server/service/queries.go (2)
server/fleet/mdm.go (1)
  • LabelsIncludeAny (868-868)
server/contexts/ctxerr/ctxerr.go (1)
  • Wrap (199-202)
ee/server/service/maintained_apps.go (1)
ee/server/service/software_installers.go (1)
  • ValidateSoftwareLabels (196-230)
ee/server/service/software_installers.go (2)
server/fleet/service.go (1)
  • Service (75-1400)
server/fleet/labels.go (1)
  • LabelIdentsWithScope (302-305)
server/mock/service/service_mock.go (2)
server/fleet/labels.go (1)
  • LabelIdent (281-284)
server/fleet/service.go (1)
  • Service (75-1400)
server/service/global_policies.go (2)
server/fleet/mdm.go (2)
  • LabelsIncludeAny (868-868)
  • LabelsExcludeAny (869-869)
server/contexts/ctxerr/ctxerr.go (1)
  • Wrap (199-202)
server/fleet/service.go (1)
server/fleet/labels.go (1)
  • LabelIdent (281-284)
ee/server/service/vpp.go (2)
ee/server/service/software_installers.go (1)
  • ValidateSoftwareLabels (196-230)
server/fleet/mdm.go (2)
  • LabelsIncludeAny (868-868)
  • LabelsExcludeAny (869-869)
cmd/fleetctl/integrationtest/gitops/software_test.go (1)
server/mock/datastore_mock.go (1)
  • LabelsByNameFunc (180-180)
server/service/labels_test.go (2)
server/contexts/authz/authz.go (1)
  • AuthorizationContext (62-68)
server/mock/datastore_mock.go (1)
  • LabelsByNameFunc (180-180)
server/service/software_installers_test.go (2)
ee/server/service/software_installers.go (1)
  • ValidateSoftwareLabels (196-230)
server/contexts/authz/authz.go (1)
  • AuthorizationContext (62-68)
server/service/labels.go (3)
server/fleet/service.go (1)
  • Service (75-1400)
server/fleet/labels.go (1)
  • LabelIdent (281-284)
server/contexts/ctxerr/ctxerr.go (1)
  • Wrap (199-202)
server/service/mdm_test.go (1)
server/mock/datastore_mock.go (1)
  • LabelsByNameFunc (180-180)
cmd/fleetctl/fleetctl/gitops_test.go (2)
server/mock/datastore_mock.go (1)
  • LabelsByNameFunc (180-180)
pkg/spec/gitops.go (1)
  • Label (159-162)
🔇 Additional comments (21)
cmd/fleetctl/fleetctl/gitops_test.go (1)

2678-2691: LGTM! Mock implementation correctly provides label objects for testing.

The LabelsByNameFunc mock properly complements the existing LabelIDsByNameFunc by returning full fleet.Label objects. The implementation correctly handles the lookup logic and returns only labels that exist in the labelToIDs map, which is appropriate for test mocking.

cmd/fleetctl/integrationtest/gitops/software_test.go (2)

554-565: LGTM! Label mock correctly resolves label names to Label objects.

The LabelsByNameFunc mock implementation properly mirrors the existing LabelIDsByNameFunc pattern and returns full fleet.Label objects for the test cases. The logic correctly filters based on c.expectedLabels.


580-580: LGTM! Assertion correctly verifies label function invocation.

The assertion appropriately checks that LabelsByNameFunc was invoked when expected labels are present, aligning with the existing verification pattern for LabelIDsByNameFunc.

ee/server/service/vpp.go (1)

149-149: LGTM! VPP label validation now correctly includes team scope.

The updated calls to ValidateSoftwareLabels properly pass the teamID parameter, enabling team-aware label validation for VPP apps. This correctly enforces the team consistency checks described in the PR objectives for app store apps across batch association, adding, and updating operations.

Also applies to: 484-484, 764-764

server/mock/service/service_mock.go (2)

165-166: Signature update matches interface; good passthrough shape.


2654-2659: BatchValidateLabels correctly forwards teamID to the mock func.

server/service/windows_mdm_profiles.go (1)

64-67: Correctly threads team context into label validation.

server/service/mdm_test.go (1)

2363-2375: LGTM! Clean test mock implementation.

The LabelsByNameFunc mock correctly maps label names to full Label objects, supporting test scenarios that need label resolution. The "baddy" exclusion enables negative test cases.

ee/server/service/maintained_apps.go (1)

43-43: LGTM! Correct team context for label validation.

The updated call to ValidateSoftwareLabels now includes teamID, ensuring labels are validated against the appropriate team scope before creating the maintained app installer.

server/service/queries.go (2)

284-286: LGTM! Appropriate label validation in query creation.

The validation correctly uses p.TeamID (from the payload) and checks labels before creating the query entity. This ensures labels exist and match the team scope.


424-427: LGTM! Correct use of existing query's team context.

The comment clarifies why query.TeamID (not payload) is used—teams cannot be changed during modification. This ensures label validation uses the correct team scope.

server/service/team_policies.go (2)

94-96: LGTM! Comprehensive label validation for policy creation.

The validation correctly combines both LabelsIncludeAny and LabelsExcludeAny to verify all labels belong to the appropriate team scope before creating the policy.


573-575: LGTM! Comprehensive label validation for policy modification.

The validation ensures all labels (both include and exclude) are verified against the policy's team context before applying modifications.

server/service/apple_mdm.go (1)

439-452: No issues found with the label validation logic for no-team profiles. The code correctly passes &teamID to validateProfileLabels, and the underlying verifyLabelsToAssociate function explicitly handles both nil and *uint(0) identically, treating both as entities that must use only global labels. This pattern is already used elsewhere in the method (line 430) and is validated by integration tests covering no-team profiles with labels.

server/service/labels_util.go (1)

10-22: loadLabelsFromNames correctness looks good (explicit not-found validation).
The post-check ensures partial results from LabelsByName can’t silently pass.

ee/server/service/software_installers.go (2)

54-60: Good: software label validation is now team-aware by construction (threads teamID into BatchValidateLabels).
This matches the “assignment checks” objective and keeps the enforcement centralized in label validation.

Also applies to: 196-230


713-716: All call sites for ValidateSoftwareLabels and BatchValidateLabels are properly updated. Verification confirms all 9 call sites of ValidateSoftwareLabels use the correct 5-parameter signature (ctx, svc, teamID, labelsIncludeAny, labelsExcludeAny), and the single production call site of BatchValidateLabels uses the correct 3-parameter signature (ctx, teamID, labelNames). No stale call sites remain.

server/service/integration_mdm_test.go (2)

19079-19104: LGTM!

The label creation setup is consistent, with explicit LabelType and LabelMembershipType fields for all three labels (team-scoped and global).


19529-19765: LGTM!

The remaining test sections (configuration profiles, software installers, VPP apps, in-house apps) comprehensively cover both positive and negative test cases for team-aware label validation. The final cleanup verifying team deletion succeeds is a good safeguard to ensure no foreign key issues arise from the test data.

server/service/mdm.go (2)

1968-2021: LGTM: Team context properly propagated through batch operations.

The signature update to BatchSetMDMProfiles correctly introduces tmID *uint and tmName *string parameters, and the team ID is properly passed through to batchValidateProfileLabels at line 2016. This ensures labels are validated against the correct team scope before profiles are batch-set.

The changes align with the PR objective to enforce team consistency in label associations.


1817-1856: The team-scoped label validation in verifyLabelsToAssociate is correctly implemented. The function properly enforces team consistency: it rejects team labels for "no team" entities, allows global labels for any entity, and prevents team entities from referencing labels that belong to other teams. Both LabelIDsByName and LabelsByName use safe SQL parameter binding with proper WHERE clauses. The acknowledged double-loading of labels is an acceptable trade-off for maintaining API error strings, as noted in the code comment.

Comment thread server/service/global_policies.go
@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 14, 2025

Codecov Report

❌ Patch coverage is 85.50725% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.96%. Comparing base (78b926d) to head (713f0bb).
⚠️ Report is 17 commits behind head on main.

Files with missing lines Patch % Lines
server/service/labels_util.go 81.25% 3 Missing and 3 partials ⚠️
server/service/testing_client.go 33.33% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #37246      +/-   ##
==========================================
+ Coverage   65.95%   65.96%   +0.01%     
==========================================
  Files        2331     2332       +1     
  Lines      185505   185556      +51     
  Branches     7809     7809              
==========================================
+ Hits       122346   122405      +59     
+ Misses      51971    51963       -8     
  Partials    11188    11188              
Flag Coverage Δ
backend 67.77% <85.50%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@iansltx iansltx left a comment

Choose a reason for hiding this comment

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

Bunch of very minor stuff, plus a few questions. Code changes look reasonabe given circumstances; all Q's are around tests/test plan.

Comment thread server/service/testing_client.go
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go Outdated
Comment thread server/service/integration_mdm_test.go
Co-authored-by: Ian Littman <iansltx@gmail.com>
@lucasmrod lucasmrod merged commit 554f268 into main Dec 15, 2025
50 checks passed
@lucasmrod lucasmrod deleted the 37104-add-assignment-labels-check branch December 15, 2025 17:11
@coderabbitai coderabbitai Bot mentioned this pull request Jan 6, 2026
2 tasks
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.

Add "assignment checks" to API endpoints that set labels on entities

2 participants