← Back to Milan
AgentMilan

Skill · Version 1.0.0

Field and relationship permissions

Enforces access based on ownership and team relationships, including different visible or editable fields on one record.

field-relationship-permissions

See how it helps

When is it useful?

Use when colleagues may share a record but must see different information.

What does it help you do?

  • Translates ownership and department rules into scoped queries and record checks.
  • Removes protected fields on the server before responses reach the browser.
  • Defines access changes after reassignment and validates restricted field updates.

Try asking this

Let sales staff view orders without supplier margins, and define what former owners retain after an account reassignment. Request the order directly and through export after reassignment. Supplier margins must be absent from responses, not merely hidden by the interface.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Field & Relationship Permissions

When to Use

Use when access depends on who owns a record, which department/team/territory/project it belongs to, or when different roles may view or edit only a subset of fields on the same entity.

1. Relationship- & Ownership-Based Access (ReBAC / ABAC)

Translate business phrases directly into explicit relational predicates enforced in both single-item checks and SQL query scopes:

  • "Can edit own accounts": account.owner_user_id = :actorId
  • "Can view accounts in own department or sub-teams": account.department_id IN (:actorDepartmentHierarchyIds)
  • "Account team members can view; only lead can edit pricing": Join account_team_members(account_id, user_id, access_level) scoped by tenant_id.
  • Ownership Transfer & Historical Access:
    • Explicitly define what happens when an account or opportunity is reassigned from Rep A to Rep B: Rep A immediately loses edit access unless retained as a collaborator in account_team_members.

2. Field-Level Read Redaction (Projection / Serialization Security)

Even when two users can both view the same Order or Employee record, they often must not see the same columns:

  • Example: A sales_rep or warehouse_picker can view order.items and shipping_address, but only finance and sales_manager can view unit_cost, supplier_margin, commission_rate, or tax_id.
  • Server-Side Serializer / DTO Projection:
    • Never send the full database row to the browser and hide sensitive columns in CSS/JS (v-if / {isManager && ...})—anyone opening DevTools Network tab sees the raw JSON!
    • Strip unauthorized fields in the backend serializer/mapper (projectVisibleFields(actor, resource)) before returning API responses, GraphQL fields, webhook payloads, or CSV exports.

3. Field-Level Write Protection (Preventing Mass Assignment)

Different roles or resource states permit editing different subsets of fields on the same endpoint (PATCH /orders/:id):

  • A sales_rep on a draft quote may update customer_notes and quantities, while only a sales_manager may update manual_discount_override, and no user may directly PATCH status: 'approved' or approved_by_id (which must only change via the dedicated approval state transition).
  • Explicit Per-Role & Per-State Allowlists:
    • Validate incoming update payloads against the intersection of writableFieldsForRole(actor.role) and writableFieldsInState(resource.status).
    • Reject (403 Forbidden or 422) when a caller attempts to mutate a restricted field, rather than silently ignoring security-sensitive fields.

Included files 1

  • SKILL.md