Stratify
Legal and compliance

Asset & Information Classification Procedure

docs/compliance/isms/procedures/PRO-15-asset-classification.md

Source updated 03. Aug. 2026

Asset & Information Classification Procedure

Formalises the classification scheme already defined and applied in register/assets.yaml's header comment into a repeatable procedure — how a new asset gets classified when it's created, and how the existing 13-asset inventory stays current rather than going stale the way dsgvo-data-flow.md's processor table did.

1. Classification scheme

Four levels, already in use across assets.yaml:

LevelMeaning
PublicIntended for open distribution; no confidentiality expectation
InternalNot published, but low sensitivity if disclosed internally
ConfidentialPersonal data or business-sensitive; disclosure would cause real harm
RestrictedHighest sensitivity — auth material, audit trail, or privileged infrastructure access

2. When this procedure triggers

A new asset needs classification whenever one of the following happens:

  • A new database table is added via a Supabase migration (supabase/migrations/00NN_*.sql).
  • A new service integration goes live (a new third-party vendor, a new internal service).
  • A new document is created that would itself qualify as an information asset (an operational

record, a register, a document containing personal or business-sensitive content).

3. Who decides

  • ISMS Owner (Toby) classifies infrastructure and code assets — database tables, services, the

production host, backups, secrets storage, the source repository itself. This matches his existing ownership of all 12 non-document entries in assets.yaml today.

  • DPO / Privacy Owner (Antonios) classifies anything privacy-relevant that isn't primarily an

infrastructure question — a new document like a RoPA entry, a new category of subscriber-facing disclosure, or any asset whose classification hinges on a legal-basis or data-subject-rights judgment rather than a technical one. ASSET-013 (dsgvo-data-flow.md itself) is already owned by Antonios on this basis.

  • Where an asset is ambiguous (e.g. a new table that is both a technical addition and privacy-bearing

by design), the ISMS Owner proposes a classification and the DPO confirms or corrects it before the entry is finalised — consistent with the Consulted/Accountable split already used for supplier review in governance/GOV-03-roles-and-raci.md.

4. Classification steps

  1. Identify the trigger (§2).
  2. Apply the classification test, in order:
  • Does it contain, or provide access to, authentication material, the audit trail, or privileged

infrastructure access? → Restricted.

  • Does it contain personal data or business/client-confidential information, where disclosure

would cause real harm? → Confidential.

  • Is it not published externally, but low-sensitivity if seen internally? → Internal.
  • Is it intended for open, public distribution? → Public.
  1. Add the entry to register/assets.yaml with all fields populated: id, name, type,

classification, owner, location, contains_pii, contains_client_confidential, retention. An entry with a classification but no retention/owner is incomplete — do not leave fields as placeholders.

  1. Cross-reference, if the asset carries personal data, with dsgvo-data-flow.md §2 so the

retention column there and the retention field in assets.yaml don't diverge.

5. Worked examples, from the real inventory

  • `public.audit_log` → restricted (`ASSET-003`). RLS is enabled with no SELECT policy at all —

the only read path is the service-role key. It contains PII (actor/subject identifiers) and is the system's compliance-critical tamper-evidence record: unauthorized disclosure or successful tampering would undermine every audit-trail claim this ISMS makes, not just leak one subscriber's data. That combination — structural lockdown plus outsized consequence if compromised — is what restricted is for.

  • The stratify source code repository → internal (`ASSET-008`). It contains no PII and no

client-confidential data directly, so it doesn't rise to confidential/restricted on the harm test. But it is not intended for open distribution either — it holds business logic, infrastructure configuration shape, and competitive detail that shouldn't be public. Internal is the correct middle tier: sensitive enough to keep private, not sensitive enough to warrant the access controls reserved for restricted assets.

  • `public.subscribers` → confidential (`ASSET-001`). Real PII (email, name, subscription state)

with disclosure consequences that matter — a genuine GDPR-relevant breach if exposed. It does not reach restricted because it is not itself an auth-material or audit-integrity asset; RLS on subscribers follows the ordinary auth.uid() = user_id self-access pattern rather than the deny-by-default posture reserved for audit_log and signal_deliveries.

  • The production host → restricted (`ASSET-009`). Both contains_pii and

contains_client_confidential are true, and it is privileged infrastructure access by definition — compromise of the host compromises every other asset transitively. This is the clearest case for restricted: it isn't data itself, it's the thing everything else's confidentiality depends on.

6. Review cadence for the existing inventory

  • Per-migration: whoever writes a new supabase/migrations/00NN_*.sql that adds a table should

add or update the corresponding assets.yaml entry in the same pull request. This is not currently enforced by CI — stated as a gap, not a control — but is the expected practice going forward.

  • Annual full pass: once a year, walk all entries in register/assets.yaml and confirm each

one's classification, owner, and retention are still accurate — particularly after any infrastructure change (a hosting migration is exactly the kind of event that can silently invalidate a location field, as it did across dsgvo-data-flow.md and pentest-rfp.md after the Hetzner cutover).

7. Evidence this procedure produces

register/assets.yaml itself, kept current — version-controlled, so every classification change has an author, timestamp, and diff (register/schema.md's "why YAML + git" rationale applies directly here).

8. Review

This procedure is reviewed annually, alongside the full inventory pass in §6.