Skip to content

Data governance

Data governance says what each field holds, who answers for it, and whether it is masked, logged, sent to a model, kept or erased.

A person asks to be erased

The Customer decides; the product finds, holds and erases, and every upstream product hears it. Filled: what the person and the Customer see.

What each field is, and who answers for it

A data class on a field changes what every part of the product does with it. Nothing else in the file has to say so.

FamilyWhat it does
Data classesclass on a field: personal, sensitive, payment, health or privileged; Model and records types it, and the one decision reads it
Roles for the dataEach Customer is the controller of its own records, you are its processor, and APIs.Dev is yours; you control your own sales record and account data
The DPAA data processing agreement generated per product from the file: the classes it holds, its regions, retention and sub-processors, versioned and accepted like any agreement
Sub-processorsAPIs.Dev, Stripe, each model provider the router may use, and each upstream product with its own list, generated and printed beside the terms
Subject requestsA person asks to find, export, correct or erase what the product holds about them; the Customer decides, and the product does it across every record
RetentionPer Noun and per class, deleting on schedule unless a legal hold stops it; history keeps that a value existed, never the value
Customer-held keysOn its own isolation, a Customer holds the key to its Namespace in its own key service; revoking it leaves the records unreadable
The model pathPer class: allow, redact (tokens in, values restored after) or refuse; only providers that keep nothing, and never training on a Customer's data
The audit logEvery change, and every read of a sensitive, health or privileged field, as a projection each Customer queries and streams to its own SIEM
The data chainWhat each hop of composition carries, under which licence, residency and processor terms; an erasure follows it upstream
ClassMasked forLogs and tracesThe model pathEdge cache and export
personalRoles without see on its NounRedactedAs privacy.models saysNever cached; exported to its Customer
sensitiveThe same, and encrypted per NamespaceRedactedredact unless the file allows itNever cached; exported to its Customer
paymentEveryone: only Stripe holds the numberNever writtenrefuseLast four digits only
healthThe same as sensitive, and every read auditedRedactedrefuse unless the provider signs for health dataNever cached; exported with its audit
privilegedEveryone outside the case's wallRedactedOnly inside the case, kept in no memoryExported only by a person with the case's Role

Example

A contact's email is personal, the notes are sensitive, the product acts as each Customer's processor, and the model router redacts both.

definition.ts
18 lines
import { define } from 'apis.dev'

/** Deals for each Customer, kicked off when won. */
export default define({
  name: 'pipeline', domain: 'pipeline.apis.dev',
  Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
  Deal: {
    title: 'string', amount: 'decimal(12,2)', company: '->Company.deals',
    contact: { type: 'email?', class: 'personal' },
    notes:   { type: 'markdown?', class: 'sensitive' },
    stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
  },
  privacy: {
    role: 'processor', keys: 'customer', requests: '30d',
    models: { personal: 'redact', sensitive: 'redact' },
  },
  offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})

A Customer's admin reads a finished erasure: what was found, what a hold kept, and which upstream product erased its copy.

Response
HTTP/1.1 200 OK
Content-Type: application/json
X-Cost: price=0, currency="USD"
X-Request-Id: req_6a0f2d93c18e7b45a9d3

{
  "id": "sr_1",
  "kind": "erase",
  "state": "done",
  "subject": { "email": "dana@acme.com" },
  "found": { "Deal": 3, "Company": 0, "events": 41 },
  "held": [{ "record": "deal_2", "reason": "legal hold" }],
  "upstream": [{ "host": "companyfacts.apis.dev", "state": "erased" }],
  "due": "2026-11-26T00:00:00Z"
}

That is GET /subject-requests/sr_1, getSubjectRequest over MCP and pipeline subject-requests get sr_1 in the CLI.

Requests, keys and lists, state by state

Every move is a Verb a Customer's admin or its agent makes on the product's own Interfaces.

Your operator reads each request that reaches the product with SubjectRequest.list on the Operator plane.

ThingStatesWhat moves it
A subject requestreceived, verifying, finding, ready, then done or refused; extended once, with noticeThe Customer's admin; the person's identity check; the deadline in privacy.requests
An erasurerequested, erasing, then erased and propagated; any record under a hold stays heldThe request; every upstream product on the data chain answers with its own state
A correctionrequested, reviewed, then applied or declinedThe Customer decides; an applied correction is a change in history, Stated by the person
A customer-held keyactive, rotating, then revokedThe Customer's own key service; a revoke makes the Namespace unreadable at once, and a restore of the key reverses it
A sub-processor changeannounced, objection_window, effectiveA deploy that adds a model provider or an upstream product; each Customer gets the notice its DPA names
A DPA versionoffered, then accepted or objectedA deploy that changes classes, regions, retention or sub-processors; acceptance follows the agreement rules

What Customers, people and reviewers meet

  • A Customer's admin. Its DPA and sub-processor list, every person's request in one queue, its own key if it holds one, and an audit log it queries.
  • A person in the records. A request made through the Customer, answered within the deadline, with what was found and what a hold kept.
  • A security reviewer. Each field's class, where it goes, which models see it and how, and the chain of products behind this one.
  • An agent. Masked fields stay masked in every tool, and a redacted value never reaches its model.

Every field carries its class from the file to the model router, so what is masked, logged, kept and erased follows one declaration.