@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
@@ -2,6 +2,8 @@
2
2
 
3
3
  export const DRAFT_VERSION = 0xff000012n
4
4
 
5
+ export type { AuthRedaction } from '../../core/auth-redaction.js'
6
+ export { REDACTION_FILL } from '../../core/auth-redaction.js'
5
7
  export type { Draft18Codec } from './codec.js'
6
8
  export {
7
9
  createDataStreamDecoder,
@@ -18,6 +20,7 @@ export {
18
20
  encodeFetchStream,
19
21
  encodeMessage,
20
22
  encodeSubgroupStream,
23
+ redactAuthTokens,
21
24
  } from './codec.js'
22
25
  export type {
23
26
  DataStreamResetCodeValue,
@@ -18,7 +18,7 @@ export interface AuthorizationToken {
18
18
  // Setup options (KVP encoding, no count prefix)
19
19
  export interface Draft18SetupOptions {
20
20
  path?: string // 0x01 odd
21
- authorization_token?: AuthorizationToken // 0x03 odd
21
+ authorization_token?: readonly AuthorizationToken[] // 0x03 odd
22
22
  max_auth_token_cache_size?: bigint // 0x04 even
23
23
  authority?: string // 0x05 odd
24
24
  moqt_implementation?: string // 0x07 odd
@@ -41,14 +41,14 @@ export interface LargestObject {
41
41
 
42
42
  // Version-specific parameters (delta-encoded types, count-prefixed)
43
43
  export interface Draft18Params {
44
- object_delivery_timeout?: bigint // 0x02 varint (renamed from delivery_timeout in draft-17)
45
- authorization_token?: AuthorizationToken // 0x03 length-prefixed nested
44
+ object_delivery_timeout?: bigint // 0x02 varint; drafts 11-17 name the same codepoint DELIVERY_TIMEOUT
45
+ authorization_token?: readonly AuthorizationToken[] // 0x03 length-prefixed nested
46
46
  rendezvous_timeout?: bigint // 0x04 varint
47
47
  subgroup_delivery_timeout?: bigint // 0x06 varint (NEW in draft-18)
48
48
  expires?: bigint // 0x08 varint
49
49
  largest_object?: LargestObject // 0x09 Location (2 bare varints)
50
50
  fill_timeout?: bigint // 0x0a varint (NEW in draft-18)
51
- forward?: bigint // 0x10 uint8 (was varint in draft-17)
51
+ forward?: bigint // 0x10 uint8; drafts 15 and 16 encode this parameter as a varint
52
52
  subscriber_priority?: bigint // 0x20 uint8
53
53
  subscription_filter?: SubscriptionFilter // 0x21 length-prefixed
54
54
  group_order?: bigint // 0x22 uint8
@@ -59,7 +59,7 @@ export interface Draft18Params {
59
59
 
60
60
  // Track properties (KVP encoding, no count prefix, read until end of payload)
61
61
  export interface Draft18TrackProperties {
62
- object_delivery_timeout?: bigint // 0x02 even varint (renamed from delivery_timeout)
62
+ object_delivery_timeout?: bigint // 0x02 even varint; drafts 11-17 name the same codepoint DELIVERY_TIMEOUT
63
63
  max_cache_duration?: bigint // 0x04 even varint
64
64
  subgroup_delivery_timeout?: bigint // 0x06 even varint (NEW in draft-18)
65
65
  immutable_properties?: Uint8Array // 0x0b odd length-prefixed
@@ -101,7 +101,7 @@ export interface Draft18Setup extends Draft18BaseMessage {
101
101
  readonly options: Draft18SetupOptions
102
102
  }
103
103
 
104
- // Subscribe — Required Request ID Delta REMOVED in draft-18
104
+ // Subscribe — draft-18 Section 10.7. No Required Request ID Delta; draft-17 alone carries that field.
105
105
  export interface Draft18Subscribe extends Draft18BaseMessage {
106
106
  readonly type: 'subscribe'
107
107
  readonly request_id: bigint
@@ -159,7 +159,7 @@ export interface Draft18NamespaceDone extends Draft18BaseMessage {
159
159
  readonly namespace_suffix: string[]
160
160
  }
161
161
 
162
- // SUBSCRIBE_NAMESPACE — type 0x50, subscribe_options field removed in draft-18
162
+ // SUBSCRIBE_NAMESPACE — type 0x50; no Subscribe Options field in draft-18.
163
163
  export interface Draft18SubscribeNamespace extends Draft18BaseMessage {
164
164
  readonly type: 'subscribe_namespace'
165
165
  readonly request_id: bigint
@@ -167,7 +167,7 @@ export interface Draft18SubscribeNamespace extends Draft18BaseMessage {
167
167
  readonly parameters: Draft18Params
168
168
  }
169
169
 
170
- // SUBSCRIBE_TRACKS — NEW in draft-18, type 0x51
170
+ // SUBSCRIBE_TRACKS — type 0x51.
171
171
  export interface Draft18SubscribeTracks extends Draft18BaseMessage {
172
172
  readonly type: 'subscribe_tracks'
173
173
  readonly request_id: bigint
@@ -214,7 +214,7 @@ export interface Draft18FetchOk extends Draft18BaseMessage {
214
214
  readonly track_properties: Draft18TrackProperties
215
215
  }
216
216
 
217
- // Track Status — same format as subscribe in draft-18 (without required_request_id_delta)
217
+ // Track Status — format identical to SUBSCRIBE (Section 10.7), minus the subscriber parameters related to Track delivery (Section 10.14).
218
218
  export interface Draft18TrackStatus extends Draft18BaseMessage {
219
219
  readonly type: 'track_status'
220
220
  readonly request_id: bigint
@@ -223,7 +223,7 @@ export interface Draft18TrackStatus extends Draft18BaseMessage {
223
223
  readonly parameters: Draft18Params
224
224
  }
225
225
 
226
- // REQUEST_OK — gained trailing Track Properties in draft-18
226
+ // REQUEST_OK — carries trailing Track Properties after the parameters.
227
227
  export interface Draft18RequestOk extends Draft18BaseMessage {
228
228
  readonly type: 'request_ok'
229
229
  readonly parameters: Draft18Params
@@ -332,10 +332,18 @@ export type Draft18DataStream = SubgroupStream | DatagramObject | FetchStream
332
332
  // Streaming data stream decoder types
333
333
  export interface SubgroupStreamHeader {
334
334
  readonly type: 'subgroup_header'
335
+ /**
336
+ * The stream Type Flags, the same value `SubgroupStream.headerType` carries.
337
+ * It is reported so the incremental decoder does not drop the flags the
338
+ * header encodes, which is what lets a consumer tell the modes apart.
339
+ */
340
+ readonly headerType: number
335
341
  readonly trackAlias: bigint
336
342
  readonly groupId: bigint
337
343
  readonly subgroupId: bigint
338
344
  readonly publisherPriority: number
345
+ readonly endOfGroup?: boolean
346
+ readonly firstObject?: boolean
339
347
  }
340
348
 
341
349
  export interface FetchStreamHeader {
@@ -1,3 +1,4 @@
1
+ import { type AuthRedaction, recordAuthValueSpan, redactWith } from '../../core/auth-redaction.js'
1
2
  import { MoqtBufferReader as BufferReader } from '../../core/buffer-reader.js'
2
3
  import { MoqtBufferWriter as BufferWriter } from '../../core/buffer-writer.js'
3
4
  import { bytesToHex, hexToBytes } from '../../core/hex.js'
@@ -75,12 +76,12 @@ function encodeSetupOptions(opts: Draft19SetupOptions, writer: BufferWriter): vo
75
76
  },
76
77
  })
77
78
  }
78
- if (opts.authorization_token !== undefined) {
79
+ for (const token of opts.authorization_token ?? []) {
79
80
  entries.push({
80
81
  type: SETUP_OPT_AUTHORIZATION_TOKEN,
81
82
  encode: (w) => {
82
83
  const tmpW = new BufferWriter(64)
83
- encodeAuthorizationToken(opts.authorization_token!, tmpW)
84
+ encodeAuthorizationToken(token, tmpW)
84
85
  const raw = tmpW.finish()
85
86
  w.writeVarInt(BigInt(raw.byteLength))
86
87
  w.writeBytes(raw)
@@ -191,7 +192,9 @@ function decodeSetupOptions(reader: BufferReader, payloadEnd: number): Draft19Se
191
192
  if (optType === SETUP_OPT_PATH) {
192
193
  result.path = textDecoder.decode(bytes)
193
194
  } else if (optType === SETUP_OPT_AUTHORIZATION_TOKEN) {
194
- result.authorization_token = decodeAuthorizationToken(new BufferReader(bytes))
195
+ const token = decodeAuthorizationToken(new BufferReader(bytes))
196
+ noteAuthTokenValue(reader.offset - length, length, token)
197
+ result.authorization_token = [...(result.authorization_token ?? []), token]
195
198
  } else if (optType === SETUP_OPT_AUTHORITY) {
196
199
  result.authority = textDecoder.decode(bytes)
197
200
  } else if (optType === SETUP_OPT_MOQT_IMPLEMENTATION) {
@@ -229,6 +232,32 @@ function encodeAuthorizationToken(token: AuthorizationToken, w: BufferWriter): v
229
232
  }
230
233
  }
231
234
 
235
+ /**
236
+ * Record where a Token Value sits, so it can be overwritten before the frame
237
+ * reaches anything that keeps it (Section 1.6).
238
+ *
239
+ * The span falls out of the decode with no second walk. The Token Value is the
240
+ * tail of the Token structure — draft-19 Section 10.2.2, Figure 5: it is NOT
241
+ * length-prefixed inside the Token and consumes the remainder of the outer
242
+ * length-prefixed parameter value. So its start is the parameter value's end
243
+ * minus the value's own length, and the fields before it (Alias Type, Token
244
+ * Alias, Token Type) are left alone deliberately: they are structure, not
245
+ * secret, and they are what distinguishes a session that failed to
246
+ * authenticate from one that never tried.
247
+ *
248
+ * DELETE (0x0) and USE_ALIAS (0x2) carry no value at all, so they record
249
+ * nothing and their frames pass through untouched.
250
+ */
251
+ function noteAuthTokenValue(
252
+ valueStart: number,
253
+ valueLength: number,
254
+ token: AuthorizationToken,
255
+ ): void {
256
+ const value = token.token_value
257
+ if (value === undefined || value.byteLength === 0) return
258
+ recordAuthValueSpan(valueStart + valueLength - value.byteLength, value.byteLength)
259
+ }
260
+
232
261
  function decodeAuthorizationToken(r: BufferReader): AuthorizationToken {
233
262
  const alias_type = r.readVarInt()
234
263
  const aliasType = Number(alias_type)
@@ -279,7 +308,7 @@ const PARAM_LARGEST_OBJECT = 0x09n
279
308
  const PARAM_FILL_TIMEOUT = 0x0an
280
309
  const PARAM_FORWARD = 0x10n
281
310
  const PARAM_SUBSCRIBER_PRIORITY = 0x20n
282
- const PARAM_LOCATION_FILTER = 0x21n // renamed from SUBSCRIPTION_FILTER in draft-19
311
+ const PARAM_LOCATION_FILTER = 0x21n // LOCATION_FILTER (draft-19 Section 10.2.9); drafts 15-18 name 0x21 SUBSCRIPTION_FILTER
283
312
  const PARAM_GROUP_ORDER = 0x22n
284
313
  const PARAM_SUBGROUP_FILTER = 0x25n // NEW in draft-19
285
314
  const PARAM_OBJECTID_FILTER = 0x26n // NEW in draft-19
@@ -403,12 +432,12 @@ function encodeParams(params: Draft19Params, writer: BufferWriter): void {
403
432
  encode: (w) => w.writeVarInt(params.object_delivery_timeout!),
404
433
  })
405
434
  }
406
- if (params.authorization_token !== undefined) {
435
+ for (const token of params.authorization_token ?? []) {
407
436
  entries.push({
408
437
  type: PARAM_AUTHORIZATION_TOKEN,
409
438
  encode: (w) => {
410
439
  const tmpW = new BufferWriter(64)
411
- encodeAuthorizationToken(params.authorization_token!, tmpW)
440
+ encodeAuthorizationToken(token, tmpW)
412
441
  const raw = tmpW.finish()
413
442
  w.writeVarInt(BigInt(raw.byteLength))
414
443
  w.writeBytes(raw)
@@ -489,34 +518,34 @@ function encodeParams(params: Draft19Params, writer: BufferWriter): void {
489
518
  encode: (w) => w.writeUint8(Number(params.group_order!)),
490
519
  })
491
520
  }
492
- if (params.subgroup_filter !== undefined) {
521
+ for (const filter of params.subgroup_filter ?? []) {
493
522
  entries.push({
494
523
  type: PARAM_SUBGROUP_FILTER,
495
- encode: (w) => encodeRangeFilter(params.subgroup_filter!, false, w),
524
+ encode: (w) => encodeRangeFilter(filter, false, w),
496
525
  })
497
526
  }
498
- if (params.objectid_filter !== undefined) {
527
+ for (const filter of params.objectid_filter ?? []) {
499
528
  entries.push({
500
529
  type: PARAM_OBJECTID_FILTER,
501
- encode: (w) => encodeRangeFilter(params.objectid_filter!, false, w),
530
+ encode: (w) => encodeRangeFilter(filter, false, w),
502
531
  })
503
532
  }
504
- if (params.priority_filter !== undefined) {
533
+ for (const filter of params.priority_filter ?? []) {
505
534
  entries.push({
506
535
  type: PARAM_PRIORITY_FILTER,
507
- encode: (w) => encodeRangeFilter(params.priority_filter!, false, w),
536
+ encode: (w) => encodeRangeFilter(filter, false, w),
508
537
  })
509
538
  }
510
- if (params.object_property_filter !== undefined) {
539
+ for (const filter of params.object_property_filter ?? []) {
511
540
  entries.push({
512
541
  type: PARAM_OBJECT_PROPERTY_FILTER,
513
- encode: (w) => encodeRangeFilter(params.object_property_filter!, true, w),
542
+ encode: (w) => encodeRangeFilter(filter, true, w),
514
543
  })
515
544
  }
516
- if (params.track_property_filter !== undefined) {
545
+ for (const filter of params.track_property_filter ?? []) {
517
546
  entries.push({
518
547
  type: PARAM_TRACK_PROPERTY_FILTER,
519
- encode: (w) => encodeRangeFilter(params.track_property_filter!, true, w),
548
+ encode: (w) => encodeRangeFilter(filter, true, w),
520
549
  })
521
550
  }
522
551
  if (params.new_group_request !== undefined) {
@@ -587,7 +616,9 @@ function decodeParams(reader: BufferReader, messageType: string): Draft19Params
587
616
  } else if (paramType === PARAM_AUTHORIZATION_TOKEN) {
588
617
  const length = Number(reader.readVarInt())
589
618
  const bytes = reader.readBytes(length)
590
- result.authorization_token = decodeAuthorizationToken(new BufferReader(bytes))
619
+ const token = decodeAuthorizationToken(new BufferReader(bytes))
620
+ noteAuthTokenValue(reader.offset - length, length, token)
621
+ result.authorization_token = [...(result.authorization_token ?? []), token]
591
622
  } else if (paramType === PARAM_RENDEZVOUS_TIMEOUT) {
592
623
  result.rendezvous_timeout = reader.readVarInt()
593
624
  } else if (paramType === PARAM_SUBGROUP_DELIVERY_TIMEOUT) {
@@ -602,7 +633,7 @@ function decodeParams(reader: BufferReader, messageType: string): Draft19Params
602
633
  } else if (paramType === PARAM_FILL_TIMEOUT) {
603
634
  result.fill_timeout = reader.readVarInt()
604
635
  } else if (paramType === PARAM_FORWARD) {
605
- // uint8 in draft-18 (was varint in draft-17)
636
+ // uint8 (Section 10.2.17); drafts 15 and 16 encode this as a varint
606
637
  result.forward = BigInt(reader.readUint8())
607
638
  } else if (paramType === PARAM_SUBSCRIBER_PRIORITY) {
608
639
  // uint8: single raw byte
@@ -632,15 +663,21 @@ function decodeParams(reader: BufferReader, messageType: string): Draft19Params
632
663
  // uint8: single raw byte
633
664
  result.group_order = BigInt(reader.readUint8())
634
665
  } else if (paramType === PARAM_SUBGROUP_FILTER) {
635
- result.subgroup_filter = decodeRangeFilter(reader, false)
666
+ result.subgroup_filter = [...(result.subgroup_filter ?? []), decodeRangeFilter(reader, false)]
636
667
  } else if (paramType === PARAM_OBJECTID_FILTER) {
637
- result.objectid_filter = decodeRangeFilter(reader, false)
668
+ result.objectid_filter = [...(result.objectid_filter ?? []), decodeRangeFilter(reader, false)]
638
669
  } else if (paramType === PARAM_PRIORITY_FILTER) {
639
- result.priority_filter = decodeRangeFilter(reader, false)
670
+ result.priority_filter = [...(result.priority_filter ?? []), decodeRangeFilter(reader, false)]
640
671
  } else if (paramType === PARAM_OBJECT_PROPERTY_FILTER) {
641
- result.object_property_filter = decodeRangeFilter(reader, true)
672
+ result.object_property_filter = [
673
+ ...(result.object_property_filter ?? []),
674
+ decodeRangeFilter(reader, true),
675
+ ]
642
676
  } else if (paramType === PARAM_TRACK_PROPERTY_FILTER) {
643
- result.track_property_filter = decodeRangeFilter(reader, true)
677
+ result.track_property_filter = [
678
+ ...(result.track_property_filter ?? []),
679
+ decodeRangeFilter(reader, true),
680
+ ]
644
681
  } else if (paramType === PARAM_NEW_GROUP_REQUEST) {
645
682
  result.new_group_request = reader.readVarInt()
646
683
  } else if (paramType === PARAM_TRACK_NAMESPACE_PREFIX) {
@@ -1466,3 +1503,38 @@ export function createDraft19Codec(): Draft19Codec {
1466
1503
  createDataStreamDecoder,
1467
1504
  }
1468
1505
  }
1506
+
1507
+ /**
1508
+ * Overwrite every Authorization Token value in a draft-19 control frame.
1509
+ *
1510
+ * One decode, whose *output is discarded*: the point is not to read the
1511
+ * message, it is to learn where the tokens were so the caller never has to hold
1512
+ * a frame that contains one. A caller that also wants the message should decode
1513
+ * the **redacted** frame with {@link decodeMessage}, which then cannot produce a
1514
+ * token value because there is no longer one in the bytes.
1515
+ *
1516
+ * A frame that fails to decode is still redacted as far as the decode got. That
1517
+ * is the useful direction to fail in: a value that was read is a value that was
1518
+ * exposed, whatever went wrong after it.
1519
+ *
1520
+ * See {@link AuthRedaction.incomplete} for the one result a caller must not
1521
+ * treat as clean, and {@link AuthRedaction.decoded} for the residual it cannot
1522
+ * close.
1523
+ */
1524
+ export function redactAuthTokens(bytes: Uint8Array): AuthRedaction {
1525
+ let payloadStart: number
1526
+ try {
1527
+ const probe = new BufferReader(bytes)
1528
+ probe.readVarInt()
1529
+ probe.readUint8()
1530
+ probe.readUint8()
1531
+ payloadStart = probe.offset
1532
+ } catch {
1533
+ // Too short to carry a message header, and so too short for the parameters
1534
+ // that carry a token. Reported as not decoded rather than as clean: the
1535
+ // framer only ever emits complete frames, so a caller that gets here is
1536
+ // holding something this function did not check.
1537
+ return { bytes, redacted: 0, incomplete: false, decoded: false }
1538
+ }
1539
+ return redactWith(bytes, payloadStart, () => decodeMessage(bytes).ok)
1540
+ }