@wishknish/knishio-client-ts 0.9.8 → 1.0.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/dist/index.cjs +211 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -34
- package/dist/index.d.ts +40 -34
- package/dist/index.iife.js +212 -48
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +212 -49
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/AuthToken.ts +47 -25
- package/src/KnishIOClient.ts +40 -12
- package/src/core/Molecule.ts +17 -7
- package/src/core/Wallet.ts +161 -32
- package/src/index.ts +2 -2
- package/src/libraries/GraphQLClient.ts +2 -2
- package/src/schemas/index.ts +2 -1
- package/src/types/crypto.ts +9 -4
- package/src/validation/schemas.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wishknish/knishio-client-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"productName": "Knish.IO TypeScript SDK Client",
|
|
5
5
|
"description": "TypeScript implementation of the Knish.IO SDK to consume Knish.IO GraphQL APIs with enhanced type safety.",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"quantum-safe",
|
|
52
52
|
"sdk",
|
|
53
53
|
"typescript",
|
|
54
|
-
"ml-
|
|
54
|
+
"ml-kem1024",
|
|
55
55
|
"cryptography",
|
|
56
56
|
"crystals-kyber",
|
|
57
57
|
"fips-202",
|
|
@@ -112,6 +112,6 @@
|
|
|
112
112
|
],
|
|
113
113
|
"packageManager": "yarn@4.15.0",
|
|
114
114
|
"engines": {
|
|
115
|
-
"node": ">=
|
|
115
|
+
"node": ">=20.0.0"
|
|
116
116
|
}
|
|
117
117
|
}
|
package/src/AuthToken.ts
CHANGED
|
@@ -48,6 +48,25 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
|
|
|
48
48
|
|
|
49
49
|
import Wallet from '@/core/Wallet'
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Persisted session shape. Shared by {@link AuthToken.restore} and {@link AuthToken.toSnapshot}
|
|
53
|
+
* so the two can never drift: a field either round-trips or neither side compiles.
|
|
54
|
+
*
|
|
55
|
+
* `wallet.mlKemParameterSet` is optional because snapshots persisted before ML-KEM-1024 became
|
|
56
|
+
* the default do not carry it — see {@link AuthToken.resolveMlKemParameterSet}.
|
|
57
|
+
*/
|
|
58
|
+
export type AuthTokenSnapshot = {
|
|
59
|
+
token: string
|
|
60
|
+
expiresAt: number
|
|
61
|
+
pubkey: string
|
|
62
|
+
encrypt: boolean
|
|
63
|
+
wallet?: {
|
|
64
|
+
position: string | null
|
|
65
|
+
characters: string | null
|
|
66
|
+
mlKemParameterSet?: 1024 | 768
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
51
70
|
/**
|
|
52
71
|
* AuthToken class for managing authentication tokens
|
|
53
72
|
*/
|
|
@@ -93,25 +112,34 @@ export default class AuthToken {
|
|
|
93
112
|
}
|
|
94
113
|
|
|
95
114
|
/**
|
|
96
|
-
*
|
|
115
|
+
* ML-KEM parameter set a restored session must use, resolved in three tiers:
|
|
116
|
+
* an explicit snapshot field, then the stored validator key's length, then ML-KEM-768.
|
|
117
|
+
*
|
|
118
|
+
* The final tier is deliberately NOT the constructor default. A snapshot with neither an
|
|
119
|
+
* explicit field nor a recognisable key can only have come from a pre-bump build, and every
|
|
120
|
+
* pre-bump build was 768-only — defaulting to 1024 would make the restored wallet advertise
|
|
121
|
+
* a public key the validator never recorded for that token.
|
|
97
122
|
*/
|
|
98
|
-
static
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
encrypt: boolean
|
|
103
|
-
wallet: {
|
|
104
|
-
position: string
|
|
105
|
-
characters: string | null
|
|
123
|
+
static resolveMlKemParameterSet(snapshot: AuthTokenSnapshot): 1024 | 768 {
|
|
124
|
+
const explicit = snapshot.wallet?.mlKemParameterSet
|
|
125
|
+
if (explicit) {
|
|
126
|
+
return Number(explicit) === 768 ? 768 : 1024
|
|
106
127
|
}
|
|
107
|
-
|
|
128
|
+
return Wallet.mlKemParameterSetFromPubkey(snapshot.pubkey) ?? 768
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Restore AuthToken from snapshot
|
|
133
|
+
*/
|
|
134
|
+
static restore(snapshot: AuthTokenSnapshot, secret: string): AuthToken {
|
|
108
135
|
const wallet = new Wallet({
|
|
109
136
|
secret,
|
|
110
137
|
token: 'AUTH',
|
|
111
|
-
position: snapshot.wallet
|
|
112
|
-
characters: snapshot.wallet
|
|
138
|
+
position: snapshot.wallet?.position ?? null,
|
|
139
|
+
characters: snapshot.wallet?.characters ?? null,
|
|
140
|
+
mlKemParameterSet: AuthToken.resolveMlKemParameterSet(snapshot)
|
|
113
141
|
})
|
|
114
|
-
|
|
142
|
+
|
|
115
143
|
return AuthToken.create({
|
|
116
144
|
token: snapshot.token,
|
|
117
145
|
expiresAt: snapshot.expiresAt,
|
|
@@ -192,18 +220,11 @@ export default class AuthToken {
|
|
|
192
220
|
}
|
|
193
221
|
|
|
194
222
|
/**
|
|
195
|
-
* Create snapshot for persistence
|
|
223
|
+
* Create snapshot for persistence. The wallet's ML-KEM parameter set is recorded beside its
|
|
224
|
+
* position and characters so a stepped-back ML-KEM-768 session restores as 768 rather than
|
|
225
|
+
* silently taking the constructor default.
|
|
196
226
|
*/
|
|
197
|
-
toSnapshot(): {
|
|
198
|
-
token: string
|
|
199
|
-
expiresAt: number
|
|
200
|
-
pubkey: string
|
|
201
|
-
encrypt: boolean
|
|
202
|
-
wallet?: {
|
|
203
|
-
position: string | null
|
|
204
|
-
characters: string | null
|
|
205
|
-
}
|
|
206
|
-
} {
|
|
227
|
+
toSnapshot(): AuthTokenSnapshot {
|
|
207
228
|
return {
|
|
208
229
|
token: this.$__token,
|
|
209
230
|
expiresAt: this.$__expiresAt,
|
|
@@ -212,7 +233,8 @@ export default class AuthToken {
|
|
|
212
233
|
...(this.$__wallet ? {
|
|
213
234
|
wallet: {
|
|
214
235
|
position: this.$__wallet.position,
|
|
215
|
-
characters: this.$__wallet.characters
|
|
236
|
+
characters: this.$__wallet.characters,
|
|
237
|
+
mlKemParameterSet: this.$__wallet.mlKemParameterSet
|
|
216
238
|
}
|
|
217
239
|
} : {})
|
|
218
240
|
}
|
package/src/KnishIOClient.ts
CHANGED
|
@@ -166,6 +166,7 @@ export default class KnishIOClient {
|
|
|
166
166
|
private $__authTokenObjects: Record<string, AuthToken | null> = {}
|
|
167
167
|
private $__authToken: AuthToken | null = null
|
|
168
168
|
private $__authInProcess: boolean = false
|
|
169
|
+
private $__mlKemParameterSet: 1024 | 768 = 1024
|
|
169
170
|
private $__remainderWallet: Wallet | null = null
|
|
170
171
|
private lastMoleculeQuery: Mutation | null = null
|
|
171
172
|
private abortControllers: Map<string, AbortController> = new Map()
|
|
@@ -189,6 +190,7 @@ export default class KnishIOClient {
|
|
|
189
190
|
logging?: boolean
|
|
190
191
|
defaultRequestPolicy?: RequestPolicy | null
|
|
191
192
|
secretStorage?: ISecretStorageProvider | null
|
|
193
|
+
mlKemParameterSet?: 1024 | 768
|
|
192
194
|
}) {
|
|
193
195
|
// Phase 2 Enhancement: Use standardized configuration validation
|
|
194
196
|
const standardValidationResult = ConfigValidator.validateClientConfig(config)
|
|
@@ -238,7 +240,8 @@ export default class KnishIOClient {
|
|
|
238
240
|
client: client as GraphQLClient | null,
|
|
239
241
|
serverSdkVersion,
|
|
240
242
|
logging,
|
|
241
|
-
defaultRequestPolicy
|
|
243
|
+
defaultRequestPolicy,
|
|
244
|
+
mlKemParameterSet: config.mlKemParameterSet ?? 1024
|
|
242
245
|
})
|
|
243
246
|
|
|
244
247
|
if (config.secretStorage) {
|
|
@@ -256,7 +259,8 @@ export default class KnishIOClient {
|
|
|
256
259
|
client = null,
|
|
257
260
|
serverSdkVersion = 3,
|
|
258
261
|
logging = false,
|
|
259
|
-
defaultRequestPolicy = null
|
|
262
|
+
defaultRequestPolicy = null,
|
|
263
|
+
mlKemParameterSet = 1024
|
|
260
264
|
}: {
|
|
261
265
|
uri: string | string[]
|
|
262
266
|
cellSlug?: string | null
|
|
@@ -265,10 +269,12 @@ export default class KnishIOClient {
|
|
|
265
269
|
serverSdkVersion?: number
|
|
266
270
|
logging?: boolean
|
|
267
271
|
defaultRequestPolicy?: RequestPolicy | null
|
|
272
|
+
mlKemParameterSet?: 1024 | 768
|
|
268
273
|
}): void {
|
|
269
274
|
this.reset()
|
|
270
275
|
|
|
271
276
|
this.$__logging = logging
|
|
277
|
+
this.setMlKemParameterSet(mlKemParameterSet)
|
|
272
278
|
this.$__authTokenObjects = {}
|
|
273
279
|
|
|
274
280
|
this.setUri(uri)
|
|
@@ -297,6 +303,19 @@ export default class KnishIOClient {
|
|
|
297
303
|
// serverSdkVersion. A re-initialize updates it.
|
|
298
304
|
this.$__defaultRequestPolicy = defaultRequestPolicy
|
|
299
305
|
}
|
|
306
|
+
getMlKemParameterSet(): 1024 | 768 {
|
|
307
|
+
return this.$__mlKemParameterSet || 1024
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
setMlKemParameterSet(parameterSet: 1024 | 768): this {
|
|
311
|
+
const paramNum = Number(parameterSet) as 1024 | 768
|
|
312
|
+
if (![1024, 768].includes(paramNum)) {
|
|
313
|
+
throw new Error(`KnishIO: unsupported ML-KEM parameter set ${parameterSet}; expected 1024 or 768.`)
|
|
314
|
+
}
|
|
315
|
+
this.$__mlKemParameterSet = paramNum
|
|
316
|
+
return this
|
|
317
|
+
}
|
|
318
|
+
|
|
300
319
|
|
|
301
320
|
/**
|
|
302
321
|
* Get random uri from specified this.$__uris
|
|
@@ -589,7 +608,8 @@ export default class KnishIOClient {
|
|
|
589
608
|
bundle,
|
|
590
609
|
token: 'USER',
|
|
591
610
|
batchId: sourceWallet!.batchId,
|
|
592
|
-
characters: sourceWallet!.characters
|
|
611
|
+
characters: sourceWallet!.characters,
|
|
612
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
593
613
|
}))
|
|
594
614
|
|
|
595
615
|
return new Molecule({
|
|
@@ -599,7 +619,8 @@ export default class KnishIOClient {
|
|
|
599
619
|
remainderWallet: this.getRemainderWallet()!,
|
|
600
620
|
cellSlug: this.getCellSlug(),
|
|
601
621
|
version: this.getServerSdkVersion(),
|
|
602
|
-
continuIdPosition
|
|
622
|
+
continuIdPosition,
|
|
623
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
603
624
|
})
|
|
604
625
|
}
|
|
605
626
|
|
|
@@ -756,7 +777,8 @@ export default class KnishIOClient {
|
|
|
756
777
|
|
|
757
778
|
if (!sourceWallet) {
|
|
758
779
|
sourceWallet = new Wallet({
|
|
759
|
-
secret: this.getSecret()
|
|
780
|
+
secret: this.getSecret(),
|
|
781
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
760
782
|
})
|
|
761
783
|
} else {
|
|
762
784
|
sourceWallet.key = Wallet.generateKey({
|
|
@@ -819,7 +841,8 @@ export default class KnishIOClient {
|
|
|
819
841
|
// Attempt to get the recipient's wallet
|
|
820
842
|
const recipientWallet = Wallet.create({
|
|
821
843
|
bundle: bundleHash,
|
|
822
|
-
token
|
|
844
|
+
token,
|
|
845
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
823
846
|
})
|
|
824
847
|
|
|
825
848
|
// Compute the batch ID for the recipient (typically used by stackable tokens)
|
|
@@ -909,7 +932,8 @@ export default class KnishIOClient {
|
|
|
909
932
|
const recipientWallets: Wallet[] = recipients.map(recipient => {
|
|
910
933
|
const recipientWallet = Wallet.create({
|
|
911
934
|
bundle: recipient.bundleHash,
|
|
912
|
-
token
|
|
935
|
+
token,
|
|
936
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
913
937
|
})
|
|
914
938
|
if (recipient.batchId !== null && recipient.batchId !== undefined) {
|
|
915
939
|
recipientWallet.batchId = recipient.batchId
|
|
@@ -1774,7 +1798,8 @@ export default class KnishIOClient {
|
|
|
1774
1798
|
secret: this.getSecret(),
|
|
1775
1799
|
bundle: this.getBundle(),
|
|
1776
1800
|
token,
|
|
1777
|
-
batchId: batchId as any
|
|
1801
|
+
batchId: batchId as any,
|
|
1802
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
1778
1803
|
})
|
|
1779
1804
|
|
|
1780
1805
|
// Initialize the create token mutation
|
|
@@ -1880,7 +1905,8 @@ export default class KnishIOClient {
|
|
|
1880
1905
|
const recipientWallet = new Wallet({
|
|
1881
1906
|
secret: this.getSecret(),
|
|
1882
1907
|
bundle: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
1883
|
-
token
|
|
1908
|
+
token,
|
|
1909
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
1884
1910
|
})
|
|
1885
1911
|
|
|
1886
1912
|
await mutation.fillMolecule({
|
|
@@ -1993,7 +2019,8 @@ export default class KnishIOClient {
|
|
|
1993
2019
|
const newWallet = new Wallet({
|
|
1994
2020
|
secret: this.getSecret(),
|
|
1995
2021
|
bundle: this.getBundle(),
|
|
1996
|
-
token
|
|
2022
|
+
token,
|
|
2023
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
1997
2024
|
})
|
|
1998
2025
|
|
|
1999
2026
|
// Initialize the create wallet mutation
|
|
@@ -2499,7 +2526,8 @@ export default class KnishIOClient {
|
|
|
2499
2526
|
// Generate a signing wallet with AUTH token (matching JavaScript SDK)
|
|
2500
2527
|
const wallet = new Wallet({
|
|
2501
2528
|
secret,
|
|
2502
|
-
token: 'AUTH'
|
|
2529
|
+
token: 'AUTH',
|
|
2530
|
+
mlKemParameterSet: this.getMlKemParameterSet()
|
|
2503
2531
|
})
|
|
2504
2532
|
|
|
2505
2533
|
// Create a molecule with the AUTH wallet as source
|
|
@@ -2515,7 +2543,7 @@ export default class KnishIOClient {
|
|
|
2515
2543
|
})
|
|
2516
2544
|
|
|
2517
2545
|
// Initialize the profile auth mutation.
|
|
2518
|
-
// PQ-transport Phase E: convey the AUTH source wallet's ML-
|
|
2546
|
+
// PQ-transport Phase E: convey the AUTH source wallet's ML-KEM public key as a SIGNED
|
|
2519
2547
|
// walletPubkey U-atom meta, so the validator can encrypt CipherHash responses back to THIS
|
|
2520
2548
|
// wallet (the one that decrypts them). Signed → MITM can't swap the target. Conveyed
|
|
2521
2549
|
// unconditionally (parity with JS/Kotlin/PHP), so even a plaintext auth primes enc_pubkey.
|
package/src/core/Molecule.ts
CHANGED
|
@@ -81,6 +81,7 @@ export default class Molecule {
|
|
|
81
81
|
public continuIdPosition: string | null
|
|
82
82
|
public parentHashes: string[]
|
|
83
83
|
public local?: number
|
|
84
|
+
public mlKemParameterSet: 1024 | 768 = 1024
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
87
|
* Create new Molecule instance
|
|
@@ -93,7 +94,8 @@ export default class Molecule {
|
|
|
93
94
|
remainderWallet = null,
|
|
94
95
|
cellSlug = null,
|
|
95
96
|
version = null,
|
|
96
|
-
continuIdPosition = null
|
|
97
|
+
continuIdPosition = null,
|
|
98
|
+
mlKemParameterSet = null
|
|
97
99
|
}: {
|
|
98
100
|
secret?: string | null
|
|
99
101
|
bundle?: string | null
|
|
@@ -102,6 +104,7 @@ export default class Molecule {
|
|
|
102
104
|
cellSlug?: string | null
|
|
103
105
|
version?: string | number | null
|
|
104
106
|
continuIdPosition?: string | null
|
|
107
|
+
mlKemParameterSet?: 1024 | 768 | null
|
|
105
108
|
} = {}) {
|
|
106
109
|
this.status = null
|
|
107
110
|
this.molecularHash = null
|
|
@@ -113,6 +116,7 @@ export default class Molecule {
|
|
|
113
116
|
this.continuIdPosition = continuIdPosition
|
|
114
117
|
this.atoms = []
|
|
115
118
|
this.parentHashes = []
|
|
119
|
+
this.mlKemParameterSet = mlKemParameterSet || sourceWallet?.mlKemParameterSet || 1024
|
|
116
120
|
|
|
117
121
|
const versionRegistry = versions as Record<string | number, any>
|
|
118
122
|
if (version !== null && Object.prototype.hasOwnProperty.call(versionRegistry, version)) {
|
|
@@ -129,7 +133,8 @@ export default class Molecule {
|
|
|
129
133
|
bundle,
|
|
130
134
|
token: sourceWallet!.token,
|
|
131
135
|
batchId: sourceWallet!.batchId,
|
|
132
|
-
characters: sourceWallet!.characters
|
|
136
|
+
characters: sourceWallet!.characters,
|
|
137
|
+
mlKemParameterSet: this.mlKemParameterSet
|
|
133
138
|
})
|
|
134
139
|
} else {
|
|
135
140
|
this.remainderWallet = null
|
|
@@ -206,7 +211,8 @@ export default class Molecule {
|
|
|
206
211
|
if (!this.remainderWallet || this.remainderWallet.token !== 'USER') {
|
|
207
212
|
this.remainderWallet = Wallet.create({
|
|
208
213
|
secret: this.secret!,
|
|
209
|
-
bundle: this.bundle
|
|
214
|
+
bundle: this.bundle!,
|
|
215
|
+
mlKemParameterSet: this.mlKemParameterSet
|
|
210
216
|
})
|
|
211
217
|
}
|
|
212
218
|
|
|
@@ -724,7 +730,8 @@ export default class Molecule {
|
|
|
724
730
|
// Create burn address wallet (null bundle = token destruction)
|
|
725
731
|
const burnWallet = new Wallet({
|
|
726
732
|
bundle: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
727
|
-
token: this.sourceWallet.token
|
|
733
|
+
token: this.sourceWallet.token,
|
|
734
|
+
mlKemParameterSet: this.mlKemParameterSet
|
|
728
735
|
})
|
|
729
736
|
|
|
730
737
|
// V-atom 1: Debit full balance from source
|
|
@@ -1099,7 +1106,8 @@ export default class Molecule {
|
|
|
1099
1106
|
position: data.sourceWallet.position,
|
|
1100
1107
|
bundle: data.sourceWallet.bundle,
|
|
1101
1108
|
batchId: data.sourceWallet.batchId,
|
|
1102
|
-
characters: data.sourceWallet.characters
|
|
1109
|
+
characters: data.sourceWallet.characters,
|
|
1110
|
+
mlKemParameterSet: molecule.mlKemParameterSet
|
|
1103
1111
|
})
|
|
1104
1112
|
|
|
1105
1113
|
// Set additional properties for validation context
|
|
@@ -1121,7 +1129,8 @@ export default class Molecule {
|
|
|
1121
1129
|
position: data.remainderWallet.position,
|
|
1122
1130
|
bundle: data.remainderWallet.bundle,
|
|
1123
1131
|
batchId: data.remainderWallet.batchId,
|
|
1124
|
-
characters: data.remainderWallet.characters
|
|
1132
|
+
characters: data.remainderWallet.characters,
|
|
1133
|
+
mlKemParameterSet: molecule.mlKemParameterSet
|
|
1125
1134
|
})
|
|
1126
1135
|
|
|
1127
1136
|
// Set additional properties for validation context
|
|
@@ -1245,7 +1254,8 @@ export default class Molecule {
|
|
|
1245
1254
|
secret: this.secret!,
|
|
1246
1255
|
bundle: this.bundle,
|
|
1247
1256
|
token: this.sourceWallet.token,
|
|
1248
|
-
batchId: this.sourceWallet.batchId
|
|
1257
|
+
batchId: this.sourceWallet.batchId,
|
|
1258
|
+
mlKemParameterSet: this.mlKemParameterSet
|
|
1249
1259
|
})
|
|
1250
1260
|
if (tradeRates) {
|
|
1251
1261
|
bufferWallet.tradeRates = tradeRates
|