@wemush/wols 0.1.0 → 1.3.0
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.
- package/CHANGELOG.md +170 -0
- package/README.md +204 -31
- package/dist/cjs/compact-url.d.ts +150 -0
- package/dist/cjs/compact-url.d.ts.map +1 -0
- package/dist/cjs/compact-url.js +64 -0
- package/dist/cjs/compact-url.js.map +1 -1
- package/dist/cjs/crypto/decrypt.d.ts +110 -0
- package/dist/cjs/crypto/decrypt.d.ts.map +1 -0
- package/dist/cjs/crypto/decrypt.js +521 -90
- package/dist/cjs/crypto/decrypt.js.map +1 -1
- package/dist/cjs/crypto/encrypt.d.ts +132 -0
- package/dist/cjs/crypto/encrypt.d.ts.map +1 -0
- package/dist/cjs/crypto/encrypt.js +288 -105
- package/dist/cjs/crypto/encrypt.js.map +1 -1
- package/dist/cjs/crypto/index.d.ts +12 -0
- package/dist/cjs/crypto/index.d.ts.map +1 -0
- package/dist/cjs/crypto/index.js +15 -2
- package/dist/cjs/crypto/index.js.map +1 -1
- package/dist/cjs/crypto/shared.d.ts +116 -0
- package/dist/cjs/crypto/shared.d.ts.map +1 -0
- package/dist/cjs/crypto/shared.js +238 -0
- package/dist/cjs/crypto/shared.js.map +1 -0
- package/dist/cjs/errors.d.ts +133 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +39 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.d.ts +29 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +70 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/parser.d.ts +30 -0
- package/dist/cjs/parser.d.ts.map +1 -0
- package/dist/cjs/parser.js +3 -0
- package/dist/cjs/parser.js.map +1 -1
- package/dist/cjs/qr/generate.d.ts +62 -0
- package/dist/cjs/qr/generate.d.ts.map +1 -0
- package/dist/cjs/qr/index.d.ts +10 -0
- package/dist/cjs/qr/index.d.ts.map +1 -0
- package/dist/cjs/specimen.d.ts +96 -0
- package/dist/cjs/specimen.d.ts.map +1 -0
- package/dist/cjs/specimen.js +95 -9
- package/dist/cjs/specimen.js.map +1 -1
- package/dist/cjs/types.d.ts +735 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +327 -3
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/cuid.d.ts +46 -0
- package/dist/cjs/utils/cuid.d.ts.map +1 -0
- package/dist/cjs/utils/cuid.js +6 -4
- package/dist/cjs/utils/cuid.js.map +1 -1
- package/dist/cjs/utils/environment.d.ts +137 -0
- package/dist/cjs/utils/environment.d.ts.map +1 -0
- package/dist/cjs/utils/environment.js +206 -0
- package/dist/cjs/utils/environment.js.map +1 -0
- package/dist/cjs/utils/iso8601.d.ts +79 -0
- package/dist/cjs/utils/iso8601.d.ts.map +1 -0
- package/dist/cjs/utils/migration.d.ts +162 -0
- package/dist/cjs/utils/migration.d.ts.map +1 -0
- package/dist/cjs/utils/migration.js +248 -0
- package/dist/cjs/utils/migration.js.map +1 -0
- package/dist/cjs/validator.d.ts +25 -0
- package/dist/cjs/validator.d.ts.map +1 -0
- package/dist/cjs/validator.js +85 -21
- package/dist/cjs/validator.js.map +1 -1
- package/dist/esm/compact-url.js +62 -0
- package/dist/esm/compact-url.js.map +1 -1
- package/dist/esm/crypto/decrypt.js +517 -90
- package/dist/esm/crypto/decrypt.js.map +1 -1
- package/dist/esm/crypto/encrypt.js +284 -105
- package/dist/esm/crypto/encrypt.js.map +1 -1
- package/dist/esm/crypto/index.js +5 -3
- package/dist/esm/crypto/index.js.map +1 -1
- package/dist/esm/crypto/shared.js +222 -0
- package/dist/esm/crypto/shared.js.map +1 -0
- package/dist/esm/errors.js +37 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +26 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/parser.js +3 -0
- package/dist/esm/parser.js.map +1 -1
- package/dist/esm/specimen.js +95 -10
- package/dist/esm/specimen.js.map +1 -1
- package/dist/esm/types.js +317 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/cuid.js +6 -4
- package/dist/esm/utils/cuid.js.map +1 -1
- package/dist/esm/utils/environment.js +193 -0
- package/dist/esm/utils/environment.js.map +1 -0
- package/dist/esm/utils/migration.js +237 -0
- package/dist/esm/utils/migration.js.map +1 -0
- package/dist/esm/validator.js +86 -22
- package/dist/esm/validator.js.map +1 -1
- package/dist/types/compact-url.d.ts +46 -0
- package/dist/types/compact-url.d.ts.map +1 -1
- package/dist/types/crypto/decrypt.d.ts +95 -18
- package/dist/types/crypto/decrypt.d.ts.map +1 -1
- package/dist/types/crypto/encrypt.d.ts +114 -14
- package/dist/types/crypto/encrypt.d.ts.map +1 -1
- package/dist/types/crypto/index.d.ts +5 -3
- package/dist/types/crypto/index.d.ts.map +1 -1
- package/dist/types/crypto/shared.d.ts +116 -0
- package/dist/types/crypto/shared.d.ts.map +1 -0
- package/dist/types/errors.d.ts +31 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +15 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/parser.d.ts.map +1 -1
- package/dist/types/specimen.d.ts +29 -4
- package/dist/types/specimen.d.ts.map +1 -1
- package/dist/types/types.d.ts +483 -17
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/cuid.d.ts +5 -3
- package/dist/types/utils/cuid.d.ts.map +1 -1
- package/dist/types/utils/environment.d.ts +137 -0
- package/dist/types/utils/environment.d.ts.map +1 -0
- package/dist/types/utils/migration.d.ts +162 -0
- package/dist/types/utils/migration.d.ts.map +1 -0
- package/dist/types/validator.d.ts +1 -1
- package/dist/types/validator.d.ts.map +1 -1
- package/package.json +32 -14
|
@@ -1,33 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WOLS Decryption Module
|
|
2
|
+
* WOLS Decryption Module (WOLS v1.3.0 encrypted format)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Decrypts `wemush://v1/encrypted/...` URLs, the equivalent
|
|
5
|
+
* {@link EncryptedSpecimen} objects, and field-level {@link EncryptedField}
|
|
6
|
+
* values, using WebCrypto only.
|
|
7
|
+
*
|
|
8
|
+
* Failures never throw; they return `{ success: false, error }` where `error`
|
|
9
|
+
* is a {@link WolsDecryptionError} with a stable, typed `reason`.
|
|
10
|
+
*
|
|
11
|
+
* Every cheap check (parameter presence, encodings, IV length, iteration
|
|
12
|
+
* bounds, key type) runs before PBKDF2, so a malformed or hostile label costs
|
|
13
|
+
* no key derivation. The iteration count comes from the label and is bounded
|
|
14
|
+
* by `maxIterations` (default 10,000,000).
|
|
15
|
+
*
|
|
16
|
+
* Legacy payloads (no `kdf`, pre-1.3.0 fixed salt) are rejected with
|
|
17
|
+
* `legacy-format` unless `allowLegacy: true` is passed.
|
|
6
18
|
*
|
|
7
19
|
* @module crypto/decrypt
|
|
8
20
|
*/
|
|
9
|
-
import type {
|
|
21
|
+
import type { DecryptResult, DecryptionOptions, EncryptedField, EncryptedSpecimen, FieldEncryptedSpecimen, Specimen } from '../types.js';
|
|
22
|
+
/**
|
|
23
|
+
* Parse an encrypted-format URL into an {@link EncryptedSpecimen} without decrypting.
|
|
24
|
+
*
|
|
25
|
+
* Only checks URL structure. Parameter rules (kdf, salt, iterations) are
|
|
26
|
+
* enforced on decryption. The path segment is percent-decoded to recover the ID.
|
|
27
|
+
*
|
|
28
|
+
* @since 1.3.0
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseEncryptedUrl(url: string): DecryptResult<EncryptedSpecimen>;
|
|
10
31
|
/**
|
|
11
|
-
* Decrypt an encrypted
|
|
32
|
+
* Decrypt an encrypted label to its exact plaintext (the embedded JSON-LD string).
|
|
12
33
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
34
|
+
* Enforces every v1.3.0 wire rule, including that the decrypted specimen's
|
|
35
|
+
* `id` equals `wemush:{id}` from the URL path. For object input the check is
|
|
36
|
+
* made against the object's `id`; an object without `id` is not bound to any
|
|
37
|
+
* ID, so prefer the URL form for untrusted input.
|
|
38
|
+
*
|
|
39
|
+
* @param input - `wemush://v1/encrypted/...` URL or an {@link EncryptedSpecimen}
|
|
40
|
+
* @param options - `key`, and optional `allowLegacy` and `maxIterations`
|
|
41
|
+
* @since 1.3.0
|
|
42
|
+
*/
|
|
43
|
+
export declare function decryptPlaintext(input: string | EncryptedSpecimen, options: DecryptionOptions): Promise<DecryptResult<string>>;
|
|
44
|
+
/**
|
|
45
|
+
* Decrypt an encrypted label and parse it into a validated Specimen.
|
|
46
|
+
*
|
|
47
|
+
* @param input - `wemush://v1/encrypted/...` URL or an {@link EncryptedSpecimen}
|
|
48
|
+
* @param options - `key`, and optional `allowLegacy` and `maxIterations`
|
|
49
|
+
* @returns DecryptResult; on failure `error.reason` gives the category
|
|
16
50
|
*
|
|
17
51
|
* @example
|
|
18
52
|
* ```typescript
|
|
19
|
-
*
|
|
53
|
+
* const result = await decryptSpecimen(url, { key: 'correct horse battery staple' });
|
|
54
|
+
* if (result.success) console.log(result.data.species);
|
|
55
|
+
* else console.error(result.error.reason, result.error.message);
|
|
56
|
+
* ```
|
|
20
57
|
*
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
|
|
58
|
+
* @since 1.3.0 Accepts encrypted URLs, raw key bytes, `allowLegacy` and `maxIterations`
|
|
59
|
+
*/
|
|
60
|
+
export declare function decryptSpecimen(input: string | EncryptedSpecimen, options: DecryptionOptions): Promise<DecryptResult<Specimen>>;
|
|
61
|
+
/**
|
|
62
|
+
* Decrypt a single field-level {@link EncryptedField} to its original value.
|
|
24
63
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
64
|
+
* `binding` names the label and field the value belongs to. It is the AES-GCM
|
|
65
|
+
* additional data (`"{id}\n{field}"`, WOLS 1.3.0), so a value moved to another
|
|
66
|
+
* field or copied from another label fails with `authentication-failed`.
|
|
67
|
+
* Legacy (pre-1.3.0) values, which have no `kdf`, carry no binding.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* const r = await decryptField(partial.strain, { key }, { id: partial.id, field: 'strain' });
|
|
30
72
|
* ```
|
|
73
|
+
*
|
|
74
|
+
* @since 1.3.0
|
|
75
|
+
*/
|
|
76
|
+
export declare function decryptField(field: EncryptedField, options: DecryptionOptions, binding: FieldBinding): Promise<DecryptResult<unknown>>;
|
|
77
|
+
/** The label and top-level field an encrypted value belongs to. */
|
|
78
|
+
export interface FieldBinding {
|
|
79
|
+
/** The label's full id, e.g. `"wemush:clx1a2b3c4"` */
|
|
80
|
+
id: string;
|
|
81
|
+
/** The top-level field name, e.g. `"strain"` */
|
|
82
|
+
field: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Decrypt every field-level encrypted value in a specimen produced by
|
|
86
|
+
* `encryptFields()`, and return the restored, validated Specimen.
|
|
87
|
+
*
|
|
88
|
+
* Before any key is derived:
|
|
89
|
+
* - a label whose identifying fields (`@context`, `@type`, `id`, `version`,
|
|
90
|
+
* `type`, `species`) include an encrypted object is refused
|
|
91
|
+
* (`identifying-field`); decrypted values never replace them
|
|
92
|
+
* - every encrypted field is validated
|
|
93
|
+
* - the iterations of each distinct (salt, iterations) pair are summed, and
|
|
94
|
+
* the label is refused if the total exceeds `maxIterations` (10,000,000)
|
|
95
|
+
*
|
|
96
|
+
* Fields sharing a salt and iteration count share one derivation. Each value
|
|
97
|
+
* is authenticated against its AAD, `"{id}\n{field}"`, so swapped or copied
|
|
98
|
+
* values fail with `authentication-failed`.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const partial = await encryptFields(specimen, { key, fields: ['strain'] });
|
|
103
|
+
* const restored = await decryptFields(partial, { key });
|
|
104
|
+
* if (restored.success) restored.data.strain?.name;
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @since 1.3.0
|
|
31
108
|
*/
|
|
32
|
-
export declare function
|
|
109
|
+
export declare function decryptFields(value: FieldEncryptedSpecimen | Record<string, unknown>, options: DecryptionOptions): Promise<DecryptResult<Specimen>>;
|
|
33
110
|
//# sourceMappingURL=decrypt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../../src/crypto/decrypt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"decrypt.d.ts","sourceRoot":"","sources":["../../../src/crypto/decrypt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EAEjB,sBAAsB,EAEtB,QAAQ,EACT,MAAM,aAAa,CAAC;AAwDrB;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAuE/E;AAwSD;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EACjC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CA8BhC;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EACjC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAIlC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAiBjC;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAsCD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvD,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAyGlC"}
|
|
@@ -1,32 +1,132 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WOLS Encryption Module
|
|
2
|
+
* WOLS Encryption Module (WOLS v1.3.0 encrypted format)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* AES-256-GCM via WebCrypto, so it runs in Node.js 20+, browsers, Deno and Bun.
|
|
5
|
+
*
|
|
6
|
+
* ## Wire format
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* wemush://v1/encrypted/{id}?e={ciphertext}&iv={iv}&kdf={pbkdf2|raw}[&salt={salt}&i={iterations}]
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* - `e`: ciphertext with the 16-byte GCM tag appended
|
|
13
|
+
* - `iv`: fresh random 12-byte IV per encryption
|
|
14
|
+
* - All binary values are base64url without padding
|
|
15
|
+
*
|
|
16
|
+
* ## Keys
|
|
17
|
+
*
|
|
18
|
+
* | `key` value | `kdf` | Notes |
|
|
19
|
+
* |-------------|-------|-------|
|
|
20
|
+
* | `string` passphrase | `pbkdf2` | PBKDF2-HMAC-SHA256, fresh random 16-byte salt per label, ≥100,000 iterations |
|
|
21
|
+
* | 32-byte `Uint8Array` / `ArrayBuffer` | `raw` | Key shared out of band |
|
|
22
|
+
* | AES-GCM 256 `CryptoKey` | `raw` | Key shared out of band |
|
|
23
|
+
*
|
|
24
|
+
* Pre-1.3.0 releases derived passphrase keys with a fixed library-wide salt.
|
|
25
|
+
* That scheme is never generated any more; see `allowLegacy` on decryption.
|
|
6
26
|
*
|
|
7
27
|
* @module crypto/encrypt
|
|
8
28
|
*/
|
|
9
|
-
import type {
|
|
29
|
+
import type { EncryptedField, EncryptedSpecimen, EncryptionOptions, FieldEncryptedSpecimen, FieldEncryptedSpecimenOf, FieldEncryptionOptions, Specimen } from '../types.js';
|
|
10
30
|
/**
|
|
11
|
-
*
|
|
31
|
+
* Build the encrypted-format URL for an encrypted specimen.
|
|
32
|
+
*
|
|
33
|
+
* Enforces the generator rules, so a hand-built object cannot produce a
|
|
34
|
+
* non-conformant label:
|
|
35
|
+
* - `payload` and `iv` are canonical unpadded base64url, the IV is 12 bytes,
|
|
36
|
+
* and the payload is at least the 16-byte GCM tag
|
|
37
|
+
* - `kdf` is present: `pbkdf2` needs 100,000 to 2^32-1 iterations and a salt
|
|
38
|
+
* of at least 16 bytes that is not the legacy library salt (compared as
|
|
39
|
+
* bytes); `raw` must not carry `salt` or `iterations`
|
|
40
|
+
*
|
|
41
|
+
* Labels with more than 10,000,000 iterations are valid but exceed the
|
|
42
|
+
* decoders' default `maxIterations`, so readers must raise it.
|
|
43
|
+
*
|
|
44
|
+
* @throws WolsEncryptionError when the object would produce a non-conformant
|
|
45
|
+
* label (including legacy payloads, which are never generated)
|
|
46
|
+
* @since 1.3.0
|
|
47
|
+
*/
|
|
48
|
+
export declare function toEncryptedUrl(encrypted: EncryptedSpecimen): string;
|
|
49
|
+
/**
|
|
50
|
+
* Encrypt a whole specimen with AES-256-GCM (WOLS v1.3.0 encrypted format).
|
|
51
|
+
*
|
|
52
|
+
* The specimen's embedded JSON-LD serialization is encrypted and the result
|
|
53
|
+
* carries `url`, the `wemush://v1/encrypted/...` string to encode in a QR code.
|
|
54
|
+
* For field-level encryption use {@link encryptFields}.
|
|
12
55
|
*
|
|
13
56
|
* @param specimen - The specimen to encrypt
|
|
14
|
-
* @param options -
|
|
15
|
-
* @
|
|
57
|
+
* @param options - `key` (passphrase or raw key) and optional `iterations`
|
|
58
|
+
* @throws WolsEncryptionError for an unusable key, too few iterations, an id
|
|
59
|
+
* without a suffix, or a runtime without WebCrypto
|
|
16
60
|
*
|
|
17
61
|
* @example
|
|
18
62
|
* ```typescript
|
|
19
|
-
*
|
|
63
|
+
* // Passphrase: kdf=pbkdf2 with a random per-label salt
|
|
64
|
+
* const enc = await encryptSpecimen(specimen, { key: 'correct horse battery staple' });
|
|
65
|
+
* enc.url; // 'wemush://v1/encrypted/clx1a2b3c4?e=...&iv=...&kdf=pbkdf2&salt=...&i=100000'
|
|
20
66
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* });
|
|
24
|
-
* // Returns: { encrypted: true, payload: "...", iv: "...", algorithm: "AES-256-GCM" }
|
|
67
|
+
* // Raw 32-byte key: kdf=raw
|
|
68
|
+
* const raw = await encryptSpecimen(specimen, { key: crypto.getRandomValues(new Uint8Array(32)) });
|
|
25
69
|
* ```
|
|
70
|
+
*
|
|
71
|
+
* @since 1.3.0 Per-label random salt, `kdf`, `id` and `url`; raw key bytes accepted.
|
|
72
|
+
* The `fields` option is deprecated in favor of `encryptFields()`.
|
|
26
73
|
*/
|
|
74
|
+
export declare function encryptSpecimen(specimen: Specimen, options: EncryptionOptions & {
|
|
75
|
+
fields: readonly string[];
|
|
76
|
+
}): Promise<FieldEncryptedSpecimen>;
|
|
27
77
|
export declare function encryptSpecimen(specimen: Specimen, options: EncryptionOptions): Promise<EncryptedSpecimen>;
|
|
28
78
|
/**
|
|
29
|
-
*
|
|
79
|
+
* Field-level encryption (WOLS v1.3.0): replace the value of each named field
|
|
80
|
+
* with an {@link EncryptedField} and leave the rest of the specimen in cleartext.
|
|
81
|
+
*
|
|
82
|
+
* One key (and, for passphrases, one random salt) per call; a fresh IV per field.
|
|
83
|
+
* Each value is bound to its label and field with AES-GCM additional data:
|
|
84
|
+
* the UTF-8 of `"{id}\n{field}"` (WOLS 1.3.0). A value moved to another field
|
|
85
|
+
* or copied into another label fails authentication. Restore with `decryptFields()`.
|
|
86
|
+
*
|
|
87
|
+
* The identifying fields (`@context`, `@type`, `id`, `version`, `type`,
|
|
88
|
+
* `species`) can't be encrypted.
|
|
89
|
+
*
|
|
90
|
+
* @param specimen - The specimen to partially encrypt
|
|
91
|
+
* @param options - `key`, `fields` (each must be present on the specimen), optional `iterations`
|
|
92
|
+
* @throws WolsEncryptionError when `fields` is empty, names a field the specimen
|
|
93
|
+
* does not have, or names a field twice; or for an unusable key
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const partial = await encryptFields(specimen, { key: passphrase, fields: ['strain'] });
|
|
98
|
+
* partial.species; // still cleartext
|
|
99
|
+
* partial.strain; // { encrypted: true, algorithm: 'AES-256-GCM', payload, iv, kdf: 'pbkdf2', salt, iterations }
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @since 1.3.0
|
|
103
|
+
*/
|
|
104
|
+
export declare function encryptFields<K extends keyof Specimen>(specimen: Specimen, options: FieldEncryptionOptions<K>): Promise<FieldEncryptedSpecimenOf<K>>;
|
|
105
|
+
/**
|
|
106
|
+
* Whether a value is a field-level {@link EncryptedField}: an encrypted value
|
|
107
|
+
* with a `kdf` and no specimen `id` or `url`.
|
|
108
|
+
*
|
|
109
|
+
* The 1.3.0 shapes are told apart structurally: whole-label objects produced
|
|
110
|
+
* by `encryptSpecimen` and `parseEncryptedUrl` always carry `id`, and field
|
|
111
|
+
* values never do. Legacy (pre-1.3.0) values have no `kdf` and are reported
|
|
112
|
+
* as {@link isEncryptedSpecimen}, whether they were whole labels or fields.
|
|
113
|
+
* `decryptFields` handles legacy field values regardless (with `allowLegacy`).
|
|
114
|
+
*
|
|
115
|
+
* @since 1.3.0
|
|
116
|
+
*/
|
|
117
|
+
export declare function isEncryptedField(value: unknown): value is EncryptedField;
|
|
118
|
+
/**
|
|
119
|
+
* Whether a value is a whole-label {@link EncryptedSpecimen} (v1.3.0 or legacy).
|
|
120
|
+
*
|
|
121
|
+
* @since 1.3.0
|
|
122
|
+
*/
|
|
123
|
+
export declare function isEncryptedSpecimen(value: unknown): value is EncryptedSpecimen;
|
|
124
|
+
/**
|
|
125
|
+
* Whether a value carries the `encrypted: true` marker: either a whole-label
|
|
126
|
+
* {@link EncryptedSpecimen} or a field-level {@link EncryptedField}. Use
|
|
127
|
+
* {@link isEncryptedSpecimen} or {@link isEncryptedField} to tell them apart.
|
|
128
|
+
*
|
|
129
|
+
* @since 1.3.0 Narrows to `EncryptedSpecimen | EncryptedField`
|
|
30
130
|
*/
|
|
31
|
-
export declare function isEncrypted(value: unknown): value is EncryptedSpecimen;
|
|
131
|
+
export declare function isEncrypted(value: unknown): value is EncryptedSpecimen | EncryptedField;
|
|
32
132
|
//# sourceMappingURL=encrypt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../../src/crypto/encrypt.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"encrypt.d.ts","sourceRoot":"","sources":["../../../src/crypto/encrypt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAEjB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,EACtB,QAAQ,EACT,MAAM,aAAa,CAAC;AA+IrB;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAmCnE;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,iBAAiB,GAAG;IAAE,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACzD,OAAO,CAAC,sBAAsB,CAAC,CAAC;AACnC,wBAAsB,eAAe,CACnC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAuC9B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,CAAC,SAAS,MAAM,QAAQ,EAC1D,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAuDtC;AAgBD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAOxE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,GAAG,cAAc,CAKvF"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WOLS Crypto Module
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* AES-256-GCM encryption and decryption for specimens in the WOLS v1.3.0
|
|
5
|
+
* encrypted format (`wemush://v1/encrypted/{id}?e=&iv=&kdf=...`).
|
|
5
6
|
*
|
|
6
7
|
* @module crypto
|
|
7
8
|
*/
|
|
8
|
-
export { encryptSpecimen, isEncrypted } from './encrypt.js';
|
|
9
|
-
export { decryptSpecimen } from './decrypt.js';
|
|
9
|
+
export { encryptSpecimen, encryptFields, isEncrypted, isEncryptedSpecimen, isEncryptedField, toEncryptedUrl, } from './encrypt.js';
|
|
10
|
+
export { decryptSpecimen, decryptPlaintext, decryptField, decryptFields, parseEncryptedUrl, type FieldBinding, } from './decrypt.js';
|
|
11
|
+
export { base64UrlEncode, base64UrlDecode, derivePassphraseKey } from './shared.js';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/crypto/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/crypto/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared primitives for the WOLS encrypted format (v1.3.0).
|
|
3
|
+
*
|
|
4
|
+
* Uses only WebCrypto (`globalThis.crypto.subtle`), so it runs unchanged in
|
|
5
|
+
* Node.js 20+, browsers, Deno, Bun and workers.
|
|
6
|
+
*
|
|
7
|
+
* `base64UrlEncode`, `base64UrlDecode` and `derivePassphraseKey` are public
|
|
8
|
+
* (re-exported from the package root and `@wemush/wols/crypto`); everything
|
|
9
|
+
* else here is internal to the crypto module.
|
|
10
|
+
*
|
|
11
|
+
* @module crypto/shared
|
|
12
|
+
*/
|
|
13
|
+
import { WolsDecryptionError } from '../errors.js';
|
|
14
|
+
import type { DecryptionFailureReason, RawEncryptionKey } from '../types.js';
|
|
15
|
+
/** Default PBKDF2 iteration count used when generating. */
|
|
16
|
+
export declare const DEFAULT_PBKDF2_ITERATIONS = 600000;
|
|
17
|
+
/** Iteration count pre-1.3.0 payloads used when they recorded none. */
|
|
18
|
+
export declare const LEGACY_PBKDF2_ITERATIONS = 100000;
|
|
19
|
+
/** Generators MUST use at least this many PBKDF2 iterations (WOLS v1.3.0). */
|
|
20
|
+
export declare const MIN_GENERATE_ITERATIONS = 100000;
|
|
21
|
+
/** Decoders MUST reject fewer PBKDF2 iterations than this (WOLS v1.3.0). */
|
|
22
|
+
export declare const MIN_DECODE_ITERATIONS = 10000;
|
|
23
|
+
/** Default largest PBKDF2 iteration count accepted from a label when decoding. */
|
|
24
|
+
export declare const DEFAULT_MAX_DECODE_ITERATIONS = 10000000;
|
|
25
|
+
/**
|
|
26
|
+
* WOLS 1.3.0 ceiling: decoders reject more than this many iterations (alone,
|
|
27
|
+
* or in total across a field-encrypted label), and generators never exceed it.
|
|
28
|
+
* A configured `maxIterations` may be lower, never higher.
|
|
29
|
+
*/
|
|
30
|
+
export declare const MAX_ITERATIONS = 10000000;
|
|
31
|
+
/** WebCrypto's PBKDF2 `iterations` is an unsigned long; nothing above this is derivable. */
|
|
32
|
+
export declare const MAX_PBKDF2_ITERATIONS = 4294967295;
|
|
33
|
+
/** Per-label PBKDF2 salt length generated (spec minimum: 16 bytes). */
|
|
34
|
+
export declare const SALT_LENGTH = 16;
|
|
35
|
+
/** AES-GCM appends a 16-byte authentication tag, so no valid ciphertext is shorter. */
|
|
36
|
+
export declare const GCM_TAG_LENGTH = 16;
|
|
37
|
+
/** AES-GCM IV length in bytes. */
|
|
38
|
+
export declare const IV_LENGTH = 12;
|
|
39
|
+
/** Raw AES-256 key length in bytes. */
|
|
40
|
+
export declare const RAW_KEY_LENGTH = 32;
|
|
41
|
+
/** Prefix of every encrypted-format URL. */
|
|
42
|
+
export declare const ENCRYPTED_URL_PREFIX = "wemush://v1/encrypted/";
|
|
43
|
+
/**
|
|
44
|
+
* Library-wide salt used by pre-1.3.0 releases. Only for decoding legacy
|
|
45
|
+
* payloads behind `allowLegacy`; never used when generating.
|
|
46
|
+
*/
|
|
47
|
+
export declare const LEGACY_PBKDF2_SALT: Uint8Array<ArrayBuffer>;
|
|
48
|
+
/**
|
|
49
|
+
* Create a decryption error carrying a stable `details.reason` category.
|
|
50
|
+
*/
|
|
51
|
+
export declare function decryptionError(reason: DecryptionFailureReason, message: string, details?: Record<string, unknown>): WolsDecryptionError;
|
|
52
|
+
/**
|
|
53
|
+
* Whether WebCrypto (`globalThis.crypto.subtle`) is available. It is global in
|
|
54
|
+
* browsers, workers, Deno, Bun and Node.js 19+ (Node 18 needs
|
|
55
|
+
* `--experimental-global-webcrypto`).
|
|
56
|
+
*/
|
|
57
|
+
export declare function hasWebCrypto(): boolean;
|
|
58
|
+
/** Message used when WebCrypto is missing. */
|
|
59
|
+
export declare const NO_WEBCRYPTO_MESSAGE: string;
|
|
60
|
+
/** Throw a WolsEncryptionError when WebCrypto is missing (encryption paths). */
|
|
61
|
+
export declare function assertWebCrypto(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Encode bytes as base64url (RFC 4648 §5) without padding.
|
|
64
|
+
*
|
|
65
|
+
* @since 1.3.0
|
|
66
|
+
*/
|
|
67
|
+
export declare function base64UrlEncode(bytes: Uint8Array | ArrayBuffer): string;
|
|
68
|
+
/**
|
|
69
|
+
* Decode base64url (RFC 4648 §5). Padded input is accepted.
|
|
70
|
+
*
|
|
71
|
+
* @throws Error if the input is not valid base64url
|
|
72
|
+
* @since 1.3.0
|
|
73
|
+
*/
|
|
74
|
+
export declare function base64UrlDecode(value: string): Uint8Array<ArrayBuffer>;
|
|
75
|
+
/** Cryptographically random bytes from WebCrypto. */
|
|
76
|
+
export declare function randomBytes(length: number): Uint8Array<ArrayBuffer>;
|
|
77
|
+
/**
|
|
78
|
+
* Derive a 256-bit key from a passphrase with PBKDF2-HMAC-SHA256.
|
|
79
|
+
*
|
|
80
|
+
* Exposed for debugging and interoperability testing (it reproduces the
|
|
81
|
+
* conformance `derive` vectors). Returns the raw key bytes.
|
|
82
|
+
*
|
|
83
|
+
* @param passphrase - Passphrase; normalized to Unicode NFC, then UTF-8 encoded (WOLS 1.3.0)
|
|
84
|
+
* @param salt - Salt bytes (the label's decoded `salt` parameter)
|
|
85
|
+
* @param iterations - PBKDF2 iteration count (positive integer)
|
|
86
|
+
* @since 1.3.0
|
|
87
|
+
*/
|
|
88
|
+
export declare function derivePassphraseKey(passphrase: string, salt: Uint8Array | ArrayBuffer, iterations: number): Promise<Uint8Array<ArrayBuffer>>;
|
|
89
|
+
/**
|
|
90
|
+
* Field-level AES-GCM additional data (WOLS 1.3.0): UTF-8 of the label's full
|
|
91
|
+
* `id`, a line feed, and the top-level field name, e.g. "wemush:clx1a2b3c4\nstrain".
|
|
92
|
+
* Binds each encrypted value to its label and field.
|
|
93
|
+
*/
|
|
94
|
+
export declare function fieldAad(id: string, field: string): Uint8Array<ArrayBuffer>;
|
|
95
|
+
/**
|
|
96
|
+
* Fields that identify or type a label. They are never encrypted, and a label
|
|
97
|
+
* in which any of them is an encrypted object is refused (WOLS 1.3.0).
|
|
98
|
+
*/
|
|
99
|
+
export declare const IDENTIFYING_FIELDS: readonly string[];
|
|
100
|
+
/** Import 32 raw key bytes as an AES-GCM key. */
|
|
101
|
+
export declare function importAesKey(bytes: Uint8Array | ArrayBuffer, usage: 'encrypt' | 'decrypt'): Promise<CryptoKey>;
|
|
102
|
+
/**
|
|
103
|
+
* Check whether a value is a WebCrypto CryptoKey without relying on the
|
|
104
|
+
* global `CryptoKey` constructor (absent in some runtimes).
|
|
105
|
+
*/
|
|
106
|
+
export declare function isCryptoKey(value: unknown): value is CryptoKey;
|
|
107
|
+
/**
|
|
108
|
+
* Resolve a raw key (bytes or CryptoKey) to an AES-256-GCM CryptoKey.
|
|
109
|
+
* Returns an error message string when the key is unusable.
|
|
110
|
+
*/
|
|
111
|
+
export declare function resolveRawKey(key: RawEncryptionKey, usage: 'encrypt' | 'decrypt'): Promise<CryptoKey | string>;
|
|
112
|
+
/** Whether a key value is a passphrase (selects kdf=pbkdf2). */
|
|
113
|
+
export declare function isPassphrase(key: unknown): key is string;
|
|
114
|
+
/** Whether a key value is raw key material (selects kdf=raw). */
|
|
115
|
+
export declare function isRawKey(key: unknown): key is RawEncryptionKey;
|
|
116
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/crypto/shared.ts"],"names":[],"mappings":"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"}
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module errors
|
|
8
8
|
*/
|
|
9
|
-
import type { ValidationError } from './types.js';
|
|
9
|
+
import type { DecryptionFailureReason, ValidationError } from './types.js';
|
|
10
10
|
/**
|
|
11
11
|
* WOLS error codes (stable, for programmatic handling).
|
|
12
12
|
*/
|
|
@@ -88,6 +88,36 @@ export declare class WolsValidationError extends WolsError {
|
|
|
88
88
|
export declare class WolsEncryptionError extends WolsError {
|
|
89
89
|
constructor(code: WolsErrorCode, message: string, details?: Record<string, unknown>);
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Decryption failure with a stable, typed {@link DecryptionFailureReason}.
|
|
93
|
+
*
|
|
94
|
+
* It extends `WolsEncryptionError` on purpose: 1.2.x returned a
|
|
95
|
+
* `WolsEncryptionError` for decryption failures, so existing
|
|
96
|
+
* `instanceof WolsEncryptionError` checks keep matching. Encryption misuse is
|
|
97
|
+
* thrown as a plain `WolsEncryptionError`; decryption failures are returned as
|
|
98
|
+
* this subclass, so check `instanceof WolsDecryptionError` to tell them apart.
|
|
99
|
+
* Malformed encrypted URLs are reported here too (`invalid-url`), not as
|
|
100
|
+
* `WolsParseError`, so every decryption input problem has one error type.
|
|
101
|
+
*
|
|
102
|
+
* Returned (never thrown) by `decryptSpecimen`, `decryptPlaintext`,
|
|
103
|
+
* `decryptField` and `decryptFields`. `reason` is also copied into
|
|
104
|
+
* `details.reason` for code that reads the generic error shape.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const r = await decryptSpecimen(url, { key });
|
|
109
|
+
* if (!r.success && r.error.reason === 'legacy-format') {
|
|
110
|
+
* // a pre-1.3.0 label: retry with { allowLegacy: true } during migration
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* @since 1.3.0
|
|
115
|
+
*/
|
|
116
|
+
export declare class WolsDecryptionError extends WolsEncryptionError {
|
|
117
|
+
/** Stable failure category */
|
|
118
|
+
readonly reason: DecryptionFailureReason;
|
|
119
|
+
constructor(reason: DecryptionFailureReason, message: string, details?: Record<string, unknown>);
|
|
120
|
+
}
|
|
91
121
|
/**
|
|
92
122
|
* Create a required field error.
|
|
93
123
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM3E;;GAEG;AACH,oBAAY,aAAa;IACvB,0BAA0B;IAC1B,WAAW,qBAAqB;IAChC,0BAA0B;IAC1B,YAAY,sBAAsB;IAClC,8BAA8B;IAC9B,cAAc,wBAAwB;IACtC,wCAAwC;IACxC,eAAe,yBAAyB;IACxC,qCAAqC;IACrC,YAAY,sBAAsB;IAClC,gDAAgD;IAChD,iBAAiB,2BAA2B;IAC5C,+BAA+B;IAC/B,eAAe,yBAAyB;IACxC,oCAAoC;IACpC,qBAAqB,+BAA+B;IACpD,gCAAgC;IAChC,cAAc,wBAAwB;IACtC,kCAAkC;IAClC,mBAAmB,6BAA6B;IAChD,0CAA0C;IAC1C,kBAAkB,4BAA4B;IAC9C,iCAAiC;IACjC,WAAW,qBAAqB;IAChC,kCAAkC;IAClC,gBAAgB,0BAA0B;IAC1C,kCAAkC;IAClC,gBAAgB,0BAA0B;IAC1C,6BAA6B;IAC7B,WAAW,qBAAqB;IAChC,uCAAuC;IACvC,aAAa,uBAAuB;IACpC,mCAAmC;IACnC,aAAa,uBAAuB;CACrC;AAMD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;gBAE1C,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAYnF;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQlC;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGpC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAU5D;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;IAChD,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC;gBAEvB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE;CASvD;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,mBAAoB,SAAQ,mBAAmB;IAC1D,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;gBAE7B,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAahG;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAc,GAAG,mBAAmB,CAQ3F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAc,GACnB,mBAAmB,CAQrB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAoBvF"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @wemush/wols - Official WOLS TypeScript Library
|
|
3
3
|
*
|
|
4
|
-
* WeMush Open Labeling Standard (WOLS) v1.
|
|
4
|
+
* WeMush Open Labeling Standard (WOLS) v1.3.0 implementation
|
|
5
5
|
* for biological specimen labeling and traceability.
|
|
6
6
|
*
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
* @module @wemush/wols
|
|
9
|
-
* @version 1.
|
|
9
|
+
* @version 1.3.0
|
|
10
10
|
*/
|
|
11
11
|
export { WOLS_VERSION, WOLS_CONTEXT } from './types.js';
|
|
12
|
-
export type { Brand, SpecimenId, SpecimenType, GrowthStage, Strain, Specimen, SpecimenInput, ParseResult, ValidationResult, ValidationError, ValidationWarning, ValidationOptions, SpecimenRef, QRCodeOptions, EncryptionOptions, DecryptionOptions, EncryptedSpecimen, } from './types.js';
|
|
12
|
+
export type { Brand, SpecimenId, SpecimenType, GrowthStage, Strain, Specimen, SpecimenInput, SpecimenMeta, CreateSpecimenOptions, ParseResult, ValidationResult, ValidationError, ValidationWarning, ValidationOptions, IdValidationMode, IdValidator, SpecimenRef, QRCodeOptions, EncryptionOptions, DecryptionOptions, EncryptedSpecimen, EncryptedField, EncryptionKdf, RawEncryptionKey, DecryptionFailureReason, DecryptResult, FieldEncryptedSpecimen, FieldEncryptionOptions, } from './types.js';
|
|
13
13
|
export { asSpecimenId, isSpecimenType, isGrowthStage, isStrain, SPECIMEN_TYPES, GROWTH_STAGES, } from './types.js';
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
14
|
+
export { registerTypeAlias, resolveTypeAlias, getTypeAliases, resolveTypeAndStage, PRIMORDIA_TYPE_ALIAS, } from './types.js';
|
|
15
|
+
export { WOLS_TO_PLATFORM_MAP, mapToWolsType, mapFromWolsType, registerPlatformType, } from './types.js';
|
|
16
|
+
export { normalizeGeneration, isValidGeneration } from './types.js';
|
|
17
|
+
export type { GenerationFormat } from './types.js';
|
|
18
|
+
export { WolsErrorCode, WolsError, WolsParseError, WolsValidationError, WolsEncryptionError, WolsDecryptionError, } from './errors.js';
|
|
19
|
+
export { createSpecimen, serializeSpecimen, PRIMORDIA_AS_TYPE_WARNING } from './specimen.js';
|
|
16
20
|
export { validateSpecimen } from './validator.js';
|
|
17
21
|
export { parseSpecimen } from './parser.js';
|
|
18
|
-
export { toCompactUrl, parseCompactUrl, SPECIES_CODES, getSpeciesFromCode, getCodeFromSpecies, registerSpeciesCode, } from './compact-url.js';
|
|
19
|
-
export { encryptSpecimen, isEncrypted, decryptSpecimen } from './crypto/index.js';
|
|
22
|
+
export { toCompactUrl, parseCompactUrl, parseCompactUrlOrThrow, parseCompactUrlOrNull, SPECIES_CODES, getSpeciesFromCode, getCodeFromSpecies, registerSpeciesCode, } from './compact-url.js';
|
|
23
|
+
export { encryptSpecimen, encryptFields, isEncrypted, isEncryptedSpecimen, isEncryptedField, toEncryptedUrl, decryptSpecimen, decryptPlaintext, decryptField, decryptFields, parseEncryptedUrl, type FieldBinding, base64UrlEncode, base64UrlDecode, derivePassphraseKey, } from './crypto/index.js';
|
|
20
24
|
export { toQRCode, toQRCodeDataURL, toQRCodeSVG, isQRAvailable, isQRAvailableSync, } from './qr/index.js';
|
|
25
|
+
export { isServer, isBrowser, isWebWorker, isDeno, isBun, getRuntimeEnvironment, supportsWebCrypto, supportsNodeCrypto, isCryptoSupported, supportsTextEncoding, supportsURLAPIs, } from './utils/environment.js';
|
|
26
|
+
export type { RuntimeEnvironment } from './utils/environment.js';
|
|
27
|
+
export { compareVersions, isOutdated, isNewer, getCurrentVersion, registerMigration, canMigrate, migrate, getMigrations, clearMigrations, } from './utils/migration.js';
|
|
28
|
+
export type { VersionComparison, MigrationHandler } from './utils/migration.js';
|
|
21
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAKxD,YAAY,EAEV,KAAK,EACL,UAAU,EAGV,YAAY,EACZ,WAAW,EACX,MAAM,EACN,QAAQ,EACR,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAKxD,YAAY,EAEV,KAAK,EACL,UAAU,EAGV,YAAY,EACZ,WAAW,EACX,MAAM,EACN,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,qBAAqB,EAGrB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EAGjB,gBAAgB,EAChB,WAAW,EAGX,WAAW,EAGX,aAAa,EAGb,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,EACb,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAKpB,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKnD,OAAO,EACL,aAAa,EACb,SAAS,EACT,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAK7F,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKlD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAK5C,OAAO,EACL,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,eAAe,EACf,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,KAAK,YAAY,EACjB,eAAe,EACf,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,QAAQ,EACR,eAAe,EACf,WAAW,EACX,aAAa,EACb,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAKvB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,EACN,KAAK,EACL,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAKjE,OAAO,EACL,eAAe,EACf,UAAU,EACV,OAAO,EACP,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,aAAa,EACb,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,EAKd,MAAM,YAAY,CAAC;AAyCpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAwGjE"}
|
package/dist/types/specimen.d.ts
CHANGED
|
@@ -2,19 +2,31 @@
|
|
|
2
2
|
* Specimen Creation and Serialization
|
|
3
3
|
*
|
|
4
4
|
* This module provides functions to create and serialize
|
|
5
|
-
* WOLS v1.
|
|
5
|
+
* WOLS v1.3.0 compliant specimen objects.
|
|
6
6
|
*
|
|
7
7
|
* @module specimen
|
|
8
8
|
*/
|
|
9
|
-
import type { Specimen, SpecimenInput } from './types.js';
|
|
9
|
+
import type { CreateSpecimenOptions, Specimen, SpecimenInput } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Warning code emitted when `PRIMORDIA` is supplied as a specimen type.
|
|
12
|
+
*
|
|
13
|
+
* @since 1.3.0
|
|
14
|
+
*/
|
|
15
|
+
export declare const PRIMORDIA_AS_TYPE_WARNING = "PRIMORDIA_AS_TYPE";
|
|
10
16
|
/**
|
|
11
17
|
* Create a new specimen with auto-generated ID and JSON-LD fields.
|
|
12
18
|
*
|
|
13
|
-
* This function creates a fully-formed WOLS v1.
|
|
19
|
+
* This function creates a fully-formed WOLS v1.3.0 compliant Specimen
|
|
14
20
|
* with automatic ID generation, version assignment, and JSON-LD context.
|
|
15
21
|
*
|
|
22
|
+
* Type aliases resolve case-insensitively. `PRIMORDIA` supplied as a type
|
|
23
|
+
* resolves to `FRUITING`, sets `stage: 'PRIMORDIA'` when no stage was given
|
|
24
|
+
* (a supplied stage is never overridden), and emits a warning.
|
|
25
|
+
*
|
|
16
26
|
* @param input - Specimen creation parameters
|
|
27
|
+
* @param options - `onWarning` receives non-fatal warnings (default: console.warn)
|
|
17
28
|
* @returns Fully-formed Specimen with JSON-LD fields
|
|
29
|
+
* @throws Error if the type is unknown or `created` is not ISO 8601
|
|
18
30
|
*
|
|
19
31
|
* @example
|
|
20
32
|
* ```typescript
|
|
@@ -44,9 +56,22 @@ import type { Specimen, SpecimenInput } from './types.js';
|
|
|
44
56
|
* species: 'Ganoderma lucidum',
|
|
45
57
|
* strain: 'Reishi Red', // Auto-expands to { name: 'Reishi Red' }
|
|
46
58
|
* });
|
|
59
|
+
*
|
|
60
|
+
* // PRIMORDIA as a type (v1.3.0) -> type FRUITING, stage PRIMORDIA, plus a warning
|
|
61
|
+
* const pinning = createSpecimen(
|
|
62
|
+
* { type: 'PRIMORDIA', species: 'Pleurotus ostreatus' },
|
|
63
|
+
* { onWarning: w => console.info(w.message) }
|
|
64
|
+
* );
|
|
65
|
+
*
|
|
66
|
+
* // Explicit creation timestamp (v1.3.0)
|
|
67
|
+
* const dated = createSpecimen({
|
|
68
|
+
* type: 'CULTURE',
|
|
69
|
+
* species: 'Pleurotus ostreatus',
|
|
70
|
+
* created: '2025-12-16T10:30:00Z',
|
|
71
|
+
* });
|
|
47
72
|
* ```
|
|
48
73
|
*/
|
|
49
|
-
export declare function createSpecimen(input: SpecimenInput): Specimen;
|
|
74
|
+
export declare function createSpecimen(input: SpecimenInput, options?: CreateSpecimenOptions): Specimen;
|
|
50
75
|
/**
|
|
51
76
|
* Serialize a specimen to JSON-LD string.
|
|
52
77
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specimen.d.ts","sourceRoot":"","sources":["../../src/specimen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"specimen.d.ts","sourceRoot":"","sources":["../../src/specimen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,QAAQ,EACR,aAAa,EAGd,MAAM,YAAY,CAAC;AAWpB;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAkC7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,qBAA0B,GAClC,QAAQ,CAmFV;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA4D5D"}
|