@majikah/majik-universal-id-client 0.0.4 → 0.0.6
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.
|
@@ -11,6 +11,7 @@ import { MAJIK_API_RESPONSE } from "./core/types";
|
|
|
11
11
|
import { ImageSignatureStub, ImageSignOptions, ImageVerificationResult } from "@majikah/majik-signature/dist/core/stamp";
|
|
12
12
|
import { CreateUniversalIDOptions, MajikUniversalID } from "@majikah/majik-universal-id";
|
|
13
13
|
import { MajikUser } from "@thezelijah/majik-user";
|
|
14
|
+
import { MajikSLink } from "@majikah/majik-slink";
|
|
14
15
|
type MajikUniversalIdClientEvents = "create-id" | "sign" | "verify" | "unlock" | "lock" | "new-account" | "new-contact" | "removed-account" | "removed-contact" | "active-account-change" | "error";
|
|
15
16
|
interface MajikUniversalIdClientStatic<T extends MajikUniversalIdClient> {
|
|
16
17
|
new (config: MajikUniversalIdClientConfig, id?: string): T;
|
|
@@ -510,13 +511,13 @@ export declare class MajikUniversalIdClient {
|
|
|
510
511
|
key?: MajikKey;
|
|
511
512
|
expectedSignerId?: string;
|
|
512
513
|
}): Promise<Array<VerificationResult & {
|
|
513
|
-
handler: string |
|
|
514
|
-
mimeType: string |
|
|
514
|
+
handler: string | undefined;
|
|
515
|
+
mimeType: string | undefined;
|
|
515
516
|
error: Error | null;
|
|
516
517
|
}>>;
|
|
517
518
|
/**
|
|
518
519
|
* Extract the embedded MajikSignature from a file.
|
|
519
|
-
* Returns
|
|
520
|
+
* Returns an array of typed MajikSignature instance, or empty if not found.
|
|
520
521
|
*
|
|
521
522
|
* Does not verify — use verifyFile() to verify.
|
|
522
523
|
*
|
|
@@ -526,7 +527,7 @@ export declare class MajikUniversalIdClient {
|
|
|
526
527
|
*/
|
|
527
528
|
extractSignature(file: Blob, options?: {
|
|
528
529
|
mimeType?: string;
|
|
529
|
-
}): Promise<MajikSignature | null>;
|
|
530
|
+
}): Promise<MajikSignature[] | null>;
|
|
530
531
|
/**
|
|
531
532
|
* Return a clean copy of the file with any embedded signature removed.
|
|
532
533
|
* The returned bytes are exactly what was originally signed.
|
|
@@ -607,7 +608,12 @@ export declare class MajikUniversalIdClient {
|
|
|
607
608
|
*/
|
|
608
609
|
getFileSignatureInfo(file: Blob, options?: {
|
|
609
610
|
mimeType?: string;
|
|
610
|
-
}): Promise<MajikSignature | null>;
|
|
611
|
+
}): Promise<MajikSignature[] | null>;
|
|
612
|
+
signURL(url: string, verified?: boolean): Promise<MajikSLink>;
|
|
613
|
+
verifySLink(slink: MajikSLink): Promise<VerificationResult & {
|
|
614
|
+
handler?: string;
|
|
615
|
+
reason?: string;
|
|
616
|
+
}>;
|
|
611
617
|
/**
|
|
612
618
|
* Sign an image with dual-layer embedding.
|
|
613
619
|
*
|
|
@@ -13,6 +13,7 @@ import { clearAllBlobs, idbLoadBlob, idbSaveBlob, } from "./core/utils/idb-majik
|
|
|
13
13
|
import { autoSaveMajikFileData, loadSavedMajikFileData, } from "./core/utils/majik-file-utils";
|
|
14
14
|
import { gunzipSync, gzipSync } from "fflate";
|
|
15
15
|
import { MajikUniversalID, } from "@majikah/majik-universal-id";
|
|
16
|
+
import { MajikSLink } from "@majikah/majik-slink";
|
|
16
17
|
// ─── MajikUniversalIdClient ─────────────────────────────────────────────────────
|
|
17
18
|
export class MajikUniversalIdClient {
|
|
18
19
|
userProfile = "default";
|
|
@@ -982,20 +983,21 @@ export class MajikUniversalIdClient {
|
|
|
982
983
|
* });
|
|
983
984
|
*/
|
|
984
985
|
async verifyFile(file, options) {
|
|
985
|
-
console.log("Verifying File");
|
|
986
986
|
try {
|
|
987
987
|
const publicKeys = await this._resolveSignerPublicKeys(options);
|
|
988
988
|
if (publicKeys) {
|
|
989
|
-
|
|
989
|
+
const results = await MajikSignature.verifyFile(file, publicKeys, {
|
|
990
990
|
expectedSignerId: options?.expectedSignerId,
|
|
991
991
|
mimeType: options?.mimeType,
|
|
992
992
|
}, true);
|
|
993
|
+
return results[0];
|
|
993
994
|
}
|
|
994
|
-
// No signer provided — extract and use self-reported keys
|
|
995
|
+
// No signer provided — extract and use self-reported keys from first signature.
|
|
996
|
+
// For full multi-sig verification, pass a contactId or publicKeyBase64.
|
|
995
997
|
const extracted = await MajikSignature.extractFrom(file, {
|
|
996
998
|
mimeType: options?.mimeType,
|
|
997
999
|
});
|
|
998
|
-
if (!extracted) {
|
|
1000
|
+
if (!extracted.length) {
|
|
999
1001
|
return {
|
|
1000
1002
|
valid: false,
|
|
1001
1003
|
signerId: "",
|
|
@@ -1004,10 +1006,12 @@ export class MajikUniversalIdClient {
|
|
|
1004
1006
|
reason: "No embedded signature found",
|
|
1005
1007
|
};
|
|
1006
1008
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
+
const firstSig = extracted[0];
|
|
1010
|
+
const results = await MajikSignature.verifyFile(file, firstSig.extractPublicKeys(), {
|
|
1011
|
+
expectedSignerId: firstSig.signerId,
|
|
1009
1012
|
mimeType: options?.mimeType,
|
|
1010
1013
|
}, true);
|
|
1014
|
+
return results[0];
|
|
1011
1015
|
}
|
|
1012
1016
|
catch (err) {
|
|
1013
1017
|
this._emit("error", err, { context: "verifyFile" });
|
|
@@ -1045,34 +1049,36 @@ export class MajikUniversalIdClient {
|
|
|
1045
1049
|
try {
|
|
1046
1050
|
let result;
|
|
1047
1051
|
if (publicKeys) {
|
|
1048
|
-
|
|
1052
|
+
const results = await MajikSignature.verifyFile(file, publicKeys, {
|
|
1049
1053
|
mimeType,
|
|
1050
1054
|
expectedSignerId,
|
|
1051
1055
|
});
|
|
1056
|
+
result = results[0];
|
|
1052
1057
|
}
|
|
1053
1058
|
else {
|
|
1054
|
-
// No signer hint — use self-reported keys from each file's envelope
|
|
1055
1059
|
const extracted = await MajikSignature.extractFrom(file, {
|
|
1056
1060
|
mimeType,
|
|
1057
1061
|
});
|
|
1058
|
-
if (!extracted) {
|
|
1062
|
+
if (!extracted.length) {
|
|
1059
1063
|
return {
|
|
1060
1064
|
valid: false,
|
|
1061
|
-
signerId:
|
|
1062
|
-
contentHash:
|
|
1065
|
+
signerId: undefined,
|
|
1066
|
+
contentHash: undefined,
|
|
1063
1067
|
timestamp: new Date().toISOString(),
|
|
1064
1068
|
reason: "No embedded signature found",
|
|
1065
|
-
handler:
|
|
1066
|
-
mimeType
|
|
1069
|
+
handler: undefined,
|
|
1070
|
+
mimeType,
|
|
1067
1071
|
error: null,
|
|
1068
1072
|
};
|
|
1069
1073
|
}
|
|
1070
|
-
|
|
1074
|
+
const firstSig = extracted[0];
|
|
1075
|
+
const results = await MajikSignature.verifyFile(file, firstSig.extractPublicKeys(), { mimeType, expectedSignerId: firstSig.signerId });
|
|
1076
|
+
result = results[0];
|
|
1071
1077
|
}
|
|
1072
1078
|
return {
|
|
1073
1079
|
...result,
|
|
1074
|
-
handler: result.handler
|
|
1075
|
-
mimeType
|
|
1080
|
+
handler: result.handler,
|
|
1081
|
+
mimeType,
|
|
1076
1082
|
error: null,
|
|
1077
1083
|
};
|
|
1078
1084
|
}
|
|
@@ -1080,11 +1086,11 @@ export class MajikUniversalIdClient {
|
|
|
1080
1086
|
this._emit("error", err, { context: "batchVerifyFiles" });
|
|
1081
1087
|
return {
|
|
1082
1088
|
valid: false,
|
|
1083
|
-
signerId:
|
|
1084
|
-
contentHash:
|
|
1089
|
+
signerId: undefined,
|
|
1090
|
+
contentHash: undefined,
|
|
1085
1091
|
timestamp: new Date().toISOString(),
|
|
1086
|
-
handler:
|
|
1087
|
-
mimeType
|
|
1092
|
+
handler: undefined,
|
|
1093
|
+
mimeType,
|
|
1088
1094
|
error: err instanceof Error ? err : new Error(String(err)),
|
|
1089
1095
|
};
|
|
1090
1096
|
}
|
|
@@ -1093,7 +1099,7 @@ export class MajikUniversalIdClient {
|
|
|
1093
1099
|
// ── Signature Utilities ───────────────────────────────────────────────────
|
|
1094
1100
|
/**
|
|
1095
1101
|
* Extract the embedded MajikSignature from a file.
|
|
1096
|
-
* Returns
|
|
1102
|
+
* Returns an array of typed MajikSignature instance, or empty if not found.
|
|
1097
1103
|
*
|
|
1098
1104
|
* Does not verify — use verifyFile() to verify.
|
|
1099
1105
|
*
|
|
@@ -1215,6 +1221,51 @@ export class MajikUniversalIdClient {
|
|
|
1215
1221
|
throw err;
|
|
1216
1222
|
}
|
|
1217
1223
|
}
|
|
1224
|
+
// ── Majik SLink ───────────────────────────
|
|
1225
|
+
async signURL(url, verified = false) {
|
|
1226
|
+
const id = this.getActiveAccount()?.id;
|
|
1227
|
+
if (!id)
|
|
1228
|
+
throw new Error("No active account — call setActiveAccount() first");
|
|
1229
|
+
if (!this.user)
|
|
1230
|
+
throw new Error("Login required - A valid Majikah account is required");
|
|
1231
|
+
try {
|
|
1232
|
+
await MajikKeyStore.ensureUnlocked(id);
|
|
1233
|
+
const key = MajikKeyStore.get(id);
|
|
1234
|
+
if (!key)
|
|
1235
|
+
throw new Error(`Account not found in keystore: "${id}"`);
|
|
1236
|
+
if (!key.hasSigningKeys) {
|
|
1237
|
+
throw new Error(`Account "${id}" has no signing keys. ` +
|
|
1238
|
+
`Re-import via importAccountFromMnemonicBackup() to enable signing.`);
|
|
1239
|
+
}
|
|
1240
|
+
return await MajikSLink.create(url, key, this.user.id, {
|
|
1241
|
+
status: verified ? "verified" : undefined,
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
catch (err) {
|
|
1245
|
+
this._emit("error", err, { context: "signURL" });
|
|
1246
|
+
throw err;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
async verifySLink(slink) {
|
|
1250
|
+
try {
|
|
1251
|
+
const id = this.getActiveAccount()?.id;
|
|
1252
|
+
if (!id)
|
|
1253
|
+
throw new Error("No active account — call setActiveAccount() first");
|
|
1254
|
+
await MajikKeyStore.ensureUnlocked(id);
|
|
1255
|
+
const key = MajikKeyStore.get(id);
|
|
1256
|
+
if (!key)
|
|
1257
|
+
throw new Error(`Account not found in keystore: "${id}"`);
|
|
1258
|
+
const publicKeys = await this._resolveSignerPublicKeys({
|
|
1259
|
+
key: key,
|
|
1260
|
+
});
|
|
1261
|
+
const results = slink.verify(publicKeys ?? undefined);
|
|
1262
|
+
return results;
|
|
1263
|
+
}
|
|
1264
|
+
catch (err) {
|
|
1265
|
+
this._emit("error", err, { context: "verifySLink" });
|
|
1266
|
+
throw err;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1218
1269
|
// ── STAMP (compression-resistant image signing) ───────────────────────────
|
|
1219
1270
|
//
|
|
1220
1271
|
// These methods delegate to MajikImageSignature, passing `MajikSignature`
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-universal-id-client",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "The core universal identity model for the Majikah ecosystem, featuring hybrid PQC signatures (Ed25519 + ML-DSA), ML-KEM-768 private info encryption, and multi-stage Didit verification graduation.",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.6",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|
|
@@ -46,7 +46,9 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@majikah/majik-key": "^0.2.3",
|
|
49
|
-
"@majikah/majik-
|
|
49
|
+
"@majikah/majik-signature": "^0.0.15",
|
|
50
|
+
"@majikah/majik-slink": "^0.0.1",
|
|
51
|
+
"@majikah/majik-universal-id": "^0.0.8",
|
|
50
52
|
"idb": "^8.0.3"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|