@molecule/api-encryption-aes 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +233 -0
  2. package/package.json +8 -7
package/README.md ADDED
@@ -0,0 +1,233 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-08-04T01:48:06.190Z
7
+ -->
8
+
9
+ # @molecule/api-encryption-aes
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ AES-256-GCM encryption provider for molecule.dev.
16
+
17
+ Uses Node.js built-in `crypto` for AES-256-GCM authenticated encryption,
18
+ SHA-256 hashing, and timing-safe verification. Supports key rotation with
19
+ versioned ciphertext format.
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import { setProvider } from '@molecule/api-encryption'
25
+ import { provider } from '@molecule/api-encryption-aes'
26
+
27
+ // Wire the provider at startup (reads ENCRYPTION_KEY from env)
28
+ setProvider(provider)
29
+
30
+ // Or create with explicit config
31
+ import { createProvider } from '@molecule/api-encryption-aes'
32
+ const customProvider = createProvider({ key: 'your-64-char-hex-key' })
33
+ setProvider(customProvider)
34
+ ```
35
+
36
+ ## Type
37
+
38
+ `provider`
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ npm install @molecule/api-encryption-aes @molecule/api-encryption @molecule/api-secrets
44
+ ```
45
+
46
+ ## API
47
+
48
+ ### Interfaces
49
+
50
+ #### `AesConfig`
51
+
52
+ Configuration options for the AES-256-GCM encryption provider.
53
+
54
+ ```typescript
55
+ interface AesConfig {
56
+ /** The current 256-bit encryption key, hex-encoded (64 hex characters). */
57
+ key: string
58
+
59
+ /**
60
+ * Version of the current `key`. Ciphertext produced by `encrypt()` is tagged
61
+ * with this version; `decrypt()` selects the key to use from the `v{n}` tag,
62
+ * so it must be stable for a given key. `rotateKey()` advances it.
63
+ *
64
+ * @default 1
65
+ */
66
+ keyVersion?: number
67
+
68
+ /**
69
+ * Prior keys to seed the keyring with, so ciphertext encrypted before a
70
+ * rotation still decrypts after this provider is (re)constructed — e.g. on a
71
+ * process restart, when the in-memory rotation state would otherwise be lost.
72
+ * Each entry maps a historical `v{n}` version to its key. The current `key`
73
+ * (at {@link AesConfig.keyVersion}) always wins over any prior entry sharing
74
+ * its version.
75
+ *
76
+ * @default []
77
+ */
78
+ priorKeys?: PriorKey[]
79
+ }
80
+ ```
81
+
82
+ #### `AesEncryptionProvider`
83
+
84
+ AES-256-GCM encryption provider.
85
+
86
+ Fully satisfies the core `EncryptionProvider` contract, so it bonds anywhere
87
+ an `EncryptionProvider` is expected. It additionally exposes
88
+ {@link AesEncryptionProvider.pruneKeyVersions} to explicitly retire old keys
89
+ once their ciphertext has been re-encrypted — rotation alone never drops a
90
+ key, so it can never orphan data.
91
+
92
+ ```typescript
93
+ interface AesEncryptionProvider extends EncryptionProvider {
94
+ /**
95
+ * Retires key versions from the in-memory keyring. Call this only AFTER every
96
+ * ciphertext encrypted under those versions has been re-encrypted under the
97
+ * current key — a pruned version can no longer decrypt its ciphertext.
98
+ *
99
+ * The current key version is ALWAYS retained (it cannot be pruned). By
100
+ * default every non-current version is removed; pass `keep` to retain
101
+ * specific older versions during a staged migration.
102
+ *
103
+ * @param keep - Old versions to retain in addition to the current one.
104
+ * @returns The versions that were removed.
105
+ */
106
+ pruneKeyVersions(keep?: number[]): number[]
107
+ }
108
+ ```
109
+
110
+ #### `PriorKey`
111
+
112
+ A historical (pre-rotation) key, retained so ciphertext encrypted under it
113
+ remains decryptable.
114
+
115
+ Ciphertext is tagged with the `v{version}` of the key that produced it; the
116
+ provider selects the matching key from its keyring at decrypt time. Seed the
117
+ keyring with the app's prior keys (from a secret store) so rotations survive
118
+ a process restart — see {@link AesConfig.priorKeys}.
119
+
120
+ ```typescript
121
+ interface PriorKey {
122
+ /** The key version tag this key decrypts (matches the `v{n}` ciphertext prefix). */
123
+ version: number
124
+
125
+ /** The 256-bit key, hex-encoded (64 hex characters). */
126
+ key: string
127
+ }
128
+ ```
129
+
130
+ ### Functions
131
+
132
+ #### `createProvider(config)`
133
+
134
+ Creates an AES-256-GCM encryption provider.
135
+
136
+ Rotation is transition-safe: keys are held in a version-keyed keyring.
137
+ `encrypt()` tags each ciphertext with the current key version, `decrypt()`
138
+ selects the key named by that tag, and `rotateKey()` ADDS the new key while
139
+ keeping prior keys — so ciphertext from before a rotation still decrypts.
140
+ Retire old keys explicitly (once their data is re-encrypted) via
141
+ `pruneKeyVersions()`.
142
+
143
+ ```typescript
144
+ function createProvider(config: AesConfig): AesEncryptionProvider
145
+ ```
146
+
147
+ - `config` — Provider configuration including the hex-encoded 256-bit key.
148
+
149
+ **Returns:** An `AesEncryptionProvider` using AES-256-GCM.
150
+
151
+ ### Constants
152
+
153
+ #### `encryptionAesSecretDefinitions`
154
+
155
+ Secret definitions required by the AES encryption bond.
156
+
157
+ ```typescript
158
+ const encryptionAesSecretDefinitions: SecretDefinition[]
159
+ ```
160
+
161
+ #### `provider`
162
+
163
+ Default AES-256-GCM encryption provider instance.
164
+
165
+ Lazily initializes on first property access using the `ENCRYPTION_KEY`
166
+ environment variable (hex-encoded 256-bit key). This singleton starts a
167
+ fresh keyring at version 1 on each process, so a rotation performed in a
168
+ prior process is NOT restored here — for rotation that survives restarts,
169
+ construct with `createProvider({ key, priorKeys })` seeding the historical
170
+ keys from your secret store.
171
+
172
+ ```typescript
173
+ const provider: AesEncryptionProvider
174
+ ```
175
+
176
+ ## Core Interface
177
+
178
+ Implements `@molecule/api-encryption` interface.
179
+
180
+ ## Bond Wiring
181
+
182
+ Setup function to register this provider with the core interface:
183
+
184
+ ```typescript
185
+ import { setProvider } from '@molecule/api-encryption'
186
+ import { provider } from '@molecule/api-encryption-aes'
187
+
188
+ export function setupEncryptionAes(): void {
189
+ setProvider(provider)
190
+ }
191
+ ```
192
+
193
+ ## Injection Notes
194
+
195
+ ### Requirements
196
+
197
+ Peer dependencies:
198
+
199
+ - `@molecule/api-encryption` ^1.0.1
200
+ - `@molecule/api-secrets` ^1.0.1
201
+
202
+ ### Environment Variables
203
+
204
+ - `ENCRYPTION_KEY` _(required)_ — AES-256 encryption key
205
+ - **Auto-generated at scaffold — no manual setup.**
206
+
207
+ ### Runtime Dependencies
208
+
209
+ - `@molecule/api-encryption`
210
+ - `@molecule/api-secrets`
211
+
212
+ - **`rotateKey()` is transition-safe — it never orphans data.** Keys live in
213
+ a version-keyed keyring: `encrypt()` tags each ciphertext with the current
214
+ `v{n}`, `decrypt()` reads that tag and selects the matching key, and
215
+ `rotateKey(oldKey, newKey)` ADDS `newKey` at the next version while RETAINING
216
+ the prior key(s). So ciphertext written before a rotation still decrypts
217
+ afterward (the core contract's "previously encrypted data can still be
218
+ decrypted during a transition period"). Once you have re-encrypted the old
219
+ ciphertext under the new key, retire the old keys explicitly with
220
+ `pruneKeyVersions()` — rotation alone deliberately keeps them.
221
+ - A ciphertext whose `v{n}` version is not in the keyring (unknown/pruned key)
222
+ fails cleanly with a descriptive error — never a silent wrong decrypt.
223
+ - Rotation state is per-process and in-memory: the lazy `provider` singleton
224
+ starts a fresh keyring at version 1 from `ENCRYPTION_KEY` on each process,
225
+ so a rotation done in a prior process is not restored. For rotation that
226
+ survives restarts, build with `createProvider({ key, priorKeys })`, seeding
227
+ the historical `{ version, key }` entries from your secret store.
228
+ - `hash()`/`verify()` are plain unsalted SHA-256 — integrity checks only.
229
+ NEVER use them for passwords; use `@molecule/api-password` with a bond
230
+ like `@molecule/api-password-bcrypt`.
231
+ - `encrypt(plaintext, context)`: the optional `context` is GCM AAD — the
232
+ SAME context string must be supplied to `decrypt()` or authentication
233
+ fails.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-encryption-aes",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "AES-256-GCM encryption provider for molecule.dev — authenticated encryption, SHA-256 hashing, and key rotation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -17,7 +17,8 @@
17
17
  }
