Engineering decisions: Security attributes

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

In the interest of better transparency, we will use this Issue to share engineering decisions that have been made, in the scope of the parent Epic: Security Attributes/Context Filtering (&18010) • Unassigned • 18.6

Finalized decisions should go in the below Decisions section, while topics that require discussion should go to a new thread below, and then the decision should be brought back here to the Description once it has been reached.

Engineering Decisions

  1. Feature Flags:
    1. security_context_labels controls whether the feature is visible at all [FF] `security_context_labels` -- Categorize pr... (#551226)
    2. custom_ability_admin_security_attributes controls whether the Edit security attributes custom ability is shown as an option for Custom roles
    3. security_categories_and_attributes
    4. bulk_edit_security_attributes (#577576)
    5. security_attribute_inventory_filters (!209690)

Product decisions

  1. GitLab Ultimate license is required to use the feature. See comment 🧵
  2. Who has permission to configure the available set of attributes for a group? We should create a new permission that can be assigned to users to give them CRUD capabilities for security attributes: (admin_security_attributes) we can include the permission in the default security role, so anyone with that role will have access by default. See comment 🧵
  3. Who has permission to apply attributes to a project? Seems like we don't need a new permission for this - any user who can view the project's security configuration can apply labels. See comment 🧵

GraphQL Proposal (still in discussion)

Here's a proposed schema:

Definitions

SecurityAttributeCategory

type SecurityAttributeCategory {
  id: ID!
  name: String!
  description: String
  multipleSelection: Boolean
  editableState: EditableStateEnum
  attributeCount: Int
  attributes: [SecurityAttribute!]
}
  • editableState can be an enum?
    • LOCKED :
    • PARTIALLY_EDITABLE :
    • EDITABLE:
    • ?

SecurityAttribute

type SecurityAttribute {
  id: ID!
  categoryId: ID!
  name: String!
  description: String
  color: String!
}
  • should we have it as name or label ? name

Queries

Group-level

getSecurityAttributes
query getSecurityAttributes($fullPath: ID!, $categoryId: ID) {
  group(fullPath: $fullPath) {
    securityAttributeCategories {
      nodes {
        id
        name
        description
        multipleSelection
        editableState
        attributeCount
      }
    }
    securityAttributes(categoryId: $categoryId) {
      nodes {
        id
        categoryId
        name
        description
        color
      }
    }
  }
}
  • is it beneficial to have two separate queries - securityAttributeCategories as well as securityAttributes ?

Project Level

List attributes applied to a project

project(fullPath: "gitlab-org/gitlab") {
  securityAttributes {
    nodes {
      id
      name
      description
      color
      category {
        id
        name
        multipleSelection
        ...
      }
    }
  }
}

Mutations

securityAttributeCategoryCreate

mutation securityAttributeCategoryCreate($input: SecurityAttributeCategoryCreateInput!) {
  securityAttributeCategoryCreate(input: $input) {
    id
    errors
    securityAttributeCategory {
      ...SecurityAttributeCategoryFragment
    }
  }
}

input SecurityAttributeCategoryCreateInput {
  groupPath: ID!                          # Full path of the top-level group
  name: String!                           # Category name (e.g., "Application Type")
  description: String                     # Optional category description
  multipleSelection: Boolean              # true for multi-select, false for single
  editableState: EditableStateEnum        # LOCKED, PARTIALLY_EDITABLE, EDITABLE
  attributes: [SecurityAttributeInput!]!  # Initial attributes to create
}

securityAttributeCategoryUpdate

mutation securityAttributeCategoryUpdate($input: SecurityAttributeCategoryUpdateInput!) {
  securityAttributeCategoryUpdate(input: $input) {
    id
    errors
    securityAttributeCategory {
      ...SecurityAttributeCategoryFragment
    }
  }
}

input SecurityAttributeCategoryUpdateInput {
  id: ID!                                 # Category ID to update
  name: String                            # Optional updates
  description: String
  multipleSelection: Boolean
  editableState: EditableStateEnum
  attributes: [SecurityAttributeInput!]!  # Modified list of attributes (can include existing or new)
}
  • should we include groupPath as well?

securityAttributeCategoryDelete

mutation securityAttributeCategoryDelete($input: SecurityAttributeCategoryDeleteInput!) {
  securityAttributeCategoryDelete(input: $input) {
    errors
  }
}

input SecurityAttributeCategoryDeleteInput {
  id: ID!                             # ID of the category to delete
  groupPath: ID!                      # For context/authorization
}
  • can groupPath be avoided?

securityAttributeDelete

mutation securityAttributeDelete($input: SecurityAttributeDeleteInput!) {
  securityAttributeDelete(input: $input) {
    errors
  }
}

input SecurityAttributeDeleteInput {
  id: ID!           # ID of the attribute to delete
  categoryId: ID!   # ID of the category the attribute belongs to (for context or validation)
  groupPath: ID!    # Full path of the group (for authorization context)
}

question:

  • can categoryId or groupPath be avoided?

Filters

  • To be evaluated
Edited by Miranda Fluharty