1import * as GCP from "alchemy/GCP";
2import * as Effect from "effect/Effect";
3
4/**
5 * The container for the key. Cloud KMS has no key ring delete API, so
6 * `alchemy destroy` only forgets the ring; an empty ring costs nothing.
7 */
8export const Keys = GCP.KMS.KeyRing("Keys", {});
9
10/**
11 * The symmetric key the service encrypts with. Key material never leaves
12 * KMS — the service only ever sees ciphertext and plaintext.
13 *
14 * KMS keeps destroyed keys for at least a day, so `alchemy destroy`
15 * *releases* this key (schedules every version for destruction and labels
16 * it `alchemy-released`). A deploy that asks for the same key id reclaims
17 * it and mints a fresh primary version.
18 */
19export const DataKey = Effect.gen(function* () {
20 const keys = yield* Keys;
21 return yield* GCP.KMS.CryptoKey("DataKey", {
22 keyRing: keys.name,
23 purpose: "ENCRYPT_DECRYPT",
24 });
25});
26
27/**
28 * The key callers must present in `x-api-key`. Only the service reads it,
29 * and only at request time.
30 *
31 * Alchemy creates the secret; adding the *version* that holds the value
32 * is an operator step:
33 *
34 * ```sh
35 * printf 'my-key' | gcloud secrets versions add "$SECRET_ID" --data-file=-
36 * ```
37 */
38export const ApiKey = GCP.SecretManager.Secret("ApiKey", {});