@calimero-network/mero-js 26.11.0 → 27.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 (220) hide show
  1. package/README.md +73 -288
  2. package/dist/cloud-v2/attestation.d.ts +91 -0
  3. package/dist/cloud-v2/attestation.js +135 -0
  4. package/dist/cloud-v2/capabilities.d.ts +30 -0
  5. package/dist/cloud-v2/capabilities.js +31 -0
  6. package/dist/cloud-v2/client.d.ts +426 -0
  7. package/dist/cloud-v2/client.js +646 -0
  8. package/dist/cloud-v2/errors.d.ts +98 -0
  9. package/dist/cloud-v2/errors.js +165 -0
  10. package/dist/cloud-v2/index.d.ts +10 -0
  11. package/dist/cloud-v2/index.js +5 -0
  12. package/dist/cloud-v2/passkey.d.ts +27 -0
  13. package/dist/cloud-v2/passkey.js +73 -0
  14. package/dist/crypto/internal.d.ts +3 -37
  15. package/dist/crypto/internal.js +3 -72
  16. package/dist/index.browser.mjs +4 -2
  17. package/dist/index.browser.mjs.map +4 -4
  18. package/dist/index.cjs +1750 -12772
  19. package/dist/index.cjs.map +4 -4
  20. package/dist/index.d.ts +3 -56
  21. package/dist/index.js +14 -75
  22. package/dist/index.mjs +1750 -12772
  23. package/dist/index.mjs.map +4 -4
  24. package/dist/sealed/index.d.ts +4 -4
  25. package/dist/sealed/index.js +2 -2
  26. package/dist/sealed/release.d.ts +21 -76
  27. package/dist/sealed/release.js +24 -108
  28. package/dist/sealed/sealed.d.ts +8 -56
  29. package/dist/sealed/sealed.js +11 -89
  30. package/dist/sealed/verify.d.ts +7 -13
  31. package/dist/sealed/verify.js +3 -7
  32. package/package.json +8 -13
  33. package/dist/account/account-admin.d.ts +0 -80
  34. package/dist/account/account-admin.js +0 -346
  35. package/dist/account/account.d.ts +0 -196
  36. package/dist/account/account.js +0 -269
  37. package/dist/account/application-id.d.ts +0 -50
  38. package/dist/account/application-id.js +0 -83
  39. package/dist/account/bootstrap-from-invitation.d.ts +0 -110
  40. package/dist/account/bootstrap-from-invitation.js +0 -80
  41. package/dist/account/create-context.d.ts +0 -103
  42. package/dist/account/create-context.js +0 -267
  43. package/dist/account/govern.d.ts +0 -24
  44. package/dist/account/govern.js +0 -50
  45. package/dist/account/index.d.ts +0 -26
  46. package/dist/account/index.js +0 -15
  47. package/dist/account/join-as-account.d.ts +0 -23
  48. package/dist/account/join-as-account.js +0 -34
  49. package/dist/account/join-with-node.d.ts +0 -115
  50. package/dist/account/join-with-node.js +0 -161
  51. package/dist/account/node-admin.d.ts +0 -20
  52. package/dist/account/node-admin.js +0 -33
  53. package/dist/account/relay-from-invitation.d.ts +0 -137
  54. package/dist/account/relay-from-invitation.js +0 -180
  55. package/dist/account/relay-login-error.d.ts +0 -32
  56. package/dist/account/relay-login-error.js +0 -34
  57. package/dist/account/session.d.ts +0 -266
  58. package/dist/account/session.js +0 -915
  59. package/dist/account/wordlist.d.ts +0 -16
  60. package/dist/account/wordlist.js +0 -273
  61. package/dist/admin-api/admin-client.d.ts +0 -688
  62. package/dist/admin-api/admin-client.js +0 -1230
  63. package/dist/admin-api/admin-factory.d.ts +0 -14
  64. package/dist/admin-api/admin-factory.js +0 -22
  65. package/dist/admin-api/admin-types.d.ts +0 -2046
  66. package/dist/admin-api/admin-types.js +0 -12
  67. package/dist/admin-api/index.d.ts +0 -4
  68. package/dist/admin-api/index.js +0 -5
  69. package/dist/admin-api/redeem-invitation.d.ts +0 -101
  70. package/dist/admin-api/redeem-invitation.js +0 -200
  71. package/dist/auth/index.d.ts +0 -34
  72. package/dist/auth/index.js +0 -67
  73. package/dist/auth-api/auth-client.d.ts +0 -31
  74. package/dist/auth-api/auth-client.js +0 -117
  75. package/dist/auth-api/auth-factory.d.ts +0 -7
  76. package/dist/auth-api/auth-factory.js +0 -41
  77. package/dist/auth-api/auth-types.d.ts +0 -130
  78. package/dist/auth-api/auth-types.js +0 -2
  79. package/dist/auth-api/index.d.ts +0 -3
  80. package/dist/auth-api/index.js +0 -4
  81. package/dist/capabilities.d.ts +0 -84
  82. package/dist/capabilities.js +0 -117
  83. package/dist/cloud/account-ownership.d.ts +0 -63
  84. package/dist/cloud/account-ownership.js +0 -87
  85. package/dist/cloud/cloud-client.d.ts +0 -949
  86. package/dist/cloud/cloud-client.js +0 -1068
  87. package/dist/cloud/connect.d.ts +0 -213
  88. package/dist/cloud/connect.js +0 -260
  89. package/dist/cloud/enrol-redirect.d.ts +0 -181
  90. package/dist/cloud/enrol-redirect.js +0 -244
  91. package/dist/cloud/index.d.ts +0 -12
  92. package/dist/cloud/index.js +0 -10
  93. package/dist/cloud/link-redirect.d.ts +0 -95
  94. package/dist/cloud/link-redirect.js +0 -121
  95. package/dist/cloud/link-state.d.ts +0 -36
  96. package/dist/cloud/link-state.js +0 -104
  97. package/dist/cloud/routing-proof.d.ts +0 -113
  98. package/dist/cloud/routing-proof.js +0 -96
  99. package/dist/device-cert/device-cert.d.ts +0 -189
  100. package/dist/device-cert/device-cert.js +0 -239
  101. package/dist/device-cert/device-scope.d.ts +0 -58
  102. package/dist/device-cert/device-scope.js +0 -76
  103. package/dist/device-cert/index.d.ts +0 -4
  104. package/dist/device-cert/index.js +0 -3
  105. package/dist/ephemeral/codec.d.ts +0 -4
  106. package/dist/ephemeral/codec.js +0 -12
  107. package/dist/ephemeral/index.d.ts +0 -57
  108. package/dist/ephemeral/index.js +0 -101
  109. package/dist/ephemeral/types.d.ts +0 -27
  110. package/dist/ephemeral/types.js +0 -1
  111. package/dist/errors/classify.d.ts +0 -65
  112. package/dist/errors/classify.js +0 -117
  113. package/dist/errors/index.d.ts +0 -2
  114. package/dist/errors/index.js +0 -1
  115. package/dist/events/group.d.ts +0 -95
  116. package/dist/events/group.js +0 -10
  117. package/dist/events/index.d.ts +0 -5
  118. package/dist/events/index.js +0 -2
  119. package/dist/events/sse.d.ts +0 -127
  120. package/dist/events/sse.js +0 -469
  121. package/dist/events/ws.d.ts +0 -57
  122. package/dist/events/ws.js +0 -212
  123. package/dist/http-client/api-response.d.ts +0 -15
  124. package/dist/http-client/api-response.js +0 -1
  125. package/dist/http-client/http-factory.d.ts +0 -71
  126. package/dist/http-client/http-factory.js +0 -68
  127. package/dist/http-client/http-types.d.ts +0 -87
  128. package/dist/http-client/http-types.js +0 -1
  129. package/dist/http-client/index.d.ts +0 -7
  130. package/dist/http-client/index.js +0 -11
  131. package/dist/http-client/path-segment.d.ts +0 -1
  132. package/dist/http-client/path-segment.js +0 -8
  133. package/dist/http-client/retry.d.ts +0 -5
  134. package/dist/http-client/retry.js +0 -82
  135. package/dist/http-client/signal-utils.d.ts +0 -2
  136. package/dist/http-client/signal-utils.js +0 -41
  137. package/dist/http-client/web-client.d.ts +0 -80
  138. package/dist/http-client/web-client.js +0 -557
  139. package/dist/invitation/index.d.ts +0 -2
  140. package/dist/invitation/index.js +0 -2
  141. package/dist/invitation/invitation.d.ts +0 -106
  142. package/dist/invitation/invitation.js +0 -104
  143. package/dist/login/index.d.ts +0 -4
  144. package/dist/login/index.js +0 -3
  145. package/dist/login/login.d.ts +0 -111
  146. package/dist/login/login.js +0 -110
  147. package/dist/login/session.d.ts +0 -124
  148. package/dist/login/session.js +0 -141
  149. package/dist/mero-js.d.ts +0 -231
  150. package/dist/mero-js.js +0 -469
  151. package/dist/namespace-op/index.d.ts +0 -2
  152. package/dist/namespace-op/index.js +0 -3
  153. package/dist/namespace-op/namespace-op.d.ts +0 -150
  154. package/dist/namespace-op/namespace-op.js +0 -191
  155. package/dist/nodeDiscovery.d.ts +0 -47
  156. package/dist/nodeDiscovery.js +0 -101
  157. package/dist/owner-op/index.d.ts +0 -2
  158. package/dist/owner-op/index.js +0 -3
  159. package/dist/owner-op/owner-op.d.ts +0 -119
  160. package/dist/owner-op/owner-op.js +0 -214
  161. package/dist/presence/relay-presence.d.ts +0 -56
  162. package/dist/presence/relay-presence.js +0 -107
  163. package/dist/presence/statement.d.ts +0 -12
  164. package/dist/presence/statement.js +0 -17
  165. package/dist/relay/index.d.ts +0 -4
  166. package/dist/relay/index.js +0 -2
  167. package/dist/relay/nonce-source.d.ts +0 -72
  168. package/dist/relay/nonce-source.js +0 -111
  169. package/dist/relay/relay-client.d.ts +0 -472
  170. package/dist/relay/relay-client.js +0 -518
  171. package/dist/relay-attestation/attest-node-key.d.ts +0 -66
  172. package/dist/relay-attestation/attest-node-key.js +0 -110
  173. package/dist/relay-attestation/index.d.ts +0 -1
  174. package/dist/relay-attestation/index.js +0 -1
  175. package/dist/request/caller-proof.d.ts +0 -43
  176. package/dist/request/caller-proof.js +0 -36
  177. package/dist/request/index.d.ts +0 -3
  178. package/dist/request/index.js +0 -3
  179. package/dist/request/proof-signer.d.ts +0 -49
  180. package/dist/request/proof-signer.js +0 -59
  181. package/dist/request/request-sig.d.ts +0 -99
  182. package/dist/request/request-sig.js +0 -95
  183. package/dist/request-proof/authorizer.d.ts +0 -41
  184. package/dist/request-proof/authorizer.js +0 -60
  185. package/dist/request-proof/index.d.ts +0 -4
  186. package/dist/request-proof/index.js +0 -2
  187. package/dist/request-proof/request-proof.d.ts +0 -53
  188. package/dist/request-proof/request-proof.js +0 -95
  189. package/dist/rpc/index.d.ts +0 -64
  190. package/dist/rpc/index.js +0 -78
  191. package/dist/signer/index.d.ts +0 -2
  192. package/dist/signer/index.js +0 -3
  193. package/dist/signer/signer.d.ts +0 -92
  194. package/dist/signer/signer.js +0 -147
  195. package/dist/token-store/index.d.ts +0 -27
  196. package/dist/token-store/index.js +0 -62
  197. package/dist/transport/index.d.ts +0 -6
  198. package/dist/transport/index.js +0 -3
  199. package/dist/transport/mero-client.d.ts +0 -294
  200. package/dist/transport/mero-client.js +0 -386
  201. package/dist/transport/relay-observer.d.ts +0 -152
  202. package/dist/transport/relay-observer.js +0 -173
  203. package/dist/transport/relay-transport.d.ts +0 -73
  204. package/dist/transport/relay-transport.js +0 -94
  205. package/dist/transport/types.d.ts +0 -100
  206. package/dist/transport/types.js +0 -32
  207. package/dist/types/api-response.d.ts +0 -15
  208. package/dist/types/api-response.js +0 -1
  209. package/dist/types/index.d.ts +0 -1
  210. package/dist/types/index.js +0 -1
  211. package/dist/warrant/creation-warrant.d.ts +0 -163
  212. package/dist/warrant/creation-warrant.js +0 -194
  213. package/dist/warrant/governance-op.d.ts +0 -202
  214. package/dist/warrant/governance-op.js +0 -355
  215. package/dist/warrant/governance-warrant.d.ts +0 -124
  216. package/dist/warrant/governance-warrant.js +0 -164
  217. package/dist/warrant/index.d.ts +0 -8
  218. package/dist/warrant/index.js +0 -5
  219. package/dist/warrant/warrant.d.ts +0 -188
  220. package/dist/warrant/warrant.js +0 -202
