@majikah/majik-message 0.2.13 → 0.2.14

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.
@@ -8,7 +8,7 @@ import { MajikMessageChat } from "./core/database/chat/majik-message-chat";
8
8
  import { MajikMessageIdentity } from "./core/database/system/identity";
9
9
  import { MajikKey } from "@majikah/majik-key";
10
10
  import { MajikFile, MajikFileJSON } from "@majikah/majik-file";
11
- import { MajikSignature, type MajikSignatureJSON, type MajikSignerPublicKeys, type VerificationResult } from "@majikah/majik-signature";
11
+ import { EnvelopeInfo, MajikSignature, SealInfo, SealVerificationResult, type MajikSignatureJSON, type MajikSignerPublicKeys, type VerificationResult } from "@majikah/majik-signature";
12
12
  type MajikMessageEvents = "message" | "envelope" | "untrusted" | "error" | "new-account" | "new-contact" | "removed-account" | "removed-contact" | "active-account-change";
13
13
  interface MajikMessageStatic<T extends MajikMessage> {
14
14
  new (config: MajikMessageConfig, id?: string): T;
@@ -818,6 +818,72 @@ export declare class MajikMessage {
818
818
  getFileSignatureInfo(file: Blob, options?: {
819
819
  mimeType?: string;
820
820
  }): Promise<MajikSignature[]>;
821
+ /**
822
+ * Return a complete summary of the envelope state in one file read.
823
+ * Covers: isMultiSig, isSealed, issuer, all signatories, allowlist, seal info.
824
+ * Useful for rendering a signing status UI without multiple separate calls.
825
+ *
826
+ * Returns null if the file has no envelope.
827
+ *
828
+ * @example
829
+ * const info = await majik.getEnvelopeInfo(file);
830
+ * if (info?.isSealed) console.log("Sealed by", info.sealInfo?.sealedBy);
831
+ * console.log(`${info?.signatories?.signed.length} of ${info?.signatories?.all.length} signed`);
832
+ */
833
+ getEnvelopeInfo(file: Blob, options?: {
834
+ mimeType?: string;
835
+ }): Promise<EnvelopeInfo | null>;
836
+ /**
837
+ * Seal a restricted multi-sig file, preventing any further signatures.
838
+ *
839
+ * Only the issuer (the signer who established the allowlist) may seal.
840
+ * Resolves the signing key from the keystore — the account must be loaded
841
+ * but does NOT need to be unlocked (sealing does not use private keys).
842
+ *
843
+ * @example
844
+ * const { blob, sealInfo } = await majik.seal(signedFile);
845
+ * console.log("Sealed at", sealInfo.sealTimestamp);
846
+ */
847
+ seal(file: Blob, options?: {
848
+ mimeType?: string;
849
+ timestamp?: string;
850
+ accountId?: string;
851
+ }): Promise<{
852
+ blob: Blob;
853
+ sealInfo: SealInfo;
854
+ handler: string;
855
+ mimeType: string;
856
+ }>;
857
+ /**
858
+ * Verify the seal hash against the current signatories and seal timestamp.
859
+ * Returns invalid if the envelope is not sealed.
860
+ * Does NOT verify individual cryptographic signatures — call verifyFile() for that.
861
+ *
862
+ * @example
863
+ * const result = await majik.verifySeal(file);
864
+ * if (result.valid) console.log("Sealed by", result.sealedBy, "at", result.sealTimestamp);
865
+ */
866
+ verifySeal(file: Blob, options?: {
867
+ mimeType?: string;
868
+ }): Promise<SealVerificationResult>;
869
+ /**
870
+ * Get seal metadata without verifying.
871
+ * Returns null if the file is not sealed or has no envelope.
872
+ *
873
+ * @example
874
+ * const info = await majik.getSealInfo(file);
875
+ * if (info) console.log("Sealed by", majik.resolveSignerLabel(info.sealedBy));
876
+ */
877
+ getSealInfo(file: Blob, options?: {
878
+ mimeType?: string;
879
+ }): Promise<SealInfo | null>;
880
+ /**
881
+ * Returns true if the file has a sealed envelope (structural check, no crypto).
882
+ * Use verifySeal() to confirm the seal hash is intact.
883
+ */
884
+ isSealed(file: Blob, options?: {
885
+ mimeType?: string;
886
+ }): Promise<boolean>;
821
887
  /**
822
888
  * Resolve MajikSignerPublicKeys from whichever signer hint was provided.
823
889
  * Returns null if no hint was given (caller should fall back to self-reported keys).
@@ -1785,6 +1785,105 @@ export class MajikMessage {
1785
1785
  throw err;
1786
1786
  }
1787
1787
  }
1788
+ /**
1789
+ * Return a complete summary of the envelope state in one file read.
1790
+ * Covers: isMultiSig, isSealed, issuer, all signatories, allowlist, seal info.
1791
+ * Useful for rendering a signing status UI without multiple separate calls.
1792
+ *
1793
+ * Returns null if the file has no envelope.
1794
+ *
1795
+ * @example
1796
+ * const info = await majik.getEnvelopeInfo(file);
1797
+ * if (info?.isSealed) console.log("Sealed by", info.sealInfo?.sealedBy);
1798
+ * console.log(`${info?.signatories?.signed.length} of ${info?.signatories?.all.length} signed`);
1799
+ */
1800
+ async getEnvelopeInfo(file, options) {
1801
+ try {
1802
+ return MajikSignature.getEnvelopeInfo(file, options);
1803
+ }
1804
+ catch (err) {
1805
+ this.emit("error", err, { context: "getEnvelopeInfo" });
1806
+ throw err;
1807
+ }
1808
+ }
1809
+ // ── Seal ──────────────────────────────────────────────────────────────────
1810
+ /**
1811
+ * Seal a restricted multi-sig file, preventing any further signatures.
1812
+ *
1813
+ * Only the issuer (the signer who established the allowlist) may seal.
1814
+ * Resolves the signing key from the keystore — the account must be loaded
1815
+ * but does NOT need to be unlocked (sealing does not use private keys).
1816
+ *
1817
+ * @example
1818
+ * const { blob, sealInfo } = await majik.seal(signedFile);
1819
+ * console.log("Sealed at", sealInfo.sealTimestamp);
1820
+ */
1821
+ async seal(file, options) {
1822
+ const id = options?.accountId ?? this.getActiveAccount()?.id;
1823
+ if (!id)
1824
+ throw new Error("No active account — call setActiveAccount() first");
1825
+ try {
1826
+ const key = MajikKeyStore.get(id);
1827
+ if (!key)
1828
+ throw new Error(`Account not found in keystore: "${id}"`);
1829
+ return MajikSignature.seal(file, key, {
1830
+ mimeType: options?.mimeType,
1831
+ timestamp: options?.timestamp,
1832
+ });
1833
+ }
1834
+ catch (err) {
1835
+ this.emit("error", err, { context: "seal" });
1836
+ throw err;
1837
+ }
1838
+ }
1839
+ /**
1840
+ * Verify the seal hash against the current signatories and seal timestamp.
1841
+ * Returns invalid if the envelope is not sealed.
1842
+ * Does NOT verify individual cryptographic signatures — call verifyFile() for that.
1843
+ *
1844
+ * @example
1845
+ * const result = await majik.verifySeal(file);
1846
+ * if (result.valid) console.log("Sealed by", result.sealedBy, "at", result.sealTimestamp);
1847
+ */
1848
+ async verifySeal(file, options) {
1849
+ try {
1850
+ return MajikSignature.verifySeal(file, options);
1851
+ }
1852
+ catch (err) {
1853
+ this.emit("error", err, { context: "verifySeal" });
1854
+ throw err;
1855
+ }
1856
+ }
1857
+ /**
1858
+ * Get seal metadata without verifying.
1859
+ * Returns null if the file is not sealed or has no envelope.
1860
+ *
1861
+ * @example
1862
+ * const info = await majik.getSealInfo(file);
1863
+ * if (info) console.log("Sealed by", majik.resolveSignerLabel(info.sealedBy));
1864
+ */
1865
+ async getSealInfo(file, options) {
1866
+ try {
1867
+ return MajikSignature.getSealInfo(file, options);
1868
+ }
1869
+ catch (err) {
1870
+ this.emit("error", err, { context: "getSealInfo" });
1871
+ throw err;
1872
+ }
1873
+ }
1874
+ /**
1875
+ * Returns true if the file has a sealed envelope (structural check, no crypto).
1876
+ * Use verifySeal() to confirm the seal hash is intact.
1877
+ */
1878
+ async isSealed(file, options) {
1879
+ try {
1880
+ return MajikSignature.isSealed(file, options);
1881
+ }
1882
+ catch (err) {
1883
+ this.emit("error", err, { context: "isSealed" });
1884
+ throw err;
1885
+ }
1886
+ }
1788
1887
  // ── Private: Signer resolution ────────────────────────────────────────────
1789
1888
  /**
1790
1889
  * Resolve MajikSignerPublicKeys from whichever signer hint was provided.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@majikah/majik-message",
3
3
  "type": "module",
4
4
  "description": "Post-quantum end-to-end encryption with ML-KEM-768. Seed phrase–based accounts. Auto-expiring messages. Offline-ready. Exportable encrypted messages. Tamper-proof threads with blockchain-like integrity. Quantum-resistant messaging.",
5
- "version": "0.2.13",
5
+ "version": "0.2.14",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",