Skip to content

Align identity-graph reads and tombstones with the module key form #1073

Description

@jwrosewell

Status, 7 October 2026. #1043 takes option 1 below. Every identity-graph read, write and tombstone reaches its key through one function, EcContext::kv_key_for, which wraps AcceptedModules::canonical_kv_key, the function batch sync and the admin lookup call directly because they have no Edge Cookie context. Identify, Edge Cookie finalization, pull sync, EID resolution and the withdrawal tombstones all use it, so the asymmetry described below no longer exists on that branch, and this issue closes when #1043 merges. Option 2 stays open as a question for the vendor module work (#1072).

One limit is stated in the code. After a deployment switches module, a withdrawal cannot reach a row created under the retired module's code, because no module the deployment reads owns that identifier, so the browser cookie is expired and the row stays until its time to live runs out.


A consistency follow-up from the module-code envelope work in #1043, filed now so it is not lost; nothing shipped today can hit it.

The asymmetry

On both mint paths (organic generation and the client-cycle resolve), the identity-graph row is written under the module-coded key with the module's canonical value form inside the envelope (kv_key_for, which calls the module's normalize_id_for_kv on the value part). Reads (identify, EID resolution) and withdrawal tombstones use the raw in-use identifier from the cookie as the key.

For every module shipped today these are the same string: the HMAC and host-signal modules use the default normalization, which lowercases a hash their generator already emits in lowercase, and the demonstration module normalizes to identity. The asymmetry only bites a future module whose canonical form differs from its minted form, for example one that case-folds: its rows would be written under a key its own reads and tombstones never produce, so a withdrawal marker could miss the row it is meant to kill.

Direction

Withdrawal and tombstoning are core-only operations on the key in use; they are not module surface, and this fix must keep them that way. Two options, to be decided when the first canonicalizing vendor value is real:

  1. Route every graph access (reads, writes, tombstones) through one keying helper, so the canonical form is applied uniformly.
  2. Drop value normalization from the write path entirely, since the module-code envelope now provides the namespacing that normalization partly existed for, and require modules to mint in canonical form.

Option 2 is simpler and removes the trap rather than managing it, but it changes the normalize_id_for_kv contract, so it belongs with the vendor module work rather than a hotfix.

Activity

  1. added theissue type on Oct 1, 2026
  2. changed the title [-]Align identity-graph reads and tombstones with the provider key form[/-] [+]Align identity-graph reads and tombstones with the module key form[/+] on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions