@shipstatic/types 0.4.18 → 0.4.20

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/index.d.ts CHANGED
@@ -339,6 +339,9 @@ export declare class ShipError extends Error {
339
339
  export declare function isShipError(error: unknown): error is ShipError;
340
340
  /**
341
341
  * Platform configuration response from API
342
+ *
343
+ * Contains ONLY dynamic, runtime-specific values (plan-based limits).
344
+ * Static constants (MIME types, validation rules) live as exported constants.
342
345
  */
343
346
  export interface ConfigResponse {
344
347
  /** Maximum individual file size in bytes */
@@ -347,9 +350,87 @@ export interface ConfigResponse {
347
350
  maxFilesCount: number;
348
351
  /** Maximum total deployment size in bytes */
349
352
  maxTotalSize: number;
350
- /** Allowed MIME type categories for file validation */
351
- allowedMimeTypes: string[];
352
353
  }
354
+ /**
355
+ * Allowed MIME types for static web hosting.
356
+ *
357
+ * This is a static platform constant, not per-user configuration.
358
+ * Safe to share across frontend/backend due to atomic deploys.
359
+ *
360
+ * Validation rules:
361
+ * - Exact match: 'application/json' allows only 'application/json'
362
+ * - Prefix match: 'image/' allows all image types (png, jpeg, webp, etc.)
363
+ *
364
+ * Coverage: 100% of browser-renderable web content
365
+ * - Core web (HTML, CSS, JS, WASM)
366
+ * - Media (images, audio, video, fonts)
367
+ * - Documents (PDF, Markdown, data formats)
368
+ * - Modern web (PWA, 3D, structured data)
369
+ *
370
+ * ============================================================================
371
+ * INTENTIONALLY EXCLUDED (Security & Platform Integrity)
372
+ * ============================================================================
373
+ *
374
+ * We are a WEB HOSTING platform, not a file distribution service.
375
+ * GitHub Pages-style parity for renderable content, more restrictive for downloads.
376
+ *
377
+ * 1. EXECUTABLES (Malware Distribution)
378
+ * → .exe, .msi, .dmg, .deb, .rpm, .app, .apk, .jar
379
+ * → Reason: Direct malware delivery vector
380
+ * → Alternative: Use GitHub Releases or dedicated software distribution CDN
381
+ *
382
+ * 2. ARCHIVES (Piracy & Abuse)
383
+ * → .zip, .rar, .tar, .gz, .7z, .bz2
384
+ * → Reason: File sharing abuse, can contain executables, no web rendering
385
+ * → Alternative: Use file hosting service (Dropbox, Google Drive) or GitHub Releases
386
+ *
387
+ * 3. SERVER-SIDE SCRIPTS (Credential Leakage)
388
+ * → .php, .asp, .jsp, .cgi
389
+ * → Reason: Source code exposure (database passwords, API keys, secrets)
390
+ * → Alternative: Static hosting only - use serverless functions for backends
391
+ *
392
+ * 4. SHELL SCRIPTS (OS Execution)
393
+ * → .sh, .bash, .bat, .cmd, .ps1, .vbs
394
+ * → Reason: Execute on user's OS outside browser sandbox, social engineering risk
395
+ * → Alternative: Embed code examples in HTML <pre><code> or link to GitHub repo
396
+ *
397
+ * 5. PROGRAMMING LANGUAGE SOURCE (Platform Scope)
398
+ * → .py, .rb, .pl, .java, .c, .cpp, .cs, .go, .rs
399
+ * → Reason: Not web-renderable, better served by GitHub/GitLab/Bitbucket
400
+ * → Alternative: Use GitHub for code hosting, link to repository
401
+ *
402
+ * 6. OFFICE DOCUMENTS (Macro Malware)
403
+ * → .doc, .docx, .xls, .xlsx, .ppt, .pptx
404
+ * → Reason: Can contain VBA macros, active exploits in the wild
405
+ * → Alternative: Use PDF for documents (fully supported)
406
+ *
407
+ * 7. GENERIC BINARIES (Unvalidatable)
408
+ * → application/octet-stream
409
+ * → Reason: Too broad - allows any binary format, cannot moderate effectively
410
+ * → Alternative: Use specific MIME types for known formats
411
+ *
412
+ * ============================================================================
413
+ * Security Model:
414
+ * - Browser sandbox (JS/WASM execute safely in controlled environment)
415
+ * - AI content moderation (scans text/image content for abuse)
416
+ * - No server-side execution (static files only)
417
+ * - Explicit allowlist (only approved formats, reject unknown)
418
+ * ============================================================================
419
+ */
420
+ export declare const ALLOWED_MIME_TYPES: readonly ["text/html", "text/css", "text/plain", "text/markdown", "text/xml", "text/csv", "text/yaml", "text/vtt", "text/calendar", "text/javascript", "image/", "audio/", "video/", "font/", "application/javascript", "application/ecmascript", "application/x-javascript", "application/wasm", "application/json", "application/ld+json", "application/manifest+json", "application/xml", "application/xhtml+xml", "application/rss+xml", "application/atom+xml", "application/yaml", "application/pdf", "model/gltf+json", "model/gltf-binary", "application/mp4", "application/font-woff", "application/font-woff2", "application/x-font-woff", "application/x-woff", "application/vnd.ms-fontobject", "application/x-font-ttf", "application/x-font-truetype", "application/x-font-otf", "application/x-font-opentype"];
421
+ /**
422
+ * Check if a MIME type is allowed for upload.
423
+ *
424
+ * Supports both exact matches and prefix matches:
425
+ * - 'application/json' matches 'application/json' exactly
426
+ * - 'text/' matches 'text/plain', 'text/html', etc.
427
+ *
428
+ * @example
429
+ * isAllowedMimeType('text/plain') // true (prefix match)
430
+ * isAllowedMimeType('application/json') // true (exact match)
431
+ * isAllowedMimeType('application/wasm') // false (not allowed)
432
+ */
433
+ export declare function isAllowedMimeType(mimeType: string): boolean;
353
434
  /**
354
435
  * Generic success response wrapper
355
436
  */
package/dist/index.js CHANGED
@@ -199,6 +199,160 @@ export function isShipError(error) {
199
199
  error.name === 'ShipError' &&
200
200
  'status' in error);
201
201
  }
202
+ /**
203
+ * Allowed MIME types for static web hosting.
204
+ *
205
+ * This is a static platform constant, not per-user configuration.
206
+ * Safe to share across frontend/backend due to atomic deploys.
207
+ *
208
+ * Validation rules:
209
+ * - Exact match: 'application/json' allows only 'application/json'
210
+ * - Prefix match: 'image/' allows all image types (png, jpeg, webp, etc.)
211
+ *
212
+ * Coverage: 100% of browser-renderable web content
213
+ * - Core web (HTML, CSS, JS, WASM)
214
+ * - Media (images, audio, video, fonts)
215
+ * - Documents (PDF, Markdown, data formats)
216
+ * - Modern web (PWA, 3D, structured data)
217
+ *
218
+ * ============================================================================
219
+ * INTENTIONALLY EXCLUDED (Security & Platform Integrity)
220
+ * ============================================================================
221
+ *
222
+ * We are a WEB HOSTING platform, not a file distribution service.
223
+ * GitHub Pages-style parity for renderable content, more restrictive for downloads.
224
+ *
225
+ * 1. EXECUTABLES (Malware Distribution)
226
+ * → .exe, .msi, .dmg, .deb, .rpm, .app, .apk, .jar
227
+ * → Reason: Direct malware delivery vector
228
+ * → Alternative: Use GitHub Releases or dedicated software distribution CDN
229
+ *
230
+ * 2. ARCHIVES (Piracy & Abuse)
231
+ * → .zip, .rar, .tar, .gz, .7z, .bz2
232
+ * → Reason: File sharing abuse, can contain executables, no web rendering
233
+ * → Alternative: Use file hosting service (Dropbox, Google Drive) or GitHub Releases
234
+ *
235
+ * 3. SERVER-SIDE SCRIPTS (Credential Leakage)
236
+ * → .php, .asp, .jsp, .cgi
237
+ * → Reason: Source code exposure (database passwords, API keys, secrets)
238
+ * → Alternative: Static hosting only - use serverless functions for backends
239
+ *
240
+ * 4. SHELL SCRIPTS (OS Execution)
241
+ * → .sh, .bash, .bat, .cmd, .ps1, .vbs
242
+ * → Reason: Execute on user's OS outside browser sandbox, social engineering risk
243
+ * → Alternative: Embed code examples in HTML <pre><code> or link to GitHub repo
244
+ *
245
+ * 5. PROGRAMMING LANGUAGE SOURCE (Platform Scope)
246
+ * → .py, .rb, .pl, .java, .c, .cpp, .cs, .go, .rs
247
+ * → Reason: Not web-renderable, better served by GitHub/GitLab/Bitbucket
248
+ * → Alternative: Use GitHub for code hosting, link to repository
249
+ *
250
+ * 6. OFFICE DOCUMENTS (Macro Malware)
251
+ * → .doc, .docx, .xls, .xlsx, .ppt, .pptx
252
+ * → Reason: Can contain VBA macros, active exploits in the wild
253
+ * → Alternative: Use PDF for documents (fully supported)
254
+ *
255
+ * 7. GENERIC BINARIES (Unvalidatable)
256
+ * → application/octet-stream
257
+ * → Reason: Too broad - allows any binary format, cannot moderate effectively
258
+ * → Alternative: Use specific MIME types for known formats
259
+ *
260
+ * ============================================================================
261
+ * Security Model:
262
+ * - Browser sandbox (JS/WASM execute safely in controlled environment)
263
+ * - AI content moderation (scans text/image content for abuse)
264
+ * - No server-side execution (static files only)
265
+ * - Explicit allowlist (only approved formats, reject unknown)
266
+ * ============================================================================
267
+ */
268
+ export const ALLOWED_MIME_TYPES = [
269
+ // =========================================================================
270
+ // TEXT CONTENT (explicit list - no prefix matching for security)
271
+ // =========================================================================
272
+ // Core web documents
273
+ 'text/html', // HTML pages
274
+ 'text/css', // Stylesheets
275
+ 'text/plain', // Plain text (robots.txt, .well-known/*, LICENSE, README.txt)
276
+ 'text/markdown', // Markdown files (.md)
277
+ 'text/xml', // XML files
278
+ // Data formats
279
+ 'text/csv', // CSV data files
280
+ 'text/yaml', // YAML config files
281
+ // Web-specific formats
282
+ 'text/vtt', // WebVTT video subtitles/captions (accessibility)
283
+ 'text/calendar', // iCalendar (.ics) event files
284
+ // JavaScript (legacy MIME type, still widely used by ~50% of servers)
285
+ 'text/javascript',
286
+ // =========================================================================
287
+ // MEDIA (prefix matching - covers all common subtypes)
288
+ // =========================================================================
289
+ // Images: PNG, JPEG, GIF, SVG, WebP, AVIF, HEIC, BMP, TIFF, ICO, etc.
290
+ 'image/',
291
+ // Audio: MP3, OGG, WAV, WebM, AAC, FLAC, Opus, etc.
292
+ 'audio/',
293
+ // Video: MP4, WebM, OGG, QuickTime, etc.
294
+ 'video/',
295
+ // Modern fonts: WOFF2, WOFF, TTF, OTF
296
+ 'font/',
297
+ // =========================================================================
298
+ // CORE WEB APPLICATION TYPES
299
+ // =========================================================================
300
+ // JavaScript (multiple MIME types for compatibility)
301
+ 'application/javascript', // Modern standard (RFC 9239)
302
+ 'application/ecmascript', // ECMAScript (legacy but still used)
303
+ 'application/x-javascript', // Legacy variant (old CDNs, Apache configs)
304
+ // WebAssembly (modern web apps, games, compute-heavy workloads)
305
+ 'application/wasm',
306
+ // JSON and structured data
307
+ 'application/json',
308
+ 'application/ld+json', // JSON-LD for structured data / SEO (Schema.org, Open Graph)
309
+ 'application/manifest+json', // PWA web app manifests
310
+ // XML and feeds
311
+ 'application/xml',
312
+ 'application/xhtml+xml', // XHTML - XML-compliant HTML (legacy sites)
313
+ 'application/rss+xml', // RSS feeds (blogs, podcasts)
314
+ 'application/atom+xml', // Atom feeds
315
+ // Configuration formats
316
+ 'application/yaml', // YAML configs (static site generators)
317
+ // Documents
318
+ 'application/pdf', // PDF documents
319
+ // =========================================================================
320
+ // 3D FORMATS (industry standard only)
321
+ // =========================================================================
322
+ // glTF - Khronos standard for 3D web content
323
+ 'model/gltf+json', // glTF JSON format
324
+ 'model/gltf-binary', // GLB binary format
325
+ // =========================================================================
326
+ // LEGACY COMPATIBILITY
327
+ // =========================================================================
328
+ // Video (some tools detect MP4 as application/mp4)
329
+ 'application/mp4',
330
+ // Legacy font MIME types (Bootstrap, Font Awesome, IE compatibility)
331
+ 'application/font-woff',
332
+ 'application/font-woff2',
333
+ 'application/x-font-woff',
334
+ 'application/x-woff',
335
+ 'application/vnd.ms-fontobject', // EOT files (Internet Explorer)
336
+ 'application/x-font-ttf',
337
+ 'application/x-font-truetype',
338
+ 'application/x-font-otf',
339
+ 'application/x-font-opentype',
340
+ ];
341
+ /**
342
+ * Check if a MIME type is allowed for upload.
343
+ *
344
+ * Supports both exact matches and prefix matches:
345
+ * - 'application/json' matches 'application/json' exactly
346
+ * - 'text/' matches 'text/plain', 'text/html', etc.
347
+ *
348
+ * @example
349
+ * isAllowedMimeType('text/plain') // true (prefix match)
350
+ * isAllowedMimeType('application/json') // true (exact match)
351
+ * isAllowedMimeType('application/wasm') // false (not allowed)
352
+ */
353
+ export function isAllowedMimeType(mimeType) {
354
+ return ALLOWED_MIME_TYPES.some(allowed => mimeType === allowed || mimeType.startsWith(allowed));
355
+ }
202
356
  // API Key Configuration
203
357
  export const API_KEY_PREFIX = 'ship-';
204
358
  export const API_KEY_HEX_LENGTH = 64;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipstatic/types",
3
- "version": "0.4.18",
3
+ "version": "0.4.20",
4
4
  "description": "Shared types for Shipstatic platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -492,6 +492,9 @@ export function isShipError(error: unknown): error is ShipError {
492
492
 
493
493
  /**
494
494
  * Platform configuration response from API
495
+ *
496
+ * Contains ONLY dynamic, runtime-specific values (plan-based limits).
497
+ * Static constants (MIME types, validation rules) live as exported constants.
495
498
  */
496
499
  export interface ConfigResponse {
497
500
  /** Maximum individual file size in bytes */
@@ -500,8 +503,185 @@ export interface ConfigResponse {
500
503
  maxFilesCount: number;
501
504
  /** Maximum total deployment size in bytes */
502
505
  maxTotalSize: number;
503
- /** Allowed MIME type categories for file validation */
504
- allowedMimeTypes: string[];
506
+ }
507
+
508
+ /**
509
+ * Allowed MIME types for static web hosting.
510
+ *
511
+ * This is a static platform constant, not per-user configuration.
512
+ * Safe to share across frontend/backend due to atomic deploys.
513
+ *
514
+ * Validation rules:
515
+ * - Exact match: 'application/json' allows only 'application/json'
516
+ * - Prefix match: 'image/' allows all image types (png, jpeg, webp, etc.)
517
+ *
518
+ * Coverage: 100% of browser-renderable web content
519
+ * - Core web (HTML, CSS, JS, WASM)
520
+ * - Media (images, audio, video, fonts)
521
+ * - Documents (PDF, Markdown, data formats)
522
+ * - Modern web (PWA, 3D, structured data)
523
+ *
524
+ * ============================================================================
525
+ * INTENTIONALLY EXCLUDED (Security & Platform Integrity)
526
+ * ============================================================================
527
+ *
528
+ * We are a WEB HOSTING platform, not a file distribution service.
529
+ * GitHub Pages-style parity for renderable content, more restrictive for downloads.
530
+ *
531
+ * 1. EXECUTABLES (Malware Distribution)
532
+ * → .exe, .msi, .dmg, .deb, .rpm, .app, .apk, .jar
533
+ * → Reason: Direct malware delivery vector
534
+ * → Alternative: Use GitHub Releases or dedicated software distribution CDN
535
+ *
536
+ * 2. ARCHIVES (Piracy & Abuse)
537
+ * → .zip, .rar, .tar, .gz, .7z, .bz2
538
+ * → Reason: File sharing abuse, can contain executables, no web rendering
539
+ * → Alternative: Use file hosting service (Dropbox, Google Drive) or GitHub Releases
540
+ *
541
+ * 3. SERVER-SIDE SCRIPTS (Credential Leakage)
542
+ * → .php, .asp, .jsp, .cgi
543
+ * → Reason: Source code exposure (database passwords, API keys, secrets)
544
+ * → Alternative: Static hosting only - use serverless functions for backends
545
+ *
546
+ * 4. SHELL SCRIPTS (OS Execution)
547
+ * → .sh, .bash, .bat, .cmd, .ps1, .vbs
548
+ * → Reason: Execute on user's OS outside browser sandbox, social engineering risk
549
+ * → Alternative: Embed code examples in HTML <pre><code> or link to GitHub repo
550
+ *
551
+ * 5. PROGRAMMING LANGUAGE SOURCE (Platform Scope)
552
+ * → .py, .rb, .pl, .java, .c, .cpp, .cs, .go, .rs
553
+ * → Reason: Not web-renderable, better served by GitHub/GitLab/Bitbucket
554
+ * → Alternative: Use GitHub for code hosting, link to repository
555
+ *
556
+ * 6. OFFICE DOCUMENTS (Macro Malware)
557
+ * → .doc, .docx, .xls, .xlsx, .ppt, .pptx
558
+ * → Reason: Can contain VBA macros, active exploits in the wild
559
+ * → Alternative: Use PDF for documents (fully supported)
560
+ *
561
+ * 7. GENERIC BINARIES (Unvalidatable)
562
+ * → application/octet-stream
563
+ * → Reason: Too broad - allows any binary format, cannot moderate effectively
564
+ * → Alternative: Use specific MIME types for known formats
565
+ *
566
+ * ============================================================================
567
+ * Security Model:
568
+ * - Browser sandbox (JS/WASM execute safely in controlled environment)
569
+ * - AI content moderation (scans text/image content for abuse)
570
+ * - No server-side execution (static files only)
571
+ * - Explicit allowlist (only approved formats, reject unknown)
572
+ * ============================================================================
573
+ */
574
+ export const ALLOWED_MIME_TYPES = [
575
+ // =========================================================================
576
+ // TEXT CONTENT (explicit list - no prefix matching for security)
577
+ // =========================================================================
578
+
579
+ // Core web documents
580
+ 'text/html', // HTML pages
581
+ 'text/css', // Stylesheets
582
+ 'text/plain', // Plain text (robots.txt, .well-known/*, LICENSE, README.txt)
583
+ 'text/markdown', // Markdown files (.md)
584
+ 'text/xml', // XML files
585
+
586
+ // Data formats
587
+ 'text/csv', // CSV data files
588
+ 'text/yaml', // YAML config files
589
+
590
+ // Web-specific formats
591
+ 'text/vtt', // WebVTT video subtitles/captions (accessibility)
592
+ 'text/calendar', // iCalendar (.ics) event files
593
+
594
+ // JavaScript (legacy MIME type, still widely used by ~50% of servers)
595
+ 'text/javascript',
596
+
597
+ // =========================================================================
598
+ // MEDIA (prefix matching - covers all common subtypes)
599
+ // =========================================================================
600
+
601
+ // Images: PNG, JPEG, GIF, SVG, WebP, AVIF, HEIC, BMP, TIFF, ICO, etc.
602
+ 'image/',
603
+
604
+ // Audio: MP3, OGG, WAV, WebM, AAC, FLAC, Opus, etc.
605
+ 'audio/',
606
+
607
+ // Video: MP4, WebM, OGG, QuickTime, etc.
608
+ 'video/',
609
+
610
+ // Modern fonts: WOFF2, WOFF, TTF, OTF
611
+ 'font/',
612
+
613
+ // =========================================================================
614
+ // CORE WEB APPLICATION TYPES
615
+ // =========================================================================
616
+
617
+ // JavaScript (multiple MIME types for compatibility)
618
+ 'application/javascript', // Modern standard (RFC 9239)
619
+ 'application/ecmascript', // ECMAScript (legacy but still used)
620
+ 'application/x-javascript', // Legacy variant (old CDNs, Apache configs)
621
+
622
+ // WebAssembly (modern web apps, games, compute-heavy workloads)
623
+ 'application/wasm',
624
+
625
+ // JSON and structured data
626
+ 'application/json',
627
+ 'application/ld+json', // JSON-LD for structured data / SEO (Schema.org, Open Graph)
628
+ 'application/manifest+json', // PWA web app manifests
629
+
630
+ // XML and feeds
631
+ 'application/xml',
632
+ 'application/xhtml+xml', // XHTML - XML-compliant HTML (legacy sites)
633
+ 'application/rss+xml', // RSS feeds (blogs, podcasts)
634
+ 'application/atom+xml', // Atom feeds
635
+
636
+ // Configuration formats
637
+ 'application/yaml', // YAML configs (static site generators)
638
+
639
+ // Documents
640
+ 'application/pdf', // PDF documents
641
+
642
+ // =========================================================================
643
+ // 3D FORMATS (industry standard only)
644
+ // =========================================================================
645
+
646
+ // glTF - Khronos standard for 3D web content
647
+ 'model/gltf+json', // glTF JSON format
648
+ 'model/gltf-binary', // GLB binary format
649
+
650
+ // =========================================================================
651
+ // LEGACY COMPATIBILITY
652
+ // =========================================================================
653
+
654
+ // Video (some tools detect MP4 as application/mp4)
655
+ 'application/mp4',
656
+
657
+ // Legacy font MIME types (Bootstrap, Font Awesome, IE compatibility)
658
+ 'application/font-woff',
659
+ 'application/font-woff2',
660
+ 'application/x-font-woff',
661
+ 'application/x-woff',
662
+ 'application/vnd.ms-fontobject', // EOT files (Internet Explorer)
663
+ 'application/x-font-ttf',
664
+ 'application/x-font-truetype',
665
+ 'application/x-font-otf',
666
+ 'application/x-font-opentype',
667
+ ] as const;
668
+
669
+ /**
670
+ * Check if a MIME type is allowed for upload.
671
+ *
672
+ * Supports both exact matches and prefix matches:
673
+ * - 'application/json' matches 'application/json' exactly
674
+ * - 'text/' matches 'text/plain', 'text/html', etc.
675
+ *
676
+ * @example
677
+ * isAllowedMimeType('text/plain') // true (prefix match)
678
+ * isAllowedMimeType('application/json') // true (exact match)
679
+ * isAllowedMimeType('application/wasm') // false (not allowed)
680
+ */
681
+ export function isAllowedMimeType(mimeType: string): boolean {
682
+ return ALLOWED_MIME_TYPES.some(allowed =>
683
+ mimeType === allowed || mimeType.startsWith(allowed)
684
+ );
505
685
  }
506
686
 
507
687
  // =============================================================================