> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tai42.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Set/remove single tag grants on a role

> Set (upsert) and/or remove single tag grants on a role WITHOUT replacing the whole
map. Admin-only; guards the reserved ``admin`` role and the block-downgrade of any
allow_all role. ``set`` overwrites a tag's level (the one sanctioned overwrite); a
``remove`` tag absent from the stored map is a loud 404. Validates the merged map before
persist; LIVE via the policy-version bump. Audits as ``edit``.



## OpenAPI

````yaml /openapi.json post /api/auth/roles/{name}/grants
openapi: 3.1.0
info:
  description: The operator HTTP surface served under /api/*.
  title: tai42-skeleton API
  version: 14.0.2
servers: []
security: []
paths:
  /api/auth/roles/{name}/grants:
    post:
      tags:
        - access-control
      summary: Set/remove single tag grants on a role
      description: >-
        Set (upsert) and/or remove single tag grants on a role WITHOUT replacing
        the whole

        map. Admin-only; guards the reserved ``admin`` role and the
        block-downgrade of any

        allow_all role. ``set`` overwrites a tag's level (the one sanctioned
        overwrite); a

        ``remove`` tag absent from the stored map is a loud 404. Validates the
        merged map before

        persist; LIVE via the policy-version bump. Audits as ``edit``.
      operationId: post_api_auth_roles_name_grants
      parameters:
        - in: path
          name: name
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RoleGrantsModify'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    $ref: '#/components/schemas/RoleDefinition'
                required:
                  - data
                type: object
          description: Success.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Malformed request.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing or invalid api key.
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Resource not found.
      security:
        - ApiKeyAuth: []
components:
  schemas:
    RoleGrantsModify:
      description: >-
        The set/remove-grants request body: ``set`` upserts a tag → level (the
        one

        sanctioned overwrite), ``remove`` drops tags. At least one must be
        non-empty; a tag may

        not appear in both.
      properties:
        remove:
          items:
            type: string
          title: Remove
          type: array
        set:
          additionalProperties:
            enum:
              - none
              - read
              - write
            type: string
          title: Set
          type: object
      title: RoleGrantsModify
      type: object
    RoleDefinition:
      description: >-
        An operator-authored role: the ONE validated shape the enforcer /

        membership-check, the management operations, and the generated Studio
        SDK all

        share.


        A role composes TWO layers. Layer 1 is a KEPT jq security base — carried
        on

        the ``condition`` field (from ``ConditionMixin``) so the body
        round-trips it,

        but NEVER authored through the grant map: the seed sets it (admin →
        ``None``,

        editor/viewer → their base jq) and a new role inherits it from its

        ``base_tier``. Layer 2 is the editable ``grants`` — a per-tag ACCESS
        LEVEL

        map (feature-group TAG name → ``none``/``read``/``write``) naming the
        role's

        level on each feature group. An absent tag means level ``none`` (deny).
      properties:
        allow_all:
          default: false
          title: Allow All
          type: boolean
        base_tier:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          title: Base Tier
        condition:
          anyOf:
            - $ref: '#/components/schemas/TemplatedText'
            - type: 'null'
          default: null
          x-tai42-expression:
            blurb: the auth context (a dumped JqAuthContext)
            keys:
              - gloss: the caller's subject id
                name: sub
              - gloss: the caller's granted scopes
                name: scopes
              - gloss: who the caller is — the token's identity claims
                name: identity
              - gloss: the caller's static policy data
                name: policy
              - gloss: dynamic environment data for this decision
                name: context
              - gloss: the operation being authorized
                name: request
              - gloss: caller-supplied time/constants (e.g. the current epoch)
                name: system
            label: condition
            language: jq
            returns: >-
              EXACTLY boolean true to allow; any other value — including any
              other truthy result — DENIES
        description:
          title: Description
          type: string
        grants:
          additionalProperties:
            enum:
              - none
              - read
              - write
            type: string
          title: Grants
          type: object
        name:
          title: Name
          type: string
        scopes:
          items:
            type: string
          title: Scopes
          type: array
      required:
        - name
        - description
        - grants
      title: RoleDefinition
      type: object
    Error:
      properties:
        code:
          description: >-
            Stable machine-readable reason a client keys a dedicated error state
            on, present on refusals that opt in (e.g. a 501 not-configured
            refusal). Optional: absent when the error carries only a
            human-readable message.
          type: string
        error:
          type: string
      required:
        - error
      type: object
    TemplatedText:
      additionalProperties: false
      description: >-
        A renderable text: its source plus the parameters its render takes.


        EXACTLY ONE source is set — ``content`` (the text inline) or ``id`` (the
        id of a

        stored resource holding the text); neither and both are refused at
        construction.

        ``kwargs`` are the render parameters for the TEXT and apply either way,
        so moving a

        text from inline to stored (or back) leaves its parameters untouched.
      properties:
        content:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          title: Content
        id:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          title: Id
        kwargs:
          additionalProperties: true
          title: Kwargs
          type: object
      title: TemplatedText
      type: object
      x-tai42-templated-text:
        language: jinja
  securitySchemes:
    ApiKeyAuth:
      in: header
      name: x-api-key
      type: apiKey

````