@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 | null;
514
- mimeType: string | null;
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 a fully typed MajikSignature instance, or null if not found.
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
- return MajikSignature.verifyFile(file, publicKeys, {
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
- return MajikSignature.verifyFile(file, extracted.extractPublicKeys(), {
1008
- expectedSignerId: options?.expectedSignerId,
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
- result = await MajikSignature.verifyFile(file, publicKeys, {
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: null,
1066
- mimeType: mimeType ?? null,
1069
+ handler: undefined,
1070
+ mimeType,
1067
1071
  error: null,
1068
1072
  };
1069
1073
  }
1070
- result = await MajikSignature.verifyFile(file, extracted.extractPublicKeys(), { mimeType, expectedSignerId });
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 ?? null,
1075
- mimeType: mimeType ?? null,
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: null,
1087
- mimeType: mimeType ?? null,
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 a fully typed MajikSignature instance, or null if not found.
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.4",
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-universal-id": "^0.0.6",
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": {