skip to content

Which fields must a secret store's access entry carry so a review three months later can name which identities read one value?

level: middleimportance: should knowfreq 45%

answer

  1. who, which value, when, whether
  2. stable identifier, not a display name
  3. the version, not the value
  4. outcome plus the rule that allowed it
  5. a correlation identifier for joining

basics

~20 s

Each entry needs the acting identity as a stable identifier, how it authenticated, the value's name and version, the operation and its outcome, the source it came from, and a precise timestamp. It must not carry the value.

solid answer

~40 s

The entry has to answer who, which value, when, from where, and whether it was served — because that is the question asked months later. So: a stable identifier for the acting identity (not a display name and not only a session reference), how that identity proved itself, the value's `name` and the `version` handed back, the operation, the outcome plus the rule that decided it, the caller's source, and a timestamp with its zone and sub-second precision. A correlation identifier lets the entry be lined up with the caller's own records. The value itself never appears — the version is what identifies which copy was read, and it does so without putting the credential into a second place.

code

json · 16 lines
json
{
  "sequence": 918273,
  "occurredAt": "2026-03-11T02:14:07.412Z",
  "actor": {
    "identityId": "id-7f3c9a",
    "displayName": "batch-reporting-worker",
    "authenticatedBy": "platform-signed-identity",
    "sessionRef": "s-4f19"
  },
  "operation": "read",
  "target": { "name": "reporting/warehouse-db", "version": 7 },
  "outcome": "allowed",
  "allowedByRule": "rule-reporting-readers",
  "source": { "address": "10.42.8.19", "caller": "batch-runner" },
  "correlationId": "req-2c81ab"
}

go deeper

for a junior

Recall the shape of the answer: an access entry says who, which value, when, from where, and whether it was served — and it never contains the credential.

for a middle

Explain why each field exists by naming the question it answers, and why the value's version belongs in the entry while the value itself does not.

for a senior

Show that you have read one of these records months later: stable identifiers over display names, the rule that allowed the read so it can be withdrawn, and a correlation identifier so the entry joins to the caller's own records.

for a principal

Frame it as a contract: the estate decides what it must be able to prove about credential access, and the entry's field list is that decision written down rather than whatever the store happened to emit.

## The record is the store's output, not a debugging byproduct A secret store's access record exists to answer a question that is never asked while the read is happening and is almost always asked long afterwards: **which identities obtained this particular value, and between which dates**. A review three months after the fact — an outside reviewer asking who could have read a reporting warehouse's database credential — can only be answered from that record, because nothing else in the estate knows. That inverts the usual design instinct. The fields are not chosen from what was convenient to emit at the call site; they are chosen from the future question, working backwards. ## The fields, and the question each one answers | Field | The question it answers | What breaks without it | |---|---|---| | Timestamp, with zone and sub-second precision | *When* | entries cannot be ordered against any other record | | Acting identity, as a **stable identifier** | *Who* | the read is attributable to nobody | | How that identity authenticated | *How it got in* | you cannot tell a stolen bootstrap value from a platform-signed identity | | The value's `name` | *Which value* | a read of the wrong branch looks identical | | The value's `version` | *Which copy of it* | you cannot say whether the leaked copy was the one served | | Operation — read, write, list, refusal | *What was done* | the record answers only one of four questions | | Outcome, plus the rule that allowed it | *Whether it was served, and why* | "allowed" cannot be traced to a grant you can withdraw | | Source address and a caller description | *From where* | a read from an unexpected place is invisible | | Correlation identifier | *Which request* | the entry cannot be joined to the caller's own records | | Sequence number | *Whether the record is complete* | a missing entry is indistinguishable from a quiet hour | ## Identity is the field that decays Two failures are common and both are visible only later. The first is recording a **display name** — a human-readable label that gets renamed, reassigned or deleted. Three months on, the entry names something that no longer resolves, or worse, resolves to a different principal. Record an identifier the store will not reissue, and carry the display name beside it as a convenience rather than as the answer. The second is recording only the **session reference** — the handle the store issued when the caller authenticated. That answers *which session*, not *which identity*, and if the session was issued to a role several people or several workloads share, attribution stops at the role. The entry should carry the authenticated identity through from the moment of authentication, and where a shared role is unavoidable, the record's honest reading is "someone holding that role", not a person. ## What the entry must never carry The value read is absent, always. Putting it in creates a second, longer-lived copy of the credential in a place designed to be widely readable and retained for a long time — which is the exact shape of the problem the store exists to prevent. The `version` does the identifying work instead: it says which copy was served without reproducing it. A digest of the value is a weaker but real version of the same mistake. Where the value has low entropy — a chosen passphrase rather than a generated key — the digest is recoverable by guessing, so the record becomes worth stealing on its own. Where the value is high-entropy, the objection is weaker, but the digest still buys nothing the version does not already give you. The same applies to anything derived from the value: a rendered connection string, a parameter set carrying it, an error message quoting it. ## Writing for a reader who is not you 1. **Prefer identifiers that survive renaming** for the identity, the value and the rule that allowed the read. 2. **Record the version on every read**, not only on writes, so a read can be tied to a specific copy after a rotation. 3. **Record the outcome and the rule together**, so a review that finds an unexpected allowed read can go straight to the grant that permitted it and withdraw it. 4. **Emit one entry per operation**, not a summary per session, so breadth and timing survive. Stores differ in how much of this they emit by default; some record reads richly and refusals thinly, some record nothing about listing at all. Treat the list above as the target shape and find out by experiment — ask your store a question at the far end of its own record and see whether it answers.

  • Why not record a digest of the value that was read, so a reviewer can confirm which one it was?
    Because the `version` already identifies the copy, and the digest adds risk. Where the value has low entropy, the digest is recoverable by guessing, so the record becomes a cracking target that is kept longer and read by more people than the store itself. Where the value is high-entropy the risk is smaller, but the digest still answers nothing the version has not.
  • The entry names a session, and four engineers share the role that session was issued to. What has the record lost?
    Attribution to a person. It establishes that someone holding that role performed the read, which is often enough to scope an exposure and never enough to answer who. The fix is upstream of the record: carry the authenticated identity into the entry, and stop issuing one shared role to several humans if the record has to name one.
  • Which field lets the store's entry be lined up with the calling service's own records?
    A correlation identifier the caller supplies and the store echoes back into the entry. Without it you are joining on a timestamp and a source address, which fails as soon as two workers on one host read in the same second, or a shared egress point rewrites the address.

saying these in an interview costs you the question

  • Recording only a timestamp and the value's name
  • Naming the session handle, so no identity can be resolved
  • Putting the credential into the entry so reviewers can confirm it
  • Assuming the source address identifies the calling workload
  • Recording a display name that gets renamed or reassigned later