@sparkvault/sdk-mobile 6.0.2 → 7.0.1

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.
Files changed (156) hide show
  1. package/README.md +5 -5
  2. package/dist/account.d.ts +4 -3
  3. package/dist/account.js +16 -11
  4. package/dist/account.js.map +1 -1
  5. package/dist/app-sdk/email-address.d.ts +37 -0
  6. package/dist/app-sdk/email-address.js +91 -0
  7. package/dist/app-sdk/email-address.js.map +1 -0
  8. package/dist/app-sdk/encoding.d.ts +64 -0
  9. package/dist/app-sdk/encoding.js +245 -0
  10. package/dist/app-sdk/encoding.js.map +1 -0
  11. package/dist/app-sdk/entropy-contract.d.ts +33 -0
  12. package/dist/app-sdk/entropy-contract.js +51 -0
  13. package/dist/app-sdk/entropy-contract.js.map +1 -0
  14. package/dist/app-sdk/filename.d.ts +93 -0
  15. package/dist/app-sdk/filename.js +161 -0
  16. package/dist/app-sdk/filename.js.map +1 -0
  17. package/dist/app-sdk/forge-url.d.ts +107 -0
  18. package/dist/app-sdk/forge-url.js +222 -0
  19. package/dist/app-sdk/forge-url.js.map +1 -0
  20. package/dist/app-sdk/ids.d.ts +48 -0
  21. package/dist/app-sdk/ids.js +65 -0
  22. package/dist/app-sdk/ids.js.map +1 -0
  23. package/dist/app-sdk/ingot-access-log.d.ts +29 -0
  24. package/dist/app-sdk/ingot-access-log.js +49 -0
  25. package/dist/app-sdk/ingot-access-log.js.map +1 -0
  26. package/dist/app-sdk/phone.d.ts +37 -0
  27. package/dist/app-sdk/phone.js +134 -0
  28. package/dist/app-sdk/phone.js.map +1 -0
  29. package/dist/app-sdk/platform-domains.d.ts +41 -0
  30. package/dist/app-sdk/platform-domains.js +82 -0
  31. package/dist/app-sdk/platform-domains.js.map +1 -0
  32. package/dist/app-sdk/request-path.d.ts +49 -0
  33. package/dist/app-sdk/request-path.js +81 -0
  34. package/dist/app-sdk/request-path.js.map +1 -0
  35. package/dist/app-sdk/transfer-retry.d.ts +298 -0
  36. package/dist/app-sdk/transfer-retry.js +535 -0
  37. package/dist/app-sdk/transfer-retry.js.map +1 -0
  38. package/dist/app-sdk/transient.d.ts +23 -0
  39. package/dist/app-sdk/transient.js +29 -0
  40. package/dist/app-sdk/transient.js.map +1 -0
  41. package/dist/app-sdk/upload-publication.d.ts +81 -0
  42. package/dist/app-sdk/upload-publication.js +93 -0
  43. package/dist/app-sdk/upload-publication.js.map +1 -0
  44. package/dist/app-sdk/vat-refusal.d.ts +66 -0
  45. package/dist/app-sdk/vat-refusal.js +69 -0
  46. package/dist/app-sdk/vat-refusal.js.map +1 -0
  47. package/dist/billing.d.ts +9 -17
  48. package/dist/billing.js +14 -17
  49. package/dist/billing.js.map +1 -1
  50. package/dist/config.d.ts +33 -1
  51. package/dist/config.js +23 -17
  52. package/dist/config.js.map +1 -1
  53. package/dist/encoding.d.ts +30 -4
  54. package/dist/encoding.js +89 -83
  55. package/dist/encoding.js.map +1 -1
  56. package/dist/entropy.d.ts +25 -4
  57. package/dist/entropy.js +62 -15
  58. package/dist/entropy.js.map +1 -1
  59. package/dist/entropy.test-d.d.ts +40 -0
  60. package/dist/entropy.test-d.js +12 -0
  61. package/dist/entropy.test-d.js.map +1 -0
  62. package/dist/errors.d.ts +105 -21
  63. package/dist/errors.js +74 -28
  64. package/dist/errors.js.map +1 -1
  65. package/dist/folders.js +8 -7
  66. package/dist/folders.js.map +1 -1
  67. package/dist/http.d.ts +57 -15
  68. package/dist/http.js +125 -138
  69. package/dist/http.js.map +1 -1
  70. package/dist/identity-dialog.js +4 -30
  71. package/dist/identity-dialog.js.map +1 -1
  72. package/dist/identity-input.d.ts +39 -0
  73. package/dist/identity-input.js +59 -0
  74. package/dist/identity-input.js.map +1 -0
  75. package/dist/index.d.ts +8 -7
  76. package/dist/index.js +5 -4
  77. package/dist/index.js.map +1 -1
  78. package/dist/ingots.d.ts +77 -32
  79. package/dist/ingots.js +152 -136
  80. package/dist/ingots.js.map +1 -1
  81. package/dist/mutex.d.ts +1 -2
  82. package/dist/mutex.js +0 -6
  83. package/dist/mutex.js.map +1 -1
  84. package/dist/notify.d.ts +7 -2
  85. package/dist/notify.js +12 -15
  86. package/dist/notify.js.map +1 -1
  87. package/dist/notify.test-d.d.ts +3 -2
  88. package/dist/notify.test-d.js +1 -1
  89. package/dist/products/identity.d.ts +5 -0
  90. package/dist/products/identity.js +40 -35
  91. package/dist/products/identity.js.map +1 -1
  92. package/dist/request-path.d.ts +32 -0
  93. package/dist/request-path.js +35 -0
  94. package/dist/request-path.js.map +1 -0
  95. package/dist/sparks.js +16 -15
  96. package/dist/sparks.js.map +1 -1
  97. package/dist/tus.d.ts +198 -16
  98. package/dist/tus.js +816 -327
  99. package/dist/tus.js.map +1 -1
  100. package/dist/types.d.ts +183 -23
  101. package/dist/users.d.ts +12 -5
  102. package/dist/users.js +27 -19
  103. package/dist/users.js.map +1 -1
  104. package/dist/validation.d.ts +20 -5
  105. package/dist/validation.js +29 -27
  106. package/dist/validation.js.map +1 -1
  107. package/dist/vaults.d.ts +34 -83
  108. package/dist/vaults.js +64 -44
  109. package/dist/vaults.js.map +1 -1
  110. package/dist/vaults.test-d.d.ts +22 -0
  111. package/dist/vaults.test-d.js +14 -0
  112. package/dist/vaults.test-d.js.map +1 -0
  113. package/package.json +4 -2
  114. package/src/account.ts +16 -11
  115. package/src/app-sdk/email-address.js +94 -0
  116. package/src/app-sdk/encoding.js +250 -0
  117. package/src/app-sdk/entropy-contract.js +56 -0
  118. package/src/app-sdk/filename.js +174 -0
  119. package/src/app-sdk/forge-url.js +224 -0
  120. package/src/app-sdk/ids.js +71 -0
  121. package/src/app-sdk/ingot-access-log.js +51 -0
  122. package/src/app-sdk/phone.js +139 -0
  123. package/src/app-sdk/platform-domains.js +99 -0
  124. package/src/app-sdk/request-path.js +81 -0
  125. package/src/app-sdk/transfer-retry.js +563 -0
  126. package/src/app-sdk/transient.js +30 -0
  127. package/src/app-sdk/upload-publication.js +102 -0
  128. package/src/app-sdk/vat-refusal.js +74 -0
  129. package/src/billing.ts +16 -25
  130. package/src/config.ts +56 -23
  131. package/src/encoding.ts +91 -103
  132. package/src/entropy.test-d.ts +47 -0
  133. package/src/entropy.ts +86 -20
  134. package/src/errors.ts +135 -38
  135. package/src/folders.ts +8 -7
  136. package/src/http.ts +145 -150
  137. package/src/identity-dialog.tsx +4 -37
  138. package/src/identity-input.ts +70 -0
  139. package/src/index.ts +13 -3
  140. package/src/ingots.ts +225 -180
  141. package/src/mutex.ts +1 -8
  142. package/src/notify.test-d.ts +3 -1
  143. package/src/notify.ts +19 -17
  144. package/src/products/identity.ts +45 -39
  145. package/src/request-path.ts +45 -0
  146. package/src/sparks.ts +16 -13
  147. package/src/tus.ts +1054 -408
  148. package/src/types.ts +181 -23
  149. package/src/users.ts +27 -17
  150. package/src/validation.ts +30 -24
  151. package/src/vaults.test-d.ts +29 -0
  152. package/src/vaults.ts +87 -153
  153. package/dist/platform-domains.generated.d.ts +0 -2
  154. package/dist/platform-domains.generated.js +0 -16
  155. package/dist/platform-domains.generated.js.map +0 -1
  156. package/src/platform-domains.generated.ts +0 -17
