@majikah/majik-message 0.2.21 → 0.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/dist/core/contacts/errors.d.ts +12 -0
- package/dist/core/contacts/errors.js +27 -0
- package/dist/core/contacts/majik-contact-directory.d.ts +2 -8
- package/dist/core/contacts/majik-contact-directory.js +1 -11
- package/dist/core/contacts/majik-contact-groups.d.ts +185 -0
- package/dist/core/contacts/majik-contact-groups.js +557 -0
- package/dist/core/contacts/majik-contact-manager.d.ts +240 -0
- package/dist/core/contacts/majik-contact-manager.js +449 -0
- package/dist/core/contacts/majik-contact-migration.d.ts +27 -0
- package/dist/core/contacts/majik-contact-migration.js +84 -0
- package/dist/core/contacts/types.d.ts +11 -0
- package/dist/core/contacts/types.js +4 -0
- package/dist/majik-message.d.ts +160 -36
- package/dist/majik-message.js +288 -128
- package/package.json +4 -4
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MajikContactDirectoryData, MajikContactManagerJSON } from "./types";
|
|
2
|
+
export interface MajikMessageRawJSON extends Record<string, unknown> {
|
|
3
|
+
id: string;
|
|
4
|
+
contacts: MajikContactManagerJSON | MajikContactDirectoryData;
|
|
5
|
+
envelopeCache: unknown;
|
|
6
|
+
ownAccounts?: unknown;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Accepts a raw parsed JSON object from IDB/storage and guarantees the
|
|
10
|
+
* returned value always uses the current `MajikContactManagerJSON` shape
|
|
11
|
+
* for its `contacts` field — even if the blob was saved before groups existed.
|
|
12
|
+
*
|
|
13
|
+
* This is the single migration choke-point. Call it once at the top of
|
|
14
|
+
* `MajikMessage.fromJSON()` before touching any field.
|
|
15
|
+
*
|
|
16
|
+
* Migration performed (legacy → current):
|
|
17
|
+
* contacts: { contacts: [...] }
|
|
18
|
+
* →
|
|
19
|
+
* contacts: { contacts: [...], groups: { groups: [] } }
|
|
20
|
+
*
|
|
21
|
+
* The empty `groups` payload means `MajikContactGroupManager.fromJSON()`
|
|
22
|
+
* will bootstrap the two system groups (Favorites, Blocked) with no members,
|
|
23
|
+
* which is exactly correct for a first-time migration.
|
|
24
|
+
*/
|
|
25
|
+
export declare function migrateMajikMessageJSON(raw: unknown): MajikMessageRawJSON & {
|
|
26
|
+
contacts: MajikContactManagerJSON;
|
|
27
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// majik-contact-migration.ts
|
|
3
|
+
//
|
|
4
|
+
// Detects whether a persisted MajikMessage JSON blob was saved before
|
|
5
|
+
// MajikContactManager existed (legacy) or after (current), and returns a
|
|
6
|
+
// normalised MajikMessageJSON that always carries the new shape.
|
|
7
|
+
//
|
|
8
|
+
// Legacy shape (pre-migration):
|
|
9
|
+
// { id, contacts: { contacts: [...] }, envelopeCache, ownAccounts?, pinHash? }
|
|
10
|
+
// ↑ contacts is a MajikContactDirectoryData — no `groups` field
|
|
11
|
+
//
|
|
12
|
+
// Current shape (post-migration):
|
|
13
|
+
// { id, contacts: { contacts: [...], groups: { groups: [...] } }, envelopeCache, ... }
|
|
14
|
+
// ↑ contacts is a MajikContactManagerJSON — always has both `contacts` and `groups`
|
|
15
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
16
|
+
/* -------------------------------
|
|
17
|
+
* Shape-detection helpers
|
|
18
|
+
* ------------------------------- */
|
|
19
|
+
/**
|
|
20
|
+
* Returns true when the blob looks like a legacy save that only has
|
|
21
|
+
* a flat `{ contacts: [...] }` directory payload — no `groups` key.
|
|
22
|
+
*/
|
|
23
|
+
function isLegacyContactsShape(raw) {
|
|
24
|
+
if (!raw || typeof raw !== "object")
|
|
25
|
+
return false;
|
|
26
|
+
const obj = raw;
|
|
27
|
+
// Must have a `contacts` field that is an object …
|
|
28
|
+
if (!obj.contacts || typeof obj.contacts !== "object")
|
|
29
|
+
return false;
|
|
30
|
+
const contacts = obj.contacts;
|
|
31
|
+
// … that contains a `contacts` array (the raw serialized contacts) …
|
|
32
|
+
if (!Array.isArray(contacts.contacts))
|
|
33
|
+
return false;
|
|
34
|
+
// … but does NOT yet have a `groups` field — that is the migration trigger.
|
|
35
|
+
return !("groups" in contacts);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Accepts a raw parsed JSON object from IDB/storage and guarantees the
|
|
39
|
+
* returned value always uses the current `MajikContactManagerJSON` shape
|
|
40
|
+
* for its `contacts` field — even if the blob was saved before groups existed.
|
|
41
|
+
*
|
|
42
|
+
* This is the single migration choke-point. Call it once at the top of
|
|
43
|
+
* `MajikMessage.fromJSON()` before touching any field.
|
|
44
|
+
*
|
|
45
|
+
* Migration performed (legacy → current):
|
|
46
|
+
* contacts: { contacts: [...] }
|
|
47
|
+
* →
|
|
48
|
+
* contacts: { contacts: [...], groups: { groups: [] } }
|
|
49
|
+
*
|
|
50
|
+
* The empty `groups` payload means `MajikContactGroupManager.fromJSON()`
|
|
51
|
+
* will bootstrap the two system groups (Favorites, Blocked) with no members,
|
|
52
|
+
* which is exactly correct for a first-time migration.
|
|
53
|
+
*/
|
|
54
|
+
export function migrateMajikMessageJSON(raw) {
|
|
55
|
+
if (!raw || typeof raw !== "object") {
|
|
56
|
+
throw new Error("migrateMajikMessageJSON: input must be a non-null object");
|
|
57
|
+
}
|
|
58
|
+
const obj = raw;
|
|
59
|
+
if (!obj.id || typeof obj.id !== "string") {
|
|
60
|
+
throw new Error("migrateMajikMessageJSON: missing required field 'id'");
|
|
61
|
+
}
|
|
62
|
+
// ── Already in current shape — pass through untouched ────────────────────
|
|
63
|
+
if (!isLegacyContactsShape(obj)) {
|
|
64
|
+
// Validate it at least has the expected structure
|
|
65
|
+
const contacts = obj.contacts;
|
|
66
|
+
if (!contacts || !Array.isArray(contacts.contacts) || !contacts.groups) {
|
|
67
|
+
throw new Error("migrateMajikMessageJSON: 'contacts' field has an unrecognised shape — " +
|
|
68
|
+
"expected either a legacy { contacts: [...] } or current { contacts: [...], groups: {...} }");
|
|
69
|
+
}
|
|
70
|
+
return obj;
|
|
71
|
+
}
|
|
72
|
+
// ── Legacy shape — lift it into the current shape ─────────────────────────
|
|
73
|
+
console.info("[MajikMessage] Migrating persisted state from legacy contacts schema → " +
|
|
74
|
+
"MajikContactManager schema. Groups will be initialised empty.");
|
|
75
|
+
const legacyContacts = obj.contacts;
|
|
76
|
+
const migratedContacts = {
|
|
77
|
+
contacts: legacyContacts, // preserve all serialized contacts as-is
|
|
78
|
+
groups: { groups: [] }, // empty groups — system groups are bootstrapped at runtime
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
...obj,
|
|
82
|
+
contacts: migratedContacts,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SerializedMajikContact, SerializedMajikContactGroup } from "@majikah/majik-contact";
|
|
2
|
+
export interface MajikContactManagerJSON {
|
|
3
|
+
contacts: MajikContactDirectoryData;
|
|
4
|
+
groups: MajikContactGroupManagerData;
|
|
5
|
+
}
|
|
6
|
+
export interface MajikContactDirectoryData {
|
|
7
|
+
contacts: SerializedMajikContact[];
|
|
8
|
+
}
|
|
9
|
+
export interface MajikContactGroupManagerData {
|
|
10
|
+
groups: SerializedMajikContactGroup[];
|
|
11
|
+
}
|
package/dist/majik-message.d.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
import { MajikContact, type MajikContactMeta, type SerializedMajikContact } from "@majikah/majik-contact";
|
|
1
|
+
import { MajikContact, MajikContactGroup, MajikContactGroupMeta, type MajikContactMeta, type SerializedMajikContact } from "@majikah/majik-contact";
|
|
2
2
|
import { MessageEnvelope } from "./core/messages/message-envelope";
|
|
3
3
|
import { EnvelopeCache, type EnvelopeCacheItem, type EnvelopeCacheJSON } from "./core/messages/envelope-cache";
|
|
4
4
|
import { MajikKeyStore } from "./core/crypto/keystore";
|
|
5
|
-
import { MajikContactDirectory, type MajikContactDirectoryData } from "./core/contacts/majik-contact-directory";
|
|
6
5
|
import type { DecryptFileOptions, EncryptFileOptions, EncryptFileResult, MAJIK_API_RESPONSE, MajikMessagePublicKey } from "./core/types";
|
|
7
6
|
import { MajikMessageChat } from "./core/database/chat/majik-message-chat";
|
|
8
7
|
import { MajikMessageIdentity } from "./core/database/system/identity";
|
|
9
8
|
import { MajikKey } from "@majikah/majik-key";
|
|
10
9
|
import { MajikFile, MajikFileJSON } from "@majikah/majik-file";
|
|
11
10
|
import { EnvelopeInfo, ExpectedSigner, MajikSignature, SealInfo, SealVerificationResult, SignatoriesFilter, SignatoriesResult, SignatoryInfo, type MajikSignatureJSON, type MajikSignerPublicKeys, type VerificationResult } from "@majikah/majik-signature";
|
|
12
|
-
|
|
11
|
+
import { MajikContactManager } from "./core/contacts/majik-contact-manager";
|
|
12
|
+
import { MajikContactManagerJSON } from "./core/contacts/types";
|
|
13
|
+
type MajikMessageEvents = "message" | "envelope" | "untrusted" | "error" | "new-account" | "new-contact" | "new-contact-group" | "removed-account" | "removed-contact" | "removed-contact-group" | "contact-group-change" | "active-account-change";
|
|
13
14
|
interface MajikMessageStatic<T extends MajikMessage> {
|
|
14
15
|
new (config: MajikMessageConfig, id?: string): T;
|
|
15
16
|
fromJSON(json: MajikMessageJSON): Promise<T>;
|
|
16
17
|
}
|
|
17
18
|
export interface MajikMessageConfig {
|
|
18
19
|
keyStore?: typeof MajikKeyStore;
|
|
19
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Optional pre-constructed MajikContactManager.
|
|
22
|
+
* When omitted, MajikMessage creates a fresh one internally.
|
|
23
|
+
* Pass one when restoring state from fromJSON() or loadState().
|
|
24
|
+
*/
|
|
25
|
+
contactManager?: MajikContactManager;
|
|
20
26
|
envelopeCache?: EnvelopeCache;
|
|
21
27
|
}
|
|
22
28
|
export interface MajikMessageJSON {
|
|
23
29
|
id: string;
|
|
24
|
-
contacts:
|
|
30
|
+
contacts: MajikContactManagerJSON;
|
|
25
31
|
envelopeCache: EnvelopeCacheJSON;
|
|
26
32
|
ownAccounts?: {
|
|
27
33
|
accounts: SerializedMajikContact[];
|
|
@@ -31,11 +37,9 @@ export interface MajikMessageJSON {
|
|
|
31
37
|
type EventCallback = (...args: any[]) => void;
|
|
32
38
|
export declare class MajikMessage {
|
|
33
39
|
private userProfile;
|
|
34
|
-
private pinHash?;
|
|
35
40
|
private id;
|
|
36
|
-
private
|
|
41
|
+
private contacts;
|
|
37
42
|
private envelopeCache;
|
|
38
|
-
private scanner;
|
|
39
43
|
private listeners;
|
|
40
44
|
private ownAccounts;
|
|
41
45
|
private ownAccountsOrder;
|
|
@@ -106,8 +110,8 @@ export declare class MajikMessage {
|
|
|
106
110
|
hasContact(id: string): boolean;
|
|
107
111
|
hasContactByPublicKeyBase64(publicKey: MajikMessagePublicKey): Promise<boolean>;
|
|
108
112
|
getContactByPublicKey(publicKeyBase64: MajikMessagePublicKey): Promise<MajikContact | null>;
|
|
109
|
-
exportContactAsJSON(
|
|
110
|
-
exportContactAsString(
|
|
113
|
+
exportContactAsJSON(contactID: string): Promise<string | null>;
|
|
114
|
+
exportContactAsString(contactID: string): Promise<string | null>;
|
|
111
115
|
importContactFromJSON(jsonStr: string): Promise<MAJIK_API_RESPONSE>;
|
|
112
116
|
importContactFromString(base64Str: string): Promise<MAJIK_API_RESPONSE>;
|
|
113
117
|
exportContactCompressed(contact: MajikContact): Promise<string>;
|
|
@@ -121,6 +125,134 @@ export declare class MajikMessage {
|
|
|
121
125
|
isContactMajikahRegistered(id: string): boolean;
|
|
122
126
|
isContactMajikahIdentityChecked(id: string): boolean;
|
|
123
127
|
setContactMajikahStatus(id: string, status: boolean): void;
|
|
128
|
+
/**
|
|
129
|
+
* Creates and registers a new user-defined group.
|
|
130
|
+
* Throws if a group with the same ID already exists.
|
|
131
|
+
*/
|
|
132
|
+
createGroup(id: string, name: string, meta?: Partial<Omit<MajikContactGroupMeta, "name">>, initialMemberIds?: string[]): this;
|
|
133
|
+
/**
|
|
134
|
+
* Registers an already-constructed MajikContactGroup instance.
|
|
135
|
+
* Throws if a group with the same ID already exists.
|
|
136
|
+
*/
|
|
137
|
+
addGroup(group: MajikContactGroup): this;
|
|
138
|
+
/**
|
|
139
|
+
* Removes a user group by ID.
|
|
140
|
+
* System groups (Favorites, Blocked) cannot be deleted.
|
|
141
|
+
*/
|
|
142
|
+
removeGroup(id: string): MAJIK_API_RESPONSE;
|
|
143
|
+
/**
|
|
144
|
+
* Returns a group by ID, or undefined if not found.
|
|
145
|
+
*/
|
|
146
|
+
getContactGroup(id: string): MajikContactGroup | undefined;
|
|
147
|
+
/**
|
|
148
|
+
* Returns a group by ID. Throws if not found.
|
|
149
|
+
*/
|
|
150
|
+
getGroupOrThrow(id: string): MajikContactGroup;
|
|
151
|
+
/**
|
|
152
|
+
* Returns true if a group with the given ID exists.
|
|
153
|
+
*/
|
|
154
|
+
hasGroup(id: string): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* Returns all groups.
|
|
157
|
+
*
|
|
158
|
+
* @param includeSystem Include system groups (Favorites, Blocked). Default: true.
|
|
159
|
+
* @param sortedByName Sort results alphabetically by group name. Default: false.
|
|
160
|
+
*/
|
|
161
|
+
listContactGroups(includeSystem?: boolean, sortedByName?: boolean): MajikContactGroup[];
|
|
162
|
+
/**
|
|
163
|
+
* Returns only user-created groups (excludes Favorites and Blocked).
|
|
164
|
+
* Sorted alphabetically by name.
|
|
165
|
+
*/
|
|
166
|
+
listUserGroups(sortedByName?: boolean): MajikContactGroup[];
|
|
167
|
+
/**
|
|
168
|
+
* Returns only system groups (Favorites and Blocked).
|
|
169
|
+
*/
|
|
170
|
+
listSystemGroups(): MajikContactGroup[];
|
|
171
|
+
/**
|
|
172
|
+
* Updates mutable metadata on a group (name, description).
|
|
173
|
+
* Name is locked on system groups — will throw if attempted.
|
|
174
|
+
*/
|
|
175
|
+
updateGroupMeta(id: string, meta: Partial<Pick<MajikContactGroupMeta, "name" | "description">>): this;
|
|
176
|
+
/**
|
|
177
|
+
* Adds a contact to a group.
|
|
178
|
+
* Validates the contact exists in the directory.
|
|
179
|
+
* If the group is the system Blocked group, also calls contact.block().
|
|
180
|
+
* Throws if the contact is already a member — use addContactToGroupIfAbsent for idempotent.
|
|
181
|
+
*/
|
|
182
|
+
addContactToGroup(groupID: string, contactID: string): this;
|
|
183
|
+
/**
|
|
184
|
+
* Adds multiple contacts to a group in one call (all-or-nothing).
|
|
185
|
+
*/
|
|
186
|
+
addContactsToGroup(groupID: string, contactIds: string[]): this;
|
|
187
|
+
/**
|
|
188
|
+
* Removes a contact from a group.
|
|
189
|
+
* If the group is the system Blocked group, also calls contact.unblock().
|
|
190
|
+
* Throws if the contact is not a member — use removeContactFromGroupIfPresent for idempotent.
|
|
191
|
+
*/
|
|
192
|
+
removeContactFromGroup(groupID: string, contactID: string): this;
|
|
193
|
+
/**
|
|
194
|
+
* Moves a contact from one group to another atomically.
|
|
195
|
+
* Throws if the contact is not a member of the source group.
|
|
196
|
+
*/
|
|
197
|
+
moveContactBetweenGroups(contactID: string, fromGroupId: string, toGroupId: string): this;
|
|
198
|
+
/**
|
|
199
|
+
* Returns all hydrated MajikContact instances in the given group.
|
|
200
|
+
* Contacts removed from the directory since last save are silently skipped.
|
|
201
|
+
*/
|
|
202
|
+
getContactsInGroup(groupID: string): MajikContact[];
|
|
203
|
+
/**
|
|
204
|
+
* Returns hydrated contacts in the group, sorted by label (or ID if no label).
|
|
205
|
+
*/
|
|
206
|
+
getContactsInGroupSorted(groupID: string): MajikContact[];
|
|
207
|
+
/**
|
|
208
|
+
* Returns true if the contact is a member of the given group.
|
|
209
|
+
*/
|
|
210
|
+
isContactInGroup(groupID: string, contactID: string): boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Returns all groups the contact belongs to.
|
|
213
|
+
*/
|
|
214
|
+
getGroupsForContact(contactID: string): MajikContactGroup[];
|
|
215
|
+
/**
|
|
216
|
+
* Returns all group IDs the contact belongs to.
|
|
217
|
+
*/
|
|
218
|
+
getGroupIdsForContact(contactID: string): string[];
|
|
219
|
+
/**
|
|
220
|
+
* Adds the contact to the Favorites group (idempotent).
|
|
221
|
+
*/
|
|
222
|
+
addContactToFavorites(contactID: string): this;
|
|
223
|
+
/**
|
|
224
|
+
* Removes the contact from the Favorites group (idempotent).
|
|
225
|
+
*/
|
|
226
|
+
removeContactFromFavorites(contactID: string): this;
|
|
227
|
+
/**
|
|
228
|
+
* Returns true if the contact is in the Favorites group.
|
|
229
|
+
*/
|
|
230
|
+
isContactFavorite(contactID: string): boolean;
|
|
231
|
+
/**
|
|
232
|
+
* Returns true if the contact is in the Blocked group.
|
|
233
|
+
*/
|
|
234
|
+
isContactBlocked(contactID: string): boolean;
|
|
235
|
+
/**
|
|
236
|
+
* Returns the Favorites system group instance.
|
|
237
|
+
*/
|
|
238
|
+
getFavoritesGroup(): MajikContactGroup;
|
|
239
|
+
/**
|
|
240
|
+
* Returns the Blocked system group instance.
|
|
241
|
+
*/
|
|
242
|
+
getBlockedGroup(): MajikContactGroup;
|
|
243
|
+
/**
|
|
244
|
+
* Returns all contacts in the Favorites group as hydrated MajikContact instances.
|
|
245
|
+
*/
|
|
246
|
+
getFavoriteContacts(): MajikContact[];
|
|
247
|
+
/**
|
|
248
|
+
* Returns all contacts in the Blocked group as hydrated MajikContact instances.
|
|
249
|
+
*/
|
|
250
|
+
getBlockedContacts(): MajikContact[];
|
|
251
|
+
/**
|
|
252
|
+
* Clears both the directory and all group memberships.
|
|
253
|
+
* System groups are preserved (re-bootstrapped by the group manager).
|
|
254
|
+
*/
|
|
255
|
+
clearDirectory(): this;
|
|
124
256
|
/**
|
|
125
257
|
* Compose and encrypt a message for one or more recipients.
|
|
126
258
|
* Single recipient → solo envelope. Two or more → group envelope.
|
|
@@ -209,7 +341,7 @@ export declare class MajikMessage {
|
|
|
209
341
|
* metadata: row,
|
|
210
342
|
* });
|
|
211
343
|
* if (signature) {
|
|
212
|
-
* const result = await majik.verifyMajikFile(file, {
|
|
344
|
+
* const result = await majik.verifyMajikFile(file, { contactID: row.user_id });
|
|
213
345
|
* }
|
|
214
346
|
* ```
|
|
215
347
|
*/
|
|
@@ -249,7 +381,7 @@ export declare class MajikMessage {
|
|
|
249
381
|
* if the instance was restored from a metadata-only Supabase row.
|
|
250
382
|
*
|
|
251
383
|
* Signer resolution:
|
|
252
|
-
* -
|
|
384
|
+
* - contactID: looked up in the contact directory (own accounts included)
|
|
253
385
|
* - publicKeyBase64: looked up via contact directory
|
|
254
386
|
* - key: used directly (skips directory lookup)
|
|
255
387
|
* - none provided: falls back to public keys embedded in the signature
|
|
@@ -260,12 +392,12 @@ export declare class MajikMessage {
|
|
|
260
392
|
* @example — verify against the file's owner contact
|
|
261
393
|
* file.attachBinary(await r2.get(row.r2_key).arrayBuffer());
|
|
262
394
|
* const result = await majik.verifyMajikFile(file, {
|
|
263
|
-
*
|
|
395
|
+
* contactID: ownerContactId,
|
|
264
396
|
* });
|
|
265
397
|
* if (result?.valid) console.log("Verified, signed by", result.signerId);
|
|
266
398
|
*/
|
|
267
399
|
verifyMajikFile(file: MajikFile, options?: {
|
|
268
|
-
|
|
400
|
+
contactID?: string;
|
|
269
401
|
publicKeyBase64?: string;
|
|
270
402
|
key?: MajikKey;
|
|
271
403
|
}): Promise<VerificationResult | null>;
|
|
@@ -285,12 +417,12 @@ export declare class MajikMessage {
|
|
|
285
417
|
*
|
|
286
418
|
* @example
|
|
287
419
|
* const result = await majik.verifyMajikFileBinary(file, {
|
|
288
|
-
*
|
|
420
|
+
* contactID: "contact_abc",
|
|
289
421
|
* });
|
|
290
422
|
* if (result.valid) console.log("Plaintext verified");
|
|
291
423
|
*/
|
|
292
424
|
verifyMajikFileBinary(file: MajikFile, options?: {
|
|
293
|
-
|
|
425
|
+
contactID?: string;
|
|
294
426
|
publicKeyBase64?: string;
|
|
295
427
|
key?: MajikKey;
|
|
296
428
|
decryptAccountId?: string;
|
|
@@ -455,12 +587,12 @@ export declare class MajikMessage {
|
|
|
455
587
|
*
|
|
456
588
|
* @example
|
|
457
589
|
* const result = await majik.verifyText("Hello world", sig, {
|
|
458
|
-
*
|
|
590
|
+
* contactID: "contact_abc",
|
|
459
591
|
* });
|
|
460
592
|
* if (result.valid) console.log("Authentic");
|
|
461
593
|
*/
|
|
462
594
|
verifyText(text: string, signature: MajikSignature | MajikSignatureJSON | string, options?: {
|
|
463
|
-
|
|
595
|
+
contactID?: string;
|
|
464
596
|
publicKeyBase64?: string;
|
|
465
597
|
key?: MajikKey;
|
|
466
598
|
expectedSignerId?: string;
|
|
@@ -479,12 +611,12 @@ export declare class MajikMessage {
|
|
|
479
611
|
* @example
|
|
480
612
|
* const row = await db.findOne({ doc_id });
|
|
481
613
|
* const result = await majik.verifyDetached(docBytes, row.signature, {
|
|
482
|
-
*
|
|
614
|
+
* contactID: row.signer_contact_id,
|
|
483
615
|
* });
|
|
484
616
|
* if (result.valid) console.log("Signed by", result.signerId);
|
|
485
617
|
*/
|
|
486
618
|
verifyDetached(content: Uint8Array | string, serializedSignature: string, options?: {
|
|
487
|
-
|
|
619
|
+
contactID?: string;
|
|
488
620
|
publicKeyBase64?: string;
|
|
489
621
|
key?: MajikKey;
|
|
490
622
|
expectedSignerId?: string;
|
|
@@ -555,9 +687,6 @@ export declare class MajikMessage {
|
|
|
555
687
|
raw: Uint8Array;
|
|
556
688
|
}>;
|
|
557
689
|
isPassphraseValid(passphrase: string, id?: string): Promise<boolean>;
|
|
558
|
-
scanDOM(rootNode: Node): void;
|
|
559
|
-
startDOMObserver(rootNode: Node): void;
|
|
560
|
-
stopDOMObserver(): void;
|
|
561
690
|
on(event: MajikMessageEvents, callback: EventCallback): void;
|
|
562
691
|
off(event: MajikMessageEvents, callback?: EventCallback): void;
|
|
563
692
|
private emit;
|
|
@@ -656,7 +785,7 @@ export declare class MajikMessage {
|
|
|
656
785
|
* > against a known contact fingerprint before trusting the result.
|
|
657
786
|
*
|
|
658
787
|
* @example — verify against a known contact
|
|
659
|
-
* const result = await majik.verifyContent(docBytes, sig, {
|
|
788
|
+
* const result = await majik.verifyContent(docBytes, sig, { contactID: "contact_abc" });
|
|
660
789
|
* if (result.valid) console.log("Authentic, signed by:", result.signerId);
|
|
661
790
|
*
|
|
662
791
|
* @example — verify using embedded keys (self-reported)
|
|
@@ -664,7 +793,7 @@ export declare class MajikMessage {
|
|
|
664
793
|
* // always check result.signerId matches a known fingerprint
|
|
665
794
|
*/
|
|
666
795
|
verifyContent(content: Uint8Array | string, signature: MajikSignature | MajikSignatureJSON, options?: {
|
|
667
|
-
|
|
796
|
+
contactID?: string;
|
|
668
797
|
publicKeyBase64?: string;
|
|
669
798
|
key?: MajikKey;
|
|
670
799
|
expectedSignerId?: string;
|
|
@@ -681,16 +810,16 @@ export declare class MajikMessage {
|
|
|
681
810
|
* envelope are used (self-reported — see security note on verifyContent).
|
|
682
811
|
*
|
|
683
812
|
* @example — verify a signed PDF against a known contact
|
|
684
|
-
* const result = await majik.verifyFile(signedPdf, {
|
|
813
|
+
* const result = await majik.verifyFile(signedPdf, { contactID: "contact_abc" });
|
|
685
814
|
* if (result.valid) console.log("Verified:", result.signerId, result.timestamp);
|
|
686
815
|
*
|
|
687
816
|
* @example — check own signed file using active account
|
|
688
817
|
* const result = await majik.verifyFile(signedWav, {
|
|
689
|
-
*
|
|
818
|
+
* contactID: majik.getActiveAccount()?.id,
|
|
690
819
|
* });
|
|
691
820
|
*/
|
|
692
821
|
verifyFile(file: Blob, options?: {
|
|
693
|
-
|
|
822
|
+
contactID?: string;
|
|
694
823
|
publicKeyBase64?: string;
|
|
695
824
|
key?: MajikKey;
|
|
696
825
|
expectedSignerId?: string;
|
|
@@ -709,7 +838,7 @@ export declare class MajikMessage {
|
|
|
709
838
|
* @example
|
|
710
839
|
* const results = await majik.batchVerifyFiles(
|
|
711
840
|
* [pdfBlob, wavBlob, mp4Blob],
|
|
712
|
-
* {
|
|
841
|
+
* { contactID: "contact_abc" },
|
|
713
842
|
* );
|
|
714
843
|
* const allValid = results.every(r => r.valid);
|
|
715
844
|
*/
|
|
@@ -718,7 +847,7 @@ export declare class MajikMessage {
|
|
|
718
847
|
mimeType?: string;
|
|
719
848
|
expectedSignerId?: string;
|
|
720
849
|
}>, options?: {
|
|
721
|
-
|
|
850
|
+
contactID?: string;
|
|
722
851
|
publicKeyBase64?: string;
|
|
723
852
|
key?: MajikKey;
|
|
724
853
|
expectedSignerId?: string;
|
|
@@ -758,7 +887,7 @@ export declare class MajikMessage {
|
|
|
758
887
|
*
|
|
759
888
|
* @example
|
|
760
889
|
* if (await majik.isFileSigned(file)) {
|
|
761
|
-
* const result = await majik.verifyFile(file, {
|
|
890
|
+
* const result = await majik.verifyFile(file, { contactID });
|
|
762
891
|
* }
|
|
763
892
|
*/
|
|
764
893
|
isFileSigned(file: Blob, options?: {
|
|
@@ -995,11 +1124,6 @@ export declare class MajikMessage {
|
|
|
995
1124
|
* throughout MajikMessage — consistent account/contact resolution in one place.
|
|
996
1125
|
*/
|
|
997
1126
|
private _resolveSignerPublicKeys;
|
|
998
|
-
setPIN(pin: string): Promise<void>;
|
|
999
|
-
clearPIN(): Promise<void>;
|
|
1000
|
-
isValidPIN(pin: string): Promise<boolean>;
|
|
1001
|
-
getPinHash(): string | null;
|
|
1002
|
-
private static _hashPIN;
|
|
1003
1127
|
toJSON(): Promise<MajikMessageJSON>;
|
|
1004
1128
|
static fromJSON<T extends MajikMessage>(this: new (config: MajikMessageConfig, id?: string) => T, json: MajikMessageJSON): Promise<T>;
|
|
1005
1129
|
private attachAutosaveHandlers;
|