@hsuite/smart-engines-sdk 3.4.0 → 3.4.1

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.4.1 — 2026-06-01
4
+
5
+ **Patch release** restoring 3 subpath exports that the 3.4.0 publish dropped despite being present in source:
6
+
7
+ - `./pqc-verify-envelope` (landed in #981, 2026-05-29 — before the 3.4.0 release)
8
+ - `./ipfs-access-key` (landed in #987, 2026-05-30)
9
+ - `./k8s-secret-reader` (landed in #985, 2026-05-30)
10
+
11
+ Root cause: SDK build config (`tsup.config.mjs` `entry` map + `package.json#scripts.build:dts` invocations) was never updated when the 3 new subpath dirs were added — only the root + `nestjs` + `pqc-verify` entry points were declared in the release commit (`ed4b9bf8`). 3.4.0 shipped with the missing dist artifacts, leaving consumers importing those subpaths with module-not-found errors.
12
+
13
+ The build config and `package.json#exports` have since been updated on `develop` (merge `d76ef2e4`), but no version bump was published. This 3.4.1 release publishes those fixes.
14
+
15
+ No source API change. No breaking change. Safe to bump from 3.4.0 to 3.4.1.
16
+
17
+ ### Regression guard
18
+
19
+ `libs/smartengine-sdk/src/__tests__/dist-exports.spec.ts` asserts that every subpath in `package.json#exports` resolves to files that exist in `dist/` after `yarn build`. Reproduces the 3.4.0 failure mode when a `dist/<name>/` subdir is missing.
20
+
3
21
  ## 3.4.0 — 2026-05-31
4
22
 
5
23
  **Production-readiness arc.** Closes the audit gap identified after 3.3.0 shipped: ~55 of ~110 third-party-facing server endpoints were wrapped; this release brings coverage to ~95/110 (the remaining ~15 are intentionally internal — operator / DKG ceremony / harbor admin). SDK test suite grew from 477 → 637 (+160 tests).
package/dist/index.d.ts CHANGED
@@ -25202,6 +25202,42 @@ export type VerifyResult = {
25202
25202
  readonly thresholdMet?: boolean;
25203
25203
  };
25204
25204
  export declare function verifyPqcAttestation(cert: unknown, payload: unknown, registrySnapshot?: ValidatorRegistrySnapshot): Promise<VerifyResult>;
25205
+ export type EnvelopeVersionLiteral = "kyber-aes-v1" | "aes-v0";
25206
+ export type SchemaValidationResult = {
25207
+ ok: true;
25208
+ version: EnvelopeVersionLiteral;
25209
+ } | {
25210
+ ok: false;
25211
+ reason: string;
25212
+ };
25213
+ export declare function validateEnvelopeSchema(envelope: unknown): SchemaValidationResult;
25214
+ export declare const KYBER_MIN_TIMESTAMP_MS = 1704067200000;
25215
+ export type VerificationDetails = {
25216
+ version: string;
25217
+ kemAlgorithm?: "ml-kem-768" | "ml-kem-1024";
25218
+ recipientPkFingerprint?: string;
25219
+ kdfLabel?: string;
25220
+ encryptedAt?: number;
25221
+ schemaValid: boolean;
25222
+ base64Valid: boolean;
25223
+ timestampPlausible: boolean;
25224
+ };
25225
+ export type EnvelopeVerificationResult = {
25226
+ valid: true;
25227
+ version: EnvelopeVersionLiteral;
25228
+ details: VerificationDetails;
25229
+ } | {
25230
+ valid: false;
25231
+ reason: string;
25232
+ details?: Partial<VerificationDetails>;
25233
+ };
25234
+ export type VerifyEnvelopeOptions = {
25235
+ expectedLabel?: string;
25236
+ expectedRecipientPkFingerprint?: string;
25237
+ minTimestamp?: number;
25238
+ maxTimestamp?: number;
25239
+ };
25240
+ export declare function verifyPqcEnvelope(envelope: unknown, options?: VerifyEnvelopeOptions): Promise<EnvelopeVerificationResult>;
25205
25241
 
25206
25242
  declare namespace bitcoin {
25207
25243
  export { btcToSatoshis, satoshisToBtc, validateBitcoinAddress };
@@ -25221,8 +25257,8 @@ declare namespace solana {
25221
25257
  declare namespace stellar {
25222
25258
  export { stroopsToXlm, validateStellarAddress, xlmToStroops };
25223
25259
  }
25224
- declare namespace pqcVerify {
25225
- export { FetchRegistryOptions, PqcCertV1, PqcCertV1Schema, PqcCertV1Signer, ValidatorRegistrySnapshot, VerifyResult, fetchRegistrySnapshot, parsePqcCert, verifyPqcAttestation };
25260
+ declare namespace pqcVerifyEnvelope {
25261
+ export { EnvelopeVerificationResult, EnvelopeVersionLiteral, KYBER_MIN_TIMESTAMP_MS, SchemaValidationResult, VerificationDetails, VerifyEnvelopeOptions, validateEnvelopeSchema, verifyPqcEnvelope };
25226
25262
  }
25227
25263
  declare namespace discovery {
25228
25264
  export { ClusterDiscoveryClient, ClusterDiscoveryConfig, ClusterEndpointsView, ClusterInfo, DiscoveryClient, DiscoveryClusterEndpoints, DiscoveryClusterRecord, DiscoveryNodeRecord, DiscoveryPlatformImageEnvelope, DiscoveryPlatformImageManifest, DiscoveryVerifyResult, MIRROR_NODE_URLS, MirrorNodeClient, MirrorNodeConfig, MirrorNodeError, PlatformImagesClient, TopicMessage, TopicMessagesResponse, ValidatorDiscoveryClient, ValidatorDiscoveryConfig, ValidatorInfo, ValidatorMetadata, ValidatorNetworkEndpoints };
@@ -25266,6 +25302,9 @@ declare namespace personhood {
25266
25302
  declare namespace baas {
25267
25303
  export { AgentBalance, AgentEvent, AgentFundRequest, AgentInfo, AgentOperation, AgentRegisterRequest, AgentRules, AgentRulesValidationResult, AgentStatus, AgentTradeRequest, AgentWithdrawRequest, AgentsClient, AuthenticateOptions, BaasAppListResponse, BaasAuthConfig, BaasAuthResult, BaasChallengeRequest, BaasChallengeResponse, BaasChannelConfig, BaasClient, BaasClientConfig, BaasConnectToClusterConfig, BaasDeleteResult, BaasDeployRequest, BaasDeployResponse, BaasDocument, BaasEndpoints, BaasError, BaasErrorDetails, BaasErrorResponse, BaasFileInfo, BaasFileMetadata, BaasFindResult, BaasFunctionDeployRequest, BaasFunctionDeployResult, BaasFunctionInfo, BaasFunctionLog, BaasFunctionLogOptions, BaasFunctionResources, BaasFunctionResult, BaasFunctionRuntime, BaasHistoryOptions, BaasInitRequest, BaasInitResponse, BaasInsertResult, BaasMerkleProof, BaasMessage, BaasPresenceInfo, BaasPresenceMember, BaasPublishResult, BaasQueryOptions, BaasRevokeKekResponse, BaasRollbackRequest, BaasRotateKekResponse, BaasRuntimeStatus, BaasService, BaasSessionInfo, BaasSetWebhookResponse, BaasStateTransition, BaasStorageUsage, BaasSupportedChain, BaasTriggerType, BaasUpdateResult, BaasUploadFrontendResponse, BaasUploadResult, BaasVerifyRequest, ChannelSubscription, CreateAccountRequest$1 as BaasCreateAccountRequest, CreateAgentRequest, CreateTokenRequest$1 as CreateTokenRequest, CreateTopicRequest, DatabaseClient, DatabaseStatsResponse, DbComparisonOperator, DbDocument, DbQuery, DeployedApp, DeployedAppInfo, DeployedAppLimits, DeployedAppStatus, DeployedAppUsage, DeploymentClient, DeprecateRuleResponse, DocumentProofResponse, EntitiesClient, EntityCreationResult, EntityInfo, EntityType$1 as BaasEntityType, FunctionsClient, LaunchpadEntityRequest, LaunchpadEntityResult, ListEntitiesFilter, ListEntitiesResponse, ListRulesFilter, ListRulesResponse, MessageHandler, MessagingClient, PublishRuleResponse, RulesClient, SimulateRuleRequest, StateRootResponse, StateTransitionsResponse, StorageClient, ValidationResult, VersionHistoryResponse, validateAgentRules };
25268
25304
  }
25305
+ declare namespace pqcVerify {
25306
+ export { FetchRegistryOptions, PqcCertV1, PqcCertV1Schema, PqcCertV1Signer, ValidatorRegistrySnapshot, VerifyResult, fetchRegistrySnapshot, parsePqcCert, verifyPqcAttestation };
25307
+ }
25269
25308
 
25270
25309
  export {
25271
25310
  RetryConfig as ResilienceRetryConfig,
@@ -25281,6 +25320,7 @@ export {
25281
25320
  operator,
25282
25321
  personhood,
25283
25322
  pqcVerify,
25323
+ pqcVerifyEnvelope,
25284
25324
  resources,
25285
25325
  settlement,
25286
25326
  subscription,
package/dist/index.js CHANGED
@@ -123,12 +123,12 @@ var require_lib = __commonJS({
123
123
  if (lengths.length > 0 && !lengths.includes(b.length))
124
124
  throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
125
125
  }
126
- function isArrayOf(isString, arr) {
126
+ function isArrayOf(isString2, arr) {
127
127
  if (!Array.isArray(arr))
128
128
  return false;
129
129
  if (arr.length === 0)
130
130
  return true;
131
- if (isString) {
131
+ if (isString2) {
132
132
  return arr.every((item) => typeof item === "string");
133
133
  } else {
134
134
  return arr.every((item) => Number.isSafeInteger(item));
@@ -11104,6 +11104,251 @@ async function verifyPqcAttestation(cert, payload, registrySnapshot) {
11104
11104
  };
11105
11105
  }
11106
11106
 
11107
+ // src/pqc-verify-envelope/index.ts
11108
+ var pqc_verify_envelope_exports = {};
11109
+ __export(pqc_verify_envelope_exports, {
11110
+ KYBER_MIN_TIMESTAMP_MS: () => KYBER_MIN_TIMESTAMP_MS,
11111
+ validateEnvelopeSchema: () => validateEnvelopeSchema,
11112
+ verifyPqcEnvelope: () => verifyPqcEnvelope
11113
+ });
11114
+
11115
+ // src/pqc-verify-envelope/envelope-schema-validator.ts
11116
+ var KEM_CT_LEN = {
11117
+ "ml-kem-768": 1088,
11118
+ "ml-kem-1024": 1568
11119
+ };
11120
+ var AES_IV_LEN = 12;
11121
+ var AES_TAG_LEN = 16;
11122
+ var KDF_SALT_LEN = 16;
11123
+ function tryDecodeBase64(s) {
11124
+ if (typeof s !== "string" || s.length === 0) return null;
11125
+ try {
11126
+ const buf = Buffer.from(s, "base64");
11127
+ if (buf.toString("base64").replace(/=+$/, "") !== s.replace(/=+$/, "")) {
11128
+ return null;
11129
+ }
11130
+ return new Uint8Array(buf);
11131
+ } catch {
11132
+ return null;
11133
+ }
11134
+ }
11135
+ function isString(v) {
11136
+ return typeof v === "string";
11137
+ }
11138
+ function isNonEmptyString(v) {
11139
+ return typeof v === "string" && v.length > 0;
11140
+ }
11141
+ function isFiniteNumber(v) {
11142
+ return typeof v === "number" && Number.isFinite(v);
11143
+ }
11144
+ function isPlainObject(v) {
11145
+ return typeof v === "object" && v !== null && !Array.isArray(v);
11146
+ }
11147
+ function validateEnvelopeSchema(envelope) {
11148
+ if (!isPlainObject(envelope)) {
11149
+ return { ok: false, reason: "envelope must be a JSON object" };
11150
+ }
11151
+ const version = envelope.version;
11152
+ if (version === "kyber-aes-v1") {
11153
+ return validateKyberAesV1(envelope);
11154
+ }
11155
+ if (version === "aes-v0") {
11156
+ return validateAesV0(envelope);
11157
+ }
11158
+ return {
11159
+ ok: false,
11160
+ reason: `unknown envelope version: ${JSON.stringify(version)}`
11161
+ };
11162
+ }
11163
+ function validateKyberAesV1(env) {
11164
+ const kemAlgorithm = env.kemAlgorithm;
11165
+ if (kemAlgorithm !== "ml-kem-768" && kemAlgorithm !== "ml-kem-1024") {
11166
+ return {
11167
+ ok: false,
11168
+ reason: `kemAlgorithm must be 'ml-kem-768' or 'ml-kem-1024'`
11169
+ };
11170
+ }
11171
+ if (!isNonEmptyString(env.kemCiphertext)) {
11172
+ return { ok: false, reason: "kemCiphertext must be a non-empty base64 string" };
11173
+ }
11174
+ const kemCtBytes = tryDecodeBase64(env.kemCiphertext);
11175
+ if (!kemCtBytes) {
11176
+ return { ok: false, reason: "kemCiphertext is not valid base64" };
11177
+ }
11178
+ const expectedKemLen = KEM_CT_LEN[kemAlgorithm];
11179
+ if (kemCtBytes.length !== expectedKemLen) {
11180
+ return {
11181
+ ok: false,
11182
+ reason: `kemCiphertext length ${kemCtBytes.length} != expected ${expectedKemLen} for ${kemAlgorithm}`
11183
+ };
11184
+ }
11185
+ if (!isString(env.recipientPkFingerprint) || !/^[0-9a-f]{32}$/i.test(env.recipientPkFingerprint)) {
11186
+ return {
11187
+ ok: false,
11188
+ reason: "recipientPkFingerprint must be a 32-char hex string (16-byte sha384 prefix)"
11189
+ };
11190
+ }
11191
+ if (env.aesAlgorithm !== "aes-256-gcm") {
11192
+ return { ok: false, reason: `aesAlgorithm must be 'aes-256-gcm'` };
11193
+ }
11194
+ if (!isNonEmptyString(env.aesIv)) {
11195
+ return { ok: false, reason: "aesIv must be a non-empty base64 string" };
11196
+ }
11197
+ const ivBytes = tryDecodeBase64(env.aesIv);
11198
+ if (!ivBytes) return { ok: false, reason: "aesIv is not valid base64" };
11199
+ if (ivBytes.length !== AES_IV_LEN) {
11200
+ return {
11201
+ ok: false,
11202
+ reason: `aesIv length ${ivBytes.length} != expected ${AES_IV_LEN} (AES-GCM 96-bit nonce)`
11203
+ };
11204
+ }
11205
+ if (typeof env.aesCiphertext !== "string") {
11206
+ return { ok: false, reason: "aesCiphertext must be a base64 string" };
11207
+ }
11208
+ if (env.aesCiphertext.length > 0) {
11209
+ const ctBytes = tryDecodeBase64(env.aesCiphertext);
11210
+ if (!ctBytes) return { ok: false, reason: "aesCiphertext is not valid base64" };
11211
+ }
11212
+ if (!isNonEmptyString(env.aesAuthTag)) {
11213
+ return { ok: false, reason: "aesAuthTag must be a non-empty base64 string" };
11214
+ }
11215
+ const tagBytes = tryDecodeBase64(env.aesAuthTag);
11216
+ if (!tagBytes) return { ok: false, reason: "aesAuthTag is not valid base64" };
11217
+ if (tagBytes.length !== AES_TAG_LEN) {
11218
+ return {
11219
+ ok: false,
11220
+ reason: `aesAuthTag length ${tagBytes.length} != expected ${AES_TAG_LEN} (AES-GCM 128-bit tag)`
11221
+ };
11222
+ }
11223
+ if (env.kdfAlgorithm !== "hkdf-sha384") {
11224
+ return { ok: false, reason: `kdfAlgorithm must be 'hkdf-sha384'` };
11225
+ }
11226
+ if (!isNonEmptyString(env.kdfSalt)) {
11227
+ return { ok: false, reason: "kdfSalt must be a non-empty base64 string" };
11228
+ }
11229
+ const saltBytes = tryDecodeBase64(env.kdfSalt);
11230
+ if (!saltBytes) return { ok: false, reason: "kdfSalt is not valid base64" };
11231
+ if (saltBytes.length !== KDF_SALT_LEN) {
11232
+ return {
11233
+ ok: false,
11234
+ reason: `kdfSalt length ${saltBytes.length} != expected ${KDF_SALT_LEN}`
11235
+ };
11236
+ }
11237
+ if (!isNonEmptyString(env.kdfLabel)) {
11238
+ return { ok: false, reason: "kdfLabel must be a non-empty string" };
11239
+ }
11240
+ if (env.kdfLabel.length > 256) {
11241
+ return {
11242
+ ok: false,
11243
+ reason: `kdfLabel length ${env.kdfLabel.length} exceeds 256-char limit`
11244
+ };
11245
+ }
11246
+ if (!isFiniteNumber(env.encryptedAt)) {
11247
+ return { ok: false, reason: "encryptedAt must be a finite number (millis epoch)" };
11248
+ }
11249
+ return { ok: true, version: "kyber-aes-v1" };
11250
+ }
11251
+ function validateAesV0(env) {
11252
+ if (!isNonEmptyString(env.aesIv)) {
11253
+ return { ok: false, reason: "aesIv must be a non-empty base64 string" };
11254
+ }
11255
+ const ivBytes = tryDecodeBase64(env.aesIv);
11256
+ if (!ivBytes) return { ok: false, reason: "aesIv is not valid base64" };
11257
+ if (ivBytes.length !== AES_IV_LEN) {
11258
+ return {
11259
+ ok: false,
11260
+ reason: `aesIv length ${ivBytes.length} != expected ${AES_IV_LEN} (AES-GCM 96-bit nonce)`
11261
+ };
11262
+ }
11263
+ if (typeof env.aesCiphertext !== "string") {
11264
+ return { ok: false, reason: "aesCiphertext must be a base64 string" };
11265
+ }
11266
+ if (env.aesCiphertext.length > 0) {
11267
+ const ctBytes = tryDecodeBase64(env.aesCiphertext);
11268
+ if (!ctBytes) return { ok: false, reason: "aesCiphertext is not valid base64" };
11269
+ }
11270
+ if (!isNonEmptyString(env.aesAuthTag)) {
11271
+ return { ok: false, reason: "aesAuthTag must be a non-empty base64 string" };
11272
+ }
11273
+ const tagBytes = tryDecodeBase64(env.aesAuthTag);
11274
+ if (!tagBytes) return { ok: false, reason: "aesAuthTag is not valid base64" };
11275
+ if (tagBytes.length !== AES_TAG_LEN) {
11276
+ return {
11277
+ ok: false,
11278
+ reason: `aesAuthTag length ${tagBytes.length} != expected ${AES_TAG_LEN} (AES-GCM 128-bit tag)`
11279
+ };
11280
+ }
11281
+ return { ok: true, version: "aes-v0" };
11282
+ }
11283
+
11284
+ // src/pqc-verify-envelope/verify-pqc-envelope.ts
11285
+ var KYBER_MIN_TIMESTAMP_MS = 17040672e5;
11286
+ async function verifyPqcEnvelope(envelope, options = {}) {
11287
+ const schema = validateEnvelopeSchema(envelope);
11288
+ if (!schema.ok) {
11289
+ return {
11290
+ valid: false,
11291
+ reason: `schema-invalid: ${schema.reason}`,
11292
+ details: { schemaValid: false, base64Valid: false, timestampPlausible: false }
11293
+ };
11294
+ }
11295
+ const env = envelope;
11296
+ const version = schema.version;
11297
+ const details = {
11298
+ version,
11299
+ schemaValid: true,
11300
+ base64Valid: true,
11301
+ // computed below for kyber-aes-v1; legacy has no encryptedAt so treat as plausible.
11302
+ timestampPlausible: true
11303
+ };
11304
+ if (version === "kyber-aes-v1") {
11305
+ details.kemAlgorithm = env.kemAlgorithm;
11306
+ details.recipientPkFingerprint = env.recipientPkFingerprint;
11307
+ details.kdfLabel = env.kdfLabel;
11308
+ details.encryptedAt = env.encryptedAt;
11309
+ const minTs = options.minTimestamp ?? KYBER_MIN_TIMESTAMP_MS;
11310
+ const maxTs = options.maxTimestamp ?? Date.now();
11311
+ const ts = details.encryptedAt;
11312
+ if (ts < minTs) {
11313
+ details.timestampPlausible = false;
11314
+ return {
11315
+ valid: false,
11316
+ reason: `timestamp-before-minimum: encryptedAt=${ts} < min=${minTs}`,
11317
+ details
11318
+ };
11319
+ }
11320
+ if (ts > maxTs) {
11321
+ details.timestampPlausible = false;
11322
+ return {
11323
+ valid: false,
11324
+ reason: `timestamp-in-future: encryptedAt=${ts} > max=${maxTs}`,
11325
+ details
11326
+ };
11327
+ }
11328
+ if (options.expectedLabel !== void 0) {
11329
+ if (details.kdfLabel !== options.expectedLabel) {
11330
+ return {
11331
+ valid: false,
11332
+ reason: `label-mismatch: expected='${options.expectedLabel}' actual='${details.kdfLabel}'`,
11333
+ details
11334
+ };
11335
+ }
11336
+ }
11337
+ if (options.expectedRecipientPkFingerprint !== void 0) {
11338
+ const a = (details.recipientPkFingerprint ?? "").toLowerCase();
11339
+ const b = options.expectedRecipientPkFingerprint.toLowerCase();
11340
+ if (a !== b) {
11341
+ return {
11342
+ valid: false,
11343
+ reason: `recipient-pk-fingerprint-mismatch: expected='${b}' actual='${a}'`,
11344
+ details
11345
+ };
11346
+ }
11347
+ }
11348
+ }
11349
+ return { valid: true, version, details };
11350
+ }
11351
+
11107
11352
  // src/rules/atoms/index.ts
11108
11353
  var atom = {
11109
11354
  timeRange: (cfg) => ({
@@ -12543,6 +12788,7 @@ exports.HistoricalBalanceClient = HistoricalBalanceClient;
12543
12788
  exports.HistoricalBalanceClientError = HistoricalBalanceClientError;
12544
12789
  exports.IPFSClient = IPFSClient;
12545
12790
  exports.KNOWN_NETWORKS = KNOWN_NETWORKS;
12791
+ exports.KYBER_MIN_TIMESTAMP_MS = KYBER_MIN_TIMESTAMP_MS;
12546
12792
  exports.KeyConditionSchema = KeyConditionSchema;
12547
12793
  exports.MIRROR_NODE_URLS = MIRROR_NODE_URLS;
12548
12794
  exports.MessagingClient = MessagingClient;
@@ -12637,6 +12883,7 @@ exports.operator = operator_exports;
12637
12883
  exports.parsePqcCert = parsePqcCert;
12638
12884
  exports.personhood = personhood_exports;
12639
12885
  exports.pqcVerify = pqc_verify_exports;
12886
+ exports.pqcVerifyEnvelope = pqc_verify_envelope_exports;
12640
12887
  exports.resilientFetch = resilientFetch;
12641
12888
  exports.resolveNetwork = resolveNetwork;
12642
12889
  exports.resources = resources_exports;
@@ -12655,7 +12902,9 @@ exports.tradingAgent = tradingAgent;
12655
12902
  exports.utilityToken = utilityToken;
12656
12903
  exports.validate = validate;
12657
12904
  exports.validateAgentRules = validateAgentRules;
12905
+ exports.validateEnvelopeSchema = validateEnvelopeSchema;
12658
12906
  exports.verifyPqcAttestation = verifyPqcAttestation;
12907
+ exports.verifyPqcEnvelope = verifyPqcEnvelope;
12659
12908
  exports.vestingSchedule = vestingSchedule;
12660
12909
  //# sourceMappingURL=index.js.map
12661
12910
  //# sourceMappingURL=index.js.map