1import type { DecryptSecretKeyError } from "@distilled.cloud/fly-io/machines";
2import type * as Effect from "effect/Effect";
3import type * as Redacted from "effect/Redacted";
4import * as Binding from "../Binding.ts";
5import type { RuntimeContext } from "../RuntimeContext.ts";
6import type { SecretKey } from "./SecretKey.ts";
7
8export interface DecryptRequest {
9 /** Ciphertext produced by {@link Encrypt}. */
10 ciphertext: Uint8Array | ArrayLike<number>;
11 /** Optional AEAD associated data. Must match encryption. */
12 associatedData?: Uint8Array | ArrayLike<number>;
13}
14
15export interface DecryptResult {
16 /** Plaintext, wrapped so it never logs. Unwrap with `Redacted.value`. */
17 plaintext: Redacted.Redacted<Uint8Array>;
18}
19
20/**
21 * Decrypt with a Fly {@link SecretKey}. The App and key name are fixed
22 * by `Decrypt(key)`.
23 *
24 *
25 * ### Decrypt a payload
26 * Provide {@link DecryptHttp}. Plaintext comes back `Redacted`. Unwrap
27 * with `Redacted.value` only where you need the raw bytes.
28 *
29 * **Example:** Decrypt
30 * ```typescript
31 * import * as Redacted from "effect/Redacted";
32 *
33 * const decrypt = yield* Fly.Decrypt(Box);
34 * const { plaintext } = yield* decrypt({ ciphertext });
35 * const bytes = Redacted.value(plaintext);
36 * ```
37 *
38 * ### Associated data
39 * `associatedData` must match the bytes passed to {@link Encrypt}.
40 *
41 * **Example:** AEAD
42 * ```typescript
43 * const { plaintext } = yield* decrypt({
44 * ciphertext,
45 * associatedData: nonce,
46 * });
47 * ```
48 *
49 * @binding
50 * @product Secret Key
51 */
52export interface Decrypt extends Binding.Service<
53 Decrypt,
54 "Fly.Decrypt",
55 (
56 key: SecretKey,
57 ) => Effect.Effect<
58 (
59 request: DecryptRequest,
60 ) => Effect.Effect<DecryptResult, DecryptSecretKeyError, RuntimeContext>
61 >
62> {}
63
64export const Decrypt = Binding.Service<Decrypt>("Fly.Decrypt");