package/dist/encoding.js CHANGED
@@ -1,5 +1,39 @@
1
- const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
2
- const BASE64_LOOKUP = new Map(Array.from(BASE64_ALPHABET).map((char, index) => [char, index]));
1
+ /**
2
+ * Base64 and UTF-8 for the mobile SDK.
3
+ *
4
+ * The base64 codec is the platform's one copy, mirrored from
5
+ * `@sparkvault/app-sdk/encoding` into `./app-sdk/encoding.js`; the decoders here
6
+ * raise this SDK's validation error where that codec refuses a text. UTF-8 is
7
+ * converted here rather than with TextEncoder/TextDecoder, which the JavaScript
8
+ * engines of the React Native versions this SDK supports need not provide.
9
+ * Decoding UTF-8 is fatal: bytes that are not UTF-8 are refused, never read as
10
+ * invented characters.
11
+ */
12
+ import { base64ToBytes as decodeBase64, base64urlToBytes as decodeBase64url, bytesToBase64, bytesToBase64url, } from './app-sdk/encoding.js';
13
+ import { SparkVaultValidationError } from './errors.js';
14
+ export { bytesToBase64, bytesToBase64url };
15
+ /**
16
+ * Decode standard base64.
17
+ * @throws SparkVaultValidationError when the text is not base64
18
+ */
19
+ export function base64ToBytes(value) {
20
+ const bytes = decodeBase64(value);
21
+ if (bytes === null) {
22
+ throw new SparkVaultValidationError('Invalid base64 input');
23
+ }
24
+ return bytes;
25
+ }
26
+ /**
27
+ * Decode base64url.
28
+ * @throws SparkVaultValidationError when the text is not base64url
29
+ */
30
+ export function base64UrlToBytes(value) {
31
+ const bytes = decodeBase64url(value);
32
+ if (bytes === null) {
33
+ throw new SparkVaultValidationError('Invalid base64url input');
34
+ }
35
+ return bytes;
36
+ }
3
37
  export function utf8ToBytes(value) {
4
38
  const bytes = [];
5
39
  for (let i = 0; i < value.length; i++) {
@@ -26,98 +60,70 @@ export function utf8ToBytes(value) {
26
60
  }
27
61
  return new Uint8Array(bytes);
28
62
  }
29
- export function base64EncodeUtf8(value) {
30
- return bytesToBase64(utf8ToBytes(value));
31
- }
63
+ /**
64
+ * Decode UTF-8 by the WHATWG decoder's rules in fatal mode: a byte that cannot
65
+ * start a sequence, a sequence cut short, an overlong form, a surrogate or a
66
+ * code point past U+10FFFF refuses the whole input.
67
+ * @throws SparkVaultValidationError when the bytes are not UTF-8
68
+ */
32
69
  export function bytesToUtf8(bytes) {
33
70
  let output = '';
34
- let i = 0;
35
- while (i < bytes.length) {
36
- const byte1 = bytes[i++];
37
- if (byte1 < 0x80) {
38
- output += String.fromCharCode(byte1);
71
+ let index = 0;
72
+ while (index < bytes.length) {
73
+ const lead = bytes[index++];
74
+ if (lead < 0x80) {
75
+ output += String.fromCharCode(lead);
39
76
  continue;
40
77
  }
41
- if (byte1 >= 0xc0 && byte1 < 0xe0) {
42
- const byte2 = bytes[i++];
43
- output += String.fromCharCode(((byte1 & 0x1f) << 6) | (byte2 & 0x3f));
44
- continue;
78
+ // The first continuation byte's range is what excludes overlong forms,
79
+ // surrogates and code points past U+10FFFF.
80
+ let continuations;
81
+ let codePoint;
82
+ let lower = 0x80;
83
+ let upper = 0xbf;
84
+ if (lead >= 0xc2 && lead <= 0xdf) {
85
+ continuations = 1;
86
+ codePoint = lead & 0x1f;
45
87
  }
46
- if (byte1 >= 0xe0 && byte1 < 0xf0) {
47
- const byte2 = bytes[i++];
48
- const byte3 = bytes[i++];
49
- output += String.fromCharCode(((byte1 & 0x0f) << 12) |
50
- ((byte2 & 0x3f) << 6) |
51
- (byte3 & 0x3f));
52
- continue;
88
+ else if (lead >= 0xe0 && lead <= 0xef) {
89
+ continuations = 2;
90
+ codePoint = lead & 0x0f;
91
+ if (lead === 0xe0)
92
+ lower = 0xa0;
93
+ if (lead === 0xed)
94
+ upper = 0x9f;
53
95
  }
54
- const byte2 = bytes[i++];
55
- const byte3 = bytes[i++];
56
- const byte4 = bytes[i++];
57
- const codePoint = (((byte1 & 0x07) << 18) |
58
- ((byte2 & 0x3f) << 12) |
59
- ((byte3 & 0x3f) << 6) |
60
- (byte4 & 0x3f)) - 0x10000;
61
- output += String.fromCharCode(0xd800 + (codePoint >> 10), 0xdc00 + (codePoint & 0x3ff));
96
+ else if (lead >= 0xf0 && lead <= 0xf4) {
97
+ continuations = 3;
98
+ codePoint = lead & 0x07;
99
+ if (lead === 0xf0)
100
+ lower = 0x90;
101
+ if (lead === 0xf4)
102
+ upper = 0x8f;
103
+ }
104
+ else {
105
+ throw new SparkVaultValidationError('Invalid UTF-8 input');
106
+ }
107
+ for (let seen = 0; seen < continuations; seen++) {
108
+ if (index >= bytes.length) {
109
+ throw new SparkVaultValidationError('Invalid UTF-8 input');
110
+ }
111
+ const next = bytes[index++];
112
+ if (next < lower || next > upper) {
113
+ throw new SparkVaultValidationError('Invalid UTF-8 input');
114
+ }
115
+ lower = 0x80;
116
+ upper = 0xbf;
117
+ codePoint = (codePoint << 6) | (next & 0x3f);
118
+ }
119
+ output += String.fromCodePoint(codePoint);
62
120
  }
63
121
  return output;
64
122
  }
65
- export function base64UrlToBytes(value) {
66
- return base64ToBytes(value);
123
+ export function base64EncodeUtf8(value) {
124
+ return bytesToBase64(utf8ToBytes(value));
67
125
  }
68
126
  export function base64UrlToUtf8(value) {
69
127
  return bytesToUtf8(base64UrlToBytes(value));
70
128
  }
71
- export function bytesToBase64(bytes) {
72
- let output = '';
73
- for (let i = 0; i < bytes.length; i += 3) {
74
- const byte1 = bytes[i];
75
- const byte2 = bytes[i + 1] ?? 0;
76
- const byte3 = bytes[i + 2] ?? 0;
77
- const triplet = (byte1 << 16) | (byte2 << 8) | byte3;
78
- output += BASE64_ALPHABET[(triplet >> 18) & 0x3f];
79
- output += BASE64_ALPHABET[(triplet >> 12) & 0x3f];
80
- output += i + 1 < bytes.length ? BASE64_ALPHABET[(triplet >> 6) & 0x3f] : '=';
81
- output += i + 2 < bytes.length ? BASE64_ALPHABET[triplet & 0x3f] : '=';
82
- }
83
- return output;
84
- }
85
- export function base64ToBytes(value) {
86
- const sanitized = value.replace(/\s/g, '').replace(/-/g, '+').replace(/_/g, '/');
87
- if (sanitized.length % 4 === 1) {
88
- throw new Error('Invalid base64 input');
89
- }
90
- const padded = sanitized.padEnd(Math.ceil(sanitized.length / 4) * 4, '=');
91
- // Preallocate the exact output size: 3 bytes per quartet, minus one byte per
92
- // '=' (a '=' in quartet positions 1-2 throws below, so counting every '=' is
93
- // safe). Multi-megabyte upload chunks decode through here, so per-byte array
94
- // growth is not acceptable.
95
- let paddingCount = 0;
96
- for (let i = 0; i < padded.length; i++) {
97
- if (padded[i] === '=')
98
- paddingCount++;
99
- }
100
- const bytes = new Uint8Array((padded.length / 4) * 3 - paddingCount);
101
- let outIndex = 0;
102
- for (let i = 0; i < padded.length; i += 4) {
103
- const c1 = padded[i];
104
- const c2 = padded[i + 1];
105
- const c3 = padded[i + 2];
106
- const c4 = padded[i + 3];
107
- const v1 = BASE64_LOOKUP.get(c1);
108
- const v2 = BASE64_LOOKUP.get(c2);
109
- const v3 = c3 === '=' ? 0 : BASE64_LOOKUP.get(c3);
110
- const v4 = c4 === '=' ? 0 : BASE64_LOOKUP.get(c4);
111
- if (v1 === undefined || v2 === undefined || v3 === undefined || v4 === undefined) {
112
- throw new Error('Invalid base64 input');
113
- }
114
- const triplet = (v1 << 18) | (v2 << 12) | (v3 << 6) | v4;
115
- bytes[outIndex++] = (triplet >> 16) & 0xff;
116
- if (c3 !== '=')
117
- bytes[outIndex++] = (triplet >> 8) & 0xff;
118
- if (c4 !== '=')
119
- bytes[outIndex++] = triplet & 0xff;
120
- }
121
- return bytes;
122
- }
123
129
  //# sourceMappingURL=encoding.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,aAAa,IAAI,YAAY,EAC7B,gBAAgB,IAAI,eAAe,EACnC,aAAa,EACb,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;AAE3C;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,yBAAyB,CAAC,yBAAyB,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAEpC,IAAI,SAAS,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACvE,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;gBACrC,SAAS,GAAG,OAAO,GAAG,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;gBACrE,CAAC,EAAE,CAAC;YACN,CAAC;QACH,CAAC;QAED,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;aAAM,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC;aAAM,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CACR,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EACxB,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAChC,IAAI,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC1B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CACR,IAAI,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EACxB,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EACjC,IAAI,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAChC,IAAI,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC1B,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5B,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACpC,SAAS;QACX,CAAC;QAED,uEAAuE;QACvE,4CAA4C;QAC5C,IAAI,aAAqB,CAAC;QAC1B,IAAI,SAAiB,CAAC;QACtB,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjC,aAAa,GAAG,CAAC,CAAC;YAClB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;QAC1B,CAAC;aAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACxC,aAAa,GAAG,CAAC,CAAC;YAClB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;YACxB,IAAI,IAAI,KAAK,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;YAChC,IAAI,IAAI,KAAK,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;QAClC,CAAC;aAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACxC,aAAa,GAAG,CAAC,CAAC;YAClB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;YACxB,IAAI,IAAI,KAAK,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;YAChC,IAAI,IAAI,KAAK,IAAI;gBAAE,KAAK,GAAG,IAAI,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,yBAAyB,CAAC,qBAAqB,CAAC,CAAC;QAC7D,CAAC;QAED,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;YAChD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC1B,MAAM,IAAI,yBAAyB,CAAC,qBAAqB,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5B,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBACjC,MAAM,IAAI,yBAAyB,CAAC,qBAAqB,CAAC,CAAC;YAC7D,CAAC;YACD,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,GAAG,IAAI,CAAC;YACb,SAAS,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,WAAW,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C,CAAC"}
package/dist/entropy.d.ts CHANGED
@@ -1,18 +1,39 @@
1
1
  import type { MobileHttpClient } from './http.js';
2
- export type EntropyFormat = 'hex' | 'base64' | 'bytes' | 'uuid';
2
+ /** An output format the entropy endpoint serves (the platform's entropy contract). */
3
+ export type EntropyFormat = 'hex' | 'base64' | 'base64url' | 'alphanumeric' | 'alphanumeric-mixed' | 'password' | 'numeric' | 'uuid' | 'bytes';
3
4
  export interface GenerateEntropyOptions {
5
+ /** Number of random bytes: 1–1024, or 1–512 for alphanumeric, alphanumeric-mixed and password. */
4
6
  bytes: number;
7
+ /** Output format. Defaults to base64. */
5
8
  format?: EntropyFormat;
6
9
  }
7
- export interface EntropyResponse {
8
- value: string;
10
+ /** The endpoint's answer: `value` is a number array for the `bytes` format and a string for every other. */
11
+ export interface EntropyResponse<Value extends string | number[] = string | number[]> {
12
+ value: Value;
9
13
  num_bytes: number;
10
14
  format?: EntropyFormat;
15
+ reference_id?: string;
11
16
  }
12
17
  export declare class MobileEntropyClient {
13
18
  private readonly http;
14
19
  constructor(http: MobileHttpClient);
20
+ generate(options: GenerateEntropyOptions & {
21
+ format: 'bytes';
22
+ }): Promise<EntropyResponse<number[]>>;
23
+ generate(options: GenerateEntropyOptions & {
24
+ format?: Exclude<EntropyFormat, 'bytes'>;
25
+ }): Promise<EntropyResponse<string>>;
15
26
  generate(options: GenerateEntropyOptions): Promise<EntropyResponse>;
16
27
  generateBytes(bytes: number): Promise<Uint8Array>;
17
- private validateByteCount;
28
+ /**
29
+ * Random bytes for the signed-in client's own working values (a key's id, a
30
+ * secret's server share), from POST /v1/entropy/first-party: answered to an
31
+ * interactive SparkVault session only, never plan- or bandwidth-gated and
32
+ * never recorded as the account's usage. Values an integration asks for come
33
+ * from `generate` / `generateBytes`.
34
+ *
35
+ * @param bytes - 1 to the entropy contract's ceiling (MAX_DRAW_BYTES)
36
+ * @returns exactly `bytes` bytes
37
+ */
38
+ drawFirstParty(bytes: number): Promise<Uint8Array>;
18
39
  }
package/dist/entropy.js CHANGED
@@ -1,35 +1,82 @@
1
- import { base64ToBytes } from './encoding.js';
1
+ import { base64ToBytes } from './app-sdk/encoding.js';
2
+ import { ENTROPY_FORMATS, MAX_DRAW_BYTES, isEntropyFormat, maxBytesFor } from './app-sdk/entropy-contract.js';
2
3
  import { SparkVaultMobileError, SparkVaultValidationError } from './errors.js';
4
+ import { apiPath } from './request-path.js';
3
5
  export class MobileEntropyClient {
4
6
  constructor(http) {
5
7
  this.http = http;
6
8
  }
7
9
  async generate(options) {
8
- this.validateByteCount(options.bytes);
9
- const response = await this.http.post('/entropy/generate', {
10
+ const format = options.format ?? 'base64';
11
+ validateEntropyRequest(options.bytes, format);
12
+ const response = await this.http.post(apiPath `/entropy/generate`, {
10
13
  num_bytes: options.bytes,
11
- format: options.format ?? 'base64',
14
+ format,
12
15
  });
13
16
  return response.data;
14
17
  }
15
18
  async generateBytes(bytes) {
16
19
  const response = await this.generate({ bytes, format: 'base64' });
17
- if (typeof response.value !== 'string' || response.value.length === 0) {
18
- throw new SparkVaultMobileError('Entropy endpoint returned no value');
19
- }
20
- const entropy = base64ToBytes(response.value);
21
- if (entropy.length !== bytes) {
22
- throw new SparkVaultMobileError(`Entropy length mismatch: expected ${bytes}, got ${entropy.length}`);
23
- }
24
- return entropy;
20
+ return drawnBytes(response.value, bytes);
25
21
  }
26
- validateByteCount(bytes) {
27
- if (!Number.isInteger(bytes) || bytes < 1 || bytes > 1024) {
28
- throw new SparkVaultValidationError('Entropy byte count must be an integer from 1 to 1024', {
22
+ /**
23
+ * Random bytes for the signed-in client's own working values (a key's id, a
24
+ * secret's server share), from POST /v1/entropy/first-party: answered to an
25
+ * interactive SparkVault session only, never plan- or bandwidth-gated and
26
+ * never recorded as the account's usage. Values an integration asks for come
27
+ * from `generate` / `generateBytes`.
28
+ *
29
+ * @param bytes - 1 to the entropy contract's ceiling (MAX_DRAW_BYTES)
30
+ * @returns exactly `bytes` bytes
31
+ */
32
+ async drawFirstParty(bytes) {
33
+ if (!Number.isInteger(bytes) || bytes < 1 || bytes > MAX_DRAW_BYTES) {
34
+ throw new SparkVaultValidationError(`Entropy byte count must be an integer from 1 to ${MAX_DRAW_BYTES}`, {
29
35
  field: 'bytes',
30
36
  received: bytes,
31
37
  });
32
38
  }
39
+ const response = await this.http.post(apiPath `/entropy/first-party`, {
40
+ num_bytes: bytes,
41
+ });
42
+ return drawnBytes(response.data.value, bytes);
43
+ }
44
+ }
45
+ /**
46
+ * The bytes a draw answered as base64, refused unless they are exactly the
47
+ * bytes asked for, so a malformed answer fails the operation that asked for it.
48
+ */
49
+ function drawnBytes(value, bytes) {
50
+ if (typeof value !== 'string' || value.length === 0) {
51
+ throw new SparkVaultMobileError('Entropy endpoint returned no value');
52
+ }
53
+ const entropy = base64ToBytes(value);
54
+ if (entropy === null) {
55
+ throw new SparkVaultMobileError('Entropy endpoint returned a value that is not base64');
56
+ }
57
+ if (entropy.length !== bytes) {
58
+ throw new SparkVaultMobileError(`Entropy length mismatch: expected ${bytes}, got ${entropy.length}`);
59
+ }
60
+ return entropy;
61
+ }
62
+ /**
63
+ * Refuse a request the endpoint would refuse, before it is sent: the format must
64
+ * be one the endpoint serves, and the byte count an integer from 1 to that
65
+ * format's ceiling.
66
+ */
67
+ function validateEntropyRequest(bytes, format) {
68
+ if (!isEntropyFormat(format)) {
69
+ throw new SparkVaultValidationError(`Entropy format must be one of: ${ENTROPY_FORMATS.join(', ')}`, {
70
+ field: 'format',
71
+ received: format,
72
+ });
73
+ }
74
+ const max = maxBytesFor(format);
75
+ if (!Number.isInteger(bytes) || bytes < 1 || bytes > max) {
76
+ throw new SparkVaultValidationError(`Entropy byte count must be an integer from 1 to ${max} for the ${format} format`, {
77
+ field: 'bytes',
78
+ received: bytes,
79
+ });
33
80
  }
34
81
  }
35
82
  //# sourceMappingURL=entropy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entropy.js","sourceRoot":"","sources":["../src/entropy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAgB/E,MAAM,OAAO,mBAAmB;IAG9B,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAA+B;QAC5C,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAkB,mBAAmB,EAAE;YAC1E,SAAS,EAAE,OAAO,CAAC,KAAK;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,QAAQ;SACnC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClE,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,qBAAqB,CAAC,oCAAoC,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC7B,MAAM,IAAI,qBAAqB,CAAC,qCAAqC,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvG,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,KAAa;QACrC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;YAC1D,MAAM,IAAI,yBAAyB,CAAC,sDAAsD,EAAE;gBAC1F,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"entropy.js","sourceRoot":"","sources":["../src/entropy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Entropy wire-contract assertions — COMPILE-TIME ONLY (see notify.test-d.ts for
3
+ * why these live in `src` under a `.test-d.ts` name).
4
+ *
5
+ * The endpoint answers a `bytes` request with a number array and every other
6
+ * format with a string, so `generate` is typed per format, and a format known
7
+ * only as an EntropyFormat resolves to either shape. The format list
8
+ * itself is pinned to the platform contract at runtime by
9
+ * tests/app-sdk-mirrors.test.ts.
10
+ */
11
+ import type { EntropyFormat, MobileEntropyClient } from './entropy.js';
12
+ /** Fails to compile unless `T` resolves to exactly `true`. */
13
+ type Assert<T extends true> = T;
14
+ /** Invariant type equality: `A` and `B` must be the same type, not merely mutually assignable. */
15
+ type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
16
+ /** What `generate` resolves to for a call with `Options`: its first overload that accepts them. */
17
+ type Answer<Options> = MobileEntropyClient['generate'] extends {
18
+ (options: infer First): infer FirstResult;
19
+ (options: infer Second): infer SecondResult;
20
+ (options: infer Third): infer ThirdResult;
21
+ } ? Options extends First ? Awaited<FirstResult> : Options extends Second ? Awaited<SecondResult> : Options extends Third ? Awaited<ThirdResult> : never : never;
22
+ export type EntropyWireContract = [
23
+ Assert<Equals<EntropyFormat, 'hex' | 'base64' | 'base64url' | 'alphanumeric' | 'alphanumeric-mixed' | 'password' | 'numeric' | 'uuid' | 'bytes'>>,
24
+ Assert<Equals<Answer<{
25
+ bytes: number;
26
+ format: 'bytes';
27
+ }>['value'], number[]>>,
28
+ Assert<Equals<Answer<{
29
+ bytes: number;
30
+ format: 'password';
31
+ }>['value'], string>>,
32
+ Assert<Equals<Answer<{
33
+ bytes: number;
34
+ }>['value'], string>>,
35
+ Assert<Equals<Answer<{
36
+ bytes: number;
37
+ format: EntropyFormat;
38
+ }>['value'], string | number[]>>
39
+ ];
40
+ export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Entropy wire-contract assertions — COMPILE-TIME ONLY (see notify.test-d.ts for
3
+ * why these live in `src` under a `.test-d.ts` name).
4
+ *
5
+ * The endpoint answers a `bytes` request with a number array and every other
6
+ * format with a string, so `generate` is typed per format, and a format known
7
+ * only as an EntropyFormat resolves to either shape. The format list
8
+ * itself is pinned to the platform contract at runtime by
9
+ * tests/app-sdk-mirrors.test.ts.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=entropy.test-d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entropy.test-d.js","sourceRoot":"","sources":["../src/entropy.test-d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
package/dist/errors.d.ts CHANGED
@@ -50,10 +50,10 @@ export declare class SparkVaultTimeoutError extends SparkVaultMobileError {
50
50
  constructor(message?: string);
51
51
  }
52
52
  /**
53
- * Thrown when a download is requested against an ingot that is still being
54
- * processed server-side (status `uploading`/`encrypting`). Transient by
55
- * nature, but retrying immediately will not help — callers should back off
56
- * until the ingot becomes active.
53
+ * Thrown when a download is requested against an ingot whose upload Forge has
54
+ * not activated yet (status `uploading`). Transient by nature, but retrying
55
+ * immediately will not help — callers should back off until the ingot becomes
56
+ * active.
57
57
  */
58
58
  export declare class IngotNotReadyError extends SparkVaultMobileError {
59
59
  /** Server-reported ingot status at the time of the request, when known. */
@@ -64,25 +64,87 @@ export declare class IngotNotReadyError extends SparkVaultMobileError {
64
64
  meta?: ApiMeta;
65
65
  });
66
66
  }
67
+ /** The ingot a create was refused over, as the server read it. */
68
+ export interface IngotNameHolder {
69
+ ingotId: string;
70
+ /**
71
+ * Lifecycle status of the holder: `active` when its upload finished,
72
+ * `uploading` when it has not (only a `refuse` create is refused over an
73
+ * unfinished holder; `complete_pending` completes one).
74
+ */
75
+ status: string;
76
+ sizeBytes: number;
77
+ }
78
+ /**
79
+ * Thrown when a create is refused because an ingot already holds the name in
80
+ * the target folder (409 `details.reason === 'NAME_HELD'`): with
81
+ * `onNameConflict: 'complete_pending'` a published holder, with `'refuse'` any
82
+ * holder. The server decided before writing anything, so the holder is
83
+ * untouched; `holder` is the row it read, which lets the caller act on it
84
+ * (send its bytes into its own row by id, adopt it, or try another name)
85
+ * without a second read.
86
+ */
87
+ export declare class IngotNameHeldError extends SparkVaultMobileError {
88
+ readonly holder: IngotNameHolder;
89
+ constructor(message: string, options: {
90
+ holder: IngotNameHolder;
91
+ details?: Record<string, unknown>;
92
+ meta?: ApiMeta;
93
+ });
94
+ }
67
95
  export declare class TusUploadError extends SparkVaultMobileError {
68
96
  readonly cause: Error | null;
69
97
  readonly filename: string | null;
70
98
  readonly fileSize: number | null;
71
- readonly phase: 'create' | 'upload' | 'network' | 'timeout' | 'cancelled' | 'stalled' | 'unknown';
99
+ /**
100
+ * Where the upload stopped: `finalize` is after the transfer, when every
101
+ * byte was on Forge but the ingot was not confirmed published.
102
+ */
103
+ readonly phase: 'create' | 'upload' | 'finalize' | 'network' | 'timeout' | 'cancelled' | 'stalled' | 'unknown';
72
104
  /**
73
105
  * True when Forge no longer has the session (it answered a status
74
- * `isSessionGone` recognises: expired or terminated), or the session
75
- * cannot carry this file. The persisted session is worthless, so the
76
- * caller starts a fresh upload instead of retrying it.
106
+ * `isSessionGone` recognises, or the expiry it named has passed), or the
107
+ * session cannot carry this file. The persisted session is worthless, so
108
+ * the caller starts a fresh upload instead of retrying it.
77
109
  */
78
110
  readonly sessionLost: boolean;
111
+ /**
112
+ * The `Retry-After` of the answer that ended the upload, in ms: the
113
+ * earliest a next attempt can expect another answer. Null when that answer
114
+ * named none, or no answer arrived.
115
+ */
116
+ readonly retryAfterMs: number | null;
117
+ /**
118
+ * True when every byte is on Forge and the session is intact but the ingot
119
+ * was not confirmed published: the vault did not read it `active` within
120
+ * the activation poll budget, or Forge was still saving the file at the
121
+ * upload's idle limit (code `upload_received_publishing`; it finishes
122
+ * without this device). The caller retries later by resuming the session
123
+ * it persisted, which asks Forge for the receipt again and sends no bytes.
124
+ */
125
+ readonly retryLater: boolean;
126
+ /**
127
+ * The code Core ended this upload with, as Forge named it. With code
128
+ * `upload_refused` a final refusal (`UPLOAD_POOL_FULL`: the account's
129
+ * storage pool cannot take it; `UPLOAD_SUPERSEDED`: a later upload replaced
130
+ * it), whose message is Core's own sentence and which no new upload of the
131
+ * same file remedies; with `sessionLost` any other code (`NOT_FOUND`: the
132
+ * file the upload was for is gone; `UPLOAD_PROTOCOL_RETIRED`; a 412's),
133
+ * which a fresh upload starts over from. Null when the answer named none.
134
+ */
135
+ readonly coreCode: string | null;
79
136
  constructor(message: string, options?: {
80
137
  cause?: Error | null;
81
138
  httpStatus?: number | null;
139
+ /** The error's code when it names an outcome of its own; otherwise the HTTP status, or `tus_upload_error`. */
140
+ code?: string;
82
141
  filename?: string | null;
83
142
  fileSize?: number | null;
84
143
  phase?: TusUploadError['phase'];
85
144
  sessionLost?: boolean;
145
+ retryAfterMs?: number | null;
146
+ retryLater?: boolean;
147
+ coreCode?: string | null;
86
148
  });
87
149
  /**
88
150
  * Wrap an error the SDK did not produce (a `fileReader` read, an
@@ -136,32 +198,54 @@ export declare function isNetworkError(err: unknown): boolean;
136
198
  * per-upload token minted with the ingot (expired, consumed, or bound to a
137
199
  * different session) — not the vault session. Re-unsealing the vault cannot
138
200
  * fix it; the caller creates a new upload session (`POST /ingots`) instead.
139
- * Use `isVatExpiredError` / `isReadOnlyVaultError` to tell the API's VAT
140
- * rejections apart.
201
+ * Use `vatRefusalReason` to tell the API's VAT refusals apart.
141
202
  */
142
203
  export declare function isAuthError(err: unknown): boolean;
143
204
  /**
144
- * True when the API rejected the vault access token because it has expired
145
- * (`details.reason === 'VAT_EXPIRED'` on a 401 or 403 — an expired VAT
146
- * answers 403 for its first hour, then 401). Re-unsealing the vault mints a
147
- * fresh VAT and the same request can be retried as-is.
205
+ * The reason the API refused the vault access token, or null when the error
206
+ * is not a VAT refusal:
207
+ * - `VAT_INVALID` (401): no, a malformed, unknown or swept token, or one a
208
+ * since-revoked DVAK minted — unseal again. Never the login.
209
+ * - `VAT_EXPIRED` (403): the token outlived its TTL — unseal again and
210
+ * retry the same request as-is.
211
+ * - `VAT_READ_ONLY` (403): a View Only token on a write — no unseal fixes it.
212
+ * A 403 with no reason is a token for another vault or account; a 401 with no
213
+ * reason is the login itself.
214
+ */
215
+ export declare function vatRefusalReason(err: unknown): string | null;
216
+ /**
217
+ * True when the API refused the vault access token because it has expired
218
+ * (403 `VAT_EXPIRED`). Re-unsealing the vault mints a fresh VAT and the same
219
+ * request can be retried as-is.
148
220
  */
149
221
  export declare function isVatExpiredError(err: unknown): err is SparkVaultMobileError;
150
222
  /**
151
- * True when the vault access token is valid but read-only
152
- * (`details.reason === 'VAT_READ_ONLY'` on a 403): the session was unsealed
153
- * with a read-only access level, so a write cannot succeed by retrying or by
154
- * re-unsealing the same way — the caller needs write access to the vault.
223
+ * True when the vault access token is valid but read-only (403
224
+ * `VAT_READ_ONLY`): the session was unsealed with a read-only access level, so
225
+ * a write cannot succeed by retrying or by re-unsealing the same way — the
226
+ * caller needs write access to the vault.
155
227
  */
156
228
  export declare function isReadOnlyVaultError(err: unknown): err is SparkVaultMobileError;
229
+ /**
230
+ * True for the API's 404 not-found answer: the resource it names does not
231
+ * exist (or is not this caller's to see). The only answer that says a vault,
232
+ * an ingot or a key's vault is missing; a rate limit, an outage or a refused
233
+ * session says nothing about it. Never true for a `TusUploadError`: Forge's
234
+ * 404 is an upload session that is gone, not a missing resource.
235
+ */
236
+ export declare function isNotFoundError(err: unknown): err is SparkVaultMobileError;
157
237
  /** True for a 429 rate-limit response — retry after a cooldown, never immediately. */
158
238
  export declare function isRateLimitError(err: unknown): boolean;
159
239
  /** Type guard for the still-processing-ingot download failure. */
160
240
  export declare function isIngotNotReadyError(err: unknown): err is IngotNotReadyError;
241
+ /** Type guard for a create refused over the same-name ingot holding its name. */
242
+ export declare function isIngotNameHeldError(err: unknown): err is IngotNameHeldError;
161
243
  /**
162
- * True when retrying a failed download can succeed. Validation failures and
163
- * deterministic 4xx responses always fail the same way again; everything else
164
- * (connectivity, 5xx, 408, 429) is worth another attempt.
244
+ * True when retrying a failed download can succeed. A validation failure always
245
+ * fails the same way again, and an HTTP refusal is retried only when the
246
+ * platform's retry rule (`isTransientHttpStatus`, mirrored from
247
+ * `@sparkvault/app-sdk/transient`) calls it transient; every other failure
248
+ * (connectivity, an answer that could not be read) is worth another attempt.
165
249
  */
166
250
  export declare function isRetryableDownloadError(err: unknown): boolean;
167
251
  /**