@request-seal/core 0.1.0 → 0.3.0

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 (128) hide show
  1. package/CHANGELOG.md +49 -1
  2. package/README.md +342 -114
  3. package/dist/accept-signature.d.ts +11 -0
  4. package/dist/accept-signature.js +7 -0
  5. package/dist/adapters/fetch/index.d.ts +10 -0
  6. package/dist/adapters/fetch/index.js +21 -4
  7. package/dist/adapters/fetch/runtime.d.ts +1 -0
  8. package/dist/adapters/fetch/runtime.js +1 -0
  9. package/dist/adapters/node-http/index.d.ts +23 -0
  10. package/dist/adapters/node-http/index.js +28 -8
  11. package/dist/brand.d.ts +5 -0
  12. package/dist/brand.js +12 -0
  13. package/dist/bytes.d.ts +4 -0
  14. package/dist/bytes.js +5 -0
  15. package/dist/constants.d.ts +64 -4
  16. package/dist/constants.js +62 -2
  17. package/dist/context.d.ts +4 -0
  18. package/dist/context.js +3 -0
  19. package/dist/crypto/algorithm.d.ts +9 -0
  20. package/dist/crypto/algorithm.js +12 -0
  21. package/dist/crypto/index.d.ts +12 -2
  22. package/dist/crypto/index.js +34 -11
  23. package/dist/crypto/options.d.ts +3 -0
  24. package/dist/crypto/options.js +15 -0
  25. package/dist/crypto/primitive.d.ts +7 -3
  26. package/dist/crypto/primitive.js +36 -10
  27. package/dist/custody/content_key.d.ts +4 -0
  28. package/dist/custody/content_key.js +4 -2
  29. package/dist/custody/index.d.ts +2 -0
  30. package/dist/custody/index.js +5 -1
  31. package/dist/custody/local.d.ts +17 -1
  32. package/dist/custody/local.js +10 -5
  33. package/dist/custody/ssh-agent/index.d.ts +2 -0
  34. package/dist/custody/ssh-agent/index.js +11 -181
  35. package/dist/custody/ssh-agent/port.d.ts +19 -0
  36. package/dist/custody/ssh-agent/port.js +183 -0
  37. package/dist/digest.d.ts +22 -0
  38. package/dist/digest.js +15 -0
  39. package/dist/discovery/body.d.ts +19 -2
  40. package/dist/discovery/body.js +36 -11
  41. package/dist/discovery/cache.d.ts +21 -2
  42. package/dist/discovery/cache.js +105 -39
  43. package/dist/discovery/headers.d.ts +3 -0
  44. package/dist/discovery/headers.js +27 -1
  45. package/dist/discovery/index.d.ts +13 -1
  46. package/dist/discovery/index.js +31 -7
  47. package/dist/discovery/node-connection.d.ts +1 -1
  48. package/dist/discovery/node-connection.js +2 -2
  49. package/dist/discovery/node-trust.d.ts +2 -0
  50. package/dist/discovery/node-trust.js +9 -0
  51. package/dist/discovery/node.d.ts +9 -1
  52. package/dist/discovery/node.js +150 -26
  53. package/dist/discovery/proof.js +2 -2
  54. package/dist/discovery/snapshot.js +3 -0
  55. package/dist/discovery/source.d.ts +7 -0
  56. package/dist/discovery/source.js +5 -0
  57. package/dist/discovery/support.js +2 -3
  58. package/dist/errors/parity.d.ts +44 -3
  59. package/dist/errors/parity.js +45 -4
  60. package/dist/errors/types.d.ts +17 -3
  61. package/dist/errors/types.js +16 -2
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.js +1 -0
  64. package/dist/jose/header.d.ts +1 -0
  65. package/dist/jose/jwe.d.ts +9 -0
  66. package/dist/jose/jwe.js +17 -3
  67. package/dist/jose/jws.d.ts +11 -0
  68. package/dist/jose/jws.js +14 -2
  69. package/dist/jose/key-management.d.ts +11 -0
  70. package/dist/jose/key-management.js +13 -2
  71. package/dist/jose/nested.d.ts +6 -0
  72. package/dist/jose/nested.js +32 -2
  73. package/dist/json.d.ts +7 -0
  74. package/dist/key_handle.d.ts +12 -3
  75. package/dist/key_handle.js +32 -25
  76. package/dist/key_identity.d.ts +7 -0
  77. package/dist/key_identity.js +10 -2
  78. package/dist/message/index.d.ts +24 -0
  79. package/dist/message/index.js +22 -1
  80. package/dist/numbers.d.ts +6 -0
  81. package/dist/numbers.js +5 -0
  82. package/dist/policy.d.ts +27 -0
  83. package/dist/policy.js +42 -21
  84. package/dist/profile.d.ts +36 -0
  85. package/dist/profile.js +215 -0
  86. package/dist/public_key.d.ts +11 -2
  87. package/dist/public_key.js +31 -8
  88. package/dist/quorum/evaluation.d.ts +1 -1
  89. package/dist/quorum/evaluation.js +18 -4
  90. package/dist/quorum/verification.d.ts +2 -0
  91. package/dist/quorum/verification.js +1 -0
  92. package/dist/quorum.d.ts +9 -0
  93. package/dist/quorum.js +7 -1
  94. package/dist/replay/claim.d.ts +5 -0
  95. package/dist/replay/claim.js +9 -1
  96. package/dist/replay/index.d.ts +6 -0
  97. package/dist/replay/index.js +13 -1
  98. package/dist/replay/postgres.d.ts +3 -0
  99. package/dist/replay/postgres.js +7 -0
  100. package/dist/replay/receipt.d.ts +1 -0
  101. package/dist/replay/receipt.js +1 -0
  102. package/dist/replay/store.d.ts +1 -0
  103. package/dist/replay/store.js +1 -0
  104. package/dist/replay-port.d.ts +6 -1
  105. package/dist/result.d.ts +3 -0
  106. package/dist/result.js +2 -0
  107. package/dist/sign.d.ts +26 -0
  108. package/dist/sign.js +25 -3
  109. package/dist/signature-base/index.d.ts +2 -0
  110. package/dist/signature-base/index.js +5 -1
  111. package/dist/signature-fields.d.ts +5 -1
  112. package/dist/signature-fields.js +9 -1
  113. package/dist/structured-fields/index.d.ts +21 -0
  114. package/dist/structured-fields/index.js +14 -1
  115. package/dist/verification.d.ts +5 -1
  116. package/dist/verification.js +9 -6
  117. package/dist/verify-quorum.d.ts +1 -0
  118. package/dist/verify-quorum.js +30 -8
  119. package/dist/verify.d.ts +23 -0
  120. package/dist/verify.js +46 -14
  121. package/dist/web-bot-auth/index.d.ts +3 -0
  122. package/dist/web-bot-auth/index.js +3 -0
  123. package/dist/web-bot-auth/policy.d.ts +8 -0
  124. package/dist/web-bot-auth/policy.js +8 -4
  125. package/dist/web-bot-auth/verification.d.ts +8 -0
  126. package/dist/web-bot-auth/verification.js +4 -2
  127. package/dist/web-bot-auth/verify.js +2 -2
  128. package/package.json +29 -6
