@moqtap/codec 0.9.0 → 0.11.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 (232) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/dist/auth-redaction-DsdLq4Qs.d.cts +102 -0
  3. package/dist/auth-redaction-DsdLq4Qs.d.ts +102 -0
  4. package/dist/{chunk-PU2KV7VP.cjs → chunk-27K5BUAG.cjs} +485 -515
  5. package/dist/{chunk-BV6MITLO.js → chunk-3RNQMGKA.js} +365 -390
  6. package/dist/{chunk-2XH6PHXR.js → chunk-5AWIXOLB.js} +442 -467
  7. package/dist/{chunk-4XLYCT5Q.cjs → chunk-5IMHJIAZ.cjs} +52 -2
  8. package/dist/{chunk-TVSFDQYE.cjs → chunk-5JGZCKJO.cjs} +513 -531
  9. package/dist/{chunk-IADVBKEJ.cjs → chunk-73K4OSAN.cjs} +407 -432
  10. package/dist/{chunk-N2V7Z37J.js → chunk-7VQKRGRD.js} +19 -3
  11. package/dist/{chunk-UZO5Z2XT.cjs → chunk-A3UCQOIB.cjs} +490 -515
  12. package/dist/{chunk-JKMYAUGY.js → chunk-A7PDMVXM.js} +35 -11
  13. package/dist/{chunk-VZHL2U2N.cjs → chunk-A7VQO6YC.cjs} +54 -38
  14. package/dist/{chunk-KCH4BQXK.cjs → chunk-ACQHZLRZ.cjs} +73 -47
  15. package/dist/{chunk-H6DTAIWM.js → chunk-BBICOMW6.js} +47 -19
  16. package/dist/{chunk-MAXEHYVB.cjs → chunk-BNIUVOCJ.cjs} +554 -612
  17. package/dist/{chunk-QGIHC6BA.cjs → chunk-CNC6ANS4.cjs} +70 -46
  18. package/dist/{chunk-NH4L6NIY.js → chunk-FDLQSWHK.js} +437 -467
  19. package/dist/{chunk-IJAF6PAY.js → chunk-FFNOE4UR.js} +19 -3
  20. package/dist/{chunk-CZNW3R5E.cjs → chunk-GMENT63T.cjs} +54 -38
  21. package/dist/{chunk-7ENEWAMZ.cjs → chunk-HM7BLRVP.cjs} +305 -305
  22. package/dist/{chunk-XHAP2YST.js → chunk-HZONHFNO.js} +19 -3
  23. package/dist/{chunk-EVCPBFSR.cjs → chunk-ILYABWDK.cjs} +83 -55
  24. package/dist/{chunk-IDV2JYJ6.cjs → chunk-KRSFTZVO.cjs} +56 -40
  25. package/dist/{chunk-RIIA4ALQ.cjs → chunk-KSPH6KMH.cjs} +54 -38
  26. package/dist/{chunk-UA5XFP4O.cjs → chunk-KTY4LAUV.cjs} +485 -494
  27. package/dist/{chunk-RZTLQAKF.js → chunk-OJNLJT5D.js} +0 -1
  28. package/dist/{chunk-YJGOD3Y4.js → chunk-PJK2ZS3I.js} +492 -550
  29. package/dist/{chunk-TMXRYOBS.js → chunk-PSMZKHOC.js} +444 -453
  30. package/dist/{chunk-7RE6KSIY.cjs → chunk-Q5JQGHWY.cjs} +0 -1
  31. package/dist/{chunk-23KRITJ6.js → chunk-SQTUQY5E.js} +37 -11
  32. package/dist/{chunk-XQGEOFGE.js → chunk-WCRLAKDW.js} +253 -253
  33. package/dist/{chunk-KYVTM5VI.js → chunk-WL2YUEXH.js} +19 -3
  34. package/dist/{chunk-Q7NSUXXB.js → chunk-YCNIVZS7.js} +464 -482
  35. package/dist/{chunk-KLPWJU6W.js → chunk-YRZQVNZO.js} +50 -0
  36. package/dist/{codec-Bym-K2q2.d.cts → codec-76xzrLTL.d.cts} +21 -2
  37. package/dist/{codec-BKsVu3Fr.d.ts → codec-8p40WdLg.d.ts} +21 -2
  38. package/dist/{codec-Dl_QIXMz.d.ts → codec-BN2Bu0KI.d.ts} +20 -1
  39. package/dist/{codec-D4RvFQmu.d.ts → codec-Bb6GKTrv.d.ts} +21 -2
  40. package/dist/{codec-DAyiF5sq.d.cts → codec-BgpfHoAd.d.cts} +21 -2
  41. package/dist/{codec-CA6nbbEk.d.ts → codec-BkheTXO7.d.ts} +21 -2
  42. package/dist/{codec-DchsPfr3.d.cts → codec-BwVDkokh.d.cts} +21 -2
  43. package/dist/{codec-CgZdadPt.d.cts → codec-C5s1eBJX.d.cts} +21 -2
  44. package/dist/codec-CM5yd6n3.d.ts +38 -0
  45. package/dist/{codec-DJmqoIsp.d.cts → codec-Cb8HC3XV.d.cts} +21 -2
  46. package/dist/codec-Clu_skx8.d.cts +38 -0
  47. package/dist/{codec-DzkdW4kO.d.cts → codec-CpOpemR8.d.cts} +20 -1
  48. package/dist/{codec-CXCjya_G.d.cts → codec-Cshdl9Tt.d.cts} +20 -1
  49. package/dist/{codec-CSBFdPgP.d.cts → codec-DELe00w_.d.cts} +21 -2
  50. package/dist/{codec-C_xxsbKy.d.cts → codec-DHzKAUCa.d.cts} +21 -2
  51. package/dist/{codec--CVeqGQv.d.ts → codec-DdVBtvx7.d.ts} +20 -1
  52. package/dist/{codec-CviAa4lp.d.ts → codec-DlxGuYMv.d.ts} +21 -2
  53. package/dist/{codec-BNy5syCU.d.ts → codec-DxtgPxJS.d.ts} +20 -1
  54. package/dist/{codec-CtvFK4aV.d.cts → codec-GAY4lybi.d.cts} +21 -2
  55. package/dist/{codec-Cfo_z5ET.d.cts → codec-I8u2pfS4.d.cts} +20 -1
  56. package/dist/{codec-vddqy0KY.d.cts → codec-XLrnreeu.d.cts} +21 -2
  57. package/dist/{codec-O-1Js7h4.d.ts → codec-c0YEwwWn.d.ts} +21 -2
  58. package/dist/{codec-Cl73EfRW.d.ts → codec-ejDu-va6.d.ts} +21 -2
  59. package/dist/{codec-C006F75E.d.ts → codec-kaBUzdpV.d.ts} +21 -2
  60. package/dist/{codec-C5evFHL-.d.ts → codec-mVYqkIUF.d.ts} +21 -2
  61. package/dist/{codec-BMwgZIgG.d.ts → codec-qSbO5nOa.d.ts} +21 -2
  62. package/dist/{codec-BQa6Qsav.d.ts → codec-yYKGOipj.d.ts} +21 -2
  63. package/dist/{codec-DzLvG8Wb.d.cts → codec-zfzg9uiy.d.cts} +21 -2
  64. package/dist/draft07.cjs +48 -4
  65. package/dist/draft07.d.cts +42 -2
  66. package/dist/draft07.d.ts +42 -2
  67. package/dist/draft07.js +49 -5
  68. package/dist/draft08.cjs +76 -3
  69. package/dist/draft08.d.cts +70 -2
  70. package/dist/draft08.d.ts +70 -2
  71. package/dist/draft08.js +77 -4
  72. package/dist/draft09.cjs +76 -3
  73. package/dist/draft09.d.cts +70 -2
  74. package/dist/draft09.d.ts +70 -2
  75. package/dist/draft09.js +77 -4
  76. package/dist/draft10.cjs +76 -3
  77. package/dist/draft10.d.cts +70 -2
  78. package/dist/draft10.d.ts +70 -2
  79. package/dist/draft10.js +77 -4
  80. package/dist/draft11-session.d.cts +1 -1
  81. package/dist/draft11-session.d.ts +1 -1
  82. package/dist/draft11.cjs +104 -3
  83. package/dist/draft11.d.cts +100 -4
  84. package/dist/draft11.d.ts +100 -4
  85. package/dist/draft11.js +105 -4
  86. package/dist/draft12-session.d.cts +1 -1
  87. package/dist/draft12-session.d.ts +1 -1
  88. package/dist/draft12.cjs +113 -3
  89. package/dist/draft12.d.cts +109 -4
  90. package/dist/draft12.d.ts +109 -4
  91. package/dist/draft12.js +114 -4
  92. package/dist/draft13-session.d.cts +1 -1
  93. package/dist/draft13-session.d.ts +1 -1
  94. package/dist/draft13.cjs +105 -3
  95. package/dist/draft13.d.cts +101 -4
  96. package/dist/draft13.d.ts +101 -4
  97. package/dist/draft13.js +106 -4
  98. package/dist/draft14-session.d.cts +1 -1
  99. package/dist/draft14-session.d.ts +1 -1
  100. package/dist/draft14.cjs +107 -3
  101. package/dist/draft14.d.cts +103 -30
  102. package/dist/draft14.d.ts +103 -30
  103. package/dist/draft14.js +108 -4
  104. package/dist/draft15-session.d.cts +1 -1
  105. package/dist/draft15-session.d.ts +1 -1
  106. package/dist/draft15.cjs +69 -3
  107. package/dist/draft15.d.cts +65 -22
  108. package/dist/draft15.d.ts +65 -22
  109. package/dist/draft15.js +70 -4
  110. package/dist/draft16-session.cjs +2 -2
  111. package/dist/draft16-session.d.cts +1 -1
  112. package/dist/draft16-session.d.ts +1 -1
  113. package/dist/draft16-session.js +1 -1
  114. package/dist/draft16.cjs +76 -8
  115. package/dist/draft16.d.cts +67 -13
  116. package/dist/draft16.d.ts +67 -13
  117. package/dist/draft16.js +73 -5
  118. package/dist/draft17-session.d.cts +1 -1
  119. package/dist/draft17-session.d.ts +1 -1
  120. package/dist/draft17.cjs +77 -3
  121. package/dist/draft17.d.cts +73 -4
  122. package/dist/draft17.d.ts +73 -4
  123. package/dist/draft17.js +78 -4
  124. package/dist/draft18-session.d.cts +1 -1
  125. package/dist/draft18-session.d.ts +1 -1
  126. package/dist/draft18.cjs +8 -3
  127. package/dist/draft18.d.cts +4 -3
  128. package/dist/draft18.d.ts +4 -3
  129. package/dist/draft18.js +9 -4
  130. package/dist/draft19-session.d.cts +1 -1
  131. package/dist/draft19-session.d.ts +1 -1
  132. package/dist/draft19.cjs +11 -4
  133. package/dist/draft19.d.cts +4 -3
  134. package/dist/draft19.d.ts +4 -3
  135. package/dist/draft19.js +12 -5
  136. package/dist/draft20-session.d.cts +1 -1
  137. package/dist/draft20-session.d.ts +1 -1
  138. package/dist/draft20.cjs +8 -3
  139. package/dist/draft20.d.cts +4 -3
  140. package/dist/draft20.d.ts +4 -3
  141. package/dist/draft20.js +9 -4
  142. package/dist/index.cjs +30 -30
  143. package/dist/index.d.cts +25 -24
  144. package/dist/index.d.ts +25 -24
  145. package/dist/index.js +15 -15
  146. package/dist/session.cjs +2 -2
  147. package/dist/session.d.cts +10 -10
  148. package/dist/session.d.ts +10 -10
  149. package/dist/session.js +1 -1
  150. package/dist/{types-zHgCS6o5.d.cts → types-Btp416jt.d.cts} +15 -7
  151. package/dist/{types-zHgCS6o5.d.ts → types-Btp416jt.d.ts} +15 -7
  152. package/dist/{types-Cm9fjeYC.d.cts → types-BxTL1NXw.d.cts} +9 -2
  153. package/dist/{types-Cm9fjeYC.d.ts → types-BxTL1NXw.d.ts} +9 -2
  154. package/dist/{types-Bio-91Rt.d.cts → types-CI_SX4Xe.d.cts} +2 -2
  155. package/dist/{types-Bio-91Rt.d.ts → types-CI_SX4Xe.d.ts} +2 -2
  156. package/dist/{types-HI_bbXka.d.cts → types-CmqT0jUf.d.cts} +1 -1
  157. package/dist/{types-HI_bbXka.d.ts → types-CmqT0jUf.d.ts} +1 -1
  158. package/dist/{types-CPaYBsMG.d.cts → types-CuibHYcf.d.cts} +9 -2
  159. package/dist/{types-CPaYBsMG.d.ts → types-CuibHYcf.d.ts} +9 -2
  160. package/dist/{types-CWCQwuvy.d.cts → types-CwN7AEoL.d.cts} +24 -12
  161. package/dist/{types-CWCQwuvy.d.ts → types-CwN7AEoL.d.ts} +24 -12
  162. package/dist/{types-Ck45Ex5S.d.cts → types-D0kTgUuL.d.cts} +1 -1
  163. package/dist/{types-Ck45Ex5S.d.ts → types-D0kTgUuL.d.ts} +1 -1
  164. package/dist/{types-D9eiB_9A.d.cts → types-DAnalt5K.d.cts} +9 -2
  165. package/dist/{types-D9eiB_9A.d.ts → types-DAnalt5K.d.ts} +9 -2
  166. package/dist/{types-CXlSn0I9.d.cts → types-DjxexghA.d.cts} +2 -2
  167. package/dist/{types-CXlSn0I9.d.ts → types-DjxexghA.d.ts} +2 -2
  168. package/dist/{types-Cqp10JtB.d.cts → types-DxXNP32l.d.cts} +10 -2
  169. package/dist/{types-Cqp10JtB.d.ts → types-DxXNP32l.d.ts} +10 -2
  170. package/package.json +3 -3
  171. package/src/core/auth-redaction.ts +192 -0
  172. package/src/drafts/draft07/codec.ts +40 -0
  173. package/src/drafts/draft07/error-codes.ts +44 -0
  174. package/src/drafts/draft07/index.ts +15 -0
  175. package/src/drafts/draft08/codec.ts +40 -0
  176. package/src/drafts/draft08/error-codes.ts +76 -0
  177. package/src/drafts/draft08/index.ts +21 -0
  178. package/src/drafts/draft09/codec.ts +40 -0
  179. package/src/drafts/draft09/error-codes.ts +76 -0
  180. package/src/drafts/draft09/index.ts +21 -0
  181. package/src/drafts/draft10/codec.ts +40 -0
  182. package/src/drafts/draft10/error-codes.ts +76 -0
  183. package/src/drafts/draft10/index.ts +21 -0
  184. package/src/drafts/draft11/codec.ts +71 -8
  185. package/src/drafts/draft11/error-codes.ts +106 -0
  186. package/src/drafts/draft11/index.ts +23 -0
  187. package/src/drafts/draft11/types.ts +1 -1
  188. package/src/drafts/draft12/codec.ts +83 -16
  189. package/src/drafts/draft12/error-codes.ts +116 -0
  190. package/src/drafts/draft12/index.ts +25 -0
  191. package/src/drafts/draft12/types.ts +2 -2
  192. package/src/drafts/draft13/codec.ts +75 -11
  193. package/src/drafts/draft13/error-codes.ts +107 -0
  194. package/src/drafts/draft13/index.ts +23 -0
  195. package/src/drafts/draft13/types.ts +3 -3
  196. package/src/drafts/draft14/codec.ts +79 -12
  197. package/src/drafts/draft14/data-streams.ts +331 -259
  198. package/src/drafts/draft14/error-codes.ts +109 -0
  199. package/src/drafts/draft14/index.ts +23 -0
  200. package/src/drafts/draft14/types.ts +1 -1
  201. package/src/drafts/draft15/codec.ts +71 -8
  202. package/src/drafts/draft15/data-streams.ts +489 -444
  203. package/src/drafts/draft15/error-codes.ts +66 -0
  204. package/src/drafts/draft15/index.ts +15 -0
  205. package/src/drafts/draft15/types.ts +9 -2
  206. package/src/drafts/draft16/codec.ts +149 -49
  207. package/src/drafts/draft16/data-streams.ts +513 -442
  208. package/src/drafts/draft16/error-codes.ts +68 -0
  209. package/src/drafts/draft16/index.ts +15 -0
  210. package/src/drafts/draft16/messages.ts +4 -4
  211. package/src/drafts/draft16/session-fsm.ts +0 -1
  212. package/src/drafts/draft16/types.ts +24 -10
  213. package/src/drafts/draft17/codec.ts +77 -10
  214. package/src/drafts/draft17/data-streams.ts +567 -488
  215. package/src/drafts/draft17/index.ts +15 -0
  216. package/src/drafts/draft17/types.ts +9 -2
  217. package/src/drafts/draft18/codec.ts +70 -7
  218. package/src/drafts/draft18/data-streams.ts +570 -482
  219. package/src/drafts/draft18/index.ts +3 -0
  220. package/src/drafts/draft18/types.ts +18 -10
  221. package/src/drafts/draft19/codec.ts +95 -23
  222. package/src/drafts/draft19/data-streams.ts +570 -482
  223. package/src/drafts/draft19/error-codes.ts +3 -1
  224. package/src/drafts/draft19/index.ts +3 -0
  225. package/src/drafts/draft19/messages.ts +3 -1
  226. package/src/drafts/draft19/types.ts +32 -18
  227. package/src/drafts/draft20/codec.ts +115 -36
  228. package/src/drafts/draft20/data-streams.ts +610 -563
  229. package/src/drafts/draft20/index.ts +3 -0
  230. package/src/drafts/draft20/types.ts +31 -13
  231. package/dist/codec-BJ7BHuiZ.d.ts +0 -18
  232. package/dist/codec-C6Mx4bwz.d.cts +0 -18
