@sema-agent/client-core 0.93.1 → 0.95.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 (321) hide show
  1. package/CHANGELOG.md +554 -0
  2. package/README.md +89 -55
  3. package/dist/adapt/arms.js +13 -11
  4. package/dist/adapt/panelTasks.js +4 -10
  5. package/dist/adapt/toolCards.js +2 -2
  6. package/dist/adapt/wireShapes.js +3 -8
  7. package/dist/adapter/activeRunSelfHeal.d.ts +8 -3
  8. package/dist/adapter/activeRunSelfHeal.js +20 -12
  9. package/dist/adapter/downstream/eventToSdkMessage.js +24 -17
  10. package/dist/adapter/downstream/terminalToSdkResult.js +13 -6
  11. package/dist/adapter/runStream.js +2 -1
  12. package/dist/adapter/types.d.ts +7 -0
  13. package/dist/adapter/types.js +15 -0
  14. package/dist/agentSession/backgroundView.js +5 -1
  15. package/dist/agentSession/engineAgentRegistryRead.js +2 -1
  16. package/dist/agentSession/engineSessionBackgroundStop.js +5 -3
  17. package/dist/agentsWireCaps.d.ts +17 -0
  18. package/dist/agentsWireCaps.js +111 -1
  19. package/dist/approvalDecidedByCapability.d.ts +0 -1
  20. package/dist/approvalDecidedByCapability.js +2 -7
  21. package/dist/approvalReachWire.d.ts +18 -0
  22. package/dist/approvalReachWire.js +58 -0
  23. package/dist/approvalsStreamLiveCapability.d.ts +0 -1
  24. package/dist/approvalsStreamLiveCapability.js +15 -14
  25. package/dist/atMostOnce.d.ts +8 -0
  26. package/dist/atMostOnce.js +36 -0
  27. package/dist/attachmentSeatCapability.d.ts +0 -1
  28. package/dist/attachmentSeatCapability.js +0 -3
  29. package/dist/attachmentsWireCaps.js +11 -6
  30. package/dist/bashExitReading.d.ts +10 -0
  31. package/dist/bashExitReading.js +12 -0
  32. package/dist/callerCwdCapability.d.ts +15 -0
  33. package/dist/callerCwdCapability.js +42 -0
  34. package/dist/centerWiringCapability.d.ts +1 -3
  35. package/dist/centerWiringCapability.js +18 -21
  36. package/dist/classifierStatus.js +4 -4
  37. package/dist/cloudConfigWireCaps.js +43 -21
  38. package/dist/compensations.js +1 -1
  39. package/dist/controlRouter.js +3 -10
  40. package/dist/coreValuePorts.d.ts +64 -1
  41. package/dist/coreValuePorts.js +30 -0
  42. package/dist/cycleOrder.d.ts +15 -0
  43. package/dist/cycleOrder.js +45 -0
  44. package/dist/decideFailureNote.js +4 -1
  45. package/dist/decideReceipt.d.ts +2 -1
  46. package/dist/decideReceipt.js +41 -13
  47. package/dist/declared/supportFloorDeclared.d.ts +1 -0
  48. package/dist/declared/supportFloorDeclared.js +5 -0
  49. package/dist/detachWire.d.ts +1 -4
  50. package/dist/detachWire.js +1 -1
  51. package/dist/deviceExecutorManagementCapability.d.ts +0 -1
  52. package/dist/deviceExecutorManagementCapability.js +36 -40
  53. package/dist/deviceFlowPolling.d.ts +5 -0
  54. package/dist/deviceFlowPolling.js +28 -0
  55. package/dist/deviceRebind.d.ts +88 -0
  56. package/dist/deviceRebind.js +242 -0
  57. package/dist/displayUntrusted.d.ts +1 -0
  58. package/dist/displayUntrusted.js +963 -30
  59. package/dist/engineAgentAbsence.d.ts +2 -2
  60. package/dist/engineAgentPanelStore.d.ts +8 -18
  61. package/dist/engineAgentPanelStore.js +19 -537
  62. package/dist/engineCapReader.d.ts +6 -6
  63. package/dist/engineCapReader.js +30 -43
  64. package/dist/engineCapsCache.d.ts +7 -2
  65. package/dist/engineCapsCache.js +64 -26
  66. package/dist/engineCredentialRequirement.d.ts +9 -0
  67. package/dist/engineCredentialRequirement.js +23 -0
  68. package/dist/engineEnvSourcing.d.ts +53 -0
  69. package/dist/engineEnvSourcing.js +81 -0
  70. package/dist/engineErrorCodes.d.ts +19 -4
  71. package/dist/engineErrorCodes.js +39 -21
  72. package/dist/engineIdentity.js +2 -0
  73. package/dist/engineNoticeCodes.d.ts +22 -2
  74. package/dist/engineNoticeCodes.js +73 -6
  75. package/dist/engineRefusedToolName.d.ts +1 -0
  76. package/dist/engineRefusedToolName.js +8 -0
  77. package/dist/engineWireSdk.js +2 -2
  78. package/dist/executionLaneCapability.d.ts +2 -3
  79. package/dist/executionLaneCapability.js +28 -28
  80. package/dist/fileHistoryCaptureCapability.d.ts +0 -1
  81. package/dist/fileHistoryCaptureCapability.js +13 -12
  82. package/dist/fileHistoryLegNotice.d.ts +14 -2
  83. package/dist/fileHistoryLegNotice.js +101 -15
  84. package/dist/fleet/fleetLedger.d.ts +2 -0
  85. package/dist/fleet/fleetLedger.js +74 -52
  86. package/dist/fleet/fleetProjection.d.ts +0 -3
  87. package/dist/fleet/fleetProjection.js +9 -16
  88. package/dist/fleetAgentPanelProjection.d.ts +4 -17
  89. package/dist/fleetAgentPanelProjection.js +7 -197
  90. package/dist/fleetAgentRowLike.d.ts +16 -0
  91. package/dist/fleetAgentRowLike.js +1 -0
  92. package/dist/gateOutcome.d.ts +2 -1
  93. package/dist/gateOutcome.js +33 -18
  94. package/dist/gateVocabulary.js +1 -1
  95. package/dist/generated/engineAskFaceTables.d.ts +3 -0
  96. package/dist/generated/engineAskFaceTables.js +12 -0
  97. package/dist/generated/engineFactTables.d.ts +4 -2
  98. package/dist/generated/engineFactTables.js +13 -0
  99. package/dist/generated/engineNoticeTables.d.ts +5 -0
  100. package/dist/generated/engineNoticeTables.js +7 -0
  101. package/dist/generated/sdkFactTables.d.ts +5 -0
  102. package/dist/generated/sdkFactTables.js +34 -0
  103. package/dist/generated/settingsSchemaFns.d.ts +10 -0
  104. package/dist/generated/settingsSchemaFns.js +22 -0
  105. package/dist/generated/settingsSchemaTables.d.ts +3 -0
  106. package/dist/generated/settingsSchemaTables.js +3 -0
  107. package/dist/headlessPermissionModeWire.d.ts +2 -2
  108. package/dist/headlessPermissionModeWire.js +11 -21
  109. package/dist/headlessReconnectWire.js +49 -20
  110. package/dist/hitl/allowRuleShadow.d.ts +1 -1
  111. package/dist/hitl/allowRuleShadow.js +49 -8
  112. package/dist/hitl/approvalCompleteParked.d.ts +1 -0
  113. package/dist/hitl/approvalCompleteParked.js +14 -0
  114. package/dist/hitl/approvalEndingCause.d.ts +5 -0
  115. package/dist/hitl/approvalEndingCause.js +61 -0
  116. package/dist/hitl/approvalHolds.d.ts +46 -0
  117. package/dist/hitl/approvalHolds.js +140 -0
  118. package/dist/hitl/approvalOutcomeNote.js +2 -1
  119. package/dist/hitl/approvalResolution.js +9 -1
  120. package/dist/hitl/approvalsFeed.js +23 -6
  121. package/dist/hitl/askGateWire.d.ts +2 -1
  122. package/dist/hitl/askGateWire.js +29 -1
  123. package/dist/hitl/automaticAnswerVerdict.d.ts +8 -2
  124. package/dist/hitl/automaticAnswerVerdict.js +71 -23
  125. package/dist/hitl/crashConverged.js +2 -0
  126. package/dist/hitl/decisionConflict.d.ts +3 -0
  127. package/dist/hitl/decisionConflict.js +43 -0
  128. package/dist/hitl/decisionRefusal.d.ts +23 -0
  129. package/dist/hitl/decisionRefusal.js +88 -0
  130. package/dist/hitl/frameRouter.d.ts +10 -0
  131. package/dist/hitl/frameRouter.js +71 -32
  132. package/dist/hitl/gateLedger.d.ts +8 -0
  133. package/dist/hitl/gateLedger.js +38 -0
  134. package/dist/hitl/hitlBridge.d.ts +14 -3
  135. package/dist/hitl/hitlBridge.js +75 -62
  136. package/dist/hitl/hitlHostSurface.d.ts +3 -0
  137. package/dist/hitl/hitlHostSurface.js +17 -15
  138. package/dist/hitl/livePendingAsk.d.ts +16 -6
  139. package/dist/hitl/livePendingAsk.js +36 -4
  140. package/dist/hitl/localAllowRule.js +2 -1
  141. package/dist/hitl/noAllowCause.d.ts +9 -0
  142. package/dist/hitl/noAllowCause.js +26 -0
  143. package/dist/hitl/parkExpiryJudgements.d.ts +19 -0
  144. package/dist/hitl/parkExpiryJudgements.js +46 -0
  145. package/dist/hitl/parkResolver.d.ts +3 -7
  146. package/dist/hitl/parkResolver.js +55 -28
  147. package/dist/hitl/parkRowBirthWait.js +2 -1
  148. package/dist/hitl/persistedRulesWire.d.ts +6 -1
  149. package/dist/hitl/persistedRulesWire.js +16 -4
  150. package/dist/hitl/planReviewWire.d.ts +2 -3
  151. package/dist/hitl/planReviewWire.js +86 -39
  152. package/dist/hitl/replayedApproval.d.ts +8 -0
  153. package/dist/hitl/replayedApproval.js +125 -10
  154. package/dist/hitl/resumeRunningCard.d.ts +2 -0
  155. package/dist/hitl/resumeRunningCard.js +15 -4
  156. package/dist/hitl/sessionPolicyDeliverable.d.ts +1 -1
  157. package/dist/hitl/sessionPolicyDeliverable.js +3 -8
  158. package/dist/hitl/sessionPolicyWire.js +1 -1
  159. package/dist/hitl/toolApprovalWire.d.ts +50 -5
  160. package/dist/hitl/toolApprovalWire.js +368 -56
  161. package/dist/hooksWireCaps.js +38 -6
  162. package/dist/host.d.ts +5 -0
  163. package/dist/host.js +3 -1
  164. package/dist/hostCallbackGuard.d.ts +1 -0
  165. package/dist/hostCallbackGuard.js +25 -0
  166. package/dist/humanTurnRead.d.ts +15 -1
  167. package/dist/humanTurnRead.js +28 -2
  168. package/dist/index.d.ts +45 -14
  169. package/dist/index.js +33 -12
  170. package/dist/interactiveInterrupt.d.ts +8 -0
  171. package/dist/interactiveInterrupt.js +54 -0
  172. package/dist/limitsWire.d.ts +5 -1
  173. package/dist/limitsWire.js +51 -13
  174. package/dist/liveModelCatalog.d.ts +109 -0
  175. package/dist/liveModelCatalog.js +344 -18
  176. package/dist/mcpEngineLeg.d.ts +25 -0
  177. package/dist/mcpEngineLeg.js +71 -15
  178. package/dist/mcpPanel.js +2 -1
  179. package/dist/mcpProbeCapability.d.ts +0 -1
  180. package/dist/mcpProbeCapability.js +13 -12
  181. package/dist/mcpReconnect.d.ts +1 -3
  182. package/dist/mcpReconnect.js +20 -10
  183. package/dist/memoryComplianceCapability.d.ts +0 -1
  184. package/dist/memoryComplianceCapability.js +14 -13
  185. package/dist/memoryOriginCapability.d.ts +0 -1
  186. package/dist/memoryOriginCapability.js +14 -13
  187. package/dist/memoryVerbsWire.d.ts +1 -1
  188. package/dist/memoryVerbsWire.js +4 -0
  189. package/dist/model/liveCatalogShape.d.ts +14 -0
  190. package/dist/model/liveCatalogShape.js +71 -0
  191. package/dist/model/modelSupplyRules.d.ts +1 -0
  192. package/dist/model/modelSupplyRules.js +30 -9
  193. package/dist/model/modelsPolicy.d.ts +21 -0
  194. package/dist/model/modelsPolicy.js +90 -0
  195. package/dist/modelIdentityResolvability.d.ts +4 -2
  196. package/dist/modelIdentityResolvability.js +25 -5
  197. package/dist/modelSwitchFallback.d.ts +69 -0
  198. package/dist/modelSwitchFallback.js +206 -0
  199. package/dist/notifications.js +12 -11
  200. package/dist/outputStyleSeatCapability.d.ts +15 -0
  201. package/dist/outputStyleSeatCapability.js +42 -0
  202. package/dist/ownKey.d.ts +7 -0
  203. package/dist/ownKey.js +58 -0
  204. package/dist/panelReduce.d.ts +114 -0
  205. package/dist/panelReduce.js +1135 -0
  206. package/dist/panelStateHolder.d.ts +17 -0
  207. package/dist/panelStateHolder.js +201 -0
  208. package/dist/peerLaneCapability.d.ts +0 -1
  209. package/dist/peerLaneCapability.js +15 -14
  210. package/dist/permissionModesCapability.d.ts +0 -1
  211. package/dist/permissionModesCapability.js +5 -10
  212. package/dist/permissionRuleIssue.js +1 -1
  213. package/dist/permissionRulesWriteCapability.d.ts +0 -1
  214. package/dist/permissionRulesWriteCapability.js +15 -14
  215. package/dist/permissionsAllowGrantCapability.d.ts +2 -1
  216. package/dist/permissionsAllowGrantCapability.js +35 -19
  217. package/dist/permissionsDeclaration.d.ts +16 -1
  218. package/dist/permissionsDeclaration.js +142 -15
  219. package/dist/printToolResultFrame.js +2 -10
  220. package/dist/promptDelivery.js +0 -8
  221. package/dist/protocolSegment.d.ts +1 -0
  222. package/dist/protocolSegment.js +13 -1
  223. package/dist/request/taskRequest.d.ts +11 -3
  224. package/dist/request/taskRequest.js +13 -1
  225. package/dist/resultFrameKeys.d.ts +4 -0
  226. package/dist/resultFrameKeys.js +13 -0
  227. package/dist/resumeRefusalCopy.d.ts +18 -1
  228. package/dist/resumeRefusalCopy.js +132 -31
  229. package/dist/retryStatus.js +6 -4
  230. package/dist/rewindArchiveCapability.d.ts +2 -1
  231. package/dist/rewindArchiveCapability.js +28 -15
  232. package/dist/rewindEngineAction.d.ts +21 -0
  233. package/dist/rewindEngineAction.js +36 -0
  234. package/dist/rewindWireCaps.d.ts +2 -1
  235. package/dist/rewindWireCaps.js +1 -0
  236. package/dist/{hitl/rosterMountedNames.d.ts → rosterMountedNames.d.ts} +1 -1
  237. package/dist/runCancelContext.js +2 -1
  238. package/dist/runTerminal.d.ts +0 -11
  239. package/dist/runTerminal.js +4 -27
  240. package/dist/sdkRegistryTransit.d.ts +2 -1
  241. package/dist/sdkRegistryTransit.js +1 -0
  242. package/dist/sealedKeyCapability.d.ts +0 -1
  243. package/dist/sealedKeyCapability.js +19 -20
  244. package/dist/seatContract.d.ts +85 -28
  245. package/dist/seatContract.js +512 -148
  246. package/dist/sessionIdSegment.d.ts +1 -0
  247. package/dist/sessionIdSegment.js +11 -0
  248. package/dist/sessionMemoryErase.d.ts +1 -1
  249. package/dist/sessionMemoryErase.js +6 -1
  250. package/dist/sessionMemoryStatus.js +3 -2
  251. package/dist/sessionPolicyCapability.d.ts +0 -1
  252. package/dist/sessionPolicyCapability.js +14 -13
  253. package/dist/sessionReadRedactionCapability.d.ts +15 -0
  254. package/dist/sessionReadRedactionCapability.js +42 -0
  255. package/dist/sessionSyncFileHistoryCapability.d.ts +0 -1
  256. package/dist/sessionSyncFileHistoryCapability.js +13 -12
  257. package/dist/skillToolListsCapability.d.ts +0 -1
  258. package/dist/skillToolListsCapability.js +13 -12
  259. package/dist/skillsWireCaps.d.ts +4 -0
  260. package/dist/skillsWireCaps.js +66 -1
  261. package/dist/sqlEngineCapability.d.ts +0 -1
  262. package/dist/sqlEngineCapability.js +21 -21
  263. package/dist/steerPriorityCapability.d.ts +0 -1
  264. package/dist/steerPriorityCapability.js +18 -19
  265. package/dist/storePostureCapability.d.ts +1 -1
  266. package/dist/storePostureCapability.js +16 -16
  267. package/dist/streamDrainingLegs.d.ts +6 -0
  268. package/dist/streamDrainingLegs.js +23 -0
  269. package/dist/subagent/agentStateDetail.d.ts +1 -0
  270. package/dist/subagent/agentStateDetail.js +41 -0
  271. package/dist/subagent/engineCompactWire.d.ts +15 -0
  272. package/dist/subagent/engineCompactWire.js +82 -45
  273. package/dist/subagent/engineDelegatedPrompt.js +10 -6
  274. package/dist/subagent/engineSubagentOutput.d.ts +0 -1
  275. package/dist/subagent/engineSubagentOutput.js +5 -20
  276. package/dist/subagent/engineSubagentTail.d.ts +0 -1
  277. package/dist/subagent/engineSubagentTail.js +7 -32
  278. package/dist/subagentContentStore.js +3 -3
  279. package/dist/supportFloor.js +2 -5
  280. package/dist/taskRequestWords.d.ts +2 -4
  281. package/dist/taskRequestWords.js +3 -2
  282. package/dist/terminalStatuses.d.ts +30 -0
  283. package/dist/terminalStatuses.js +67 -0
  284. package/dist/toolResult.d.ts +5 -0
  285. package/dist/toolResult.js +88 -36
  286. package/dist/types/engineState.d.ts +2 -1
  287. package/dist/usageAnalytics.d.ts +146 -0
  288. package/dist/usageAnalytics.js +311 -0
  289. package/dist/userAttachmentEnvelope.d.ts +22 -1
  290. package/dist/userAttachmentEnvelope.js +90 -2
  291. package/dist/userInvokedSkillsCapability.d.ts +0 -1
  292. package/dist/userInvokedSkillsCapability.js +13 -12
  293. package/dist/webSearchBackendCapability.d.ts +0 -1
  294. package/dist/webSearchBackendCapability.js +20 -19
  295. package/dist/webSearchWireCaps.js +3 -11
  296. package/dist/wireErrorTriage.d.ts +11 -0
  297. package/dist/wireErrorTriage.js +35 -0
  298. package/dist/wireFailureShape.d.ts +10 -0
  299. package/dist/wireFailureShape.js +72 -5
  300. package/dist/wireRefusalCopy.d.ts +6 -1
  301. package/dist/wireRefusalCopy.js +23 -25
  302. package/dist/wiringInstructionsAttribution.d.ts +10 -0
  303. package/dist/wiringInstructionsAttribution.js +67 -0
  304. package/dist/workflowClient.js +19 -2
  305. package/dist/workflowsJournalCapability.d.ts +0 -1
  306. package/dist/workflowsJournalCapability.js +13 -12
  307. package/dist/writeProtectionCapability.d.ts +0 -1
  308. package/dist/writeProtectionCapability.js +26 -26
  309. package/docs/INTEGRATION-CLIENTS.md +1733 -52
  310. package/package.json +5 -5
  311. package/dist/askSurvivesStandingAnswer.d.ts +0 -13
  312. package/dist/askSurvivesStandingAnswer.js +0 -53
  313. package/dist/engineCapsGenerationGuard.d.ts +0 -4
  314. package/dist/engineCapsGenerationGuard.js +0 -19
  315. package/dist/hitl/askSurvivesPosture.d.ts +0 -20
  316. package/dist/hitl/askSurvivesPosture.js +0 -48
  317. package/dist/panelRunningHistory.d.ts +0 -22
  318. package/dist/panelRunningHistory.js +0 -82
  319. package/dist/registryConflict.d.ts +0 -3
  320. package/dist/registryConflict.js +0 -44
  321. /package/dist/{hitl/rosterMountedNames.js → rosterMountedNames.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { SETTINGS_SECRET_LITERAL_RE } from './generated/settingsSchemaTables.js';
1
+ import { SETTINGS_PRIVATE_KEY_PEM_HEADER, SETTINGS_SECRET_LITERAL_RE } from './generated/settingsSchemaTables.js';
2
2
  export const REDACTION_MARKER_PREFIX = '\u00abredacted';
3
3
  const MARKER_RE = /^\u00abredacted(?::[a-z-]{1,16}){0,2}\u00bb$/;
4
4
  const REDACTED_USERINFO = '\u00abredacted:userinfo\u00bb';
@@ -28,9 +28,12 @@ const UNIT_NONE = 0;
28
28
  const UNIT_SEQUENCE = 1;
29
29
  const UNIT_SINGLE = 2;
30
30
  const SECRET_LITERAL_RE = SETTINGS_SECRET_LITERAL_RE;
31
+ const PRIVATE_KEY_PEM_HEADER = SETTINGS_PRIVATE_KEY_PEM_HEADER;
31
32
  const SCHEME_TOKEN_RE = /(?:^|[^A-Za-z0-9_-])(?:bearer|basic)[ \t]+\S{8,4096}/i;
32
33
  const JWT_RE = /(?:^|[^A-Za-z0-9_-])eyJ[A-Za-z0-9_-]{8,2048}\.[A-Za-z0-9_-]{8,2048}\.[A-Za-z0-9_-]{4,2048}/i;
33
34
  function scanForSecretLiteral(s) {
35
+ if (PRIVATE_KEY_PEM_HEADER.test(s))
36
+ return true;
34
37
  if (SECRET_LITERAL_RE.test(s) || SCHEME_TOKEN_RE.test(s) || JWT_RE.test(s))
35
38
  return true;
36
39
  return s.split(/[^A-Za-z0-9_-]+/).some(tok => tok !== '' && SECRET_LITERAL_RE.test(tok));
@@ -100,8 +103,8 @@ function valueIsWholeMarker(S, start, end, tokenInner = true) {
100
103
  return j >= end || !isKeyWordChar(text.charCodeAt(j)) || credentialWordStartsExactlyAt(text, j, tokenInner) || credentialPairAt(S, j);
101
104
  }
102
105
  const CREDENTIAL_NAME = /(?:(?:access|refresh|id|client|api|x[-_]api|session|auth)[-_]?)?(?:token|key|secret|password|authorization|credential)s?|bearer|basic/iy;
103
- const LABEL_SEPARATOR = /(?:\\*["'])?[\s\u115F\u1160\u3164\uFFA0\u2800]*[:=\uFF1A\uFF1D]/y;
104
- const SCHEME_SEPARATOR = /[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]/y;
106
+ const LABEL_SEPARATOR = /(?:\\*["'])?(?:[\s\u115F\u1160\u3164\uFFA0\u2800]|\\t)*[:=\uFF1A\uFF1D]/y;
107
+ const SCHEME_SEPARATOR = /(?:[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]|\\t)/y;
105
108
  function credentialPairAt(S, at) {
106
109
  const text = S.text;
107
110
  const re = new RegExp(CREDENTIAL_NAME.source, 'iy');
@@ -283,15 +286,22 @@ function pathCandidates(src, base, path, opaqueSegments, edits, soft) {
283
286
  for (const segment of path.split('/')) {
284
287
  const semi = segment.indexOf(';');
285
288
  const head = semi === -1 ? segment : segment.slice(0, semi);
286
- if (opaqueSegments && isKnownSecretSegment(head)) {
289
+ if (opaqueSegments) {
287
290
  let a = 0;
288
291
  let b = head.length;
289
292
  while (a < b && !isKeyWordChar(head.charCodeAt(a)))
290
293
  a++;
291
294
  while (b > a && !isKeyWordChar(head.charCodeAt(b - 1)))
292
295
  b--;
293
- if (b > a)
294
- pushEdit(edits, src, pos + a, pos + b, REDACTED_SECRET);
296
+ if (isKnownSecretSegment(head)) {
297
+ if (b > a)
298
+ pushEdit(edits, src, pos + a, pos + b, REDACTED_SECRET);
299
+ }
300
+ else if (b > a) {
301
+ const glued = gluedLiteralStart(head.slice(a, b));
302
+ if (glued > 0)
303
+ pushEdit(edits, src, pos + a + glued, pos + b, REDACTED_SECRET);
304
+ }
295
305
  }
296
306
  if (semi !== -1) {
297
307
  let ppos = pos + semi + 1;
@@ -398,6 +408,7 @@ function urlCandidates(text, out, regions, unitPos = () => false, soft) {
398
408
  runStart--;
399
409
  if (runStart < end && !VALUE_BOUNDARY_TAIL.test(text.slice(start, runStart)))
400
410
  end = runStart;
411
+ end = trailingCloserEnd(text, start, mark + 3, end, unitPos);
401
412
  const tokenEdits = [];
402
413
  urlTokenCandidatesAt(text, start, end, tokenEdits, soft);
403
414
  editsToCandidates(tokenEdits, 'url', out, end);
@@ -417,6 +428,47 @@ function urlCandidates(text, out, regions, unitPos = () => false, soft) {
417
428
  mark = text.indexOf('://', end > mark + 3 ? end : mark + 3);
418
429
  }
419
430
  }
431
+ function trailingCloserEnd(text, start, floor, end, unitPos) {
432
+ const opens = new Map();
433
+ const closes = new Map();
434
+ for (const [o, c] of BRACKET_PAIRS) {
435
+ opens.set(o, 0);
436
+ closes.set(c, 0);
437
+ }
438
+ for (let k = start; k < end; k++) {
439
+ if (unitPos(k))
440
+ continue;
441
+ const ch = text.charAt(k);
442
+ const o = opens.get(ch);
443
+ if (o !== undefined)
444
+ opens.set(ch, o + 1);
445
+ const c = closes.get(ch);
446
+ if (c !== undefined)
447
+ closes.set(ch, c + 1);
448
+ }
449
+ let e = end;
450
+ for (;;) {
451
+ if (e <= floor || unitPos(e - 1))
452
+ return e;
453
+ const ch = text.charAt(e - 1);
454
+ const c = closes.get(ch);
455
+ if (c === undefined)
456
+ return e;
457
+ let open = '';
458
+ for (const [o, cl] of BRACKET_PAIRS)
459
+ if (cl === ch)
460
+ open = o;
461
+ if (c <= (opens.get(open) ?? 0))
462
+ return e;
463
+ closes.set(ch, c - 1);
464
+ e--;
465
+ let runStart = e;
466
+ while (runStart > floor && TRAILING_PUNCTUATION.has(text.charAt(runStart - 1)))
467
+ runStart--;
468
+ if (runStart < e && !VALUE_BOUNDARY_TAIL.test(text.slice(start, runStart)))
469
+ e = runStart;
470
+ }
471
+ }
420
472
  function atInAuthority(text, from) {
421
473
  for (let p = from; p < text.length; p++) {
422
474
  const ch = text.charAt(p);
@@ -760,9 +812,9 @@ const NAME_BLANK_RANGES = [
760
812
  const isNameBlank = (cp) => NAME_BLANK_RANGES.some(([a, b]) => cp >= a && cp <= b);
761
813
  const isFoldedBlank = (c) => isNameBlank(c) && isRegexSpace(c);
762
814
  const isUnicodeBlank = (c) => (c > 0x7f && isRegexSpace(c) && c !== 0xfeff) || isNameBlank(c);
763
- const SECRET_SCHEME_WORD = /(?:\b|(?<=\\[A-Za-z"']))(bearer|basic|token)[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]+/gi;
815
+ const SECRET_SCHEME_WORD = /(?:\b|(?<=\\[A-Za-z"']))(?!(?<=(?<!\\)\\)(?:bearer|basic|token)\\t)(bearer|basic|token)(?:[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]|\\t)+/gi;
764
816
  const schemeWordIsInner = (word, tokenInner) => tokenInner || word.toLowerCase() !== 'token';
765
- const SECRET_LABELLED_WORD = /(?:\b|(?<=_)|(?<=\\[A-Za-z"']))((?:access[-_ ]?|refresh[-_ ]?|id[-_ ]?|client[-_ ]?|api[-_ ]?|x[-_]api[-_ ]?|session[-_ ]?|auth[-_ ]?)?(?:token|key|secret|password|authorization|credential)s?)(?:\\*["'])?[\s\u115F\u1160\u3164\uFFA0\u2800]*[:=\uFF1A\uFF1D][\s\u115F\u1160\u3164\uFFA0\u2800]*/gi;
817
+ const SECRET_LABELLED_WORD = /(?:\b|(?<=_)|(?<=\\[A-Za-z"']))((?:access[-_ ]?|refresh[-_ ]?|id[-_ ]?|client[-_ ]?|api[-_ ]?|x[-_]api[-_ ]?|session[-_ ]?|auth[-_ ]?)?(?:token|key|secret|password|authorization|credential)s?)(?:\\*["'])?(?:[\s\u115F\u1160\u3164\uFFA0\u2800]|\\t)*[:=\uFF1A\uFF1D](?:[\s\u115F\u1160\u3164\uFFA0\u2800]|\\t)*/gi;
766
818
  const DIAGNOSTIC_VALUE_WORDS = new Set([
767
819
  'missing', 'required', 'invalid', 'expired', 'unauthorized', 'unauthenticated', 'authentication',
768
820
  'authorization', 'credential', 'credentials', 'unsupported', 'malformed', 'rejected', 'absent',
@@ -817,18 +869,67 @@ const AUTH_SCHEME_WORDS = new Set([
817
869
  const AUTH_SIGNATURE_SCHEME = /^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+){2,}$/;
818
870
  const BARE_VALUE_STOP_CHARS = new Set([',', ';', '"', "'", '\\', '(', ')', '[', ']', '{', '}', '<', '>']);
819
871
  const isBareValueStop = (ch) => ch <= ' ' || BARE_VALUE_STOP_CHARS.has(ch);
872
+ function isPlainAt(S, rawUnit, k) {
873
+ if (S.dropped(k) || S.painted(k) || S.unitAt(k) !== UNIT_NONE)
874
+ return false;
875
+ return rawUnit === null || rawUnit[S.rawStart(k)] !== 1;
876
+ }
877
+ function codeSpanClose(text, plain) {
878
+ const n = text.length;
879
+ const close = new Int32Array(n + 1).fill(-1);
880
+ let openLen = 0;
881
+ let spanFrom = -1;
882
+ let k = 0;
883
+ while (k < n) {
884
+ const c = text.charCodeAt(k);
885
+ if (c === 0x0a || c === 0x0d || c === 0x2028 || c === 0x2029) {
886
+ openLen = 0;
887
+ spanFrom = -1;
888
+ k++;
889
+ continue;
890
+ }
891
+ if (c !== 0x60 || !plain(k)) {
892
+ k++;
893
+ continue;
894
+ }
895
+ let e = k;
896
+ while (e < n && text.charCodeAt(e) === 0x60 && plain(e))
897
+ e++;
898
+ const len = e - k;
899
+ if (openLen === 0) {
900
+ openLen = len;
901
+ spanFrom = e;
902
+ }
903
+ else if (len === openLen) {
904
+ for (let x = spanFrom; x < k; x++)
905
+ close[x] = k;
906
+ openLen = 0;
907
+ spanFrom = -1;
908
+ }
909
+ k = e;
910
+ }
911
+ return close;
912
+ }
913
+ const BRACKET_PAIRS = new Map([['(', ')'], ['[', ']']]);
820
914
  class InnerWordIndex {
821
915
  text;
822
916
  tokenInner;
823
917
  probes;
824
- constructor(text, tokenInner = true) {
918
+ plain;
919
+ spanClose = null;
920
+ constructor(text, tokenInner = true, plain = () => true) {
825
921
  this.text = text;
826
922
  this.tokenInner = tokenInner;
923
+ this.plain = plain;
827
924
  this.probes = [
828
925
  { re: new RegExp(SECRET_LABELLED_WORD.source, SECRET_LABELLED_WORD.flags), scheme: false, from: -1, hit: null },
829
926
  { re: new RegExp(SECRET_SCHEME_WORD.source, SECRET_SCHEME_WORD.flags), scheme: true, from: -1, hit: null },
830
927
  ];
831
928
  }
929
+ closingTickFrom(i) {
930
+ this.spanClose ??= codeSpanClose(this.text, this.plain);
931
+ return this.spanClose[i] ?? -1;
932
+ }
832
933
  next(q) {
833
934
  let best = null;
834
935
  for (const p of this.probes) {
@@ -854,6 +955,45 @@ class InnerWordIndex {
854
955
  return best;
855
956
  }
856
957
  }
958
+ const WRAPPED_PLACEHOLDER = /^(?:[A-Z]{1,12}(?:_[A-Z]{1,12})*|[a-z]{1,12}(?:-[a-z]{1,12})*)$/;
959
+ function wrappedValueAt(text, from, idx) {
960
+ let k = from;
961
+ while (k < text.length && text[k] === VIEW_SEPARATOR)
962
+ k++;
963
+ const close = BRACKET_PAIRS.get(text.charAt(k));
964
+ if (close === undefined || credentialWordStartsAt(text, k + 1, idx.tokenInner))
965
+ return null;
966
+ const inner = scanSecretValue(text, k + 1, idx);
967
+ if (inner === null || inner.start !== k + 1)
968
+ return null;
969
+ let c = inner.end;
970
+ while (c < text.length && text[c] === VIEW_SEPARATOR)
971
+ c++;
972
+ if (text.charAt(c) !== close || (close === ']' && text.charAt(c + 1) === '('))
973
+ return null;
974
+ return inner;
975
+ }
976
+ function tokenSchemeValueEnd(text, start, end, idx) {
977
+ if (withoutSeparators(text.slice(start, end)).toLowerCase() !== 'token')
978
+ return -1;
979
+ const re = new RegExp(SECRET_SCHEME_WORD.source, 'iy');
980
+ re.lastIndex = start;
981
+ const m = re.exec(text);
982
+ if (m === null || (m[1] ?? '').toLowerCase() !== 'token')
983
+ return -1;
984
+ const sepEnd = start + m[0].length;
985
+ if (/[\n\r\u2028\u2029:=\uFF1A\uFF1D]/.test(text.slice(start + (m[1] ?? '').length, sepEnd)))
986
+ return -1;
987
+ if (credentialWordStartsAt(text, sepEnd, idx.tokenInner))
988
+ return -1;
989
+ const iv = scanSecretValue(text, sepEnd, idx);
990
+ if (iv === null)
991
+ return -1;
992
+ const inner = withoutSeparators(text.slice(iv.start, iv.end));
993
+ if (schemeFollowerReleased('token', inner, false) || isDiagnosticWord(inner))
994
+ return -1;
995
+ return iv.end;
996
+ }
857
997
  function innerWordFits(text, w) {
858
998
  for (let k = w.start; k <= w.sepAt && k < text.length; k++)
859
999
  if (isBareValueStop(text.charAt(k)))
@@ -909,6 +1049,7 @@ function scanSecretValue(text, from, idx) {
909
1049
  let pending = cuttable ? idx.next(i + 1) : null;
910
1050
  let cut = false;
911
1051
  let j = i;
1052
+ const closingTick = idx === undefined ? -1 : idx.closingTickFrom(i);
912
1053
  while (j < text.length) {
913
1054
  if (pending !== null && j >= pending.start) {
914
1055
  if (j === pending.start && innerWordFits(text, pending)) {
@@ -933,6 +1074,18 @@ function scanSecretValue(text, from, idx) {
933
1074
  }
934
1075
  while (j > i && text[j - 1] === VIEW_SEPARATOR)
935
1076
  j--;
1077
+ if (closingTick > i && closingTick < j) {
1078
+ let t = closingTick;
1079
+ while (t < j && text.charCodeAt(t) === 0x60)
1080
+ t++;
1081
+ while (t < j && TRAILING_PUNCTUATION.has(text.charAt(t)))
1082
+ t++;
1083
+ if (t === j && text.charCodeAt(closingTick) === 0x60) {
1084
+ j = closingTick;
1085
+ while (j > i && text[j - 1] === VIEW_SEPARATOR)
1086
+ j--;
1087
+ }
1088
+ }
936
1089
  if (cut) {
937
1090
  while (j > i && isCutDelimiter(text.charAt(j - 1))) {
938
1091
  j--;
@@ -952,6 +1105,9 @@ function isDiagnosticValue(value, raw = value) {
952
1105
  return true;
953
1106
  if (ADDRESS_SCHEME_RE.test(raw))
954
1107
  return true;
1108
+ return isDiagnosticWord(value);
1109
+ }
1110
+ function isDiagnosticWord(value) {
955
1111
  const bare = value.replace(/^\.+/, '').replace(/[.,;:!?)\]}'"]{0,8}$/, '').toLowerCase();
956
1112
  return bare === '' || DIAGNOSTIC_VALUE_WORDS.has(bare);
957
1113
  }
@@ -1011,6 +1167,26 @@ function isNamedNotValue(label, value) {
1011
1167
  return true;
1012
1168
  return isBacktickedCredentialName(value);
1013
1169
  }
1170
+ function schemeIsLabelValue(text, at) {
1171
+ let k = at;
1172
+ while (k > 0 && text[k - 1] === VIEW_SEPARATOR)
1173
+ k--;
1174
+ if (k > 0 && isQuoteChar(text.charAt(k - 1))) {
1175
+ k--;
1176
+ while (k > 0 && text.charCodeAt(k - 1) === 0x5c)
1177
+ k--;
1178
+ }
1179
+ return k > 0 && labelEndsAt(text, k);
1180
+ }
1181
+ function labelQuotedAt(text, at, sep) {
1182
+ const q = text.charAt(at - 1);
1183
+ if (!isQuoteChar(q))
1184
+ return false;
1185
+ let k = 0;
1186
+ while (sep.charCodeAt(k) === 0x5c)
1187
+ k++;
1188
+ return sep.charAt(k) === q;
1189
+ }
1014
1190
  function labelStartsAt(text, at) {
1015
1191
  const re = new RegExp(SECRET_LABELLED_WORD.source, 'iy');
1016
1192
  re.lastIndex = at;
@@ -1474,13 +1650,467 @@ function quotedAddressEnd(S, from, to) {
1474
1650
  }
1475
1651
  return to;
1476
1652
  }
1653
+ function isInlineBlank(ch) {
1654
+ if (ch === VIEW_SEPARATOR)
1655
+ return true;
1656
+ const c = ch.charCodeAt(0);
1657
+ if (c === 0x0a || c === 0x0d || c === 0x2028 || c === 0x2029)
1658
+ return false;
1659
+ return isRegexSpace(c) || isNameBlank(c);
1660
+ }
1661
+ const isAnyBlank = (ch) => ch === VIEW_SEPARATOR || isRegexSpace(ch.charCodeAt(0)) || isNameBlank(ch.charCodeAt(0));
1662
+ function nodePropertyEnd(text, at) {
1663
+ const sigil = text.charAt(at);
1664
+ let j = at + 1;
1665
+ if (sigil === '!') {
1666
+ if (text.charAt(j) === '<') {
1667
+ const limit = Math.min(text.length, j + 512);
1668
+ let k = j + 1;
1669
+ while (k < limit && text.charAt(k) !== '>' && !isAnyBlank(text.charAt(k)))
1670
+ k++;
1671
+ if (text.charAt(k) !== '>' || k === j + 1)
1672
+ return -1;
1673
+ j = k + 1;
1674
+ }
1675
+ else {
1676
+ while (j < text.length && !isBareValueStop(text.charAt(j)))
1677
+ j++;
1678
+ }
1679
+ }
1680
+ else if (sigil === '&') {
1681
+ while (j < text.length && !isBareValueStop(text.charAt(j)))
1682
+ j++;
1683
+ if (j === at + 1)
1684
+ return -1;
1685
+ }
1686
+ else
1687
+ return -1;
1688
+ return j < text.length && isInlineBlank(text.charAt(j)) ? j : -1;
1689
+ }
1690
+ function nodeProperties(text, from) {
1691
+ let i = from;
1692
+ while (text.charAt(i) === VIEW_SEPARATOR)
1693
+ i++;
1694
+ const start = i;
1695
+ let end = -1;
1696
+ for (;;) {
1697
+ const c = text.charAt(i);
1698
+ if (c !== '!' && c !== '&')
1699
+ break;
1700
+ const e = nodePropertyEnd(text, i);
1701
+ if (e === -1)
1702
+ break;
1703
+ end = e;
1704
+ i = e;
1705
+ while (i < text.length && isInlineBlank(text.charAt(i)))
1706
+ i++;
1707
+ }
1708
+ return end === -1 ? null : { start, end, next: i };
1709
+ }
1710
+ function propertiesSameLine(S, pr) {
1711
+ if (pr.next >= S.text.length)
1712
+ return false;
1713
+ const a = S.rawStart(pr.start);
1714
+ const b = S.rawStart(pr.next);
1715
+ return b >= a && !/[\n\r\u2028\u2029\u0085]/.test(S.raw.slice(a, b));
1716
+ }
1717
+ function hasValueAt(text, at) {
1718
+ if (at >= text.length)
1719
+ return false;
1720
+ const c = text.charAt(at);
1721
+ if (c === '|' || c === '>' || c === '[' || c === '\\' || isQuoteChar(c))
1722
+ return true;
1723
+ return !isBareValueStop(c) && c !== VIEW_SEPARATOR;
1724
+ }
1725
+ const SGR_REMNANT = /^\[[0-9;]*m(?:\u00abredacted|\s|$)/;
1726
+ function bracketPairs(text) {
1727
+ const pairs = new Int32Array(text.length).fill(-1);
1728
+ const stack = [];
1729
+ for (let i = 0; i < text.length; i++) {
1730
+ const c = text.charCodeAt(i);
1731
+ if (c === 0x5b)
1732
+ stack.push(i);
1733
+ else if (c === 0x5d) {
1734
+ const o = stack.pop();
1735
+ if (o !== undefined)
1736
+ pairs[o] = i;
1737
+ }
1738
+ }
1739
+ return pairs;
1740
+ }
1741
+ const LIST_NEUTRAL_ITEM = /^(?:object Object|Object|Array|Circular|Getter|Setter|Getter\/Setter|native code|hidden|masked|omitted|truncated)$/i;
1742
+ function afterClosingQuote(text, end) {
1743
+ let k = end;
1744
+ while (text.charAt(k) === VIEW_SEPARATOR)
1745
+ k++;
1746
+ let q = k;
1747
+ while (text.charCodeAt(q) === 0x5c)
1748
+ q++;
1749
+ const c = text.charAt(q);
1750
+ return isQuoteChar(c) ? q + 1 : end;
1751
+ }
1752
+ function matchBrace(text, open) {
1753
+ let depth = 0;
1754
+ let quote = '';
1755
+ for (let i = open; i < text.length; i++) {
1756
+ const c = text.charAt(i);
1757
+ if (quote !== '') {
1758
+ if (c === '\\')
1759
+ i++;
1760
+ else if (c === quote)
1761
+ quote = '';
1762
+ continue;
1763
+ }
1764
+ if (isQuoteChar(c))
1765
+ quote = c;
1766
+ else if (c === '{')
1767
+ depth++;
1768
+ else if (c === '}' && --depth === 0)
1769
+ return i;
1770
+ }
1771
+ return text.length;
1772
+ }
1773
+ function flowListItems(text, open, idx, budget) {
1774
+ if (budget.left <= 0 || SGR_REMNANT.test(text.slice(open, open + 32)))
1775
+ return null;
1776
+ budget.pairs ??= bracketPairs(text);
1777
+ const plainClose = budget.pairs[open] ?? -1;
1778
+ if (plainClose >= 0 && text.charAt(plainClose + 1) === '(')
1779
+ return null;
1780
+ const out = flowListScan(text, open, idx);
1781
+ budget.left -= out.end - open;
1782
+ return out.link ? null : { items: out.items, end: out.end };
1783
+ }
1784
+ function flowListScan(text, open, idx) {
1785
+ const items = [];
1786
+ const n = text.length;
1787
+ let depth = 0;
1788
+ let i = open;
1789
+ while (i < n) {
1790
+ const ch = text.charAt(i);
1791
+ if (ch === '[') {
1792
+ depth++;
1793
+ i++;
1794
+ continue;
1795
+ }
1796
+ if (ch === ']') {
1797
+ depth--;
1798
+ i++;
1799
+ if (depth <= 0)
1800
+ return { items, end: i, link: text.charAt(i) === '(' };
1801
+ continue;
1802
+ }
1803
+ if (ch === ',' || ch === '}' || isAnyBlank(ch) || ch === '\n' || ch === '\r') {
1804
+ i++;
1805
+ continue;
1806
+ }
1807
+ const escapedBreak = ch === '\\' ? lineBreakLengthAt(text, i) : 0;
1808
+ if (escapedBreak > 0) {
1809
+ i += escapedBreak;
1810
+ continue;
1811
+ }
1812
+ if (ch === '{') {
1813
+ const e = matchBrace(text, i);
1814
+ if (e > i + 1)
1815
+ items.push({ start: i + 1, end: e });
1816
+ i = Math.min(n, e + 1);
1817
+ continue;
1818
+ }
1819
+ let q = i;
1820
+ while (text.charCodeAt(q) === 0x5c)
1821
+ q++;
1822
+ if (isQuoteChar(text.charAt(q))) {
1823
+ const v = scanSecretValue(text, i, idx);
1824
+ if (v === null) {
1825
+ i = q + 1;
1826
+ continue;
1827
+ }
1828
+ items.push({ start: v.start, end: v.end, quoted: true });
1829
+ i = Math.max(afterClosingQuote(text, v.end), i + 1);
1830
+ continue;
1831
+ }
1832
+ let j = i;
1833
+ while (j < n) {
1834
+ const c = text.charAt(j);
1835
+ if (c === ',' || c === ']' || c === '[' || c === '{' || c === '}' || c === '\n' || c === '\r' || (c === '\\' && lineBreakLengthAt(text, j) > 0))
1836
+ break;
1837
+ j++;
1838
+ }
1839
+ let e = j;
1840
+ while (e > i && isAnyBlank(text.charAt(e - 1)))
1841
+ e--;
1842
+ if (e > i)
1843
+ items.push({ start: i, end: e });
1844
+ i = j > i ? j : i + 1;
1845
+ }
1846
+ return { items, end: n, link: false };
1847
+ }
1848
+ const PAIR_ITEM = /^[A-Za-z_][A-Za-z0-9_.-]*(?:=|:(?!\/))[^\s,;]/;
1849
+ function lineBreakAtView(S, k) {
1850
+ const ch = S.text.charAt(k);
1851
+ if (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029')
1852
+ return true;
1853
+ if (ch !== VIEW_SEPARATOR)
1854
+ return false;
1855
+ const a = S.rawStart(k);
1856
+ return /[\n\r\u2028\u2029\u0085]/.test(S.raw.slice(a, Math.max(a + 1, S.rawEnd(k))));
1857
+ }
1858
+ function scanListItem(S, i, idx) {
1859
+ const text = S.text;
1860
+ const v = scanSecretValue(text, i, idx);
1861
+ if (v === null)
1862
+ return null;
1863
+ let q = i;
1864
+ while (text.charCodeAt(q) === 0x5c)
1865
+ q++;
1866
+ if (isQuoteChar(text.charAt(q)))
1867
+ return v;
1868
+ for (let k = v.start; k < v.end; k++) {
1869
+ if (text.charAt(k) !== VIEW_SEPARATOR || !lineBreakAtView(S, k))
1870
+ continue;
1871
+ let e = k;
1872
+ while (e > v.start && text.charAt(e - 1) === VIEW_SEPARATOR)
1873
+ e--;
1874
+ return e > v.start ? { start: v.start, end: e } : null;
1875
+ }
1876
+ return v;
1877
+ }
1878
+ function commaListTail(S, from, idx) {
1879
+ const text = S.text;
1880
+ const items = [];
1881
+ const n = text.length;
1882
+ let i = from;
1883
+ let end = from;
1884
+ for (;;) {
1885
+ let k = i;
1886
+ while (k < n && isInlineBlank(text.charAt(k)) && !lineBreakAtView(S, k))
1887
+ k++;
1888
+ if (text.charAt(k) !== ',')
1889
+ break;
1890
+ k++;
1891
+ while (k < n && isInlineBlank(text.charAt(k)) && !lineBreakAtView(S, k))
1892
+ k++;
1893
+ if (k >= n || credentialWordStartsAt(text, k, idx.tokenInner) || PAIR_ITEM.test(text.slice(k, k + 256)))
1894
+ break;
1895
+ let q = k;
1896
+ while (text.charCodeAt(q) === 0x5c)
1897
+ q++;
1898
+ const quotedItem = isQuoteChar(text.charAt(q));
1899
+ if (q > k && !quotedItem)
1900
+ break;
1901
+ const v = scanListItem(S, k, idx);
1902
+ if (v === null)
1903
+ break;
1904
+ const after = quotedItem ? afterClosingQuote(text, v.end) : v.end;
1905
+ let t = after;
1906
+ let lineEnd = false;
1907
+ while (t < n && isInlineBlank(text.charAt(t))) {
1908
+ if (lineBreakAtView(S, t)) {
1909
+ lineEnd = true;
1910
+ break;
1911
+ }
1912
+ t++;
1913
+ }
1914
+ const term = text.charAt(t);
1915
+ const stops = lineEnd || t >= n || term === ',' || term === ';' || term === ')' || term === ']' || term === '}' || term === '\\' || isQuoteChar(term) || term === '\n' || term === '\r';
1916
+ if (!stops)
1917
+ break;
1918
+ items.push(v);
1919
+ i = after;
1920
+ end = after;
1921
+ }
1922
+ return { items, end };
1923
+ }
1924
+ function viewIndexOfRaw(S, p) {
1925
+ let lo = 0;
1926
+ let hi = S.text.length;
1927
+ while (lo < hi) {
1928
+ const mid = (lo + hi) >> 1;
1929
+ if (S.rawStart(mid) < p)
1930
+ lo = mid + 1;
1931
+ else
1932
+ hi = mid;
1933
+ }
1934
+ while (lo < S.text.length && S.text.charAt(lo) === VIEW_SEPARATOR)
1935
+ lo++;
1936
+ return lo;
1937
+ }
1938
+ function dotsBeforeMarker(raw, p) {
1939
+ let k = p;
1940
+ while (raw.charCodeAt(k) === 0x2e)
1941
+ k++;
1942
+ if (k === p)
1943
+ return p;
1944
+ let m = k;
1945
+ while (m < k + 3 && (raw.charCodeAt(m) === 0x5c || raw.charCodeAt(m) === 0x22 || raw.charCodeAt(m) === 0x27))
1946
+ m++;
1947
+ if (raw.startsWith(REDACTION_MARKER_PREFIX, m) || /^\[[0-9;]{0,12}m\u00abredacted/.test(raw.slice(k, k + 24)))
1948
+ return k;
1949
+ return p;
1950
+ }
1951
+ function escapedBlankLen(raw, p) {
1952
+ if (raw.charCodeAt(p) !== 0x5c || raw.charCodeAt(p + 1) !== 0x75)
1953
+ return 0;
1954
+ const hex = raw.slice(p + 2, p + 6);
1955
+ return /^[0-9A-Fa-f]{4}$/.test(hex) && isRawBlank(Number.parseInt(hex, 16)) ? 6 : 0;
1956
+ }
1957
+ function dotsBeforeDash(raw, p) {
1958
+ let k = p;
1959
+ while (raw.charCodeAt(k) === 0x2e)
1960
+ k++;
1961
+ return k > p && raw.charCodeAt(k) === 0x2d ? k : p;
1962
+ }
1963
+ function dashEntryAt(scan, p, escaped) {
1964
+ const raw = scan.raw;
1965
+ if (raw.charCodeAt(p) !== 0x2d)
1966
+ return false;
1967
+ if (p + 1 >= raw.length)
1968
+ return true;
1969
+ return isRawBlank(raw.charCodeAt(p + 1)) || scan.view.rawUnit[p + 1] === 1 || blockBreakAt(raw, p + 1, escaped) > 0 || escapedBlankLen(raw, p + 1) > 0 || dotsBeforeMarker(raw, p + 1) !== p + 1;
1970
+ }
1971
+ function lineContentStart(scan, lines, i, skipDots = true) {
1972
+ const raw = scan.raw;
1973
+ const unit = scan.view.rawUnit;
1974
+ const { seq, payload } = blockMarks(scan);
1975
+ const end = lines.ends[i] ?? raw.length;
1976
+ let k = lines.starts[i] ?? 0;
1977
+ while (k < end) {
1978
+ if (payload[k] === 1)
1979
+ break;
1980
+ if (seq[k] === 1 || isRawBlank(raw.charCodeAt(k)) || unit[k] === 1)
1981
+ k++;
1982
+ else if (escapedBlankLen(raw, k) > 0)
1983
+ k += 6;
1984
+ else
1985
+ break;
1986
+ }
1987
+ return skipDots && k < end ? dotsBeforeDash(raw, k) : k;
1988
+ }
1989
+ function seqLineIndent(scan, lines, i) {
1990
+ const base = lines.indent[i] ?? -1;
1991
+ if (base < 0)
1992
+ return base;
1993
+ const raw = scan.raw;
1994
+ const unit = scan.view.rawUnit;
1995
+ const { seq, payload } = blockMarks(scan);
1996
+ const end = lines.ends[i] ?? raw.length;
1997
+ let k = lines.starts[i] ?? 0;
1998
+ let width = 0;
1999
+ while (k < end) {
2000
+ if (payload[k] === 1)
2001
+ break;
2002
+ if (escapedBlankLen(raw, k) > 0) {
2003
+ width++;
2004
+ k += 6;
2005
+ }
2006
+ else if (seq[k] === 1)
2007
+ k++;
2008
+ else if (isRawBlank(raw.charCodeAt(k))) {
2009
+ width++;
2010
+ k++;
2011
+ }
2012
+ else if (unit[k] === 1)
2013
+ k++;
2014
+ else
2015
+ break;
2016
+ }
2017
+ if (k < end) {
2018
+ const d = dotsBeforeDash(raw, k);
2019
+ width += d - k;
2020
+ }
2021
+ return width;
2022
+ }
2023
+ function blockSeqEntries(scan, rawFrom, rawLabel) {
2024
+ const raw = scan.raw;
2025
+ const unit = scan.view.rawUnit;
2026
+ let p = dotsBeforeDash(raw, rawFrom);
2027
+ let escaped = false;
2028
+ if (raw.charCodeAt(p) === 0x5c && lineBreakLengthAt(raw, p) > 0) {
2029
+ escaped = true;
2030
+ for (;;) {
2031
+ const n = lineBreakLengthAt(raw, p);
2032
+ if (n === 0 || raw.charCodeAt(p) !== 0x5c)
2033
+ break;
2034
+ p += n;
2035
+ while (p < raw.length && (isRawBlank(raw.charCodeAt(p)) || unit[p] === 1 || escapedBlankLen(raw, p) > 0)) {
2036
+ const n = escapedBlankLen(raw, p);
2037
+ p += n > 0 ? n : 1;
2038
+ }
2039
+ p = dotsBeforeDash(raw, p);
2040
+ }
2041
+ }
2042
+ if (!dashEntryAt(scan, p, escaped))
2043
+ return null;
2044
+ const lines = blockLines(scan, escaped);
2045
+ const first = blockLineOf(lines, p);
2046
+ const labelLine = blockLineOf(lines, rawLabel);
2047
+ const labelIndent = Math.max(0, lines.indent[labelLine] ?? 0);
2048
+ const entryIndent = seqLineIndent(scan, lines, first);
2049
+ const labelHead = lineContentStart(scan, lines, labelLine, false);
2050
+ const labelFirst = rawLabel >= labelHead && !/\s/.test(raw.slice(labelHead, rawLabel));
2051
+ if (lineContentStart(scan, lines, first) !== p || entryIndent < 0 || (labelFirst ? entryIndent < labelIndent : entryIndent <= labelIndent))
2052
+ return null;
2053
+ const out = [];
2054
+ const work = [first];
2055
+ const total = lines.starts.length;
2056
+ while (work.length > 0) {
2057
+ let i = work.pop() ?? total;
2058
+ const ind = seqLineIndent(scan, lines, i);
2059
+ while (i < total) {
2060
+ const dash = lineContentStart(scan, lines, i);
2061
+ const end = lines.ends[i] ?? raw.length;
2062
+ let v = dash + 1;
2063
+ while (v < end && (isRawBlank(raw.charCodeAt(v)) || unit[v] === 1 || escapedBlankLen(raw, v) > 0)) {
2064
+ const n = escapedBlankLen(raw, v);
2065
+ v += n > 0 ? n : 1;
2066
+ }
2067
+ v = dotsBeforeMarker(raw, v);
2068
+ if (v < end) {
2069
+ let whole = -1;
2070
+ if (dashEntryAt(scan, v, escaped)) {
2071
+ let last = (lines.outOf[i] ?? total) - 1;
2072
+ while (last > i && (lines.indent[last] ?? -1) === -1)
2073
+ last--;
2074
+ whole = lines.ends[last] ?? end;
2075
+ }
2076
+ out.push({ dash, value: v, whole });
2077
+ }
2078
+ else {
2079
+ const k = lines.nextContent[i + 1] ?? total;
2080
+ if (k < total && seqLineIndent(scan, lines, k) > ind) {
2081
+ const kp = lineContentStart(scan, lines, k);
2082
+ if (dashEntryAt(scan, kp, escaped)) {
2083
+ out.push({ dash, value: -1, whole: -1 });
2084
+ work.push(k);
2085
+ }
2086
+ else
2087
+ out.push({ dash, value: kp, whole: -1 });
2088
+ }
2089
+ else
2090
+ out.push({ dash, value: -1, whole: -1 });
2091
+ }
2092
+ const j = lines.outOf[i] ?? total;
2093
+ if (j >= total || seqLineIndent(scan, lines, j) !== ind || !dashEntryAt(scan, lineContentStart(scan, lines, j), escaped))
2094
+ break;
2095
+ i = j;
2096
+ }
2097
+ }
2098
+ return out;
2099
+ }
1477
2100
  function labelCandidates(S, pass, regions, out, blocks) {
1478
2101
  const text = S.text;
1479
2102
  const unitAt = (k) => S.unitAt(k);
1480
2103
  const re = pass === 'label' ? SECRET_LABELLED_WORD : SECRET_SCHEME_WORD;
1481
2104
  const schemePass = pass !== 'label';
1482
2105
  const tokenPass = pass === 'token';
1483
- const idx = new InnerWordIndex(text, tokenPass);
2106
+ const rawUnitMap = blocks?.view.rawUnit ?? null;
2107
+ const plainAt = (k) => isPlainAt(S, rawUnitMap, k);
2108
+ const idx = new InnerWordIndex(text, tokenPass, plainAt);
2109
+ let listIdx = null;
2110
+ const listIndex = () => (listIdx ??= new InnerWordIndex(text, idx.tokenInner, plainAt));
2111
+ let skipFrom = -1;
2112
+ let skipTo = -1;
2113
+ const flowBudget = { left: 4 * text.length + 4096, pairs: null };
1484
2114
  const extensionCache = new Map();
1485
2115
  let stops;
1486
2116
  const push = (start, end, kindText, te = -1, cls) => {
@@ -1603,6 +2233,88 @@ function labelCandidates(S, pass, regions, out, blocks) {
1603
2233
  r0++;
1604
2234
  maskGaps(r0, outerEnd);
1605
2235
  };
2236
+ const itemNeutral = (a, b) => {
2237
+ const rawItem = text.slice(a, b);
2238
+ const item = withoutSeparators(rawItem).trim();
2239
+ if (item === '')
2240
+ return true;
2241
+ return valueIsWholeMarker(S, a, b, idx.tokenInner) || MARKER_WITH_DOTS.test(item) || isDiagnosticValue(item, rawItem) || LIST_NEUTRAL_ITEM.test(item);
2242
+ };
2243
+ const flowListLike = (label, items) => {
2244
+ if (/s$/i.test(label) || items.length !== 1)
2245
+ return true;
2246
+ const only = items[0];
2247
+ return only === undefined || only.quoted === true || !/\s/.test(withoutSeparators(text.slice(only.start, only.end)).trim());
2248
+ };
2249
+ const listMask = (label, spans, valueLike) => {
2250
+ const neutral = spans.map((s) => itemNeutral(s.start, s.end));
2251
+ const names = !valueLike && spans.every((s, i) => neutral[i] === true || isNamedNotValue(label, withoutSeparators(text.slice(s.start, s.end)).trim()));
2252
+ return spans.map((_, i) => !names && neutral[i] !== true);
2253
+ };
2254
+ const seqItems = (scan, ents, label) => {
2255
+ const li = listIndex();
2256
+ const spans = [];
2257
+ let valueLike = false;
2258
+ for (const e of ents) {
2259
+ if (e.value < 0)
2260
+ continue;
2261
+ if (e.whole >= 0) {
2262
+ scan.out.push({ start: e.value, end: e.whole, kind: 'secret', cls: 'word', tokenEnd: e.whole, pretrimmed: true });
2263
+ valueLike = true;
2264
+ continue;
2265
+ }
2266
+ let vi = viewIndexOfRaw(S, e.value);
2267
+ if (vi >= text.length)
2268
+ continue;
2269
+ const pr = nodeProperties(text, vi);
2270
+ if (pr !== null && hasValueAt(text, pr.next) && propertiesSameLine(S, pr)) {
2271
+ push(pr.start, pr.end, REDACTED_SECRET);
2272
+ vi = pr.next;
2273
+ }
2274
+ const c = text.charAt(vi);
2275
+ if (c === '|' || c === '>') {
2276
+ const blk = blockScalarExtent(scan, S.rawStart(vi), e.dash);
2277
+ if (blk !== null) {
2278
+ scan.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
2279
+ valueLike = true;
2280
+ continue;
2281
+ }
2282
+ }
2283
+ if (c === '[') {
2284
+ const fl = flowListItems(text, vi, li, flowBudget);
2285
+ if (fl !== null && flowListLike(label, fl.items)) {
2286
+ for (const it of fl.items)
2287
+ spans.push(it);
2288
+ continue;
2289
+ }
2290
+ }
2291
+ if (c === '{') {
2292
+ const close = matchBrace(text, vi);
2293
+ if (close > vi + 1)
2294
+ spans.push({ start: vi + 1, end: close });
2295
+ continue;
2296
+ }
2297
+ if (c === '*')
2298
+ continue;
2299
+ let q = vi;
2300
+ while (text.charCodeAt(q) === 0x5c)
2301
+ q++;
2302
+ const quotedItem = isQuoteChar(text.charAt(q));
2303
+ const v = scanListItem(S, vi, li);
2304
+ if (v === null)
2305
+ continue;
2306
+ const keyAt = quotedItem ? afterClosingQuote(text, v.end) : v.end - 1;
2307
+ const keyNext = text.charAt(keyAt + 1);
2308
+ if (text.charAt(keyAt) === ':' && (keyAt + 1 >= text.length || isAnyBlank(keyNext) || keyNext === '\n' || keyNext === '\r'))
2309
+ continue;
2310
+ spans.push(v);
2311
+ }
2312
+ const flags = listMask(label, spans, valueLike);
2313
+ spans.forEach((s, i) => {
2314
+ if (flags[i] === true)
2315
+ push(s.start, s.end, REDACTED_SECRET);
2316
+ });
2317
+ };
1606
2318
  const regionKind = regions.length === 0 ? null : new Uint8Array(text.length);
1607
2319
  if (regionKind !== null)
1608
2320
  for (const r of regions)
@@ -1632,8 +2344,10 @@ function labelCandidates(S, pass, regions, out, blocks) {
1632
2344
  return a;
1633
2345
  };
1634
2346
  re.lastIndex = 0;
1635
- for (let hit = re.exec(text); hit !== null; hit = re.exec(text)) {
2347
+ hits: for (let hit = re.exec(text); hit !== null; hit = re.exec(text)) {
1636
2348
  const label = hit[1] ?? '';
2349
+ if (hit.index >= skipFrom && hit.index < skipTo)
2350
+ continue;
1637
2351
  if (schemePass && (label.toLowerCase() === 'token') !== tokenPass)
1638
2352
  continue;
1639
2353
  if (isTokenCountLabel(text, hit.index, label))
@@ -1642,18 +2356,89 @@ function labelCandidates(S, pass, regions, out, blocks) {
1642
2356
  continue;
1643
2357
  if (schemePass && labelStartsAt(text, hit.index))
1644
2358
  continue;
1645
- const from = hit.index + hit[0].length;
1646
- if (blocks !== undefined && (text.charCodeAt(from) === 0x7c || text.charCodeAt(from) === 0x3e) && isColonSeparator(hit[0].slice((hit[1] ?? '').length))) {
1647
- const blk = blockScalarExtent(blocks, S.rawStart(from), S.rawStart(hit.index));
1648
- if (blk !== null)
1649
- blocks.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
1650
- }
1651
- if (credentialWordStartsAt(text, from, idx.tokenInner)) {
1652
- pushInnerRemainder(from);
1653
- re.lastIndex = from;
1654
- continue;
2359
+ let from = hit.index + hit[0].length;
2360
+ if (!schemePass && text.charCodeAt(from) === 0x3e && text.charCodeAt(from - 1) === 0x3d && labelQuotedAt(text, hit.index, hit[0].slice(label.length))) {
2361
+ let k = from + 1;
2362
+ while (k < text.length && isInlineBlank(text.charAt(k)))
2363
+ k++;
2364
+ let q = k;
2365
+ while (text.charCodeAt(q) === 0x5c)
2366
+ q++;
2367
+ if (isQuoteChar(text.charAt(q)))
2368
+ from = k;
2369
+ }
2370
+ const colonSep = isColonSeparator(hit[0].slice((hit[1] ?? '').length));
2371
+ let bulletSkipped = false;
2372
+ for (;;) {
2373
+ if (colonSep) {
2374
+ const pr = nodeProperties(text, from);
2375
+ if (pr !== null && hasValueAt(text, pr.next) && propertiesSameLine(S, pr) && !credentialWordStartsAt(text, pr.next, idx.tokenInner)) {
2376
+ push(pr.start, pr.end, REDACTED_SECRET);
2377
+ from = pr.next;
2378
+ }
2379
+ }
2380
+ if (blocks !== undefined && (text.charCodeAt(from) === 0x7c || text.charCodeAt(from) === 0x3e) && colonSep) {
2381
+ const blk = blockScalarExtent(blocks, S.rawStart(from), S.rawStart(hit.index));
2382
+ if (blk !== null)
2383
+ blocks.out.push({ start: blk.start, end: blk.end, kind: 'secret', cls: 'word', tokenEnd: blk.end, pretrimmed: true });
2384
+ }
2385
+ if (credentialWordStartsAt(text, from, idx.tokenInner)) {
2386
+ pushInnerRemainder(from);
2387
+ re.lastIndex = from;
2388
+ continue hits;
2389
+ }
2390
+ if (!schemePass && text.charAt(from) === '[') {
2391
+ const fl = flowListItems(text, from, listIndex(), flowBudget);
2392
+ if (fl !== null && flowListLike(label, fl.items)) {
2393
+ const flags = listMask(label, fl.items, false);
2394
+ fl.items.forEach((s, i) => {
2395
+ if (flags[i] === true)
2396
+ push(s.start, s.end, REDACTED_SECRET);
2397
+ });
2398
+ re.lastIndex = Math.max(fl.end, from);
2399
+ continue hits;
2400
+ }
2401
+ }
2402
+ if (!schemePass && colonSep && blocks !== undefined && (text.charAt(from) === '-' || text.charAt(from) === '\\' || text.charAt(from) === '.')) {
2403
+ const ents = blockSeqEntries(blocks, S.rawStart(from), S.rawStart(hit.index));
2404
+ if (ents !== null) {
2405
+ seqItems(blocks, ents, label);
2406
+ re.lastIndex = from;
2407
+ continue hits;
2408
+ }
2409
+ }
2410
+ if (!(colonSep && text.charAt(from) === '-' && from + 1 < text.length))
2411
+ break;
2412
+ const afterDots = dotsBeforeMarker(text, from + 1);
2413
+ if (!(isInlineBlank(text.charAt(from + 1)) || S.gapAfter(from) || afterDots !== from + 1))
2414
+ break;
2415
+ let b = afterDots;
2416
+ while (b < text.length && isInlineBlank(text.charAt(b)))
2417
+ b++;
2418
+ if (b >= text.length || isAnyBlank(text.charAt(b)))
2419
+ break;
2420
+ from = b;
2421
+ bulletSkipped = true;
2422
+ }
2423
+ if (bulletSkipped) {
2424
+ const first = scanListItem(S, from, listIndex());
2425
+ const j = first === null ? from : first.end;
2426
+ if (j > from + 1 && text.charAt(j - 1) === ':' && (j >= text.length || isAnyBlank(text.charAt(j)))) {
2427
+ re.lastIndex = from;
2428
+ continue;
2429
+ }
1655
2430
  }
1656
2431
  let v0s = scanSecretValue(text, from, idx);
2432
+ let wrapEnd = -1;
2433
+ if (v0s === null) {
2434
+ const w = wrappedValueAt(text, from, idx);
2435
+ if (w !== null) {
2436
+ if (WRAPPED_PLACEHOLDER.test(withoutSeparators(text.slice(w.start, w.end))))
2437
+ continue;
2438
+ v0s = w;
2439
+ wrapEnd = w.end;
2440
+ }
2441
+ }
1657
2442
  if (v0s === null) {
1658
2443
  let k = from;
1659
2444
  while (k < text.length && text[k] === VIEW_SEPARATOR)
@@ -1702,6 +2487,23 @@ function labelCandidates(S, pass, regions, out, blocks) {
1702
2487
  continue;
1703
2488
  }
1704
2489
  }
2490
+ let forceFirstMask = false;
2491
+ if (!schemePass && /s$/i.test(label) && !inQuery(v.start)) {
2492
+ const afterFirst = quoted ? afterClosingQuote(text, v0.end) : v0.end;
2493
+ const tail = commaListTail(S, afterFirst, listIndex());
2494
+ if (tail.items.length > 0) {
2495
+ const spans = [{ start: v.start, end: v.end }, ...tail.items];
2496
+ const flags = listMask(label, spans, false);
2497
+ for (let i = 1; i < spans.length; i++) {
2498
+ const s = spans[i];
2499
+ if (s !== undefined && flags[i] === true)
2500
+ push(s.start, s.end, REDACTED_SECRET);
2501
+ }
2502
+ forceFirstMask = flags[0] === true;
2503
+ skipFrom = afterFirst;
2504
+ skipTo = tail.end;
2505
+ }
2506
+ }
1705
2507
  if (valueIsWholeMarker(S, v.start, v.end, idx.tokenInner)) {
1706
2508
  re.lastIndex = quoted ? from : v.end;
1707
2509
  continue;
@@ -1733,6 +2535,13 @@ function labelCandidates(S, pass, regions, out, blocks) {
1733
2535
  if (a !== -1)
1734
2536
  v.end = a;
1735
2537
  }
2538
+ if (wrapEnd !== -1 && v.end > wrapEnd)
2539
+ v.end = wrapEnd;
2540
+ if (!schemePass && !quoted && wrapEnd === -1 && !inQuery(v.start) && !/authorizations?$/i.test(label)) {
2541
+ const ext = tokenSchemeValueEnd(text, v.start, v.end, idx);
2542
+ if (ext > v.end)
2543
+ v.end = ext;
2544
+ }
1736
2545
  if (!quoted) {
1737
2546
  const trailing = trailingLabelStart(text, v.start, v.end, idx.tokenInner);
1738
2547
  if (trailing > 0 && innerWordHasValue(text, v.start + trailing, idx)) {
@@ -1757,7 +2566,7 @@ function labelCandidates(S, pass, regions, out, blocks) {
1757
2566
  re.lastIndex = v.end;
1758
2567
  continue;
1759
2568
  }
1760
- if (!schemePass && isNamedNotValue(label, value)) {
2569
+ if (!schemePass && !forceFirstMask && isNamedNotValue(label, value)) {
1761
2570
  re.lastIndex = v.end;
1762
2571
  continue;
1763
2572
  }
@@ -1795,6 +2604,11 @@ function labelCandidates(S, pass, regions, out, blocks) {
1795
2604
  const trailing = trailingLabelStart(text, v.start, end, idx.tokenInner);
1796
2605
  if (trailing !== -1)
1797
2606
  end = v.start + trailing;
2607
+ if (schemePass && schemeIsLabelValue(text, hit.index)) {
2608
+ push(v.start, Math.max(end, v.end), REDACTED_SECRET);
2609
+ re.lastIndex = quoted ? from : Math.max(end, v.end);
2610
+ continue;
2611
+ }
1798
2612
  if (gluedToSingleUnit(v.start, hit.index, unitAt) || userinfoHostHidden(text, v.start, unitAt)) {
1799
2613
  const cut = trailing !== -1 ? end : Math.max(end, v.end);
1800
2614
  const schemeHit = ADDRESS_SCHEME_RE.exec(text.slice(v.start, v.start + 20))?.[0] ?? '';
@@ -1866,8 +2680,20 @@ function longestAlnumRun(word) {
1866
2680
  return best;
1867
2681
  }
1868
2682
  const JWT_WORD = /^eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}$/;
1869
- const PEM_BEGIN_SOURCE = '-----BEGIN [A-Z0-9 ]*PRIVATE KEY(?: BLOCK)?-----';
2683
+ const PEM_BEGIN_SOURCE = `${PRIVATE_KEY_PEM_HEADER.source}(?: BLOCK)?-----`;
2684
+ const PEM_CASE_FLAGS = PRIVATE_KEY_PEM_HEADER.flags.includes('i') ? 'i' : '';
2685
+ const PEM_LEAD = '-----BEGIN';
1870
2686
  const PEM_END_MARK = '-----END';
2687
+ function pemEndIndex(text, from) {
2688
+ const re = new RegExp(PEM_END_MARK, `g${PEM_CASE_FLAGS}`);
2689
+ re.lastIndex = from;
2690
+ const m = re.exec(text);
2691
+ return m === null ? -1 : m.index;
2692
+ }
2693
+ function pemLeadAt(s, at) {
2694
+ const seg = s.slice(at, at + PEM_LEAD.length);
2695
+ return PEM_CASE_FLAGS === 'i' ? seg.toUpperCase() === PEM_LEAD : seg === PEM_LEAD;
2696
+ }
1871
2697
  function lineBreakLengthAt(text, at) {
1872
2698
  if (text.startsWith('\r\n', at))
1873
2699
  return 2;
@@ -1971,7 +2797,18 @@ function blockLines(scan, escaped) {
1971
2797
  nextContent[starts.length] = starts.length;
1972
2798
  for (let i = starts.length - 1; i >= 0; i--)
1973
2799
  nextContent[i] = (indent[i] ?? -1) !== -1 ? i : (nextContent[i + 1] ?? starts.length);
1974
- const built = { starts, ends, indent, nextContent, memo: new Map() };
2800
+ const outOf = new Int32Array(starts.length + 1).fill(starts.length);
2801
+ const stack = [];
2802
+ for (let i = starts.length - 1; i >= 0; i--) {
2803
+ const ind = indent[i] ?? -1;
2804
+ if (ind === -1)
2805
+ continue;
2806
+ while (stack.length > 0 && (indent[stack[stack.length - 1] ?? 0] ?? -1) > ind)
2807
+ stack.pop();
2808
+ outOf[i] = stack.length > 0 ? (stack[stack.length - 1] ?? starts.length) : starts.length;
2809
+ stack.push(i);
2810
+ }
2811
+ const built = { starts, ends, indent, nextContent, outOf, memo: new Map() };
1975
2812
  scan.lines[slot] = built;
1976
2813
  return built;
1977
2814
  }
@@ -2068,11 +2905,11 @@ function pemBodyEndWithoutTrailer(text, from) {
2068
2905
  }
2069
2906
  function pemBlocks(text, soft = () => false) {
2070
2907
  const out = [];
2071
- if (!text.includes('-----BEGIN'))
2908
+ if (!(PEM_CASE_FLAGS === 'i' ? text.toUpperCase().includes(PEM_LEAD) : text.includes(PEM_LEAD)))
2072
2909
  return out;
2073
2910
  const head = pemHeadView(text, soft);
2074
- const begin = new RegExp(PEM_BEGIN_SOURCE, 'g');
2075
- const trailer = /-----END[A-Z0-9 ]*-----/y;
2911
+ const begin = new RegExp(PEM_BEGIN_SOURCE, `g${PEM_CASE_FLAGS}`);
2912
+ const trailer = new RegExp(`${PEM_END_MARK}[A-Z0-9 ]*-----`, `y${PEM_CASE_FLAGS}`);
2076
2913
  let nextEnd = -2;
2077
2914
  for (let b = begin.exec(head); b !== null; b = begin.exec(head)) {
2078
2915
  let bodyStart = b.index + b[0].length;
@@ -2083,7 +2920,7 @@ function pemBlocks(text, soft = () => false) {
2083
2920
  while (bodyStart < text.length && (text[bodyStart] === ' ' || text[bodyStart] === '\t'))
2084
2921
  bodyStart++;
2085
2922
  if (nextEnd !== -1 && nextEnd < bodyStart)
2086
- nextEnd = text.indexOf(PEM_END_MARK, bodyStart);
2923
+ nextEnd = pemEndIndex(text, bodyStart);
2087
2924
  let bodyEnd;
2088
2925
  let regionEnd;
2089
2926
  if (nextEnd === -1) {
@@ -2114,8 +2951,8 @@ function pemHeadView(text, soft) {
2114
2951
  return chars === null ? text : chars.join('');
2115
2952
  }
2116
2953
  function pemBeginAt(S, at) {
2117
- const k = at + '-----BEGIN'.length;
2118
- return S.text.startsWith('-----BEGIN', at) && (S.text[k] === ' ' || (k < S.text.length && pemSoft(S, k)));
2954
+ const k = at + PEM_LEAD.length;
2955
+ return pemLeadAt(S.text, at) && (S.text[k] === ' ' || (k < S.text.length && pemSoft(S, k)));
2119
2956
  }
2120
2957
  const pemSoft = (S, k) => S.dropped(k) || S.painted(k);
2121
2958
  function pemBlockToRaw(S, blk) {
@@ -2169,6 +3006,90 @@ function authParamEdits(text) {
2169
3006
  }
2170
3007
  return edits;
2171
3008
  }
3009
+ const LITERAL_PROBE_WINDOW = 64;
3010
+ function gluedLiteralStart(word) {
3011
+ const n = word.length;
3012
+ if (n < PROSE_LITERAL_MIN_RUN + 2)
3013
+ return 0;
3014
+ const runFrom = new Int32Array(n + 1);
3015
+ let best = 0;
3016
+ let run = 0;
3017
+ for (let k = n - 1; k >= 0; k--) {
3018
+ if (isAlnumCode(word.charCodeAt(k))) {
3019
+ run++;
3020
+ if (run > best)
3021
+ best = run;
3022
+ }
3023
+ else
3024
+ run = 0;
3025
+ runFrom[k] = best;
3026
+ }
3027
+ for (let k = 1; k < n; k++) {
3028
+ const left = word.charCodeAt(k - 1);
3029
+ if ((left !== 0x5f && left !== 0x2d) || !isAlnumCode(word.charCodeAt(k)))
3030
+ continue;
3031
+ if ((runFrom[k] ?? 0) < PROSE_LITERAL_MIN_RUN)
3032
+ return 0;
3033
+ if (SECRET_LITERAL_RE.test(word.slice(k, k + LITERAL_PROBE_WINDOW)))
3034
+ return k;
3035
+ }
3036
+ return 0;
3037
+ }
3038
+ const OPAQUE_MIN_LENGTH = 24;
3039
+ const OPAQUE_MIN_ENTROPY = 3.5;
3040
+ const OPAQUE_MAX_AVG_SEGMENT = 2.5;
3041
+ const BASE64_FILE_SIGNATURES = ['iVBORw0KGgo', 'R0lGOD', 'UklGR', 'JVBERi0', 'UEsDB', 'H4sI', 'PHN2Zy', 'PD94bWwg', 'AAABAA'];
3042
+ const NON_SECRET_ID_PREFIXES = new Set(['toolu', 'srvtoolu', 'msg', 'msgbatch', 'req', 'file', 'chatcmpl', 'call', 'resp']);
3043
+ function isOpaqueWord(text, i, end) {
3044
+ if (end - i < OPAQUE_MIN_LENGTH)
3045
+ return false;
3046
+ const prev = text.charAt(i - 1);
3047
+ const next = text.charAt(end);
3048
+ if (prev === '+' || prev === '@' || next === '+' || next === '/' || next === '=' || next === '@')
3049
+ return false;
3050
+ if (next === '.' && isKeyWordChar(text.charCodeAt(end + 1)))
3051
+ return false;
3052
+ if (text.slice(Math.max(0, i - 7), i).toLowerCase() === 'base64,')
3053
+ return false;
3054
+ const word = text.slice(i, end);
3055
+ if (/^[0-9A-Fa-f_-]+$/.test(word) || /^sha(?:1|256|384|512)-/i.test(word))
3056
+ return false;
3057
+ if (BASE64_FILE_SIGNATURES.some((sig) => word.startsWith(sig)))
3058
+ return false;
3059
+ const typed = /^([a-z]+)[_-]/.exec(word);
3060
+ if (typed !== null && NON_SECRET_ID_PREFIXES.has(typed[1] ?? ''))
3061
+ return false;
3062
+ let upper = false;
3063
+ let lower = false;
3064
+ let digit = false;
3065
+ const counts = new Map();
3066
+ for (let k = 0; k < word.length; k++) {
3067
+ const c = word.charCodeAt(k);
3068
+ if (c >= 0x41 && c <= 0x5a)
3069
+ upper = true;
3070
+ else if (c >= 0x61 && c <= 0x7a)
3071
+ lower = true;
3072
+ else if (c >= 0x30 && c <= 0x39)
3073
+ digit = true;
3074
+ counts.set(c, (counts.get(c) ?? 0) + 1);
3075
+ }
3076
+ if (!upper || !lower || !digit)
3077
+ return false;
3078
+ let entropy = 0;
3079
+ for (const n of counts.values()) {
3080
+ const p = n / word.length;
3081
+ entropy -= p * Math.log2(p);
3082
+ }
3083
+ if (entropy < OPAQUE_MIN_ENTROPY)
3084
+ return false;
3085
+ let segments = 0;
3086
+ let segmentChars = 0;
3087
+ for (const m of word.matchAll(/[A-Z]?[a-z]+|[A-Z]+(?![a-z])|[0-9]+/g)) {
3088
+ segments++;
3089
+ segmentChars += m[0].length;
3090
+ }
3091
+ return segments > 0 && segmentChars / segments <= OPAQUE_MAX_AVG_SEGMENT;
3092
+ }
2172
3093
  function proseLiteralEdits(text) {
2173
3094
  const edits = [];
2174
3095
  let i = 0;
@@ -2203,6 +3124,13 @@ function proseLiteralEdits(text) {
2203
3124
  if (!pathish && SECRET_LITERAL_RE.test(word) && longestAlnumRun(word) >= PROSE_LITERAL_MIN_RUN) {
2204
3125
  pushEdit(edits, text, i, end, REDACTED_SECRET);
2205
3126
  }
3127
+ else if (!pathish) {
3128
+ const glued = gluedLiteralStart(word);
3129
+ if (glued > 0)
3130
+ pushEdit(edits, text, i + glued, end, REDACTED_SECRET);
3131
+ else if (!hostSlot && isOpaqueWord(text, i, end))
3132
+ pushEdit(edits, text, i, end, REDACTED_SECRET);
3133
+ }
2206
3134
  i = end;
2207
3135
  }
2208
3136
  return edits;
@@ -3451,6 +4379,10 @@ export function displayUntrusted(text, opts = {}) {
3451
4379
  const out = renderUntrusted(text, opts, null);
3452
4380
  return typeof out === 'string' ? out : out.text;
3453
4381
  }
4382
+ export function quoteUntrustedForSentence(text, max) {
4383
+ const shown = displayUntrusted(text, { max, blanks: true, escapeBackslashes: true });
4384
+ return shown.trim() === '' ? undefined : `"${shown.replace(/"/g, '\\"')}"`;
4385
+ }
3454
4386
  export function displayUntrustedMarks(text, opts = {}) {
3455
4387
  const ledger = { cps: [], lens: [] };
3456
4388
  const out = renderUntrusted(text, opts, ledger);
@@ -3458,3 +4390,4 @@ export function displayUntrustedMarks(text, opts = {}) {
3458
4390
  return { text: out, marks: [] };
3459
4391
  return { text: out.text, marks: collectMarks(out, ledger) };
3460
4392
  }
4393
+ const isQuoteChar = (c) => c.charCodeAt(0) === 0x22 || c.charCodeAt(0) === 0x27;