Runbooks / Attribute Sensitivity

Attribute Sensitivity

Operator runbook for IdentityMesh’s per-attribute sensitivity classification — schema-level metadata that lets you mark each attribute as Public, Internal, Confidential, or Restricted. Phase 1 today: the classification is metadata only and surfaces in the schema view; later releases consume it for data masking and DSAR scoping. Maps to ISO 27001:2022 Annex A 5.12 (Classification of information) and 5.13 (Labelling of information).

Why it exists

Auditors and compliance reviewers ask a sharp version of the same question every time: “How do you tell the difference between someone’s display name and their salary?” Without a classification taxonomy at the schema level, every downstream tool — masking, exports, DSARs, audit-log redaction — has to invent its own ad-hoc rule for “is this field sensitive?” and they all drift.

The Sensitivity column on IM_MeshAttributeSchema gives you a single, authoritative answer that everything else can build on.

The four levels

The taxonomy is deliberately small. Four levels is the standard pattern in 27001 / NIST guidance because it fits neatly onto operator intuition and avoids decision paralysis when you classify a new attribute.

LevelNumericExamplesDefault visibility
Public0display name, login alias, public emailAnywhere — including unauthenticated
Internal1department, manager, location, job titleAuthenticated operators (default)
Confidential2cost-center, internal employee IDs, badge numbersOperators with explicit need-to-know
Restricted3SSN / TFN, salary, health markers, passport numberTightly held; auditing every access

The numeric values are stable across releases — they form the storage and wire contract. They will never be renumbered. New levels, if ever added, will use new numbers above 3.

Internal is the default. When you create a new attribute schema entry without specifying a level, it lands at Internal. When the ER-049 migration runs against an existing database, every existing row gets Internal too. This is deliberate: it’s the safe-but-visible level, and it forces a conscious decision to upgrade something to Confidential or Restricted rather than silently downgrading anything to Public.

How to set it

On creation

POST /api/attribute-schemas accepts an optional sensitivity property in the request body. Either form works:

{
  "attributeName": "salary",
  "objectType": "User",
  "dataType": "int",
  "sensitivity": "Restricted"
}
{
  "attributeName": "costCenter",
  "objectType": "User",
  "dataType": "string",
  "sensitivity": 2
}

Omit it and you get Internal.

On an existing entry

Two routes update the classification:

  1. PUT /api/attribute-schemas/{id} — the existing full-update route. Include sensitivity to change it; omit it and the stored value is left intact (a legacy client that doesn’t know about the field can’t accidentally down-classify anything).

  2. PATCH /api/attribute-schemas/{id}/sensitivity — the focused single-field route. This is the one to use when all you’re doing is reclassifying:

    PATCH /api/attribute-schemas/42/sensitivity
    Content-Type: application/json
    
    { "sensitivity": "Confidential" }

Both routes are gated on the schema.write permission and are recorded automatically in IM_AdminAudit by the admin-audit middleware. The auditor’s question — “who reclassified this field, when?” — has a single-query answer.

Reading the classification

GET /api/attribute-schemas and GET /api/attribute-schemas/{id} both return sensitivity on every entry.

What it does today

What it does NOT do today (yet)

Phase 1 is metadata only. These are explicitly out of scope for this release and will land in follow-up work:

These gaps are intentional. Phase 1 establishes the taxonomy and the system of record; phases 2 and 3 build the enforcement and redaction layers on top.

Choosing the right level

A few rules of thumb:

When in doubt, classify higher. You can always reclassify down once a field is in production and you’ve watched the access patterns; reclassifying a leaked field up after the fact is a much harder conversation.