@@ -1,3 +1,4 @@
1
+ import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
1
2
  import { BufferReader } from '../../core/buffer-reader.js'
2
3
  import { BufferWriter } from '../../core/buffer-writer.js'
3
4
  import { bytesToHex, hexToBytes } from '../../core/hex.js'
@@ -213,6 +214,11 @@ function decodeParams(r: BufferReader): Draft07Params {
213
214
 
214
215
  if (paramType === PARAM_AUTHORIZATION_INFO) {
215
216
  const bytes = r.readBytes(length)
217
+ // The credential is the whole value in this draft: a bare UTF-8 string,
218
+ // with no alias and no token type around it. What survives the overwrite
219
+ // is the parameter's presence, which is what says authorization was
220
+ // attempted at all.
221
+ recordAuthValueSpan(r.offset - length, length)
216
222
  result.authorization_info = textDecoder.decode(bytes)
217
223
  } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
218
224
  const blob = r.readBytes(length)
@@ -1056,3 +1062,37 @@ export function createDraft07Codec(): Draft07Codec {
1056
1062
 
1057
1063
  // Export data-stream decoder map for callers that need to disambiguate
1058
1064
  export { dataStreamDecoders }
1065
+
1066
+ /**
1067
+ * Overwrite every AUTHORIZATION_INFO value in a draft-07 control frame.
1068
+ *
1069
+ * One decode, whose *output is discarded*: the point is not to read the
1070
+ * message, it is to learn where the credentials were so the caller never has to
1071
+ * hold a frame that contains one. A caller that also wants the message should
1072
+ * decode the **redacted** frame with {@link decodeMessage}, which then cannot
1073
+ * produce a value because there is no longer one in the bytes.
1074
+ *
1075
+ * A frame that fails to decode is still redacted as far as the decode got. That
1076
+ * is the useful direction to fail in: a value that was read is a value that was
1077
+ * exposed, whatever went wrong after it.
1078
+ *
1079
+ * See {@link AuthRedaction.incomplete} for the one result a caller must not
1080
+ * treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
1081
+ * close.
1082
+ */
1083
+ export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
1084
+ let payloadStart: number
1085
+ try {
1086
+ const probe = new BufferReader(bytes)
1087
+ probe.readVarInt()
1088
+ probe.readVarInt()
1089
+ payloadStart = probe.offset
1090
+ } catch {
1091
+ // Too short to carry a message header, and so too short for the parameters
1092
+ // that carry a credential. Reported as not decoded rather than as clean: a
1093
+ // framer only ever emits complete frames, so a caller that gets here is
1094
+ // holding something this function did not check.
1095
+ return { bytes, redacted: 0, incomplete: false, decoded: false }
1096
+ }
1097
+ return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
1098
+ }
@@ -0,0 +1,44 @@
1
+ // Draft-07 error, status and termination code registries.
2
+
3
+ export const SessionErrorCode = {
4
+ NoError: 0x0n,
5
+ InternalError: 0x1n,
6
+ Unauthorized: 0x2n,
7
+ ProtocolViolation: 0x3n,
8
+ DuplicateTrackAlias: 0x4n,
9
+ ParameterLengthMismatch: 0x5n,
10
+ TooManySubscribes: 0x6n,
11
+ GoawayTimeout: 0x10n,
12
+ } as const
13
+ export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
14
+
15
+ export const SubscribeErrorCode = {
16
+ InternalError: 0x0n,
17
+ InvalidRange: 0x1n,
18
+ RetryTrackAlias: 0x2n,
19
+ TrackDoesNotExist: 0x3n,
20
+ Unauthorized: 0x4n,
21
+ Timeout: 0x5n,
22
+ } as const
23
+ export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
24
+
25
+ export const SubscribeDoneStatusCode = {
26
+ Unsubscribed: 0x0n,
27
+ InternalError: 0x1n,
28
+ Unauthorized: 0x2n,
29
+ TrackEnded: 0x3n,
30
+ SubscriptionEnded: 0x4n,
31
+ GoingAway: 0x5n,
32
+ Expired: 0x6n,
33
+ } as const
34
+ export type SubscribeDoneStatusCodeValue =
35
+ (typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
36
+
37
+ export const TrackStatusCode = {
38
+ InProgress: 0x00n,
39
+ TrackDoesNotExist: 0x01n,
40
+ NotYetBegun: 0x02n,
41
+ Finished: 0x03n,
42
+ RelayStatusUnavailable: 0x04n,
43
+ } as const
44
+ export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
@@ -1,5 +1,7 @@
1
1
  export const DRAFT_VERSION = 0xff000007n
2
2
 
3
+ export type { AuthRedaction } from '../../core/auth-redaction.js'
4
+ export { REDACTION_FILL } from '../../core/auth-redaction.js'
3
5
  export type { DecodeErrorCode, DecodeResult } from '../../core/types.js'
4
6
  // Re-export types consumers need
5
7
  export { DecodeError } from '../../core/types.js'
@@ -12,7 +14,20 @@ export {
12
14
  encodeDatagram,
13
15
  encodeFetchStream,
14
16
  encodeSubgroupStream,
17
+ redactAuthTokens,
15
18
  } from './codec.js'
19
+ export type {
20
+ SessionErrorCodeValue,
21
+ SubscribeDoneStatusCodeValue,
22
+ SubscribeErrorCodeValue,
23
+ TrackStatusCodeValue,
24
+ } from './error-codes.js'
25
+ export {
26
+ SessionErrorCode,
27
+ SubscribeDoneStatusCode,
28
+ SubscribeErrorCode,
29
+ TrackStatusCode,
30
+ } from './error-codes.js'
16
31
  export {
17
32
  MESSAGE_ID_MAP,
18
33
  MESSAGE_TYPE_MAP,
@@ -1,3 +1,4 @@
1
+ import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
1
2
  import { BufferReader } from '../../core/buffer-reader.js'
2
3
  import { BufferWriter } from '../../core/buffer-writer.js'
3
4
  import { bytesToHex, hexToBytes } from '../../core/hex.js'
@@ -183,6 +184,11 @@ function decodeParams(r: BufferReader): Draft08Params {
183
184
 
184
185
  if (paramType === PARAM_AUTHORIZATION_INFO) {
185
186
  const bytes = r.readBytes(length)
187
+ // The credential is the whole value in this draft: a bare UTF-8 string,
188
+ // with no alias and no token type around it. What survives the overwrite
189
+ // is the parameter's presence, which is what says authorization was
190
+ // attempted at all.
191
+ recordAuthValueSpan(r.offset - length, length)
186
192
  result.authorization_info = textDecoder.decode(bytes)
187
193
  } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
188
194
  const blob = r.readBytes(length)
@@ -983,3 +989,37 @@ export function createDraft08Codec(): Draft08Codec {
983
989
  createStreamDecoder,
984
990
  }
985
991
  }
992
+
993
+ /**
994
+ * Overwrite every AUTHORIZATION_INFO value in a draft-08 control frame.
995
+ *
996
+ * One decode, whose *output is discarded*: the point is not to read the
997
+ * message, it is to learn where the credentials were so the caller never has to
998
+ * hold a frame that contains one. A caller that also wants the message should
999
+ * decode the **redacted** frame with {@link decodeMessage}, which then cannot
1000
+ * produce a value because there is no longer one in the bytes.
1001
+ *
1002
+ * A frame that fails to decode is still redacted as far as the decode got. That
1003
+ * is the useful direction to fail in: a value that was read is a value that was
1004
+ * exposed, whatever went wrong after it.
1005
+ *
1006
+ * See {@link AuthRedaction.incomplete} for the one result a caller must not
1007
+ * treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
1008
+ * close.
1009
+ */
1010
+ export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
1011
+ let payloadStart: number
1012
+ try {
1013
+ const probe = new BufferReader(bytes)
1014
+ probe.readVarInt()
1015
+ probe.readVarInt()
1016
+ payloadStart = probe.offset
1017
+ } catch {
1018
+ // Too short to carry a message header, and so too short for the parameters
1019
+ // that carry a credential. Reported as not decoded rather than as clean: a
1020
+ // framer only ever emits complete frames, so a caller that gets here is
1021
+ // holding something this function did not check.
1022
+ return { bytes, redacted: 0, incomplete: false, decoded: false }
1023
+ }
1024
+ return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
1025
+ }
@@ -0,0 +1,76 @@
1
+ // Draft-08 error, status and termination code registries.
2
+
3
+ export const SessionErrorCode = {
4
+ NoError: 0x0n,
5
+ InternalError: 0x1n,
6
+ Unauthorized: 0x2n,
7
+ ProtocolViolation: 0x3n,
8
+ DuplicateTrackAlias: 0x4n,
9
+ ParameterLengthMismatch: 0x5n,
10
+ TooManySubscribes: 0x6n,
11
+ GoawayTimeout: 0x10n,
12
+ ControlMessageTimeout: 0x11n,
13
+ DataStreamTimeout: 0x12n,
14
+ } as const
15
+ export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
16
+
17
+ export const AnnounceErrorCode = {
18
+ InternalError: 0x0n,
19
+ Unauthorized: 0x1n,
20
+ Timeout: 0x2n,
21
+ NotSupported: 0x3n,
22
+ Uninterested: 0x4n,
23
+ } as const
24
+ export type AnnounceErrorCodeValue = (typeof AnnounceErrorCode)[keyof typeof AnnounceErrorCode]
25
+
26
+ export const SubscribeErrorCode = {
27
+ InternalError: 0x0n,
28
+ Unauthorized: 0x1n,
29
+ Timeout: 0x2n,
30
+ NotSupported: 0x3n,
31
+ TrackDoesNotExist: 0x4n,
32
+ InvalidRange: 0x5n,
33
+ RetryTrackAlias: 0x6n,
34
+ } as const
35
+ export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
36
+
37
+ export const FetchErrorCode = {
38
+ InternalError: 0x0n,
39
+ Unauthorized: 0x1n,
40
+ Timeout: 0x2n,
41
+ NotSupported: 0x3n,
42
+ TrackDoesNotExist: 0x4n,
43
+ InvalidRange: 0x5n,
44
+ } as const
45
+ export type FetchErrorCodeValue = (typeof FetchErrorCode)[keyof typeof FetchErrorCode]
46
+
47
+ export const SubscribeDoneStatusCode = {
48
+ InternalError: 0x0n,
49
+ Unauthorized: 0x1n,
50
+ TrackEnded: 0x2n,
51
+ SubscriptionEnded: 0x3n,
52
+ GoingAway: 0x4n,
53
+ Expired: 0x5n,
54
+ TooFarBehind: 0x6n,
55
+ } as const
56
+ export type SubscribeDoneStatusCodeValue =
57
+ (typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
58
+
59
+ export const SubscribeAnnouncesErrorCode = {
60
+ InternalError: 0x0n,
61
+ Unauthorized: 0x1n,
62
+ Timeout: 0x2n,
63
+ NotSupported: 0x3n,
64
+ NamespacePrefixUnknown: 0x4n,
65
+ } as const
66
+ export type SubscribeAnnouncesErrorCodeValue =
67
+ (typeof SubscribeAnnouncesErrorCode)[keyof typeof SubscribeAnnouncesErrorCode]
68
+
69
+ export const TrackStatusCode = {
70
+ InProgress: 0x00n,
71
+ TrackDoesNotExist: 0x01n,
72
+ NotYetBegun: 0x02n,
73
+ Finished: 0x03n,
74
+ RelayStatusUnavailable: 0x04n,
75
+ } as const
76
+ export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
@@ -1,5 +1,7 @@
1
1
  export const DRAFT_VERSION = 0xff000008n
2
2
 
3
+ export type { AuthRedaction } from '../../core/auth-redaction.js'
4
+ export { REDACTION_FILL } from '../../core/auth-redaction.js'
3
5
  export type { Draft08Codec } from './codec.js'
4
6
  export {
5
7
  createDraft08Codec,
@@ -15,7 +17,26 @@ export {
15
17
  encodeFetchStream,
16
18
  encodeMessage,
17
19
  encodeSubgroupStream,
20
+ redactAuthTokens,
18
21
  } from './codec.js'
22
+ export type {
23
+ AnnounceErrorCodeValue,
24
+ FetchErrorCodeValue,
25
+ SessionErrorCodeValue,
26
+ SubscribeAnnouncesErrorCodeValue,
27
+ SubscribeDoneStatusCodeValue,
28
+ SubscribeErrorCodeValue,
29
+ TrackStatusCodeValue,
30
+ } from './error-codes.js'
31
+ export {
32
+ AnnounceErrorCode,
33
+ FetchErrorCode,
34
+ SessionErrorCode,
35
+ SubscribeAnnouncesErrorCode,
36
+ SubscribeDoneStatusCode,
37
+ SubscribeErrorCode,
38
+ TrackStatusCode,
39
+ } from './error-codes.js'
19
40
  export {
20
41
  MESSAGE_ID_MAP,
21
42
  MESSAGE_TYPE_MAP,
@@ -1,3 +1,4 @@
1
+ import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
1
2
  import { BufferReader } from '../../core/buffer-reader.js'
2
3
  import { BufferWriter } from '../../core/buffer-writer.js'
3
4
  import { bytesToHex, hexToBytes } from '../../core/hex.js'
@@ -182,6 +183,11 @@ function decodeParams(r: BufferReader): Draft09Params {
182
183
 
183
184
  if (paramType === PARAM_AUTHORIZATION_INFO) {
184
185
  const bytes = r.readBytes(length)
186
+ // The credential is the whole value in this draft: a bare UTF-8 string,
187
+ // with no alias and no token type around it. What survives the overwrite
188
+ // is the parameter's presence, which is what says authorization was
189
+ // attempted at all.
190
+ recordAuthValueSpan(r.offset - length, length)
185
191
  result.authorization_info = textDecoder.decode(bytes)
186
192
  } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
187
193
  const blob = r.readBytes(length)
@@ -975,3 +981,37 @@ export function createDraft09Codec(): Draft09Codec {
975
981
  createStreamDecoder,
976
982
  }
977
983
  }
984
+
985
+ /**
986
+ * Overwrite every AUTHORIZATION_INFO value in a draft-09 control frame.
987
+ *
988
+ * One decode, whose *output is discarded*: the point is not to read the
989
+ * message, it is to learn where the credentials were so the caller never has to
990
+ * hold a frame that contains one. A caller that also wants the message should
991
+ * decode the **redacted** frame with {@link decodeMessage}, which then cannot
992
+ * produce a value because there is no longer one in the bytes.
993
+ *
994
+ * A frame that fails to decode is still redacted as far as the decode got. That
995
+ * is the useful direction to fail in: a value that was read is a value that was
996
+ * exposed, whatever went wrong after it.
997
+ *
998
+ * See {@link AuthRedaction.incomplete} for the one result a caller must not
999
+ * treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
1000
+ * close.
1001
+ */
1002
+ export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
1003
+ let payloadStart: number
1004
+ try {
1005
+ const probe = new BufferReader(bytes)
1006
+ probe.readVarInt()
1007
+ probe.readVarInt()
1008
+ payloadStart = probe.offset
1009
+ } catch {
1010
+ // Too short to carry a message header, and so too short for the parameters
1011
+ // that carry a credential. Reported as not decoded rather than as clean: a
1012
+ // framer only ever emits complete frames, so a caller that gets here is
1013
+ // holding something this function did not check.
1014
+ return { bytes, redacted: 0, incomplete: false, decoded: false }
1015
+ }
1016
+ return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
1017
+ }
@@ -0,0 +1,76 @@
1
+ // Draft-09 error, status and termination code registries.
2
+
3
+ export const SessionErrorCode = {
4
+ NoError: 0x0n,
5
+ InternalError: 0x1n,
6
+ Unauthorized: 0x2n,
7
+ ProtocolViolation: 0x3n,
8
+ DuplicateTrackAlias: 0x4n,
9
+ ParameterLengthMismatch: 0x5n,
10
+ TooManySubscribes: 0x6n,
11
+ GoawayTimeout: 0x10n,
12
+ ControlMessageTimeout: 0x11n,
13
+ DataStreamTimeout: 0x12n,
14
+ } as const
15
+ export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
16
+
17
+ export const AnnounceErrorCode = {
18
+ InternalError: 0x0n,
19
+ Unauthorized: 0x1n,
20
+ Timeout: 0x2n,
21
+ NotSupported: 0x3n,
22
+ Uninterested: 0x4n,
23
+ } as const
24
+ export type AnnounceErrorCodeValue = (typeof AnnounceErrorCode)[keyof typeof AnnounceErrorCode]
25
+
26
+ export const SubscribeErrorCode = {
27
+ InternalError: 0x0n,
28
+ Unauthorized: 0x1n,
29
+ Timeout: 0x2n,
30
+ NotSupported: 0x3n,
31
+ TrackDoesNotExist: 0x4n,
32
+ InvalidRange: 0x5n,
33
+ RetryTrackAlias: 0x6n,
34
+ } as const
35
+ export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
36
+
37
+ export const FetchErrorCode = {
38
+ InternalError: 0x0n,
39
+ Unauthorized: 0x1n,
40
+ Timeout: 0x2n,
41
+ NotSupported: 0x3n,
42
+ TrackDoesNotExist: 0x4n,
43
+ InvalidRange: 0x5n,
44
+ } as const
45
+ export type FetchErrorCodeValue = (typeof FetchErrorCode)[keyof typeof FetchErrorCode]
46
+
47
+ export const SubscribeDoneStatusCode = {
48
+ InternalError: 0x0n,
49
+ Unauthorized: 0x1n,
50
+ TrackEnded: 0x2n,
51
+ SubscriptionEnded: 0x3n,
52
+ GoingAway: 0x4n,
53
+ Expired: 0x5n,
54
+ TooFarBehind: 0x6n,
55
+ } as const
56
+ export type SubscribeDoneStatusCodeValue =
57
+ (typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
58
+
59
+ export const SubscribeAnnouncesErrorCode = {
60
+ InternalError: 0x0n,
61
+ Unauthorized: 0x1n,
62
+ Timeout: 0x2n,
63
+ NotSupported: 0x3n,
64
+ NamespacePrefixUnknown: 0x4n,
65
+ } as const
66
+ export type SubscribeAnnouncesErrorCodeValue =
67
+ (typeof SubscribeAnnouncesErrorCode)[keyof typeof SubscribeAnnouncesErrorCode]
68
+
69
+ export const TrackStatusCode = {
70
+ InProgress: 0x00n,
71
+ TrackDoesNotExist: 0x01n,
72
+ NotYetBegun: 0x02n,
73
+ Finished: 0x03n,
74
+ RelayStatusUnavailable: 0x04n,
75
+ } as const
76
+ export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
@@ -1,5 +1,7 @@
1
1
  export const DRAFT_VERSION = 0xff000009n
2
2
 
3
+ export type { AuthRedaction } from '../../core/auth-redaction.js'
4
+ export { REDACTION_FILL } from '../../core/auth-redaction.js'
3
5
  export type { Draft09Codec } from './codec.js'
4
6
  export {
5
7
  createDraft09Codec,
@@ -15,7 +17,26 @@ export {
15
17
  encodeFetchStream,
16
18
  encodeMessage,
17
19
  encodeSubgroupStream,
20
+ redactAuthTokens,
18
21
  } from './codec.js'
22
+ export type {
23
+ AnnounceErrorCodeValue,
24
+ FetchErrorCodeValue,
25
+ SessionErrorCodeValue,
26
+ SubscribeAnnouncesErrorCodeValue,
27
+ SubscribeDoneStatusCodeValue,
28
+ SubscribeErrorCodeValue,
29
+ TrackStatusCodeValue,
30
+ } from './error-codes.js'
31
+ export {
32
+ AnnounceErrorCode,
33
+ FetchErrorCode,
34
+ SessionErrorCode,
35
+ SubscribeAnnouncesErrorCode,
36
+ SubscribeDoneStatusCode,
37
+ SubscribeErrorCode,
38
+ TrackStatusCode,
39
+ } from './error-codes.js'
19
40
  export {
20
41
  MESSAGE_ID_MAP,
21
42
  MESSAGE_TYPE_MAP,
@@ -1,3 +1,4 @@
1
+ import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
1
2
  import { BufferReader } from '../../core/buffer-reader.js'
2
3
  import { BufferWriter } from '../../core/buffer-writer.js'
3
4
  import { bytesToHex, hexToBytes } from '../../core/hex.js'
@@ -182,6 +183,11 @@ function decodeParams(r: BufferReader): Draft10Params {
182
183
 
183
184
  if (paramType === PARAM_AUTHORIZATION_INFO) {
184
185
  const bytes = r.readBytes(length)
186
+ // The credential is the whole value in this draft: a bare UTF-8 string,
187
+ // with no alias and no token type around it. What survives the overwrite
188
+ // is the parameter's presence, which is what says authorization was
189
+ // attempted at all.
190
+ recordAuthValueSpan(r.offset - length, length)
185
191
  result.authorization_info = textDecoder.decode(bytes)
186
192
  } else if (paramType === PARAM_DELIVERY_TIMEOUT) {
187
193
  const blob = r.readBytes(length)
@@ -975,3 +981,37 @@ export function createDraft10Codec(): Draft10Codec {
975
981
  createStreamDecoder,
976
982
  }
977
983
  }
984
+
985
+ /**
986
+ * Overwrite every AUTHORIZATION_INFO value in a draft-10 control frame.
987
+ *
988
+ * One decode, whose *output is discarded*: the point is not to read the
989
+ * message, it is to learn where the credentials were so the caller never has to
990
+ * hold a frame that contains one. A caller that also wants the message should
991
+ * decode the **redacted** frame with {@link decodeMessage}, which then cannot
992
+ * produce a value because there is no longer one in the bytes.
993
+ *
994
+ * A frame that fails to decode is still redacted as far as the decode got. That
995
+ * is the useful direction to fail in: a value that was read is a value that was
996
+ * exposed, whatever went wrong after it.
997
+ *
998
+ * See {@link AuthRedaction.incomplete} for the one result a caller must not
999
+ * treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
1000
+ * close.
1001
+ */
1002
+ export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
1003
+ let payloadStart: number
1004
+ try {
1005
+ const probe = new BufferReader(bytes)
1006
+ probe.readVarInt()
1007
+ probe.readVarInt()
1008
+ payloadStart = probe.offset
1009
+ } catch {
1010
+ // Too short to carry a message header, and so too short for the parameters
1011
+ // that carry a credential. Reported as not decoded rather than as clean: a
1012
+ // framer only ever emits complete frames, so a caller that gets here is
1013
+ // holding something this function did not check.
1014
+ return { bytes, redacted: 0, incomplete: false, decoded: false }
1015
+ }
1016
+ return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
1017
+ }
@@ -0,0 +1,76 @@
1
+ // Draft-10 error, status and termination code registries.
2
+
3
+ export const SessionErrorCode = {
4
+ NoError: 0x0n,
5
+ InternalError: 0x1n,
6
+ Unauthorized: 0x2n,
7
+ ProtocolViolation: 0x3n,
8
+ DuplicateTrackAlias: 0x4n,
9
+ ParameterLengthMismatch: 0x5n,
10
+ TooManySubscribes: 0x6n,
11
+ GoawayTimeout: 0x10n,
12
+ ControlMessageTimeout: 0x11n,
13
+ DataStreamTimeout: 0x12n,
14
+ } as const
15
+ export type SessionErrorCodeValue = (typeof SessionErrorCode)[keyof typeof SessionErrorCode]
16
+
17
+ export const SubscribeErrorCode = {
18
+ InternalError: 0x0n,
19
+ Unauthorized: 0x1n,
20
+ Timeout: 0x2n,
21
+ NotSupported: 0x3n,
22
+ TrackDoesNotExist: 0x4n,
23
+ InvalidRange: 0x5n,
24
+ RetryTrackAlias: 0x6n,
25
+ } as const
26
+ export type SubscribeErrorCodeValue = (typeof SubscribeErrorCode)[keyof typeof SubscribeErrorCode]
27
+
28
+ export const SubscribeDoneStatusCode = {
29
+ InternalError: 0x0n,
30
+ Unauthorized: 0x1n,
31
+ TrackEnded: 0x2n,
32
+ SubscriptionEnded: 0x3n,
33
+ GoingAway: 0x4n,
34
+ Expired: 0x5n,
35
+ TooFarBehind: 0x6n,
36
+ } as const
37
+ export type SubscribeDoneStatusCodeValue =
38
+ (typeof SubscribeDoneStatusCode)[keyof typeof SubscribeDoneStatusCode]
39
+
40
+ export const FetchErrorCode = {
41
+ InternalError: 0x0n,
42
+ Unauthorized: 0x1n,
43
+ Timeout: 0x2n,
44
+ NotSupported: 0x3n,
45
+ TrackDoesNotExist: 0x4n,
46
+ InvalidRange: 0x5n,
47
+ } as const
48
+ export type FetchErrorCodeValue = (typeof FetchErrorCode)[keyof typeof FetchErrorCode]
49
+
50
+ export const AnnounceErrorCode = {
51
+ InternalError: 0x0n,
52
+ Unauthorized: 0x1n,
53
+ Timeout: 0x2n,
54
+ NotSupported: 0x3n,
55
+ Uninterested: 0x4n,
56
+ } as const
57
+ export type AnnounceErrorCodeValue = (typeof AnnounceErrorCode)[keyof typeof AnnounceErrorCode]
58
+
59
+ export const SubscribeAnnouncesErrorCode = {
60
+ InternalError: 0x0n,
61
+ Unauthorized: 0x1n,
62
+ Timeout: 0x2n,
63
+ NotSupported: 0x3n,
64
+ NamespacePrefixUnknown: 0x4n,
65
+ } as const
66
+ export type SubscribeAnnouncesErrorCodeValue =
67
+ (typeof SubscribeAnnouncesErrorCode)[keyof typeof SubscribeAnnouncesErrorCode]
68
+
69
+ export const TrackStatusCode = {
70
+ InProgress: 0x00n,
71
+ TrackDoesNotExist: 0x01n,
72
+ NotYetBegun: 0x02n,
73
+ Finished: 0x03n,
74
+ RelayStatusUnavailable: 0x04n,
75
+ } as const
76
+ export type TrackStatusCodeValue = (typeof TrackStatusCode)[keyof typeof TrackStatusCode]
@@ -1,5 +1,7 @@
1
1
  export const DRAFT_VERSION = 0xff00000an
2
2
 
3
+ export type { AuthRedaction } from '../../core/auth-redaction.js'
4
+ export { REDACTION_FILL } from '../../core/auth-redaction.js'
3
5
  export type { Draft10Codec } from './codec.js'
4
6
  export {
5
7
  createDraft10Codec,
@@ -15,7 +17,26 @@ export {
15
17
  encodeFetchStream,
16
18
  encodeMessage,
17
19
  encodeSubgroupStream,
20
+ redactAuthTokens,
18
21
  } from './codec.js'
22
+ export type {
23
+ AnnounceErrorCodeValue,
24
+ FetchErrorCodeValue,
25
+ SessionErrorCodeValue,
26
+ SubscribeAnnouncesErrorCodeValue,
27
+ SubscribeDoneStatusCodeValue,
28
+ SubscribeErrorCodeValue,
29
+ TrackStatusCodeValue,
30
+ } from './error-codes.js'
31
+ export {
32
+ AnnounceErrorCode,
33
+ FetchErrorCode,
34
+ SessionErrorCode,
35
+ SubscribeAnnouncesErrorCode,
36
+ SubscribeDoneStatusCode,
37
+ SubscribeErrorCode,
38
+ TrackStatusCode,
39
+ } from './error-codes.js'
19
40
  export {
20
41
  MESSAGE_ID_MAP,
21
42
  MESSAGE_TYPE_MAP,