PersonalData
Crypto-shredding for personal data. The log is append-only, so the personal fields of an event are encrypted with a key that belongs to the person they describe, the subject. Forgetting a subject destroys that key: the events stay where they are and keep their amounts, dates and ids, while their personal fields read as the replacement each field declares.
const AccountEvent = Schema.TaggedUnion({ AccountOpened: { owner: PersonalData.field(Schema.String, { redacted: "[forgotten]" }), currency: Schema.Literals(["CHF", "EUR"]) }, TransferSent: { to: Schema.String, // Encrypted with the key of the receiver rather than the account holder. beneficiary: PersonalData.field(Schema.String, { redacted: "[forgotten]", subject: "to" }), amount: Schema.Number }})A field belongs to the aggregate id of its stream unless it names a sibling
property that holds its subject. Schemas stay plain: encryption happens where
AggregateService writes and reads the store, which then needs Keys.
Each subject has its own data key. The key store keeps it only wrapped by a MasterKey, which can live in a KMS, so the master key can change without touching events. forget destroys the data key, refuses keys for that subject from then on and records the request in the log.
Encryption is AES-256-GCM through a Cipher: WebCrypto by default, which
also runs in browsers, or node:crypto from PersonalDataNode.
Classes
Section titled “Classes”Defined in: src/PersonalData.ts:455
The data keys of subjects, created on first use and cached for a while.
Extends
Section titled “Extends”Shape<"effect-cqrs/PersonalData/Keys", {cipher:Cipher;decryptionKey(subject,keyId):Effect<Option<CipherKey>,PersonalDataError>;encryptionKey(subject):Effect<DataKey,PersonalDataError|SubjectForgotten>;forget(subject):Effect<void,PersonalDataError>;isForgotten(subject):Effect<boolean,PersonalDataError>;rewrap(options?):Effect<RewrapResult,PersonalDataError>; },this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new Keys(
_):Keys
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/Context.d.ts:121
Parameters
Section titled “Parameters”never
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”Context.Service<Keys, { /** What encrypts and decrypts with the keys. */ readonly cipher: Cipher /** The key to encrypt with, created when the subject has none. Fails for a forgotten subject. */ encryptionKey(subject: string): Effect.Effect<DataKey, SubjectForgotten | PersonalDataError> /** * The key to decrypt with, `None` when the subject was forgotten. A subject * without any key fails: losing the key store must not pass for forgetting. */ decryptionKey(subject: string, keyId: string): Effect.Effect<Option.Option<CipherKey>, PersonalDataError> isForgotten(subject: string): Effect.Effect<boolean, PersonalDataError> /** Destroys the key of a subject. Prefer {@link forget}, which also records it in the log. */ forget(subject: string): Effect.Effect<void, PersonalDataError> /** See {@link rewrap}. */ rewrap(options?: RewrapOptions): Effect.Effect<RewrapResult, PersonalDataError> }>()(“effect-cqrs/PersonalData/Keys”).constructor
MasterKey
Section titled “MasterKey”Defined in: src/PersonalData.ts:376
Wraps the data keys of subjects, so the key store only ever holds them encrypted. Implement it on top of a KMS to keep the master key out of the process, or use layerMasterKey with a key from configuration.
Extends
Section titled “Extends”Shape<"effect-cqrs/PersonalData/MasterKey", {keyId:string;unwrap(wrapped,context):Effect<Uint8Array<ArrayBuffer>,PersonalDataError>;wrap(dataKey,context):Effect<Uint8Array<ArrayBuffer>,PersonalDataError>; },this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new MasterKey(
_):MasterKey
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/Context.d.ts:121
Parameters
Section titled “Parameters”never
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”Context.Service<MasterKey, { /** The key new data keys are wrapped with. */ readonly keyId: string wrap( dataKey: Uint8Array<ArrayBuffer>, context: { readonly subject: string; readonly keyId: string } ): Effect.Effect<Uint8Array<ArrayBuffer>, PersonalDataError> /** Unwraps a key wrapped by `masterKeyId`, which may be an earlier master key. */ unwrap( wrapped: Uint8Array<ArrayBuffer>, context: { readonly subject: string; readonly keyId: string; readonly masterKeyId: string } ): Effect.Effect<Uint8Array<ArrayBuffer>, PersonalDataError> }>()("effect-cqrs/PersonalData/MasterKey").constructor
PersonalDataError
Section titled “PersonalDataError”Defined in: src/PersonalData.ts:68
A key that couldn’t be read, created or used, or a field that didn’t decrypt.
Extends
Section titled “Extends”object&YieldableError<this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new PersonalDataError(…
args):PersonalDataError
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/Schema.d.ts:10979
Parameters
Section titled “Parameters”…[props: object, options?: MakeOptions]
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”Schema.TaggedError<PersonalDataError>()("PersonalDataError", { operation: Schema.String, subject: Schema.String, message: Schema.String, cause: Schema.optional(Schema.Defect()) }).constructor
Properties
Section titled “Properties”cause?
Section titled “cause?”
optionalcause?:unknown
Defined in: src/PersonalData.ts:72
Inherited from
Section titled “Inherited from”Schema.TaggedError<PersonalDataError>()("PersonalDataError", { operation: Schema.String, subject: Schema.String, message: Schema.String, cause: Schema.optional(Schema.Defect()) }).cause
message
Section titled “message”message:
string=Schema.String
Defined in: src/PersonalData.ts:71
Inherited from
Section titled “Inherited from”Schema.TaggedError<PersonalDataError>()("PersonalDataError", { operation: Schema.String, subject: Schema.String, message: Schema.String, cause: Schema.optional(Schema.Defect()) }).message
operation
Section titled “operation”
readonlyoperation:string=Schema.String
Defined in: src/PersonalData.ts:69
Inherited from
Section titled “Inherited from”Schema.TaggedError<PersonalDataError>()("PersonalDataError", { operation: Schema.String, subject: Schema.String, message: Schema.String, cause: Schema.optional(Schema.Defect()) }).operation
subject
Section titled “subject”
readonlysubject:string=Schema.String
Defined in: src/PersonalData.ts:70
Inherited from
Section titled “Inherited from”Schema.TaggedError<PersonalDataError>()("PersonalDataError", { operation: Schema.String, subject: Schema.String, message: Schema.String, cause: Schema.optional(Schema.Defect()) }).subject
SubjectForgotten
Section titled “SubjectForgotten”Defined in: src/PersonalData.ts:63
Extends
Section titled “Extends”object&YieldableError<this>
Constructors
Section titled “Constructors”Constructor
Section titled “Constructor”new SubjectForgotten(…
args):SubjectForgotten
Defined in: node_modules/.pnpm/effect@4.0.6/node_modules/effect/dist/Schema.d.ts:10979
Parameters
Section titled “Parameters”…[props: object, options?: MakeOptions]
Returns
Section titled “Returns”Inherited from
Section titled “Inherited from”Schema.TaggedError<SubjectForgotten>()("SubjectForgotten", { subject: Schema.String }).constructor
Properties
Section titled “Properties”subject
Section titled “subject”
readonlysubject:string=Schema.String
Defined in: src/PersonalData.ts:64
Inherited from
Section titled “Inherited from”Schema.TaggedError<SubjectForgotten>()("SubjectForgotten", { subject: Schema.String }).subject
Interfaces
Section titled “Interfaces”Backend
Section titled “Backend”Defined in: src/PersonalData.ts:402
Where keys are kept. Keep it apart from the events, with backups that expire.
Properties
Section titled “Properties”afterCommit?
Section titled “afterCommit?”
readonlyoptionalafterCommit?: <R>(effect) =>Effect<void,never,R>
Defined in: src/PersonalData.ts:420
Runs an effect when the caller’s transaction commits, or at once outside one.
Type Parameters
Section titled “Type Parameters”R
Parameters
Section titled “Parameters”effect
Section titled “effect”Effect<void, never, R>
Returns
Section titled “Returns”Effect<void, never, R>
create
Section titled “create”
readonlycreate: (subject,key) =>Effect<KeyRecord,PersonalDataError>
Defined in: src/PersonalData.ts:408
Stores a key unless the subject already has a record, and returns the record
the subject has afterwards: a racing writer’s key, or Forgotten.
Parameters
Section titled “Parameters”subject
Section titled “subject”string
"Active"
string
masterKeyId
Section titled “masterKeyId”string
wrapped
Section titled “wrapped”Uint8Array<ArrayBuffer>
The data key, wrapped by the master key.
Returns
Section titled “Returns”Effect<KeyRecord, PersonalDataError>
forget
Section titled “forget”
readonlyforget: (subject,forgottenAt) =>Effect<void,PersonalDataError>
Defined in: src/PersonalData.ts:413
Deletes the key and records that the subject is forgotten, in one step.
Parameters
Section titled “Parameters”subject
Section titled “subject”string
forgottenAt
Section titled “forgottenAt”number
Returns
Section titled “Returns”Effect<void, PersonalDataError>
readonlyget: (subject) =>Effect<Option<KeyRecord>,PersonalDataError>
Defined in: src/PersonalData.ts:403
Parameters
Section titled “Parameters”subject
Section titled “subject”string
Returns
Section titled “Returns”Effect<Option<KeyRecord>, PersonalDataError>
inTransaction?
Section titled “inTransaction?”
readonlyoptionalinTransaction?:Effect<boolean,never,never>
Defined in: src/PersonalData.ts:418
Whether a call now joins a transaction of the caller, whose writes a rollback can still undo. What is read or created there is cached only once it commits.
replaceWrapped?
Section titled “replaceWrapped?”
readonlyoptionalreplaceWrapped?: (subject,from,to) =>Effect<boolean,PersonalDataError>
Defined in: src/PersonalData.ts:440
Stores a key wrapped anew, if the subject still has the key from: not
forgotten, nor wrapped again meanwhile. Returns whether it did.
Parameters
Section titled “Parameters”subject
Section titled “subject”string
string
masterKeyId
Section titled “masterKeyId”string
masterKeyId
Section titled “masterKeyId”string
wrapped
Section titled “wrapped”Uint8Array<ArrayBuffer>
Returns
Section titled “Returns”Effect<boolean, PersonalDataError>
wrappedByOthers?
Section titled “wrappedByOthers?”
readonlyoptionalwrappedByOthers?: (masterKeyId,afterSubject,limit) =>Effect<readonlyobject[],PersonalDataError>
Defined in: src/PersonalData.ts:426
Up to limit subjects after afterSubject, in order, whose key is wrapped by
another master key than masterKeyId. With Backend.replaceWrapped, what
rewrap needs.
Parameters
Section titled “Parameters”masterKeyId
Section titled “masterKeyId”string
afterSubject
Section titled “afterSubject”string
number
Returns
Section titled “Returns”Effect<readonly object[], PersonalDataError>
Cipher
Section titled “Cipher”Defined in: src/PersonalData.ts:296
AES-256-GCM, which encrypts personal fields and wraps data keys. What it produces is a random IV of ivLength bytes, the ciphertext and a tag of tagLength bytes, so data written by one implementation reads with any other.
The default, webCrypto, works in Node and in browsers but is
asynchronous. PersonalDataNode.layerCipher runs on node:crypto
synchronously, which costs a fraction per field.
Properties
Section titled “Properties”asynchronous
Section titled “asynchronous”
readonlyasynchronous:boolean
Defined in: src/PersonalData.ts:301
Whether an operation waits on something outside the fiber, as WebCrypto does. Events of a stream then decrypt several at a time.
Methods
Section titled “Methods”decrypt()
Section titled “decrypt()”decrypt(
key,sealed,additionalData):Effect<Uint8Array<ArrayBuffer>,UnknownError>
Defined in: src/PersonalData.ts:310
Fails when the data was altered, or belongs to another key or other additional data.
Parameters
Section titled “Parameters”sealed
Section titled “sealed”Uint8Array<ArrayBuffer>
additionalData
Section titled “additionalData”Uint8Array<ArrayBuffer>
Returns
Section titled “Returns”Effect<Uint8Array<ArrayBuffer>, UnknownError>
encrypt()
Section titled “encrypt()”encrypt(
key,plaintext,additionalData):Effect<Uint8Array<ArrayBuffer>,UnknownError>
Defined in: src/PersonalData.ts:304
Parameters
Section titled “Parameters”plaintext
Section titled “plaintext”Uint8Array<ArrayBuffer>
additionalData
Section titled “additionalData”Uint8Array<ArrayBuffer>
Returns
Section titled “Returns”Effect<Uint8Array<ArrayBuffer>, UnknownError>
importKey()
Section titled “importKey()”importKey(
bytes):Effect<CipherKey,UnknownError>
Defined in: src/PersonalData.ts:303
Imports a key of 32 bytes. The caller zeroes the bytes afterwards.
Parameters
Section titled “Parameters”Uint8Array<ArrayBuffer>
Returns
Section titled “Returns”Effect<CipherKey, UnknownError>
CipherKey
Section titled “CipherKey”Defined in: src/PersonalData.ts:282
A key imported by a Cipher, which only that cipher can use.
Properties
Section titled “Properties”[CipherKeyTypeId]
Section titled “[CipherKeyTypeId]”
readonly[CipherKeyTypeId]: typeofCipherKeyTypeId
Defined in: src/PersonalData.ts:283
DataKey
Section titled “DataKey”Defined in: src/PersonalData.ts:449
Properties
Section titled “Properties”
readonlykey:CipherKey
Defined in: src/PersonalData.ts:451
readonlykeyId:string
Defined in: src/PersonalData.ts:450
Defined in: src/PersonalData.ts:113
Where a personal field sits in an encoded payload, and how to find its subject.
Properties
Section titled “Properties”
readonlypath: readonlystring[]
Defined in: src/PersonalData.ts:114
redacted
Section titled “redacted”
readonlyredacted:Json
Defined in: src/PersonalData.ts:117
subject
Section titled “subject”
readonlysubject:string|undefined
Defined in: src/PersonalData.ts:116
The sibling property holding the subject, or undefined for the aggregate id.
KeysOptions
Section titled “KeysOptions”Defined in: src/PersonalData.ts:482
Properties
Section titled “Properties”cacheSize?
Section titled “cacheSize?”
readonlyoptionalcacheSize?:number
Defined in: src/PersonalData.ts:484
How many subjects to keep in memory, with their unwrapped keys. Defaults to 10,000.
cacheTtl?
Section titled “cacheTtl?”
readonlyoptionalcacheTtl?:Input
Defined in: src/PersonalData.ts:490
How long what the store said about a subject is used before it is asked again. It bounds how long another process keeps using the key of a subject forgotten here. Defaults to one minute.
Location
Section titled “Location”Defined in: src/PersonalData.ts:1087
Where a payload is stored, which the ciphertext of its fields is bound to.
Properties
Section titled “Properties”aggregateId
Section titled “aggregateId”
readonlyaggregateId:string
Defined in: src/PersonalData.ts:1089
aggregateName
Section titled “aggregateName”
readonlyaggregateName:string
Defined in: src/PersonalData.ts:1088
readonlytype:string
Defined in: src/PersonalData.ts:1090
RewrapOptions
Section titled “RewrapOptions”Defined in: src/PersonalData.ts:472
Properties
Section titled “Properties”batchSize?
Section titled “batchSize?”
readonlyoptionalbatchSize?:number
Defined in: src/PersonalData.ts:474
How many keys are read from the store at a time. Defaults to 100.
RewrapResult
Section titled “RewrapResult”Defined in: src/PersonalData.ts:477
Properties
Section titled “Properties”rewrapped
Section titled “rewrapped”
readonlyrewrapped:number
Defined in: src/PersonalData.ts:479
The keys now wrapped by the current master key.
SqlOptions
Section titled “SqlOptions”Defined in: src/PersonalData.ts:864
Properties
Section titled “Properties”migrate?
Section titled “migrate?”
readonlyoptionalmigrate?:boolean
Defined in: src/PersonalData.ts:871
Creates the table on startup when it doesn’t exist. Defaults to true. Turn
it off to run migrations with your own tooling instead.
table?
Section titled “table?”
readonlyoptionaltable?:string
Defined in: src/PersonalData.ts:866
Defaults to cqrs_personal_data_keys.
WithSubjects
Section titled “WithSubjects”Defined in: src/PersonalData.ts:1174
A payload, with the subjects whose personal data it holds.
Properties
Section titled “Properties”payload
Section titled “payload”
readonlypayload:Json
Defined in: src/PersonalData.ts:1175
subjects
Section titled “subjects”
readonlysubjects: readonlystring[]
Defined in: src/PersonalData.ts:1176
Type Aliases
Section titled “Type Aliases”KeyRecord
Section titled “KeyRecord”KeyRecord = {
_tag:"Active";keyId:string;masterKeyId:string;wrapped:Uint8Array<ArrayBuffer>; } | {_tag:"Forgotten";forgottenAt:number; }
Defined in: src/PersonalData.ts:391
What the key store holds for a subject.
Union Members
Section titled “Union Members”Type Literal
Section titled “Type Literal”{ _tag: "Active"; keyId: string; masterKeyId: string; wrapped: Uint8Array<ArrayBuffer>; }
readonly_tag:"Active"
readonlykeyId:string
masterKeyId
Section titled “masterKeyId”
readonlymasterKeyId:string
wrapped
Section titled “wrapped”
readonlywrapped:Uint8Array<ArrayBuffer>
The data key, wrapped by the master key.
Type Literal
Section titled “Type Literal”{ _tag: "Forgotten"; forgottenAt: number; }
Sealed
Section titled “Sealed”Sealed = typeof
Sealed.Type
Defined in: src/PersonalData.ts:1247
Text encrypted once with the key of each subject, so destroying any one of the keys makes it unreadable.
Variables
Section titled “Variables”Cipher
Section titled “Cipher”Cipher:
Reference<Cipher>
Defined in: src/PersonalData.ts:296
The cipher that keys, master keys and fields use, webCrypto unless another is provided.
forget
Section titled “forget”
constforget: (…args) =>Effect<void,EventStoreError|PersonalDataError,Keys|EventStore>
Defined in: src/PersonalData.ts:1045
Forgets a subject: destroys its key, so its personal fields read as their
replacements everywhere, and records a SubjectForgotten event in the stream
of the subject, with the current causation and metadata as the audit trail.
Running it again records nothing new.
The key goes first, so that no event says a subject is forgotten while its key
still exists. A store that can’t be reached is tried a few more times; when it
still fails, the subject is forgotten but the event is missing, and onForget
handlers haven’t run. Call forget again until it succeeds.
Other processes stop using the key once their cache expires, see KeysOptions.cacheTtl.
Parameters
Section titled “Parameters”…[subject: string]
Returns
Section titled “Returns”Effect<void, EventStoreError | PersonalDataError, Keys | EventStore>
ivLength
Section titled “ivLength”
constivLength:12=12
Defined in: src/PersonalData.ts:317
keyLength
Section titled “keyLength”
constkeyLength:32=32
Defined in: src/PersonalData.ts:319
layerMasterKeyEphemeral
Section titled “layerMasterKeyEphemeral”
constlayerMasterKeyEphemeral:Layer.Layer<MasterKey>
Defined in: src/PersonalData.ts:642
A random master key that lasts as long as the layer. Keys it wrapped can’t be read by another process or after a restart, so it suits tests and demos.
constmake: (…args) =>Effect<{cipher:Cipher;decryptionKey(subject,keyId):Effect<Option<CipherKey>,PersonalDataError>;encryptionKey(subject):Effect<DataKey,PersonalDataError|SubjectForgotten>;forget(subject):Effect<void,PersonalDataError>;isForgotten(subject):Effect<boolean,PersonalDataError>;rewrap(options?):Effect<RewrapResult,PersonalDataError>; },never,MasterKey>
Defined in: src/PersonalData.ts:664
Builds Keys on a key store. Reads of the store are cached per subject, and concurrent misses for one subject share a single read, unwrap and, for a new subject, a single key creation.
Parameters
Section titled “Parameters”…[backend: Backend, options?: KeysOptions]
Returns
Section titled “Returns”Effect<{ cipher: Cipher; decryptionKey(subject, keyId): Effect<Option<CipherKey>, PersonalDataError>; encryptionKey(subject): Effect<DataKey, PersonalDataError | SubjectForgotten>; forget(subject): Effect<void, PersonalDataError>; isForgotten(subject): Effect<boolean, PersonalDataError>; rewrap(options?): Effect<RewrapResult, PersonalDataError>; }, never, MasterKey>
makeMasterKey
Section titled “makeMasterKey”
constmakeMasterKey: (…args) =>Effect<{keyId:string;unwrap(wrapped,context):Effect<Uint8Array<ArrayBuffer>,PersonalDataError>;wrap(dataKey,context):Effect<Uint8Array<ArrayBuffer>,PersonalDataError>; },PersonalDataError,never>
Defined in: src/PersonalData.ts:543
A master key held by the process, given as 32 bytes. Keys wrapped by earlier
master keys stay readable while those are listed in previous. The bytes are
copied, so the caller can zero its own.
Parameters
Section titled “Parameters”…[options: object]
Returns
Section titled “Returns”Effect<{ keyId: string; unwrap(wrapped, context): Effect<Uint8Array<ArrayBuffer>, PersonalDataError>; wrap(dataKey, context): Effect<Uint8Array<ArrayBuffer>, PersonalDataError>; }, PersonalDataError, never>
makeSqlBackend
Section titled “makeSqlBackend”
constmakeSqlBackend: (…args) =>Effect<{afterCommit: <R>(effect) =>Effect<void,never,R>;create: (subject,key) =>Effect<KeyRecord,PersonalDataError,never>;forget: (subject,forgottenAt) =>Effect<void,PersonalDataError,never>;get: (subject) =>Effect<Option<KeyRecord>,PersonalDataError,never>;inTransaction:Effect<boolean,never,never>;replaceWrapped: (subject,from,to) =>Effect<boolean,PersonalDataError,never>;wrappedByOthers: (masterKeyId,afterSubject,limit) =>Effect<object[],PersonalDataError,never>; },PersonalDataError,SqlClient>
Defined in: src/PersonalData.ts:918
A key store in a SQL table, on SQLite or PostgreSQL. The table is created on
startup unless migrate is false. Provide it a client of its own to keep
keys in another database than the events, with other permissions and backups.
Forgetting overwrites the row. The database may keep the old bytes for a while, in free pages, dead rows or its write-ahead log, and backups keep them as long as they are kept: let backups of this table expire.
Parameters
Section titled “Parameters”…[options?: SqlOptions]
Returns
Section titled “Returns”Effect<{ afterCommit: <R>(effect) => Effect<void, never, R>; create: (subject, key) => Effect<KeyRecord, PersonalDataError, never>; forget: (subject, forgottenAt) => Effect<void, PersonalDataError, never>; get: (subject) => Effect<Option<KeyRecord>, PersonalDataError, never>; inTransaction: Effect<boolean, never, never>; replaceWrapped: (subject, from, to) => Effect<boolean, PersonalDataError, never>; wrappedByOthers: (masterKeyId, afterSubject, limit) => Effect<object[], PersonalDataError, never>; }, PersonalDataError, SqlClient>
openText
Section titled “openText”
constopenText: (…args) =>Effect<Option<string>,PersonalDataError,never>
Defined in: src/PersonalData.ts:1271
Opens text from sealText, None when one of its subjects was forgotten.
Parameters
Section titled “Parameters”…[keys: object, sealed: object, purpose: string]
Returns
Section titled “Returns”Effect<Option<string>, PersonalDataError, never>
Sealed
Section titled “Sealed”
constSealed:Struct<{data:String;subjects:$Array<Struct<{keyId:String;subject:String; }>>; }>
Defined in: src/PersonalData.ts:1247
Text encrypted once with the key of each subject, so destroying any one of the keys makes it unreadable.
sealText
Section titled “sealText”
constsealText: (…args) =>Effect<{data:string;subjects:object[]; },PersonalDataError|SubjectForgotten,never>
Defined in: src/PersonalData.ts:1254
Seals text such as a snapshot of a state that holds the personal data of subjects.
Parameters
Section titled “Parameters”…[keys: object, subjects: readonly string[], text: string, purpose: string]
Returns
Section titled “Returns”Effect<{ data: string; subjects: object[]; }, PersonalDataError | SubjectForgotten, never>
streamName
Section titled “streamName”
conststreamName:"effect-cqrs/personal-data"="effect-cqrs/personal-data"
Defined in: src/PersonalData.ts:1026
The stream that records forgotten subjects, one stream per subject.
subjectForgottenType
Section titled “subjectForgottenType”
constsubjectForgottenType:"SubjectForgotten"="SubjectForgotten"
Defined in: src/PersonalData.ts:1029
The type of the event forget records. Its payload is empty.
tagLength
Section titled “tagLength”
consttagLength:16=16
Defined in: src/PersonalData.ts:318
webCrypto
Section titled “webCrypto”
constwebCrypto:Cipher
Defined in: src/PersonalData.ts:329
AES-256-GCM on WebCrypto.
Functions
Section titled “Functions”field()
Section titled “field()”field<
S>(schema,options):S
Defined in: src/PersonalData.ts:95
Marks a field as personal data. redacted is what the field reads as once
its subject is forgotten, and has to be a valid value of the field. subject
names a property next to the field that holds the id of the person it
describes, by default the aggregate id of the stream.
Type Parameters
Section titled “Type Parameters”S extends PlainSchema
Parameters
Section titled “Parameters”schema
Section titled “schema”S
options
Section titled “options”redacted
Section titled “redacted”S["Type"]
subject?
Section titled “subject?”string
Returns
Section titled “Returns”S
fieldsByTag()
Section titled “fieldsByTag()”fieldsByTag(
schema,where):ReadonlyMap<string, readonlyField[]>
Defined in: src/PersonalData.ts:259
The personal fields of each event in a union of tagged events. Events without any are left out.
Parameters
Section titled “Parameters”schema
Section titled “schema”Top
string
Returns
Section titled “Returns”ReadonlyMap<string, readonly Field[]>
fieldsOf()
Section titled “fieldsOf()”fieldsOf(
schema,where): readonlyField[]
Defined in: src/PersonalData.ts:252
The personal fields of one schema, such as an old version of an event.
Parameters
Section titled “Parameters”schema
Section titled “schema”Top
string
Returns
Section titled “Returns”readonly Field[]
layerMasterKey()
Section titled “layerMasterKey()”layerMasterKey(
options):Layer<MasterKey,PersonalDataError>
Defined in: src/PersonalData.ts:587
Parameters
Section titled “Parameters”options
Section titled “options”Redacted<Uint8Array<ArrayBufferLike>>
string
previous?
Section titled “previous?”readonly object[]
Returns
Section titled “Returns”Layer<MasterKey, PersonalDataError>
layerMasterKeyConfig()
Section titled “layerMasterKeyConfig()”layerMasterKeyConfig(
options?):Layer<MasterKey,PersonalDataError|ConfigError>
Defined in: src/PersonalData.ts:600
A master key from configuration: an id, and 32 bytes in base64. By default
PERSONAL_DATA_MASTER_KEY_ID and PERSONAL_DATA_MASTER_KEY.
Earlier master keys, which keys created before a rotation are still wrapped by,
come from PERSONAL_DATA_MASTER_KEY_PREVIOUS by default, as id:base64 pairs
separated by commas. Leave it unset when there are none, and empty it once
rewrap has moved every key to the current master key.
Parameters
Section titled “Parameters”options?
Section titled “options?”Config<Redacted<string>>
keyId?
Section titled “keyId?”Config<string>
previous?
Section titled “previous?”Config<Redacted<string>>
Returns
Section titled “Returns”Layer<MasterKey, PersonalDataError | ConfigError>
layerMemory()
Section titled “layerMemory()”Defined in: src/PersonalData.ts:861
Keys kept in process memory, for tests and demos.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”layerSql()
Section titled “layerSql()”layerSql(
options?):Layer<Keys,PersonalDataError,SqlClient|MasterKey>
Defined in: src/PersonalData.ts:1007
Keys in a SQL table, see makeSqlBackend.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Layer<Keys, PersonalDataError, SqlClient | MasterKey>
makeMemoryBackend()
Section titled “makeMemoryBackend()”makeMemoryBackend():
Backend
Defined in: src/PersonalData.ts:823
A key store in process memory, gone after a restart along with access to everything it encrypted.
Returns
Section titled “Returns”migrations()
Section titled “migrations()”migrations(
options?): readonlyMigration[]
Defined in: src/PersonalData.ts:883
The migrations of the key table of makeSqlBackend, the same on SQLite and PostgreSQL, for teams that run migrations themselves. They are safe to run again.
Parameters
Section titled “Parameters”options?
Section titled “options?”table?
Section titled “table?”string
Returns
Section titled “Returns”readonly Migration[]
open()
Section titled “open()”open(
keys,fields,location,payload):Effect<WithSubjects,PersonalDataError>
Defined in: src/PersonalData.ts:1186
Decrypts the personal fields of a stored payload, putting the replacement in place of the fields of forgotten subjects. A field stored in plaintext, from before it was marked personal, is left as it is. A field has to be encrypted for the subject it would be sealed for now: the aggregate id, or the sibling it names.
Parameters
Section titled “Parameters”cipher
Section titled “cipher”What encrypts and decrypts with the keys.
decryptionKey
Section titled “decryptionKey”(subject, keyId) => Effect<Option<CipherKey>, PersonalDataError>
The key to decrypt with, None when the subject was forgotten. A subject
without any key fails: losing the key store must not pass for forgetting.
encryptionKey
Section titled “encryptionKey”(subject) => Effect<DataKey, PersonalDataError | SubjectForgotten>
The key to encrypt with, created when the subject has none. Fails for a forgotten subject.
forget
Section titled “forget”(subject) => Effect<void, PersonalDataError>
Destroys the key of a subject. Prefer forget, which also records it in the log.
isForgotten
Section titled “isForgotten”(subject) => Effect<boolean, PersonalDataError>
rewrap
Section titled “rewrap”(options?) => Effect<RewrapResult, PersonalDataError>
See rewrap.
fields
Section titled “fields”readonly Field[]
location
Section titled “location”payload
Section titled “payload”Json
Returns
Section titled “Returns”Effect<WithSubjects, PersonalDataError>
rewrap()
Section titled “rewrap()”rewrap(
options?):Effect<RewrapResult,PersonalDataError,Keys>
Defined in: src/PersonalData.ts:1022
Wraps every subject key that an earlier master key wrapped with the current
one, so the earlier one can be dropped from previous. Keys stay the same, so
nothing encrypted with them changes, and running it again only rewraps what is
left. Keys created meanwhile are wrapped by the current master key already.
Parameters
Section titled “Parameters”options?
Section titled “options?”Returns
Section titled “Returns”Effect<RewrapResult, PersonalDataError, Keys>
seal()
Section titled “seal()”seal(
keys,fields,location,payload):Effect<WithSubjects,PersonalDataError|SubjectForgotten>
Defined in: src/PersonalData.ts:1127
Encrypts the personal fields of an encoded payload. Fields without a value are
left alone. aggregateId is the subject of fields that don’t name one.
Returns the subjects whose keys were used.
Parameters
Section titled “Parameters”cipher
Section titled “cipher”What encrypts and decrypts with the keys.
decryptionKey
Section titled “decryptionKey”(subject, keyId) => Effect<Option<CipherKey>, PersonalDataError>
The key to decrypt with, None when the subject was forgotten. A subject
without any key fails: losing the key store must not pass for forgetting.
encryptionKey
Section titled “encryptionKey”(subject) => Effect<DataKey, PersonalDataError | SubjectForgotten>
The key to encrypt with, created when the subject has none. Fails for a forgotten subject.
forget
Section titled “forget”(subject) => Effect<void, PersonalDataError>
Destroys the key of a subject. Prefer forget, which also records it in the log.
isForgotten
Section titled “isForgotten”(subject) => Effect<boolean, PersonalDataError>
rewrap
Section titled “rewrap”(options?) => Effect<RewrapResult, PersonalDataError>
See rewrap.
fields
Section titled “fields”readonly Field[]
location
Section titled “location”Omit<Location, "aggregateId"> & object
payload
Section titled “payload”Json
Returns
Section titled “Returns”Effect<WithSubjects, PersonalDataError | SubjectForgotten>