@@ -0,0 +1,98 @@
1
+ /**
2
+ * What the cloud node's refusals mean to a caller (spec D64, D70).
3
+ *
4
+ * The node answers an error as `{ error: CODE, message, details }` with an HTTP
5
+ * status. {@link errorFrom} is the one place the client turns that into an
6
+ * error a caller can switch on; every call, view and event stream goes through
7
+ * it. It matches the status and the code together, never the status alone: the
8
+ * node sends other 409s (`CONFLICT`, `NOT_INSTALLED`) that are not an
9
+ * idempotency mismatch, and other 413s (`TOO_LARGE` from the sealed transport)
10
+ * that are not oversized call arguments. Anything it does not recognise stays a
11
+ * plain {@link CalimeroError} carrying both.
12
+ *
13
+ * Every typed error extends {@link CalimeroError}, so `instanceof CalimeroError`
14
+ * and its `status` and `code` (the node's code) keep working for all of them.
15
+ */
16
+ export declare class CalimeroError extends Error {
17
+ readonly status: number;
18
+ readonly code: string;
19
+ readonly details: Record<string, unknown>;
20
+ constructor(status: number, code: string, message: string, details?: Record<string, unknown>);
21
+ }
22
+ /** `401 UNAUTHENTICATED`: sign in (again) and repeat the request. */
23
+ export declare class LoginRequired extends CalimeroError {
24
+ constructor(message: string, details?: Record<string, unknown>);
25
+ }
26
+ /**
27
+ * `404 NOT_FOUND`: what the request names does not exist for this caller. For
28
+ * an app this does not say whether it exists: an account the app does not
29
+ * admit gets the same answer as a missing app.
30
+ */
31
+ export declare class NotFound extends CalimeroError {
32
+ constructor(message: string, details?: Record<string, unknown>);
33
+ }
34
+ /**
35
+ * `412 CONFIRM_REQUIRED`: the call needs the account holder's passkey over a
36
+ * challenge in `details`. The `*Confirmed` methods answer it themselves; it
37
+ * reaches a caller only from a method that was given no passkey.
38
+ */
39
+ export declare class ConfirmRequired extends CalimeroError {
40
+ constructor(message: string, details?: Record<string, unknown>);
41
+ }
42
+ /** The user declined the passkey prompt a confirmation asked for. Nothing was sent. */
43
+ export declare class ConfirmCancelled extends Error {
44
+ readonly cause?: unknown;
45
+ constructor(cause?: unknown);
46
+ }
47
+ /** `413 ARGS_TOO_LARGE`: the call's arguments are over the node's limit; it did not run. */
48
+ export declare class ArgsTooLarge extends CalimeroError {
49
+ constructor(message: string, details?: Record<string, unknown>);
50
+ }
51
+ /** `409 IDEMPOTENCY_MISMATCH`: the idempotency key was used before with different arguments. */
52
+ export declare class IdempotencyMismatch extends CalimeroError {
53
+ constructor(message: string, details?: Record<string, unknown>);
54
+ }
55
+ /**
56
+ * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
57
+ * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
58
+ * logged, so its idempotency key is spent.
59
+ */
60
+ export declare class AppError extends CalimeroError {
61
+ readonly appCode: string;
62
+ readonly fields: Record<string, unknown>;
63
+ constructor(message: string, details?: Record<string, unknown>);
64
+ }
65
+ /** `422 TRAP`: the run trapped (`OutOfFuel`, `OutOfMemory`, ...). The call was logged. */
66
+ export declare class TrapError extends CalimeroError {
67
+ readonly kind: string;
68
+ constructor(message: string, details?: Record<string, unknown>);
69
+ }
70
+ /**
71
+ * Whether a call the node answered 503 may have committed: `false` when the
72
+ * node says it did not (`TIMEOUT`, `MIGRATING`), `"unknown"` otherwise (a call
73
+ * that raced a leader change). Never a plain boolean: `"unknown"` must not read
74
+ * as "no".
75
+ */
76
+ export type Committed = false | 'unknown';
77
+ /**
78
+ * Any `503`, or a connection that failed, after the client's retries with the
79
+ * same idempotency key ran out. `reason` is the node's code in lower case
80
+ * (`timeout`, `migrating`, `unavailable`, ...), or `network` when the node gave
81
+ * no answer at all (code `NETWORK`, `cause` the `fetch` failure); such a call
82
+ * may have committed, so its `committed` is `'unknown'`.
83
+ */
84
+ export declare class UnavailableError extends CalimeroError {
85
+ readonly reason: string;
86
+ readonly committed: Committed;
87
+ /** Seconds the node asked to wait, when it said. */
88
+ readonly retryAfter: number | undefined;
89
+ /** What failed, when the node gave no answer. */
90
+ readonly cause: unknown;
91
+ constructor(code: string, message: string, details?: Record<string, unknown>, retryAfter?: number, cause?: unknown);
92
+ }
93
+ /**
94
+ * The error for a refusal the node answered with `status` and `body` (its JSON
95
+ * `{ error, message, details }`, or whatever it sent). The one place statuses
96
+ * become typed errors.
97
+ */
98
+ export declare function errorFrom(status: number, body: unknown, retryAfterHeader?: string | null): CalimeroError;
@@ -0,0 +1,165 @@
1
+ /**
2
+ * What the cloud node's refusals mean to a caller (spec D64, D70).
3
+ *
4
+ * The node answers an error as `{ error: CODE, message, details }` with an HTTP
5
+ * status. {@link errorFrom} is the one place the client turns that into an
6
+ * error a caller can switch on; every call, view and event stream goes through
7
+ * it. It matches the status and the code together, never the status alone: the
8
+ * node sends other 409s (`CONFLICT`, `NOT_INSTALLED`) that are not an
9
+ * idempotency mismatch, and other 413s (`TOO_LARGE` from the sealed transport)
10
+ * that are not oversized call arguments. Anything it does not recognise stays a
11
+ * plain {@link CalimeroError} carrying both.
12
+ *
13
+ * Every typed error extends {@link CalimeroError}, so `instanceof CalimeroError`
14
+ * and its `status` and `code` (the node's code) keep working for all of them.
15
+ */
16
+ export class CalimeroError extends Error {
17
+ constructor(status, code, message, details = {}) {
18
+ super(`${status} ${code}: ${message}`);
19
+ this.status = status;
20
+ this.code = code;
21
+ this.details = details;
22
+ this.name = 'CalimeroError';
23
+ }
24
+ }
25
+ /** `401 UNAUTHENTICATED`: sign in (again) and repeat the request. */
26
+ export class LoginRequired extends CalimeroError {
27
+ constructor(message, details = {}) {
28
+ super(401, 'UNAUTHENTICATED', message, details);
29
+ this.name = 'LoginRequired';
30
+ }
31
+ }
32
+ /**
33
+ * `404 NOT_FOUND`: what the request names does not exist for this caller. For
34
+ * an app this does not say whether it exists: an account the app does not
35
+ * admit gets the same answer as a missing app.
36
+ */
37
+ export class NotFound extends CalimeroError {
38
+ constructor(message, details = {}) {
39
+ super(404, 'NOT_FOUND', message, details);
40
+ this.name = 'NotFound';
41
+ }
42
+ }
43
+ /**
44
+ * `412 CONFIRM_REQUIRED`: the call needs the account holder's passkey over a
45
+ * challenge in `details`. The `*Confirmed` methods answer it themselves; it
46
+ * reaches a caller only from a method that was given no passkey.
47
+ */
48
+ export class ConfirmRequired extends CalimeroError {
49
+ constructor(message, details = {}) {
50
+ super(412, 'CONFIRM_REQUIRED', message, details);
51
+ this.name = 'ConfirmRequired';
52
+ }
53
+ }
54
+ /** The user declined the passkey prompt a confirmation asked for. Nothing was sent. */
55
+ export class ConfirmCancelled extends Error {
56
+ constructor(cause) {
57
+ super('the passkey confirmation was cancelled');
58
+ this.cause = cause;
59
+ this.name = 'ConfirmCancelled';
60
+ }
61
+ }
62
+ /** `413 ARGS_TOO_LARGE`: the call's arguments are over the node's limit; it did not run. */
63
+ export class ArgsTooLarge extends CalimeroError {
64
+ constructor(message, details = {}) {
65
+ super(413, 'ARGS_TOO_LARGE', message, details);
66
+ this.name = 'ArgsTooLarge';
67
+ }
68
+ }
69
+ /** `409 IDEMPOTENCY_MISMATCH`: the idempotency key was used before with different arguments. */
70
+ export class IdempotencyMismatch extends CalimeroError {
71
+ constructor(message, details = {}) {
72
+ super(409, 'IDEMPOTENCY_MISMATCH', message, details);
73
+ this.name = 'IdempotencyMismatch';
74
+ }
75
+ }
76
+ /**
77
+ * `422 APP_ERROR`: the app refused the call. `appCode` is the app's declared
78
+ * error (`Taken`, `Forbidden`, ...) and `fields` its named fields. The call was
79
+ * logged, so its idempotency key is spent.
80
+ */
81
+ export class AppError extends CalimeroError {
82
+ constructor(message, details = {}) {
83
+ super(422, 'APP_ERROR', message, details);
84
+ this.name = 'AppError';
85
+ const { appCode, fields } = appErrorOf(details);
86
+ this.appCode = appCode;
87
+ this.fields = fields;
88
+ }
89
+ }
90
+ /** `422 TRAP`: the run trapped (`OutOfFuel`, `OutOfMemory`, ...). The call was logged. */
91
+ export class TrapError extends CalimeroError {
92
+ constructor(message, details = {}) {
93
+ super(422, 'TRAP', message, details);
94
+ this.name = 'TrapError';
95
+ this.kind = typeof details.kind === 'string' ? details.kind : '';
96
+ }
97
+ }
98
+ /**
99
+ * Any `503`, or a connection that failed, after the client's retries with the
100
+ * same idempotency key ran out. `reason` is the node's code in lower case
101
+ * (`timeout`, `migrating`, `unavailable`, ...), or `network` when the node gave
102
+ * no answer at all (code `NETWORK`, `cause` the `fetch` failure); such a call
103
+ * may have committed, so its `committed` is `'unknown'`.
104
+ */
105
+ export class UnavailableError extends CalimeroError {
106
+ constructor(code, message, details = {}, retryAfter, cause) {
107
+ super(503, code, message, details);
108
+ this.name = 'UnavailableError';
109
+ this.reason = code.toLowerCase();
110
+ this.committed = code === 'TIMEOUT' || code === 'MIGRATING' ? false : 'unknown';
111
+ this.retryAfter = retryAfter;
112
+ this.cause = cause;
113
+ }
114
+ }
115
+ function record(value) {
116
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
117
+ }
118
+ /**
119
+ * The app's code and named fields. The node puts them in `details` as
120
+ * `{ code, fields }`; an older node nests the app's error under `details.error`.
121
+ * Positional payloads (`"0"`, `"1"`) are never read as fields (D63).
122
+ */
123
+ function appErrorOf(details) {
124
+ const source = typeof details.code === 'string' ? details : record(details.error);
125
+ const appCode = typeof source.code === 'string' ? source.code : '';
126
+ return { appCode, fields: { ...record(source.fields) } };
127
+ }
128
+ function retryAfterOf(details, header) {
129
+ for (const candidate of [details.retryAfter, header == null ? undefined : Number(header)]) {
130
+ if (typeof candidate === 'number' && Number.isFinite(candidate) && candidate >= 0)
131
+ return candidate;
132
+ }
133
+ return undefined;
134
+ }
135
+ /**
136
+ * The error for a refusal the node answered with `status` and `body` (its JSON
137
+ * `{ error, message, details }`, or whatever it sent). The one place statuses
138
+ * become typed errors.
139
+ */
140
+ export function errorFrom(status, body, retryAfterHeader) {
141
+ const value = record(body);
142
+ const code = typeof value.error === 'string' ? value.error : 'ERROR';
143
+ const message = typeof value.message === 'string' ? value.message : '';
144
+ const details = record(value.details);
145
+ if (status === 503)
146
+ return new UnavailableError(code, message, details, retryAfterOf(details, retryAfterHeader));
147
+ switch (`${status} ${code}`) {
148
+ case '401 UNAUTHENTICATED':
149
+ return new LoginRequired(message, details);
150
+ case '404 NOT_FOUND':
151
+ return new NotFound(message, details);
152
+ case '409 IDEMPOTENCY_MISMATCH':
153
+ return new IdempotencyMismatch(message, details);
154
+ case '412 CONFIRM_REQUIRED':
155
+ return new ConfirmRequired(message, details);
156
+ case '413 ARGS_TOO_LARGE':
157
+ return new ArgsTooLarge(message, details);
158
+ case '422 APP_ERROR':
159
+ return new AppError(message, details);
160
+ case '422 TRAP':
161
+ return new TrapError(message, details);
162
+ default:
163
+ return new CalimeroError(status, code, message, details);
164
+ }
165
+ }
@@ -0,0 +1,10 @@
1
+ export { CalimeroClient } from './client.js';
2
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.js';
3
+ export type { Committed } from './errors.js';
4
+ export type { AppInfo, BlobInfo, CallResult, CalimeroClientOptions, CloudEvent, CalimeroSession, PackageInfo, PackageInstalled, CloudRetryOptions, OrgUpgradeTarget, PresenceEntry, UpgradeRun, ViewResult, } from './client.js';
5
+ export { claimedRelease, fetchAttestedKey, MOCK_QUOTE_HEADER } from './attestation.js';
6
+ export type { AttestationDoc, CloudPolicy, CloudReleasePolicy } from './attestation.js';
7
+ export { browserPasskey, b64url, fromB64url } from './passkey.js';
8
+ export type { AssertionJSON, PasskeyProvider, RegistrationJSON } from './passkey.js';
9
+ export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';
10
+ export type { OrgCapability } from './capabilities.js';
@@ -0,0 +1,5 @@
1
+ export { CalimeroClient } from './client.js';
2
+ export { AppError, ArgsTooLarge, CalimeroError, ConfirmCancelled, ConfirmRequired, IdempotencyMismatch, LoginRequired, NotFound, TrapError, UnavailableError, errorFrom, } from './errors.js';
3
+ export { claimedRelease, fetchAttestedKey, MOCK_QUOTE_HEADER } from './attestation.js';
4
+ export { browserPasskey, b64url, fromB64url } from './passkey.js';
5
+ export { DEFAULT_ORG_CAPABILITIES, ORG_CAPABILITIES, orgCapabilities } from './capabilities.js';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Passkeys: the browser's WebAuthn API, or anything that answers like it.
3
+ *
4
+ * Every binary field crosses the wire as base64url, matching
5
+ * `calimero-identity`'s `Registration` and `Assertion`.
6
+ */
7
+ export interface RegistrationJSON {
8
+ attestationObject: string;
9
+ clientDataJson: string;
10
+ }
11
+ export interface AssertionJSON {
12
+ credentialId: string;
13
+ authenticatorData: string;
14
+ clientDataJson: string;
15
+ signature: string;
16
+ }
17
+ /** Something that holds a passkey. */
18
+ export interface PasskeyProvider {
19
+ /** Answer `navigator.credentials.create` for the node's options. */
20
+ create(options: Record<string, unknown>): Promise<RegistrationJSON>;
21
+ /** Sign `challenge` (an assertion), optionally limited to `allowCredentials`. */
22
+ get(challenge: Uint8Array, rpId: string, allowCredentials?: string[]): Promise<AssertionJSON>;
23
+ }
24
+ export declare function b64url(bytes: Uint8Array): string;
25
+ export declare function fromB64url(s: string): Uint8Array;
26
+ /** The platform authenticator (Touch ID, Face ID, Windows Hello, a security key, a synced passkey). */
27
+ export declare function browserPasskey(): PasskeyProvider;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Passkeys: the browser's WebAuthn API, or anything that answers like it.
3
+ *
4
+ * Every binary field crosses the wire as base64url, matching
5
+ * `calimero-identity`'s `Registration` and `Assertion`.
6
+ */
7
+ export function b64url(bytes) {
8
+ let bin = '';
9
+ for (const b of bytes)
10
+ bin += String.fromCharCode(b);
11
+ return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
12
+ }
13
+ export function fromB64url(s) {
14
+ const pad = s.replace(/-/g, '+').replace(/_/g, '/') + '==='.slice((s.length + 3) % 4);
15
+ const bin = atob(pad);
16
+ const out = new Uint8Array(bin.length);
17
+ for (let i = 0; i < bin.length; i++)
18
+ out[i] = bin.charCodeAt(i);
19
+ return out;
20
+ }
21
+ const buf = (b) => b.buffer.slice(b.byteOffset, b.byteOffset + b.byteLength);
22
+ /** A dismissed prompt, named as WebAuthn names one (`NotAllowedError`), so a confirmation reads it as declined. */
23
+ function cancelled(message) {
24
+ const error = new Error(message);
25
+ error.name = 'NotAllowedError';
26
+ return error;
27
+ }
28
+ /** The platform authenticator (Touch ID, Face ID, Windows Hello, a security key, a synced passkey). */
29
+ export function browserPasskey() {
30
+ return {
31
+ async create(options) {
32
+ const o = options;
33
+ const cred = (await navigator.credentials.create({
34
+ publicKey: {
35
+ challenge: buf(fromB64url(o.challenge)),
36
+ rp: o.rp,
37
+ user: { ...o.user, id: buf(fromB64url(o.user.id)) },
38
+ pubKeyCredParams: o.pubKeyCredParams,
39
+ excludeCredentials: (o.excludeCredentials ?? []).map((c) => ({ type: c.type, id: buf(fromB64url(c.id)) })),
40
+ authenticatorSelection: o.authenticatorSelection,
41
+ attestation: 'none',
42
+ timeout: o.timeout,
43
+ },
44
+ }));
45
+ if (!cred)
46
+ throw cancelled('passkey creation was cancelled');
47
+ const r = cred.response;
48
+ return {
49
+ attestationObject: b64url(new Uint8Array(r.attestationObject)),
50
+ clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),
51
+ };
52
+ },
53
+ async get(challenge, rpId, allowCredentials) {
54
+ const cred = (await navigator.credentials.get({
55
+ publicKey: {
56
+ challenge: buf(challenge),
57
+ rpId,
58
+ userVerification: 'preferred',
59
+ allowCredentials: (allowCredentials ?? []).map((id) => ({ type: 'public-key', id: buf(fromB64url(id)) })),
60
+ },
61
+ }));
62
+ if (!cred)
63
+ throw cancelled('passkey sign-in was cancelled');
64
+ const r = cred.response;
65
+ return {
66
+ credentialId: b64url(new Uint8Array(cred.rawId)),
67
+ authenticatorData: b64url(new Uint8Array(r.authenticatorData)),
68
+ clientDataJson: b64url(new Uint8Array(r.clientDataJSON)),
69
+ signature: b64url(new Uint8Array(r.signature)),
70
+ };
71
+ },
72
+ };
73
+ }
@@ -1,11 +1,7 @@
1
1
  /**
2
- * Byte-level primitives shared by everything in this package that signs.
3
- *
4
- * Extracted from `warrant/warrant.ts` when the device-cert signer arrived and
5
- * needed the same `domainHash`, hex handling and ed25519 import. Keeping one
6
- * copy is the point: these have to stay byte-identical with core, and two
7
- * copies drifting apart is exactly the failure the byte-parity e2e exists to
8
- * catch. Internal — not exported from the package root.
2
+ * Byte-level primitives shared by the sealed transport, the attestation check
3
+ * and the agent gate: hex handling, fixed-width integers and concatenation.
4
+ * Internal — not exported from the package root.
9
5
  */
