@majikah/majik-file 0.0.8 → 0.0.9

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.
@@ -53,6 +53,8 @@ export interface MjkbSinglePayload {
53
53
  n: string | null;
54
54
  /** Original MIME type (e.g. "image/png"). Short key keeps the binary compact. */
55
55
  m: string | null;
56
+ /** Usage context — determines downstream UX and access control. */
57
+ c: FileContext | null;
56
58
  }
57
59
  /**
58
60
  * JSON payload embedded in a group .mjkb binary.
@@ -66,6 +68,8 @@ export interface MjkbGroupPayload {
66
68
  n: string | null;
67
69
  /** Original MIME type (e.g. "image/png"). Short key keeps the binary compact. */
68
70
  m: string | null;
71
+ /** Usage context — determines downstream UX and access control. */
72
+ c: FileContext | null;
69
73
  }
70
74
  export type MjkbPayload = MjkbSinglePayload | MjkbGroupPayload;
71
75
  export declare function isMjkbGroupPayload(p: MjkbPayload): p is MjkbGroupPayload;
@@ -214,7 +214,7 @@ export class MajikFile {
214
214
  * @throws MajikFileError on validation or crypto failure
215
215
  */
216
216
  static async create(options) {
217
- const { data, identity, context, recipients = [], originalName = null, mimeType: rawMimeType = null, isTemporary = false, isShared = false, id = generateUUID(), bypassSizeLimit = false, expiresAt = null, chatMessageId = null, threadMessageId = null, conversationId = null, userId } = options;
217
+ const { data, identity, context, recipients = [], originalName = null, mimeType: rawMimeType = null, isTemporary = false, isShared = false, id = generateUUID(), bypassSizeLimit = false, expiresAt = null, chatMessageId = null, threadMessageId = null, conversationId = null, userId, } = options;
218
218
  // ── Input validation ─────────────────────────────────────────────────
219
219
  if (!data)
220
220
  throw MajikFileError.invalidInput("data is required");
@@ -292,7 +292,9 @@ export class MajikFile {
292
292
  // WebP and therefore skipped here — WebP is already codec-compressed.
293
293
  // For user_upload and thread_attachment, compressible images (PNG, BMP,
294
294
  // TIFF, SVG, etc.) are Zstd-compressed at level 22.
295
- const compressible = shouldCompress(resolvedMimeType);
295
+ const compressible = context === "user_upload" || context === "thread_attachment"
296
+ ? true
297
+ : shouldCompress(resolvedMimeType);
296
298
  const compressed = compressible
297
299
  ? await MajikCompressor.compress(processedBytes)
298
300
  : processedBytes;
@@ -317,6 +319,7 @@ export class MajikFile {
317
319
  mlKemCipherText: arrayToBase64(mlKemCT),
318
320
  n: originalName ?? null,
319
321
  m: resolvedMimeType ?? null,
322
+ c: context ?? null,
320
323
  };
321
324
  }
322
325
  else {
@@ -349,6 +352,7 @@ export class MajikFile {
349
352
  keys,
350
353
  n: originalName ?? null,
351
354
  m: resolvedMimeType ?? null,
355
+ c: context ?? null,
352
356
  };
353
357
  }
354
358
  // ── 6. Encode .mjkb ───────────────────────────────────────────────
@@ -451,11 +455,17 @@ export class MajikFile {
451
455
  else {
452
456
  throw MajikFileError.formatError(".mjkb payload JSON is neither a single nor group payload");
453
457
  }
454
- const compressed = aesGcmDecrypt(aesKey, iv, ciphertext);
455
- if (!compressed) {
458
+ const decrypted = aesGcmDecrypt(aesKey, iv, ciphertext);
459
+ if (!decrypted) {
456
460
  throw MajikFileError.decryptionFailed("Decryption failed — wrong key or corrupted .mjkb file");
457
461
  }
458
- return await MajikCompressor.decompress(compressed);
462
+ const compressible = payload.c === "user_upload" || payload.c === "thread_attachment"
463
+ ? true
464
+ : shouldCompress(payload.m);
465
+ const returnData = compressible
466
+ ? await MajikCompressor.decompress(decrypted)
467
+ : decrypted;
468
+ return returnData;
459
469
  }
460
470
  catch (err) {
461
471
  if (err instanceof MajikFileError)
@@ -509,11 +519,16 @@ export class MajikFile {
509
519
  else {
510
520
  throw MajikFileError.formatError(".mjkb payload JSON is neither a single nor group payload");
511
521
  }
512
- const compressed = aesGcmDecrypt(aesKey, iv, ciphertext);
513
- if (!compressed) {
522
+ const decrypted = aesGcmDecrypt(aesKey, iv, ciphertext);
523
+ if (!decrypted) {
514
524
  throw MajikFileError.decryptionFailed("Decryption failed — wrong key or corrupted .mjkb file");
515
525
  }
516
- const bytes = await MajikCompressor.decompress(compressed);
526
+ const compressible = payload.c === "user_upload" || payload.c === "thread_attachment"
527
+ ? true
528
+ : shouldCompress(payload.m);
529
+ const bytes = compressible
530
+ ? await MajikCompressor.decompress(decrypted)
531
+ : decrypted;
517
532
  // Extract original filename and MIME type from the payload.
518
533
  // Written at encryption time as short keys n/m to keep the binary compact.
519
534
  // Older .mjkb files without these fields return null — callers should fall
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@majikah/majik-file",
3
3
  "type": "module",
4
4
  "description": "Majik File is the core cryptographic engine for secure file handling in the Majikah ecosystem. It provides a post-quantum secure \"MJKB\" format designed for file encryption, multi-recipient key encapsulation, and transparent compression using NIST-standardized algorithms.",
5
- "version": "0.0.8",
5
+ "version": "0.0.9",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",