---
type: Axis
title: sensitivity (data-classification axis)
description: The sensitivity/data-classification architecture axis — how guarded a piece of persisted data is (public → internal → PII → secret). A per-entity-with-default axis whose commitment surface is the persistent-data schema (the classification + the handling obligations it forces). DEEP (RFC #75 5A.5 / P1 #851); worked example is the encrypted-credentials store (3.5.0) and TWINE-token leakage scar.
tags: [axis, architecture, sensitivity, classification, pii, secret, security, rfc-75, deep]
timestamp: 2026-06-20T00:00:00Z
---

# Sensitivity (data-classification axis)

> **DEEP axis (P1 #851).** Full §6 depth with a worked example from the skill's
> own history — the encrypted-credentials store (3.5.0) and the recurring
> TWINE-token leakage scar. Distinct from `authz-granularity` (how finely *access*
> is decided) and `visibility` (the share-scope of a record): sensitivity is the
> intrinsic *classification* of the data, which forces handling obligations
> regardless of who is asking.

## Concept

Sensitivity is the **data-classification** axis (RFC #75 §3): how guarded a
persisted attribute or entity is, which forces a ladder of handling obligations.
The ladder runs public (freely disclosable; no handling rules) → internal
(non-public but low-harm; access-controlled, not encrypted) → PII (personally
identifiable; subject rights, encryption-in-transit, audited access) → secret
(credentials/keys; encryption-at-rest, never logged, rotation, redaction
everywhere). Its **commitment surface is the persistent-data schema** (§4): the
classification is bound to the column — once data lands at a tier, the
obligations (encryption, redaction, audit) attach to every read/write/log/backup
of that column, and *removing* the obligation later is the asymmetric cost (you
must prove the data never leaked at the higher tier). Its **scope is
per-entity-with-default** (§5): a system-wide default ("data is internal") with
per-column escalation that must be declared.

## Why it is an axis (discriminator test — §2)

1. **Ordered tiers** — each rung strictly adds handling obligations (public ⊂
   internal ⊂ PII ⊂ secret in what they demand).
2. **Cross-cutting bundle** — a rung ripples through the column model, the
   logging path (redaction), the backup/export path, encryption, the audit
   surface, and the test obligations (no-secret-in-logs assertions).
3. **Asymmetric migration cost** — escalating is a code-and-schema sweep
   (encrypt, redact, audit every touch point); *de-escalating* is far worse —
   you cannot un-leak data that was logged in clear at the lower tier, so a
   misclassified secret is unrecoverable.
4. **Requirement-keyed selection** — falsifiable probes (below) pick the rung.

## Tiers (the ladder)

| Tier | Adds | Commitment surface | Forecloses next-cost |
|---|---|---|---|
| `public` | nothing | persistent-data-schema | trivial → tighten to internal |
| `internal` | access control | persistent-data-schema | low; logs still carry it |
| `pii` | subject rights + audit + in-transit crypto | persistent-data-schema | medium; every export filters |
| `secret` | at-rest crypto + redaction + rotation | persistent-data-schema | high; no plaintext anywhere |

## Schema view (the §6 entry — validated by `axis_catalog`)

```yaml
id: sensitivity
kind: architecture-axis
scope: per-entity-with-default
default_tier: internal
maintenance_discipline: >-
  data is INTERNAL by default — access-controlled but not encrypted. A column is
  escalated to PII or secret by an explicit declaration in the entity record's
  axis-materialization facet, never silently; once escalated the handling
  obligations (redaction, encryption, audit) attach to EVERY touch point and a
  new code path that reads the column inherits them. De-escalation requires
  proof the data never leaked at the higher tier (the TWINE-leakage scar — a
  secret that hit a log is permanently compromised). Per-column deviations live
  in the entity record.
selection:
  probes:
    - "Is this data freely disclosable to anyone? → public."
    - "Is it non-public but low-harm if seen internally? → internal."
    - "Does it identify a natural person (name, email, address)? → pii."
    - "Is it a credential, token, or key that grants access? → secret."
    - "Would this value in a log/backup/error message be a breach? → secret (and redact everywhere)."
composes_with:
  - "handling obligations = sensitivity × authz-granularity (who may see which tier)"
  - "data-subject duties = sensitivity × principal (a PII subject is a principal)"
  - "secure history = sensitivity × temporality (a secret in an append-log is forever)"
applies_when: []
tiers:
  - tier: public
    commitment_delta:
      surface: persistent-data-schema
      delta: "freely disclosable data; no handling rules, no access control, safe in logs and exports."
    admin_tool: "none."
    enforcement:
      - "no obligation; the column may appear anywhere."
    tests:
      - "the value is present in a public export without redaction."
    forecloses: "nothing; this is the floor."
    migration_cost_to_next: "trivial — add an access check to make it internal."
  - tier: internal
    commitment_delta:
      surface: persistent-data-schema
      delta: "non-public, low-harm data; access-controlled but stored in clear and may appear in internal logs."
    admin_tool: "access-control config."
    enforcement:
      - "reads require an authenticated principal; the column is not exposed on public surfaces."
    tests:
      - "an unauthenticated request cannot read the column."
    forecloses: "appearance on public/unauthenticated surfaces."
    migration_cost_to_next: "medium — add subject-rights handling, in-transit encryption, and access auditing for PII."
  - tier: pii
    commitment_delta:
      surface: persistent-data-schema
      delta: "personally identifiable data; encrypted in transit, access audited, subject to access/erasure rights, filtered from general exports."
    admin_tool: "access-audit log viewer; subject-access/erasure export tool."
    enforcement:
      - "every read of the column is audited; exports redact or filter it; in-transit encryption is mandatory."
    tests:
      - "a read produces an audit record; a general export omits the PII column; a subject-erasure removes it."
    forecloses: "unaudited reads; bulk export without a subject-rights path."
    migration_cost_to_next: "high — encrypt at rest, redact in ALL logs, add rotation (secret)."
  - tier: secret
    commitment_delta:
      surface: persistent-data-schema
      delta: "credentials, tokens, keys; encrypted at rest, NEVER logged in clear, redacted in every error/diagnostic surface, rotatable."
    admin_tool: "secret store + rotation tool; redaction-coverage report."
    enforcement:
      - "the value is encrypted at rest; every log/error/diagnostic redacts it; rotation invalidates the old value."
    tests:
      - "the secret never appears in any log/error fixture (no-secret-in-logs assertion); rotation works; storage is encrypted."
    forecloses: "any plaintext appearance anywhere; debugging that prints the raw value."
    migration_cost_to_next: "n/a — top of the ladder."
examples:
  - "The skill's own climb: credentials moved to an ENCRYPTED store in 3.5.0 (the daemon's forge tokens — secret tier: encrypted at rest, never rendered in the read-only repo viewer). The recurring TWINE_PASSWORD / token-leakage scar is the de-escalation impossibility this axis encodes — a token that leaks into a process env dump or a cut log is permanently compromised and must be rotated, never just reclassified. Most canonical-store columns sit at INTERNAL (issue/discussion bodies are access-controlled but stored in clear)."
```

## Selection procedure (§8)

Bidirectional check per column under the internal default. The escalation pass
asks "would this value in a log/backup/export be a breach?" — a yes forces PII
or secret. The de-escalation pass is constrained: a column may only drop a tier
if it provably never leaked at the higher one. Recorded in the entity record;
`code_design_drift_gap` flags a column that grew a secret-shaped value
(token/key naming) without a declared `secret` tier (5A.5).

## Composition (§5)

Sensitivity is half of several **products** (derived, not authored here):
handling obligations = **sensitivity × authz-granularity** (the tier sets *what*
must be guarded, authz sets *how finely*); data-subject duties = **sensitivity ×
principal** (a PII row's subject is a principal with access/erasure rights);
secure history = **sensitivity × temporality** (a secret written into an
append-only log can never be expunged). The interaction table derives these
(5A.3).
