src/key-rotation-types.tsTypeScript
@@ -0,0 +1,96 @@
1+
export interface EncryptedDocument {2+
id: string;3+
tenantId: string;4+
revision: number;5+
keyId: string;6+
ciphertext: Uint8Array;7+
quarantined: boolean;8+
}9+
10+
export type KeyRotationPhase =11+
| "created"12+
| "target-active"13+
| "scanning"14+
| "verifying"15+
| "complete";16+
17+
export interface KeyRotationRecord {18+
tenantId: string;19+
sourceKeyId: string;20+
targetKeyId: string;21+
phase: KeyRotationPhase;22+
checkpoint?: string;23+
writerEpoch?: number;24+
}25+
26+
export interface TenantRotationLease {27+
readonly fencingToken: number;28+
release(): Promise<void>;29+
}30+
31+
export interface KeyRotationDependencies {32+
keys: {33+
active(tenantId: string): Promise<string>;34+
create(tenantId: string): Promise<string>;35+
activate(tenantId: string, keyId: string): Promise<void>;36+
retire(tenantId: string, keyId: string): Promise<void>;37+
};38+
cryptography: {39+
decrypt(keyId: string, ciphertext: Uint8Array): Promise<Uint8Array>;40+
encrypt(keyId: string, plaintext: Uint8Array): Promise<Uint8Array>;41+
};42+
documents: {43+
scan(tenantId: string, afterId: string | undefined, limit: number): Promise<EncryptedDocument[]>;44+
put(document: EncryptedDocument): Promise<void>;45+
countUsingKey(tenantId: string, keyId: string): Promise<number>;46+
get(47+
tenantId: string,48+
documentId: string,49+
): Promise<EncryptedDocument | undefined>;50+
compareAndSwapReencrypted(51+
tenantId: string,52+
documentId: string,53+
expectedRevision: number,54+
replacement: { keyId: string; ciphertext: Uint8Array },55+
): Promise<"updated" | "revision-conflict">;56+
countNonQuarantinedUsingKey(57+
tenantId: string,58+
keyId: string,59+
): Promise<number>;60+
};61+
checkpoints: {62+
load(tenantId: string): Promise<string | undefined>;63+
save(tenantId: string, documentId: string): Promise<void>;64+
};65+
leases: {66+
acquire(tenantId: string): Promise<TenantRotationLease>;67+
};68+
rotations: {69+
startOrResume(70+
tenantId: string,71+
lease: TenantRotationLease,72+
): Promise<KeyRotationRecord>;73+
save(74+
record: KeyRotationRecord,75+
lease: TenantRotationLease,76+
): Promise<void>;77+
};78+
quarantine: {79+
record(input: {80+
tenantId: string;81+
documentId: string;82+
revision: number;83+
keyId: string;84+
reason: "decrypt-failed";85+
}): Promise<void>;86+
countReferencingKey(tenantId: string, keyId: string): Promise<number>;87+
};88+
writers: {89+
activateTarget(90+
tenantId: string,91+
targetKeyId: string,92+
lease: TenantRotationLease,93+
): Promise<number>;94+
waitUntilAcknowledged(tenantId: string, writerEpoch: number): Promise<void>;95+
};96+
}