10
6
  /** Little-endian u32, for borsh fixed-width fields and epoch counters. */
11
7
  export declare function u32le(value: number): Uint8Array;
@@ -24,33 +20,3 @@ export declare function fromHex(value: string, label: string, expectedBytes: num
24
20
  export declare function fromHexUnsized(value: string, label: string): Uint8Array;
25
21
  export declare function u64le(value: number | bigint): Uint8Array;
26
22
  export declare function concat(...parts: Uint8Array[]): Uint8Array;
27
- /**
28
- * core's `domain_hash`: SHA-256 over the length-prefixed domain, then each
29
- * length-prefixed part. The lengths are what stop two different field splits from
30
- * hashing alike.
31
- */
32
- export declare function domainHash(domain: Uint8Array, parts: Uint8Array[]): Promise<Uint8Array>;
33
- export declare function importSigningKey(secretHex: string): Promise<CryptoKey>;
34
- /**
35
- * Check an ed25519 signature against a public key, both raw.
36
- *
37
- * The one primitive here that consumes rather than produces a signature: a page
38
- * handed a credential by another origin has to check it before it acts on it,
39
- * and "the node will reject it later" is not the same safeguard — by then the
40
- * page has already stored an account it does not control.
41
- *
42
- * `raw` import is the public-key counterpart of the PKCS#8 import above and is
43
- * available on exactly the runtimes that can sign, so a runtime that got this
44
- * far will not fail here for lack of support.
45
- *
46
- * @param publicKey 64 hex, the key the signature must verify against
47
- */
48
- export declare function verifySignature(publicKey: string, signature: Uint8Array, payload: Uint8Array): Promise<boolean>;
49
- /**
50
- * The public half of an ed25519 seed.
51
- *
52
- * Derived rather than taken as an argument, for the reason core does the same: a
53
- * caller able to name a key it does not hold could produce a warrant it cannot
54
- * sign, and the field would stop meaning "who authorised this".
55
- */
56
- export declare function derivePublicKey(secretHex: string): Promise<Uint8Array>;
@@ -1,16 +1,8 @@
1
1
  /**
2
- * Byte-level primitives shared by everything in this package that signs.
3
- *
4
- * Extracted from `warrant/warrant.ts` when the device-cert signer arrived and
5
- * needed the same `domainHash`, hex handling and ed25519 import. Keeping one
6
- * copy is the point: these have to stay byte-identical with core, and two
7
- * copies drifting apart is exactly the failure the byte-parity e2e exists to
8
- * catch. Internal — not exported from the package root.
2
+ * Byte-level primitives shared by the sealed transport, the attestation check
3
+ * and the agent gate: hex handling, fixed-width integers and concatenation.
4
+ * Internal — not exported from the package root.
9
5
  */
10
- const PKCS8_ED25519_PREFIX = new Uint8Array([
11
- 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04,
12
- 0x22, 0x04, 0x20,
13
- ]);
14
6
  /** Little-endian u32, for borsh fixed-width fields and epoch counters. */
15
7
  export function u32le(value) {
16
8
  const out = new Uint8Array(4);
@@ -69,64 +61,3 @@ export function concat(...parts) {
69
61
  }
70
62
  return out;
71
63
  }
72
- /**
73
- * core's `domain_hash`: SHA-256 over the length-prefixed domain, then each
74
- * length-prefixed part. The lengths are what stop two different field splits from
75
- * hashing alike.
76
- */
77
- export async function domainHash(domain, parts) {
78
- const chunks = [u64le(domain.length), domain];
79
- for (const part of parts) {
80
- chunks.push(u64le(part.length), part);
81
- }
82
- return new Uint8Array(await crypto.subtle.digest('SHA-256', concat(...chunks)));
83
- }
84
- export async function importSigningKey(secretHex) {
85
- const seed = fromHex(secretHex, 'deviceSecret', 32);
86
- const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
87
- try {
88
- return await crypto.subtle.importKey('pkcs8', pkcs8, { name: 'Ed25519' }, false, ['sign']);
89
- }
90
- catch (cause) {
91
- // The original message is folded in rather than passed as `cause`: this
92
- // package targets ES2020, where `Error` has no `cause` option.
93
- const detail = cause instanceof Error ? `: ${cause.message}` : '';
94
- throw new Error('this runtime has no WebCrypto Ed25519, so a warrant cannot be signed ' +
95
- 'here. Node 18.4+, Safari 17+, Firefox 129+ and Chrome 137+ have it; ' +
96
- 'otherwise mint the warrant with `merod account warrant`' +
97
- detail);
98
- }
99
- }
100
- /**
101
- * Check an ed25519 signature against a public key, both raw.
102
- *
103
- * The one primitive here that consumes rather than produces a signature: a page
104
- * handed a credential by another origin has to check it before it acts on it,
105
- * and "the node will reject it later" is not the same safeguard — by then the
106
- * page has already stored an account it does not control.
107
- *
108
- * `raw` import is the public-key counterpart of the PKCS#8 import above and is
109
- * available on exactly the runtimes that can sign, so a runtime that got this
110
- * far will not fail here for lack of support.
111
- *
112
- * @param publicKey 64 hex, the key the signature must verify against
113
- */
114
- export async function verifySignature(publicKey, signature, payload) {
115
- const key = await crypto.subtle.importKey('raw', fromHex(publicKey, 'publicKey', 32), { name: 'Ed25519' }, false, ['verify']);
116
- return crypto.subtle.verify({ name: 'Ed25519' }, key, signature, payload);
117
- }
118
- /**
119
- * The public half of an ed25519 seed.
120
- *
121
- * Derived rather than taken as an argument, for the reason core does the same: a
122
- * caller able to name a key it does not hold could produce a warrant it cannot
123
- * sign, and the field would stop meaning "who authorised this".
124
- */
125
- export async function derivePublicKey(secretHex) {
126
- const seed = fromHex(secretHex, 'deviceSecret', 32);
127
- const pkcs8 = concat(PKCS8_ED25519_PREFIX, seed);
128
- const key = await crypto.subtle.importKey('pkcs8', pkcs8, { name: 'Ed25519' }, true, ['sign']);
129
- const jwk = await crypto.subtle.exportKey('jwk', key);
130
- const raw = jwk.x;
131
- return Uint8Array.from(atob(raw.replace(/-/g, '+').replace(/_/g, '/')), (c) => c.charCodeAt(0));
132
- }