@majikah/majik-message 0.2.20 → 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 +162 -37
- package/dist/majik-message.js +292 -127
- 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;
|
|
@@ -104,9 +108,10 @@ export declare class MajikMessage {
|
|
|
104
108
|
updatePassphrase(currentPassphrase: string, newPassphrase: string, id?: string): Promise<void>;
|
|
105
109
|
getContactByID(id: string): MajikContact | null;
|
|
106
110
|
hasContact(id: string): boolean;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
hasContactByPublicKeyBase64(publicKey: MajikMessagePublicKey): Promise<boolean>;
|
|
112
|
+
getContactByPublicKey(publicKeyBase64: MajikMessagePublicKey): Promise<MajikContact | null>;
|
|
113
|
+
exportContactAsJSON(contactID: string): Promise<string | null>;
|
|
114
|
+
exportContactAsString(contactID: string): Promise<string | null>;
|
|
110
115
|
importContactFromJSON(jsonStr: string): Promise<MAJIK_API_RESPONSE>;
|
|
111
116
|
importContactFromString(base64Str: string): Promise<MAJIK_API_RESPONSE>;
|
|
112
117
|
exportContactCompressed(contact: MajikContact): Promise<string>;
|
|
@@ -120,6 +125,134 @@ export declare class MajikMessage {
|
|
|
120
125
|
isContactMajikahRegistered(id: string): boolean;
|
|
121
126
|
isContactMajikahIdentityChecked(id: string): boolean;
|
|
122
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;
|
|
123
256
|
/**
|
|
124
257
|
* Compose and encrypt a message for one or more recipients.
|
|
125
258
|
* Single recipient → solo envelope. Two or more → group envelope.
|
|
@@ -208,7 +341,7 @@ export declare class MajikMessage {
|
|
|
208
341
|
* metadata: row,
|
|
209
342
|
* });
|
|
210
343
|
* if (signature) {
|
|
211
|
-
* const result = await majik.verifyMajikFile(file, {
|
|
344
|
+
* const result = await majik.verifyMajikFile(file, { contactID: row.user_id });
|
|
212
345
|
* }
|
|
213
346
|
* ```
|
|
214
347
|
*/
|
|
@@ -248,7 +381,7 @@ export declare class MajikMessage {
|
|
|
248
381
|
* if the instance was restored from a metadata-only Supabase row.
|
|
249
382
|
*
|
|
250
383
|
* Signer resolution:
|
|
251
|
-
* -
|
|
384
|
+
* - contactID: looked up in the contact directory (own accounts included)
|
|
252
385
|
* - publicKeyBase64: looked up via contact directory
|
|
253
386
|
* - key: used directly (skips directory lookup)
|
|
254
387
|
* - none provided: falls back to public keys embedded in the signature
|
|
@@ -259,12 +392,12 @@ export declare class MajikMessage {
|
|
|
259
392
|
* @example — verify against the file's owner contact
|
|
260
393
|
* file.attachBinary(await r2.get(row.r2_key).arrayBuffer());
|
|
261
394
|
* const result = await majik.verifyMajikFile(file, {
|
|
262
|
-
*
|
|
395
|
+
* contactID: ownerContactId,
|
|
263
396
|
* });
|
|
264
397
|
* if (result?.valid) console.log("Verified, signed by", result.signerId);
|
|
265
398
|
*/
|
|
266
399
|
verifyMajikFile(file: MajikFile, options?: {
|
|
267
|
-
|
|
400
|
+
contactID?: string;
|
|
268
401
|
publicKeyBase64?: string;
|
|
269
402
|
key?: MajikKey;
|
|
270
403
|
}): Promise<VerificationResult | null>;
|
|
@@ -284,12 +417,12 @@ export declare class MajikMessage {
|
|
|
284
417
|
*
|
|
285
418
|
* @example
|
|
286
419
|
* const result = await majik.verifyMajikFileBinary(file, {
|
|
287
|
-
*
|
|
420
|
+
* contactID: "contact_abc",
|
|
288
421
|
* });
|
|
289
422
|
* if (result.valid) console.log("Plaintext verified");
|
|
290
423
|
*/
|
|
291
424
|
verifyMajikFileBinary(file: MajikFile, options?: {
|
|
292
|
-
|
|
425
|
+
contactID?: string;
|
|
293
426
|
publicKeyBase64?: string;
|
|
294
427
|
key?: MajikKey;
|
|
295
428
|
decryptAccountId?: string;
|
|
@@ -454,12 +587,12 @@ export declare class MajikMessage {
|
|
|
454
587
|
*
|
|
455
588
|
* @example
|
|
456
589
|
* const result = await majik.verifyText("Hello world", sig, {
|
|
457
|
-
*
|
|
590
|
+
* contactID: "contact_abc",
|
|
458
591
|
* });
|
|
459
592
|
* if (result.valid) console.log("Authentic");
|
|
460
593
|
*/
|
|
461
594
|
verifyText(text: string, signature: MajikSignature | MajikSignatureJSON | string, options?: {
|
|
462
|
-
|
|
595
|
+
contactID?: string;
|
|
463
596
|
publicKeyBase64?: string;
|
|
464
597
|
key?: MajikKey;
|
|
465
598
|
expectedSignerId?: string;
|
|
@@ -478,12 +611,12 @@ export declare class MajikMessage {
|
|
|
478
611
|
* @example
|
|
479
612
|
* const row = await db.findOne({ doc_id });
|
|
480
613
|
* const result = await majik.verifyDetached(docBytes, row.signature, {
|
|
481
|
-
*
|
|
614
|
+
* contactID: row.signer_contact_id,
|
|
482
615
|
* });
|
|
483
616
|
* if (result.valid) console.log("Signed by", result.signerId);
|
|
484
617
|
*/
|
|
485
618
|
verifyDetached(content: Uint8Array | string, serializedSignature: string, options?: {
|
|
486
|
-
|
|
619
|
+
contactID?: string;
|
|
487
620
|
publicKeyBase64?: string;
|
|
488
621
|
key?: MajikKey;
|
|
489
622
|
expectedSignerId?: string;
|
|
@@ -554,9 +687,6 @@ export declare class MajikMessage {
|
|
|
554
687
|
raw: Uint8Array;
|
|
555
688
|
}>;
|
|
556
689
|
isPassphraseValid(passphrase: string, id?: string): Promise<boolean>;
|
|
557
|
-
scanDOM(rootNode: Node): void;
|
|
558
|
-
startDOMObserver(rootNode: Node): void;
|
|
559
|
-
stopDOMObserver(): void;
|
|
560
690
|
on(event: MajikMessageEvents, callback: EventCallback): void;
|
|
561
691
|
off(event: MajikMessageEvents, callback?: EventCallback): void;
|
|
562
692
|
private emit;
|
|
@@ -655,7 +785,7 @@ export declare class MajikMessage {
|
|
|
655
785
|
* > against a known contact fingerprint before trusting the result.
|
|
656
786
|
*
|
|
657
787
|
* @example — verify against a known contact
|
|
658
|
-
* const result = await majik.verifyContent(docBytes, sig, {
|
|
788
|
+
* const result = await majik.verifyContent(docBytes, sig, { contactID: "contact_abc" });
|
|
659
789
|
* if (result.valid) console.log("Authentic, signed by:", result.signerId);
|
|
660
790
|
*
|
|
661
791
|
* @example — verify using embedded keys (self-reported)
|
|
@@ -663,7 +793,7 @@ export declare class MajikMessage {
|
|
|
663
793
|
* // always check result.signerId matches a known fingerprint
|
|
664
794
|
*/
|
|
665
795
|
verifyContent(content: Uint8Array | string, signature: MajikSignature | MajikSignatureJSON, options?: {
|
|
666
|
-
|
|
796
|
+
contactID?: string;
|
|
667
797
|
publicKeyBase64?: string;
|
|
668
798
|
key?: MajikKey;
|
|
669
799
|
expectedSignerId?: string;
|
|
@@ -680,16 +810,16 @@ export declare class MajikMessage {
|
|
|
680
810
|
* envelope are used (self-reported — see security note on verifyContent).
|
|
681
811
|
*
|
|
682
812
|
* @example — verify a signed PDF against a known contact
|
|
683
|
-
* const result = await majik.verifyFile(signedPdf, {
|
|
813
|
+
* const result = await majik.verifyFile(signedPdf, { contactID: "contact_abc" });
|
|
684
814
|
* if (result.valid) console.log("Verified:", result.signerId, result.timestamp);
|
|
685
815
|
*
|
|
686
816
|
* @example — check own signed file using active account
|
|
687
817
|
* const result = await majik.verifyFile(signedWav, {
|
|
688
|
-
*
|
|
818
|
+
* contactID: majik.getActiveAccount()?.id,
|
|
689
819
|
* });
|
|
690
820
|
*/
|
|
691
821
|
verifyFile(file: Blob, options?: {
|
|
692
|
-
|
|
822
|
+
contactID?: string;
|
|
693
823
|
publicKeyBase64?: string;
|
|
694
824
|
key?: MajikKey;
|
|
695
825
|
expectedSignerId?: string;
|
|
@@ -708,7 +838,7 @@ export declare class MajikMessage {
|
|
|
708
838
|
* @example
|
|
709
839
|
* const results = await majik.batchVerifyFiles(
|
|
710
840
|
* [pdfBlob, wavBlob, mp4Blob],
|
|
711
|
-
* {
|
|
841
|
+
* { contactID: "contact_abc" },
|
|
712
842
|
* );
|
|
713
843
|
* const allValid = results.every(r => r.valid);
|
|
714
844
|
*/
|
|
@@ -717,7 +847,7 @@ export declare class MajikMessage {
|
|
|
717
847
|
mimeType?: string;
|
|
718
848
|
expectedSignerId?: string;
|
|
719
849
|
}>, options?: {
|
|
720
|
-
|
|
850
|
+
contactID?: string;
|
|
721
851
|
publicKeyBase64?: string;
|
|
722
852
|
key?: MajikKey;
|
|
723
853
|
expectedSignerId?: string;
|
|
@@ -757,7 +887,7 @@ export declare class MajikMessage {
|
|
|
757
887
|
*
|
|
758
888
|
* @example
|
|
759
889
|
* if (await majik.isFileSigned(file)) {
|
|
760
|
-
* const result = await majik.verifyFile(file, {
|
|
890
|
+
* const result = await majik.verifyFile(file, { contactID });
|
|
761
891
|
* }
|
|
762
892
|
*/
|
|
763
893
|
isFileSigned(file: Blob, options?: {
|
|
@@ -994,11 +1124,6 @@ export declare class MajikMessage {
|
|
|
994
1124
|
* throughout MajikMessage — consistent account/contact resolution in one place.
|
|
995
1125
|
*/
|
|
996
1126
|
private _resolveSignerPublicKeys;
|
|
997
|
-
setPIN(pin: string): Promise<void>;
|
|
998
|
-
clearPIN(): Promise<void>;
|
|
999
|
-
isValidPIN(pin: string): Promise<boolean>;
|
|
1000
|
-
getPinHash(): string | null;
|
|
1001
|
-
private static _hashPIN;
|
|
1002
1127
|
toJSON(): Promise<MajikMessageJSON>;
|
|
1003
1128
|
static fromJSON<T extends MajikMessage>(this: new (config: MajikMessageConfig, id?: string) => T, json: MajikMessageJSON): Promise<T>;
|
|
1004
1129
|
private attachAutosaveHandlers;
|