@@ -1,5 +1,6 @@
1
- // Derived from pinned Elixir constructors and call sites; regenerate with scripts/render-parity.ts --update-table.
2
- export const ELIXIR_ERROR_PIN = 'b2392871933d99641a7cb2ca2726aefd20081dee';
1
+ // Derived from pinned Elixir constructors and call sites; regenerate with scripts/generate-parity.ts or scripts/render-parity.ts --update-table.
2
+ /** The immutable reference release used for the error vocabulary. */
3
+ export const ELIXIR_ERROR_PIN = '53b6690ccd5036d58b280d08cf0cacc6427262fe';
3
4
  const entries = [
4
5
  {
5
6
  "kind": "core",
@@ -253,6 +254,12 @@ const entries = [
253
254
  "reason": "unsupported_component",
254
255
  "rule_id": "core/input.unsupported_component"
255
256
  },
257
+ {
258
+ "kind": "core",
259
+ "layer": "internal",
260
+ "reason": "internal",
261
+ "rule_id": "core/internal.internal"
262
+ },
256
263
  {
257
264
  "kind": "core",
258
265
  "layer": "key",
@@ -355,6 +362,12 @@ const entries = [
355
362
  "reason": "binding_unsatisfied",
356
363
  "rule_id": "core/quorum.binding_unsatisfied"
357
364
  },
365
+ {
366
+ "kind": "core",
367
+ "layer": "quorum",
368
+ "reason": "deadline",
369
+ "rule_id": "core/quorum.deadline"
370
+ },
358
371
  {
359
372
  "kind": "core",
360
373
  "layer": "quorum",
@@ -705,6 +718,11 @@ const entries = [
705
718
  "reason": "invalid_key",
706
719
  "rule_id": "crypto/invalid_key"
707
720
  },
721
+ {
722
+ "kind": "crypto",
723
+ "reason": "invalid_options",
724
+ "rule_id": "crypto/invalid_options"
725
+ },
708
726
  {
709
727
  "kind": "crypto",
710
728
  "reason": "invalid_signature",
@@ -860,6 +878,11 @@ const entries = [
860
878
  "reason": "directory_unsigned",
861
879
  "rule_id": "discovery/directory_unsigned"
862
880
  },
881
+ {
882
+ "kind": "discovery",
883
+ "reason": "domain_not_found",
884
+ "rule_id": "discovery/domain_not_found"
885
+ },
863
886
  {
864
887
  "kind": "discovery",
865
888
  "reason": "invalid_key_set",
@@ -1239,6 +1262,10 @@ const retryableRules = {
1239
1262
  "kind": "constant",
1240
1263
  "value": false
1241
1264
  },
1265
+ "deadline": {
1266
+ "kind": "constant",
1267
+ "value": true
1268
+ },
1242
1269
  "digest_mismatch": {
1243
1270
  "kind": "constant",
1244
1271
  "value": false
@@ -1267,6 +1294,10 @@ const retryableRules = {
1267
1294
  "kind": "constant",
1268
1295
  "value": false
1269
1296
  },
1297
+ "internal": {
1298
+ "kind": "constant",
1299
+ "value": false
1300
+ },
1270
1301
  "invalid_accept_signature": {
1271
1302
  "kind": "constant",
1272
1303
  "value": false
@@ -1713,6 +1744,10 @@ const retryableRules = {
1713
1744
  "kind": "constant",
1714
1745
  "value": false
1715
1746
  },
1747
+ "invalid_options": {
1748
+ "kind": "constant",
1749
+ "value": false
1750
+ },
1716
1751
  "invalid_signature": {
1717
1752
  "kind": "constant",
1718
1753
  "value": false
@@ -1841,6 +1876,10 @@ const retryableRules = {
1841
1876
  "kind": "constant",
1842
1877
  "value": false
1843
1878
  },
1879
+ "domain_not_found": {
1880
+ "kind": "constant",
1881
+ "value": false
1882
+ },
1844
1883
  "invalid_key_set": {
1845
1884
  "kind": "constant",
1846
1885
  "value": false
@@ -1871,7 +1910,7 @@ const retryableRules = {
1871
1910
  },
1872
1911
  "resolution_failed": {
1873
1912
  "kind": "constant",
1874
- "value": false
1913
+ "value": true
1875
1914
  },
1876
1915
  "revoked_key": {
1877
1916
  "kind": "constant",
@@ -1898,7 +1937,7 @@ const retryableRules = {
1898
1937
  "minimum": 500,
1899
1938
  "maximum": 599,
1900
1939
  "path": "lib/request_seal/discovery.ex",
1901
- "line": 301
1940
+ "line": 517
1902
1941
  },
1903
1942
  "unknown_key": {
1904
1943
  "kind": "constant",
@@ -2105,9 +2144,11 @@ const retryableRules = {
2105
2144
  }
2106
2145
  };
2107
2146
  export const ERROR_RETRYABLE = Object.freeze(Object.fromEntries(Object.entries(retryableRules).map(([kind, rules]) => [kind, Object.freeze(Object.fromEntries(Object.entries(rules).map(([reason, rule]) => [reason, Object.freeze(rule)])))])));
2147
+ /** The pinned reason, layer, and retryability table. */
2108
2148
  export const ERROR_PARITY = Object.freeze(entries.map(entry => Object.freeze(entry)));
2109
2149
  const rules = new Set(ERROR_PARITY.map(e => e.rule_id));
2110
2150
  // A frozen Set still exposes mutation methods; the facade keeps the backing Set private.
2151
+ /** The complete set of rule IDs derived from the parity table. */
2111
2152
  export const RULE_IDS = Object.freeze({
2112
2153
  get size() { return rules.size; },
2113
2154
  has: (value) => rules.has(value),
@@ -1,30 +1,37 @@
1
1
  import { type Reason, type Layer } from './parity.ts';
2
- export type CoreDetail = Reason<'core'> | Reason<'signature_base'> | 'legacy_string' | 'invalid_dictionary' | 'duplicate_member' | 'invalid_member' | 'missing_member' | 'unsupported_type' | 'not_an_origin' | 'untrusted_agent' | 'source_mismatch' | 'revoked_key' | 'source_unavailable' | 'timeout';
2
+ /** The bounded detail vocabulary for core failures. */
3
+ export type CoreDetail = Reason<'core'> | Reason<'signature_base'> | 'legacy_string' | 'invalid_dictionary' | 'duplicate_member' | 'invalid_member' | 'missing_member' | 'unsupported_type' | 'not_an_origin' | 'untrusted_agent' | 'source_mismatch' | 'revoked_key' | 'source_unavailable' | 'timeout' | 'TypeError' | 'RangeError' | 'URIError' | 'EvalError' | 'ReferenceError' | 'SyntaxError' | 'Error' | 'throw';
4
+ /** A core failure with layer, correlation, and optional bounded source. */
3
5
  export type CoreError = Readonly<{
4
6
  kind: 'core';
5
7
  reason: Reason<'core'>;
6
8
  layer: Layer<'core'>;
7
9
  correlation: string;
8
- retryable: false;
10
+ retryable: boolean;
9
11
  detail: CoreDetail | null;
10
12
  message: string | null;
11
13
  source: CustodyError | null;
12
14
  }>;
15
+ /** Error families carrying only a reason. @inline */
13
16
  type SimpleKind = 'message' | 'structured_fields' | 'signature_base' | 'digest' | 'crypto';
17
+ /** A reason-only error for message, field, digest, or crypto operations. */
14
18
  export type SimpleError<K extends SimpleKind> = Readonly<{
15
19
  kind: K;
16
20
  reason: Reason<K>;
17
21
  }>;
22
+ /** A custody failure with an explicit retryability flag. */
18
23
  export type CustodyError = Readonly<{
19
24
  kind: 'custody';
20
25
  reason: Reason<'custody'>;
21
26
  retryable: boolean;
22
27
  }>;
28
+ /** A discovery failure with an explicit retryability flag. */
23
29
  export type DiscoveryError = Readonly<{
24
30
  kind: 'discovery';
25
31
  reason: Reason<'discovery'>;
26
32
  retryable: boolean;
27
33
  }>;
34
+ /** A JOSE failure with layer and explicit retryability. */
28
35
  export type JoseError = Readonly<{
29
36
  kind: 'jose';
30
37
  reason: Reason<'jose'>;
@@ -32,11 +39,13 @@ export type JoseError = Readonly<{
32
39
  correlation: null;
33
40
  retryable: boolean;
34
41
  }>;
42
+ /** A nonretryable replay-store failure. */
35
43
  export type ReplayError = Readonly<{
36
44
  kind: 'replay';
37
45
  reason: Reason<'replay'>;
38
46
  retryable: false;
39
47
  }>;
48
+ /** A bounded adapter failure with stage, attempt, and optional source. */
40
49
  export type AdapterError = Readonly<{
41
50
  kind: 'adapter';
42
51
  reason: Reason<'adapter'>;
@@ -47,10 +56,14 @@ export type AdapterError = Readonly<{
47
56
  correlation: string;
48
57
  retryable: false;
49
58
  }>;
59
+ /** The union of all branded, bounded public error families. */
50
60
  export type RequestSealError = CoreError | {
51
61
  [K in SimpleKind]: SimpleError<K>;
52
62
  }[SimpleKind] | CustodyError | DiscoveryError | JoseError | ReplayError | AdapterError;
63
+ /** Check whether an error belongs to the private error brand. */
53
64
  export declare function isRequestSealError(value: unknown): value is RequestSealError;
65
+ /** The bounded exception class for an internal-fault detail. */
66
+ export declare function faultClass(e: unknown): CoreDetail;
54
67
  export declare function coreError(reason: Reason<'core'>, layer: Layer<'core'>, detail?: CoreDetail | null, source?: CustodyError | null): CoreError;
55
68
  export declare const messageError: (reason: Reason<'message'>) => Readonly<{
56
69
  kind: "message";
@@ -70,12 +83,13 @@ export declare const digestError: (reason: Reason<'digest'>) => Readonly<{
70
83
  }>;
71
84
  export declare const cryptoError: (reason: Reason<'crypto'>) => Readonly<{
72
85
  kind: "crypto";
73
- reason: "invalid_data" | "invalid_key" | "invalid_signature" | "key_mismatch" | "unsupported_algorithm" | "unsupported_format";
86
+ reason: "invalid_data" | "invalid_key" | "invalid_options" | "invalid_signature" | "key_mismatch" | "unsupported_algorithm" | "unsupported_format";
74
87
  }>;
75
88
  export declare function custodyError(reason: Reason<'custody'>): CustodyError;
76
89
  export declare function discoveryError(reason: Reason<'discovery'>, status?: number): DiscoveryError;
77
90
  export declare function joseError(reason: Reason<'jose'>, layer: Layer<'jose'>): JoseError;
78
91
  export declare function replayError(reason: Reason<'replay'>): ReplayError;
79
92
  export declare function adapterError(reason: Reason<'adapter'>, adapter: AdapterError['adapter'], stage: AdapterError['stage'], attempt: number, source?: AdapterError['source']): AdapterError;
93
+ /** Format an error's family, layer when present, and reason as a rule ID. */
80
94
  export declare function ruleId(error: RequestSealError): string;
81
95
  export {};
@@ -4,6 +4,7 @@ const addError = errors.add.bind(errors), hasError = errors.has.bind(errors);
4
4
  const random = globalThis.crypto.getRandomValues.bind(globalThis.crypto);
5
5
  function correlation() { return Array.from(random(new Uint8Array(8)), b => b.toString(16).padStart(2, '0')).join(''); }
6
6
  function freeze(error) { addError(error); return Object.freeze(error); }
7
+ /** Check whether an error belongs to the private error brand. */
7
8
  export function isRequestSealError(value) { return typeof value === 'object' && value !== null && hasError(value); }
8
9
  function reasonFor(kind, reason) {
9
10
  if (!ERROR_PARITY.some(e => e.kind === kind && e.reason === reason))
@@ -13,13 +14,25 @@ function reasonFor(kind, reason) {
13
14
  const signatureDetails = new Set(['limit', 'wrong_message_kind', 'missing_request_context', 'unavailable_origin', 'unavailable_trailers', 'missing_field', 'non_ascii', 'unknown_field_schema', 'invalid_field_schema', 'invalid_structured_field', 'missing_dictionary_key', 'noncanonical_query_name', 'invalid_query_encoding', 'missing_query_parameter', 'ambiguous_query_parameter']);
14
15
  const agentDetails = new Set(['missing_member', 'unsupported_type', 'not_an_origin', 'untrusted_agent', 'source_mismatch', 'unknown_key', 'revoked_key', 'source_unavailable', 'timeout']);
15
16
  const fieldDetails = new Set(['legacy_string', 'invalid_dictionary', 'duplicate_member', 'invalid_member']);
17
+ // The bounded exception-class vocabulary an internal fault can name: the
18
+ // global error classes, a closed "Error" for any other Error subclass, and
19
+ // "throw" for non-error throws. No message or stack text ever enters a detail.
20
+ const internalDetails = new Set(['TypeError', 'RangeError', 'URIError', 'EvalError', 'ReferenceError', 'SyntaxError', 'Error', 'throw']);
21
+ /** The bounded exception class for an internal-fault detail. */
22
+ export function faultClass(e) {
23
+ if (e instanceof Error) {
24
+ const name = e.constructor?.name;
25
+ return typeof name === "string" && internalDetails.has(name) ? name : "Error";
26
+ }
27
+ return "throw";
28
+ }
16
29
  export function coreError(reason, layer, detail = null, source = null) {
17
30
  if (!ERROR_PARITY.some(e => e.kind === 'core' && e.layer === layer && e.reason === reason))
18
31
  throw new TypeError('Unknown core error pair');
19
32
  if (source !== null && (reason !== 'signing_failed' || !isRequestSealError(source) || source.kind !== 'custody'))
20
33
  throw new TypeError('Invalid core source');
21
- const allowed = reason === 'signature_base_failed' ? signatureDetails : reason === 'agent_unresolved' ? agentDetails : reason === 'invalid_signature_agent' ? fieldDetails : reason === 'nonqualifying_signature' ? new Set(ERROR_PARITY.filter(e => e.kind === 'core').map(e => e.reason)) : new Set();
22
- return freeze({ kind: 'core', reason, layer, correlation: correlation(), retryable: false, source, message: reason === 'signer_algorithm_mismatch' ? 'signer algorithm does not match signature specification' : null, detail: typeof detail === 'string' && allowed.has(detail) ? detail : null });
34
+ const allowed = reason === 'signature_base_failed' ? signatureDetails : reason === 'agent_unresolved' ? agentDetails : reason === 'invalid_signature_agent' ? fieldDetails : reason === 'internal' ? internalDetails : reason === 'nonqualifying_signature' ? new Set(ERROR_PARITY.filter(e => e.kind === 'core').map(e => e.reason)) : new Set();
35
+ return freeze({ kind: 'core', reason, layer, correlation: correlation(), retryable: reason === 'deadline', source, message: reason === 'signer_algorithm_mismatch' ? 'signer algorithm does not match signature specification' : null, detail: typeof detail === 'string' && allowed.has(detail) ? detail : null });
23
36
  }
24
37
  function simple(kind, reason) {
25
38
  return freeze({ kind, reason: reasonFor(kind, reason) });
@@ -58,4 +71,5 @@ export function adapterError(reason, adapter, stage, attempt, source = null) {
58
71
  throw new TypeError('Invalid adapter source');
59
72
  return freeze({ kind: 'adapter', reason, adapter, stage, attempt, source, correlation: correlation(), retryable: false });
60
73
  }
74
+ /** Format an error's family, layer when present, and reason as a rule ID. */
61
75
  export function ruleId(error) { return 'layer' in error ? `${error.kind}/${error.layer}.${error.reason}` : `${error.kind}/${error.reason}`; }
package/dist/index.d.ts CHANGED
@@ -45,3 +45,4 @@ export { verifyQuorum } from './verify-quorum.ts';
45
45
  export { isQuorumVerification } from './quorum/verification.ts';
46
46
  export type { QuorumVerification } from './quorum/verification.ts';
47
47
  export * from './web-bot-auth/index.ts';
48
+ export { Profile, type ProfileStamp, type ProfileMetadataValue, type SignatureDictionaries } from './profile.ts';
package/dist/index.js CHANGED
@@ -33,3 +33,4 @@ export { AcceptSignature, parseAcceptSignature, serializeAcceptSignature, fulfil
33
33
  export { verifyQuorum } from './verify-quorum.js';
34
34
  export { isQuorumVerification } from './quorum/verification.js';
35
35
  export * from './web-bot-auth/index.js';
36
+ export { Profile } from './profile.js';
@@ -1,6 +1,7 @@
1
1
  import { type JsonNode } from "../json.ts";
2
2
  import { type JoseError } from "../errors/types.ts";
3
3
  import { type Result } from "../result.ts";
4
+ /** An ordered JOSE protected-header sequence of JSON members. */
4
5
  export type Header = readonly (readonly [string, JsonNode])[];
5
6
  export declare function fail(reason: JoseError["reason"], layer?: JoseError["layer"]): never;
6
7
  export declare function need(value: unknown, reason: JoseError["reason"], layer?: JoseError["layer"]): asserts value;
@@ -1,6 +1,8 @@
1
1
  import type { Result } from "../result.ts";
2
2
  import { type Header } from "./header.ts";
3
+ /** Check the private brand of an authenticated JWE result. */
3
4
  export declare function isJweResult(value: unknown): value is JweResult;
5
+ /** A branded authenticated JWE result that confines plaintext bytes. */
4
6
  export declare class JweResult {
5
7
  #private;
6
8
  readonly algorithm: string;
@@ -13,12 +15,19 @@ export declare class JweResult {
13
15
  readonly authorization = "not_evaluated";
14
16
  constructor(t: object, algorithm: string, encryption: string, header: Header, protectedPart: string, plaintext: Uint8Array);
15
17
  get plaintext(): Uint8Array<ArrayBuffer>;
18
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
16
19
  toJSON(): unknown;
17
20
  }
21
+ /** Encrypt content into compact JWE using explicit key-management and content algorithms. */
18
22
  export declare function encrypt(protectedPairs: unknown, plaintext: unknown, recipient: unknown, options?: unknown): Promise<Result<string>>;
23
+ /** Authenticate and decrypt compact JWE under an explicit policy. */
19
24
  export declare function decrypt(input: unknown, inputPolicy: unknown, options?: unknown): Promise<Result<JweResult>>;
25
+ /** Compact JWE encryption and authenticated decryption operations. */
20
26
  export declare const JWE: Readonly<{
27
+ /** Encrypt content into compact JWE using explicit key-management and content algorithms. */
21
28
  encrypt: typeof encrypt;
29
+ /** Authenticate and decrypt compact JWE under an explicit policy. */
22
30
  decrypt: typeof decrypt;
31
+ /** Check the private brand of the operation result. */
23
32
  isResult: typeof isJweResult;
24
33
  }>;
package/dist/jose/jwe.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { denoInspection } from "../brand.js";
1
2
  import { encodeJson } from "../json.js";
2
3
  import { encodeUtf8 } from "../runtime.js";
3
4
  import { encodeBase64Url, decodeBase64Url } from "../bytes.js";
@@ -11,9 +12,11 @@ import { bytes, serialize, parse, compact, headerValue, need, } from "./header.j
11
12
  import { JWE_ALGORITHMS, ENCRYPTION, context, policy, resolve, selected, bounded, publicSafe, alive, take, ok, err, } from "./support.js";
12
13
  import { random, wrapPublic } from "./key-management.js";
13
14
  const branded = new WeakSet(), token = Object.freeze({});
15
+ /** Check the private brand of an authenticated JWE result. */
14
16
  export function isJweResult(value) {
15
17
  return typeof value === "object" && value !== null && branded.has(value);
16
18
  }
19
+ /** A branded authenticated JWE result that confines plaintext bytes. */
17
20
  export class JweResult {
18
21
  algorithm;
19
22
  encryption;
@@ -38,6 +41,7 @@ export class JweResult {
38
41
  get plaintext() {
39
42
  return new Uint8Array(this.#plaintext);
40
43
  }
44
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
41
45
  toJSON() {
42
46
  return Object.freeze({
43
47
  algorithm: this.algorithm,
@@ -51,8 +55,8 @@ export class JweResult {
51
55
  [Symbol.for("nodejs.util.inspect.custom")]() {
52
56
  return this.toJSON();
53
57
  }
54
- [Symbol.for("Deno.customInspect")]() {
55
- return this.toJSON();
58
+ [Symbol.for("Deno.customInspect")](render) {
59
+ return denoInspection(render, this.toJSON());
56
60
  }
57
61
  }
58
62
  Object.freeze(JweResult.prototype);
@@ -71,6 +75,7 @@ function encryptedKey(alg, ek, h) {
71
75
  else
72
76
  need(ek.length >= 256 && ek.length <= 1024, "decryption_failed", "crypto");
73
77
  }
78
+ /** Encrypt content into compact JWE using explicit key-management and content algorithms. */
74
79
  export async function encrypt(protectedPairs, plaintext, recipient, options = {}) {
75
80
  return publicSafe(async () => {
76
81
  const c = context(options, 5000, true), data = bytes(plaintext), initial = take(serialize(protectedPairs)), alg = selected(initial.header, JWE_ALGORITHMS, ENCRYPTION), enc = headerValue(initial.header, "enc");
@@ -152,6 +157,7 @@ export async function encrypt(protectedPairs, plaintext, recipient, options = {}
152
157
  }, "signer_failed");
153
158
  });
154
159
  }
160
+ /** Authenticate and decrypt compact JWE under an explicit policy. */
155
161
  export async function decrypt(input, inputPolicy, options = {}) {
156
162
  return publicSafe(async () => {
157
163
  const p = policy(inputPolicy, "jwe"), c = context(options, p.timeout);
@@ -252,4 +258,12 @@ export async function decrypt(input, inputPolicy, options = {}) {
252
258
  }, "decryption_failed");
253
259
  });
254
260
  }
255
- export const JWE = Object.freeze({ encrypt, decrypt, isResult: isJweResult });
261
+ /** Compact JWE encryption and authenticated decryption operations. */
262
+ export const JWE = Object.freeze({
263
+ /** Encrypt content into compact JWE using explicit key-management and content algorithms. */
264
+ encrypt,
265
+ /** Authenticate and decrypt compact JWE under an explicit policy. */
266
+ decrypt,
267
+ /** Check the private brand of the operation result. */
268
+ isResult: isJweResult
269
+ });
@@ -1,6 +1,8 @@
1
1
  import type { Result } from "../result.ts";
2
2
  import { type Header } from "./header.ts";
3
+ /** Check the private brand of a verified JWS result. */
3
4
  export declare function isJwsResult(value: unknown): value is JwsResult;
5
+ /** A branded verified JWS result that confines payload bytes. */
4
6
  export declare class JwsResult {
5
7
  #private;
6
8
  readonly algorithm: string;
@@ -11,14 +13,23 @@ export declare class JwsResult {
11
13
  readonly authorization = "not_evaluated";
12
14
  constructor(t: object, algorithm: string, header: Header, protectedPart: string, payload: Uint8Array);
13
15
  get payload(): Uint8Array<ArrayBuffer>;
16
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
14
17
  toJSON(): unknown;
15
18
  }
19
+ /** Sign a compact JWS with an explicit algorithm and caller-owned signer. */
16
20
  export declare function sign(protectedPairs: unknown, payload: unknown, handle: unknown, options?: unknown): Promise<Result<string>>;
21
+ /** Sign a compact JWS while preserving the supplied protected-header bytes. */
17
22
  export declare function signProtected(protectedBytes: unknown, payload: unknown, handle: unknown, options?: unknown): Promise<Result<string>>;
23
+ /** Verify a compact JWS under an explicit algorithm and key policy. */
18
24
  export declare function verify(input: unknown, inputPolicy: unknown, options?: unknown): Promise<Result<JwsResult>>;
25
+ /** Compact JWS signing and verification operations. */
19
26
  export declare const JWS: Readonly<{
27
+ /** Sign a compact JWS with an explicit algorithm and caller-owned signer. */
20
28
  sign: typeof sign;
29
+ /** Sign a compact JWS while preserving the supplied protected-header bytes. */
21
30
  signProtected: typeof signProtected;
31
+ /** Verify a compact JWS under an explicit algorithm and key policy. */
22
32
  verify: typeof verify;
33
+ /** Check the private brand of the operation result. */
23
34
  isResult: typeof isJwsResult;
24
35
  }>;
package/dist/jose/jws.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { denoInspection } from "../brand.js";
1
2
  import { encodeBase64Url, decodeBase64Url } from "../bytes.js";
2
3
  import { encodeUtf8 } from "../runtime.js";
3
4
  import { isKeyHandle } from "../key_handle.js";
@@ -10,9 +11,11 @@ import { joseError, isRequestSealError } from "../errors/types.js";
10
11
  import { bytes, json, serialize, parse, compact, need, } from "./header.js";
11
12
  import { JWS_ALGORITHMS, context, policy, resolve, selected, bounded, publicSafe, alive, take, ok, err, } from "./support.js";
12
13
  const branded = new WeakSet(), token = Object.freeze({});
14
+ /** Check the private brand of a verified JWS result. */
13
15
  export function isJwsResult(value) {
14
16
  return typeof value === "object" && value !== null && branded.has(value);
15
17
  }
18
+ /** A branded verified JWS result that confines payload bytes. */
16
19
  export class JwsResult {
17
20
  algorithm;
18
21
  header;
@@ -34,6 +37,7 @@ export class JwsResult {
34
37
  get payload() {
35
38
  return new Uint8Array(this.#payload);
36
39
  }
40
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
37
41
  toJSON() {
38
42
  return Object.freeze({
39
43
  algorithm: this.algorithm,
@@ -45,8 +49,8 @@ export class JwsResult {
45
49
  [Symbol.for("nodejs.util.inspect.custom")]() {
46
50
  return this.toJSON();
47
51
  }
48
- [Symbol.for("Deno.customInspect")]() {
49
- return this.toJSON();
52
+ [Symbol.for("Deno.customInspect")](render) {
53
+ return denoInspection(render, this.toJSON());
50
54
  }
51
55
  }
52
56
  Object.freeze(JwsResult.prototype);
@@ -106,6 +110,7 @@ async function signing(protectedPart, h, payload, handle, c) {
106
110
  data.fill(0);
107
111
  }
108
112
  }
113
+ /** Sign a compact JWS with an explicit algorithm and caller-owned signer. */
109
114
  export async function sign(protectedPairs, payload, handle, options = {}) {
110
115
  return publicSafe(async () => {
111
116
  const c = context(options, 5000, true);
@@ -120,6 +125,7 @@ export async function sign(protectedPairs, payload, handle, options = {}) {
120
125
  }
121
126
  });
122
127
  }
128
+ /** Sign a compact JWS while preserving the supplied protected-header bytes. */
123
129
  export async function signProtected(protectedBytes, payload, handle, options = {}) {
124
130
  return publicSafe(async () => {
125
131
  const c = context(options, 5000, true);
@@ -134,6 +140,7 @@ export async function signProtected(protectedBytes, payload, handle, options = {
134
140
  }
135
141
  });
136
142
  }
143
+ /** Verify a compact JWS under an explicit algorithm and key policy. */
137
144
  export async function verify(input, inputPolicy, options = {}) {
138
145
  return publicSafe(async () => {
139
146
  const p = policy(inputPolicy, "jws"), c = context(options, p.timeout);
@@ -183,9 +190,14 @@ export async function verify(input, inputPolicy, options = {}) {
183
190
  }, "invalid_signature");
184
191
  });
185
192
  }
193
+ /** Compact JWS signing and verification operations. */
186
194
  export const JWS = Object.freeze({
195
+ /** Sign a compact JWS with an explicit algorithm and caller-owned signer. */
187
196
  sign,
197
+ /** Sign a compact JWS while preserving the supplied protected-header bytes. */
188
198
  signProtected,
199
+ /** Verify a compact JWS under an explicit algorithm and key policy. */
189
200
  verify,
201
+ /** Check the private brand of the operation result. */
190
202
  isResult: isJwsResult,
191
203
  });
@@ -4,10 +4,12 @@ import { type PublicKey } from "../public_key.ts";
4
4
  import { type KeyHandle } from "../key_handle.ts";
5
5
  import { type Result } from "../result.ts";
6
6
  import { type Header } from "./header.ts";
7
+ /** Owned encrypted-key and content-encryption-key bytes from key wrapping. */
7
8
  export type WrapResult = Readonly<{
8
9
  encrypted_key: Uint8Array<ArrayBuffer>;
9
10
  header: Header;
10
11
  }>;
12
+ /** Check the private brand of a JOSE key-management handle. */
11
13
  export declare function isKeyManagementHandle(value: unknown): value is KeyManagementHandle;
12
14
  /** Caller-owned custodian primitives. RSA private and AES keys never escape as
13
15
  * CryptoKey references. Primitive decrypt releases bytes only after authentication. */
@@ -15,16 +17,25 @@ export declare class KeyManagementHandle {
15
17
  #private;
16
18
  readonly algorithm: string;
17
19
  private constructor();
20
+ /** Import caller-owned local key material into a confined capability. */
18
21
  static local(algorithm: unknown, material: unknown): Promise<Result<KeyManagementHandle>>;
22
+ /** Wrap a generated content-encryption key with the bound key-management algorithm. */
19
23
  wrap(algorithm: unknown, content: unknown, context?: Context): Promise<Result<WrapResult>>;
24
+ /** Authenticate and decrypt content using the bound direct-encryption key. */
20
25
  decrypt(encryptedKey: unknown, header: Header, context?: Context): Promise<Result<Uint8Array<ArrayBuffer>>>;
26
+ /** Confine an unwrapped content-encryption key in a decryption capability. */
21
27
  unwrap(encryptedKey: unknown, header: Header, context?: Context): Promise<Result<UnwrappedKey>>;
28
+ /** Release retained key-management custody and invalidate the capability. */
22
29
  release(): Promise<Result<true>>;
30
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
23
31
  toJSON(): unknown;
24
32
  }
25
33
  export declare function random(length: number): Uint8Array<ArrayBuffer>;
26
34
  export declare function wrapPublic(key: PublicKey | KeyHandle, algorithm: string, content: Uint8Array, context: Context): Promise<Result<WrapResult>>;
35
+ /** Constructors and branding checks for JOSE key-management capabilities. */
27
36
  export declare const KeyManagement: Readonly<{
37
+ /** Import caller-owned local key material into a confined capability. */
28
38
  local: typeof KeyManagementHandle.local;
39
+ /** Check the private brand of a key-management capability. */
29
40
  isHandle: typeof isKeyManagementHandle;
30
41
  }>;
@@ -1,3 +1,4 @@
1
+ import { denoInspection } from "../brand.js";
1
2
  import { now } from "../runtime.js";
2
3
  import { isContext, withDeadline } from "../context.js";
3
4
  import { Custody } from "../custody/index.js";
@@ -14,6 +15,7 @@ import { resolveAlgorithm, importParameters } from "../crypto/algorithm.js";
14
15
  import { bytes, headerValue, need, take } from "./header.js";
15
16
  import { bounded, publicSafe, alive, JWE_ALGORITHMS } from "./support.js";
16
17
  const branded = new WeakSet(), token = Object.freeze({});
18
+ /** Check the private brand of a JOSE key-management handle. */
17
19
  export function isKeyManagementHandle(value) {
18
20
  return typeof value === "object" && value !== null && branded.has(value);
19
21
  }
@@ -32,6 +34,7 @@ export class KeyManagementHandle {
32
34
  branded.add(this);
33
35
  Object.freeze(this);
34
36
  }
37
+ /** Import caller-owned local key material into a confined capability. */
35
38
  static async local(algorithm, material) {
36
39
  return publicSafe(async () => {
37
40
  need(typeof algorithm === "string" && JWE_ALGORITHMS.includes(algorithm), "algorithm_not_permitted");
@@ -96,6 +99,7 @@ export class KeyManagementHandle {
96
99
  }
97
100
  });
98
101
  }
102
+ /** Wrap a generated content-encryption key with the bound key-management algorithm. */
99
103
  async wrap(algorithm, content, context) {
100
104
  return publicSafe(async () => {
101
105
  need(algorithm === this.algorithm && this.algorithm.endsWith("GCMKW"), "algorithm_mismatch", "key");
@@ -128,6 +132,7 @@ export class KeyManagementHandle {
128
132
  }, "signer_failed");
129
133
  });
130
134
  }
135
+ /** Authenticate and decrypt content using the bound direct-encryption key. */
131
136
  async decrypt(encryptedKey, header, context) {
132
137
  return publicSafe(async () => {
133
138
  const c = context === undefined ? take(withDeadline()) : context;
@@ -170,6 +175,7 @@ export class KeyManagementHandle {
170
175
  }, "decryption_failed");
171
176
  });
172
177
  }
178
+ /** Confine an unwrapped content-encryption key in a decryption capability. */
173
179
  async unwrap(encryptedKey, header, context) {
174
180
  return publicSafe(async () => {
175
181
  const c = context === undefined ? take(withDeadline()) : context;
@@ -214,10 +220,12 @@ export class KeyManagementHandle {
214
220
  }, "decryption_failed");
215
221
  });
216
222
  }
223
+ /** Release retained key-management custody and invalidate the capability. */
217
224
  async release() {
218
225
  this.#key = undefined;
219
226
  return ok(true);
220
227
  }
228
+ /** Return a bounded public inspection view without retained cryptographic bytes. */
221
229
  toJSON() {
222
230
  return Object.freeze({
223
231
  kind: "KeyManagementHandle",
@@ -227,8 +235,8 @@ export class KeyManagementHandle {
227
235
  [Symbol.for("nodejs.util.inspect.custom")]() {
228
236
  return this.toJSON();
229
237
  }
230
- [Symbol.for("Deno.customInspect")]() {
231
- return this.toJSON();
238
+ [Symbol.for("Deno.customInspect")](render) {
239
+ return denoInspection(render, this.toJSON());
232
240
  }
233
241
  }
234
242
  Object.freeze(KeyManagementHandle.prototype);
@@ -259,7 +267,10 @@ export async function wrapPublic(key, algorithm, content, context) {
259
267
  return ok(Object.freeze({ encrypted_key: encrypted, header: Object.freeze([]) }));
260
268
  }, "signer_failed");
261
269
  }
270
+ /** Constructors and branding checks for JOSE key-management capabilities. */
262
271
  export const KeyManagement = Object.freeze({
272
+ /** Import caller-owned local key material into a confined capability. */
263
273
  local: KeyManagementHandle.local,
274
+ /** Check the private brand of a key-management capability. */
264
275
  isHandle: isKeyManagementHandle,
265
276
  });
@@ -1,14 +1,20 @@
1
1
  import { type Result } from "../result.ts";
2
2
  import { type JweResult } from "./jwe.ts";
3
3
  import { type JwsResult } from "./jws.ts";
4
+ /** A branded pair of authenticated outer JWE and verified inner JWS results. */
4
5
  export type NestedResult = Readonly<{
5
6
  jwe: JweResult;
6
7
  jws: JwsResult;
7
8
  }>;
9
+ /** Check the private brand of a nested JOSE result. */
8
10
  export declare function isNestedResult(value: unknown): value is NestedResult;
9
11
  export declare function innerCompact(input: Uint8Array): Result<readonly string[]>;
12
+ /** Authenticate an outer JWE and verify its inner compact JWS. */
10
13
  export declare function decrypt(input: unknown, policy: unknown, options: unknown): Promise<Result<NestedResult>>;
14
+ /** One-level nested JWE decryption and JWS verification operations. */
11
15
  export declare const Nested: Readonly<{
16
+ /** Authenticate an outer JWE and verify its inner compact JWS. */
12
17
  decrypt: typeof decrypt;
18
+ /** Check the private brand of the operation result. */
13
19
  isResult: typeof isNestedResult;
14
20
  }>;