18
18
  },
19
19
  "files": [
20
- "dist"
20
+ "dist",
21
+ "README.md"
21
22
  ],
22
23
  "keywords": [
23
24
  "molecule",
@@ -29,21 +30,21 @@
29
30
  ],
30
31
  "license": "Apache-2.0",
31
32
  "peerDependencies": {
32
- "@molecule/api-encryption": "^1.0.0",
33
- "@molecule/api-secrets": "^1.0.0"
33
+ "@molecule/api-encryption": "^1.0.1",
34
+ "@molecule/api-secrets": "^1.0.1"
34
35
  },
35
36
  "devDependencies": {
36
- "@molecule/api-encryption": "1.0.0",
37
+ "@molecule/api-encryption": "1.0.2",
37
38
  "@types/node": "26.1.2",
38
39
  "typescript": "6.0.3",
39
- "vitest": "4.1.10"
40
+ "vitest": "4.1.11"
40
41
  },
41
42
  "repository": {
42
43
  "type": "git",
43
44
  "url": "https://github.com/molecule-dev/molecule.git",
44
45
  "directory": "packages/api/bonds/encryption/aes"
45
46
  },
46
- "homepage": "https://github.com/molecule-dev/molecule/tree/main/packages/api/bonds/encryption/aes",
47
+ "homepage": "https://www.molecule.dev/packages/api-encryption-aes",
47
48
  "bugs": "https://github.com/molecule-dev/molecule/issues",
48
49
  "publishConfig": {
49
50
  "access": "public"