instar 1.3.1649 → 1.3.1650

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 (451) hide show
  1. package/dashboard/console/accounts.js +2 -1
  2. package/dashboard/console/agents-model.js +3 -3
  3. package/dashboard/console/agents.js +7 -4
  4. package/dashboard/console/console.css +1 -0
  5. package/dashboard/console/console.js +35 -4
  6. package/dashboard/console/costs-model.js +12 -0
  7. package/dashboard/console/costs.js +6 -3
  8. package/dashboard/console/development-model.js +9 -3
  9. package/dashboard/console/development.js +7 -4
  10. package/dashboard/console/home-model.js +30 -14
  11. package/dashboard/console/mandates.js +3 -3
  12. package/dashboard/console/needs-model.js +105 -0
  13. package/dashboard/console/plans.js +2 -1
  14. package/dashboard/console/secrets.js +2 -2
  15. package/dashboard/console/ticket-model.js +36 -0
  16. package/dashboard/console/ui.js +3 -0
  17. package/dist/cli.js +8 -0
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/install.d.ts +9 -7
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +2 -19
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/reflect.d.ts.map +1 -1
  24. package/dist/commands/reflect.js +2 -0
  25. package/dist/commands/reflect.js.map +1 -1
  26. package/dist/commands/route.d.ts.map +1 -1
  27. package/dist/commands/route.js +2 -0
  28. package/dist/commands/route.js.map +1 -1
  29. package/dist/commands/server.d.ts.map +1 -1
  30. package/dist/commands/server.js +315 -14
  31. package/dist/commands/server.js.map +1 -1
  32. package/dist/commands/setClaudeKey.d.ts +8 -0
  33. package/dist/commands/setClaudeKey.d.ts.map +1 -0
  34. package/dist/commands/setClaudeKey.js +35 -0
  35. package/dist/commands/setClaudeKey.js.map +1 -0
  36. package/dist/core/AccountFollowMeOrchestrator.d.ts.map +1 -1
  37. package/dist/core/AccountFollowMeOrchestrator.js +4 -0
  38. package/dist/core/AccountFollowMeOrchestrator.js.map +1 -1
  39. package/dist/core/AppMediaStore.d.ts.map +1 -1
  40. package/dist/core/AppMediaStore.js +3 -0
  41. package/dist/core/AppMediaStore.js.map +1 -1
  42. package/dist/core/BackupManager.d.ts.map +1 -1
  43. package/dist/core/BackupManager.js +2 -0
  44. package/dist/core/BackupManager.js.map +1 -1
  45. package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
  46. package/dist/core/ClaudeCliIntelligenceProvider.js +11 -3
  47. package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
  48. package/dist/core/ClaudeKeyHealth.d.ts +141 -0
  49. package/dist/core/ClaudeKeyHealth.d.ts.map +1 -0
  50. package/dist/core/ClaudeKeyHealth.js +467 -0
  51. package/dist/core/ClaudeKeyHealth.js.map +1 -0
  52. package/dist/core/CodexTaskContinuationStore.d.ts.map +1 -1
  53. package/dist/core/CodexTaskContinuationStore.js +7 -0
  54. package/dist/core/CodexTaskContinuationStore.js.map +1 -1
  55. package/dist/core/CoherenceJournal.d.ts +1 -1
  56. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  57. package/dist/core/CoherenceJournal.js +11 -2
  58. package/dist/core/CoherenceJournal.js.map +1 -1
  59. package/dist/core/Config.d.ts +8 -0
  60. package/dist/core/Config.d.ts.map +1 -1
  61. package/dist/core/Config.js +26 -0
  62. package/dist/core/Config.js.map +1 -1
  63. package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
  64. package/dist/core/CredentialSwapExecutor.js +10 -0
  65. package/dist/core/CredentialSwapExecutor.js.map +1 -1
  66. package/dist/core/DecisionQualityRecorderImpl.d.ts.map +1 -1
  67. package/dist/core/DecisionQualityRecorderImpl.js +6 -0
  68. package/dist/core/DecisionQualityRecorderImpl.js.map +1 -1
  69. package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
  70. package/dist/core/DiscoveryEvaluator.js +4 -0
  71. package/dist/core/DiscoveryEvaluator.js.map +1 -1
  72. package/dist/core/IdentityReannounceClaimant.d.ts.map +1 -1
  73. package/dist/core/IdentityReannounceClaimant.js +4 -0
  74. package/dist/core/IdentityReannounceClaimant.js.map +1 -1
  75. package/dist/core/IntelligenceRouter.d.ts.map +1 -1
  76. package/dist/core/IntelligenceRouter.js +9 -0
  77. package/dist/core/IntelligenceRouter.js.map +1 -1
  78. package/dist/core/JournalSyncApplier.d.ts +1 -0
  79. package/dist/core/JournalSyncApplier.d.ts.map +1 -1
  80. package/dist/core/JournalSyncApplier.js +48 -0
  81. package/dist/core/JournalSyncApplier.js.map +1 -1
  82. package/dist/core/LeaseCoordinator.d.ts +4 -0
  83. package/dist/core/LeaseCoordinator.d.ts.map +1 -1
  84. package/dist/core/LeaseCoordinator.js +64 -1
  85. package/dist/core/LeaseCoordinator.js.map +1 -1
  86. package/dist/core/MessagingToneGate.d.ts +11 -7
  87. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  88. package/dist/core/MessagingToneGate.js +15 -1
  89. package/dist/core/MessagingToneGate.js.map +1 -1
  90. package/dist/core/MobileDeviceKeys.d.ts +10 -0
  91. package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
  92. package/dist/core/MobileDeviceKeys.js +17 -0
  93. package/dist/core/MobileDeviceKeys.js.map +1 -1
  94. package/dist/core/MultiMachineCoordinator.d.ts +12 -0
  95. package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
  96. package/dist/core/MultiMachineCoordinator.js +115 -3
  97. package/dist/core/MultiMachineCoordinator.js.map +1 -1
  98. package/dist/core/MutualSshRuntime.d.ts +1 -0
  99. package/dist/core/MutualSshRuntime.d.ts.map +1 -1
  100. package/dist/core/MutualSshRuntime.js +17 -1
  101. package/dist/core/MutualSshRuntime.js.map +1 -1
  102. package/dist/core/ObservedEndpointTracker.d.ts +1 -0
  103. package/dist/core/ObservedEndpointTracker.d.ts.map +1 -1
  104. package/dist/core/ObservedEndpointTracker.js +17 -0
  105. package/dist/core/ObservedEndpointTracker.js.map +1 -1
  106. package/dist/core/OverloadShedPlanner.d.ts.map +1 -1
  107. package/dist/core/OverloadShedPlanner.js +9 -0
  108. package/dist/core/OverloadShedPlanner.js.map +1 -1
  109. package/dist/core/OwnershipApplier.d.ts.map +1 -1
  110. package/dist/core/OwnershipApplier.js +7 -0
  111. package/dist/core/OwnershipApplier.js.map +1 -1
  112. package/dist/core/OwnershipReconciler.d.ts.map +1 -1
  113. package/dist/core/OwnershipReconciler.js +5 -0
  114. package/dist/core/OwnershipReconciler.js.map +1 -1
  115. package/dist/core/PostUpdateMigrator.d.ts +8 -0
  116. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  117. package/dist/core/PostUpdateMigrator.js +76 -2
  118. package/dist/core/PostUpdateMigrator.js.map +1 -1
  119. package/dist/core/PrHandLease.d.ts.map +1 -1
  120. package/dist/core/PrHandLease.js +2 -0
  121. package/dist/core/PrHandLease.js.map +1 -1
  122. package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
  123. package/dist/core/ProactiveSwapMonitor.js +7 -0
  124. package/dist/core/ProactiveSwapMonitor.js.map +1 -1
  125. package/dist/core/ProjectRoundExecution.d.ts.map +1 -1
  126. package/dist/core/ProjectRoundExecution.js +3 -2
  127. package/dist/core/ProjectRoundExecution.js.map +1 -1
  128. package/dist/core/QueueDrainLoop.d.ts +7 -0
  129. package/dist/core/QueueDrainLoop.d.ts.map +1 -1
  130. package/dist/core/QueueDrainLoop.js +37 -1
  131. package/dist/core/QueueDrainLoop.js.map +1 -1
  132. package/dist/core/RemoteAckStore.d.ts.map +1 -1
  133. package/dist/core/RemoteAckStore.js +4 -0
  134. package/dist/core/RemoteAckStore.js.map +1 -1
  135. package/dist/core/ReplicatedStoreReconcilerWiring.d.ts.map +1 -1
  136. package/dist/core/ReplicatedStoreReconcilerWiring.js +1 -0
  137. package/dist/core/ReplicatedStoreReconcilerWiring.js.map +1 -1
  138. package/dist/core/SecretSync.d.ts +1 -0
  139. package/dist/core/SecretSync.d.ts.map +1 -1
  140. package/dist/core/SecretSync.js +16 -0
  141. package/dist/core/SecretSync.js.map +1 -1
  142. package/dist/core/SessionManager.d.ts +11 -0
  143. package/dist/core/SessionManager.d.ts.map +1 -1
  144. package/dist/core/SessionManager.js +125 -14
  145. package/dist/core/SessionManager.js.map +1 -1
  146. package/dist/core/SessionPoolFailoverRunner.d.ts.map +1 -1
  147. package/dist/core/SessionPoolFailoverRunner.js +4 -0
  148. package/dist/core/SessionPoolFailoverRunner.js.map +1 -1
  149. package/dist/core/SleepWakeDetector.d.ts.map +1 -1
  150. package/dist/core/SleepWakeDetector.js +10 -0
  151. package/dist/core/SleepWakeDetector.js.map +1 -1
  152. package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
  153. package/dist/core/SubscriptionReloginStore.js +10 -1
  154. package/dist/core/SubscriptionReloginStore.js.map +1 -1
  155. package/dist/core/TopicPinMutation.d.ts.map +1 -1
  156. package/dist/core/TopicPinMutation.js +5 -0
  157. package/dist/core/TopicPinMutation.js.map +1 -1
  158. package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
  159. package/dist/core/UnjustifiedStopGate.js +22 -0
  160. package/dist/core/UnjustifiedStopGate.js.map +1 -1
  161. package/dist/core/WindowRunCadenceExecutor.d.ts.map +1 -1
  162. package/dist/core/WindowRunCadenceExecutor.js +20 -0
  163. package/dist/core/WindowRunCadenceExecutor.js.map +1 -1
  164. package/dist/core/claudeChildAuth.d.ts +68 -0
  165. package/dist/core/claudeChildAuth.d.ts.map +1 -0
  166. package/dist/core/claudeChildAuth.js +173 -0
  167. package/dist/core/claudeChildAuth.js.map +1 -0
  168. package/dist/core/claudeKeyProbe.d.ts +23 -0
  169. package/dist/core/claudeKeyProbe.d.ts.map +1 -0
  170. package/dist/core/claudeKeyProbe.js +68 -0
  171. package/dist/core/claudeKeyProbe.js.map +1 -0
  172. package/dist/core/codexDeviceLimitWiring.d.ts.map +1 -1
  173. package/dist/core/codexDeviceLimitWiring.js +12 -0
  174. package/dist/core/codexDeviceLimitWiring.js.map +1 -1
  175. package/dist/core/deliverToConversation.d.ts.map +1 -1
  176. package/dist/core/deliverToConversation.js +11 -0
  177. package/dist/core/deliverToConversation.js.map +1 -1
  178. package/dist/core/meteredCallEntry.d.ts.map +1 -1
  179. package/dist/core/meteredCallEntry.js +21 -0
  180. package/dist/core/meteredCallEntry.js.map +1 -1
  181. package/dist/core/nobodyPollingActuator.d.ts.map +1 -1
  182. package/dist/core/nobodyPollingActuator.js +5 -0
  183. package/dist/core/nobodyPollingActuator.js.map +1 -1
  184. package/dist/core/operatorSurfaceReferral.d.ts +18 -0
  185. package/dist/core/operatorSurfaceReferral.d.ts.map +1 -0
  186. package/dist/core/operatorSurfaceReferral.js +32 -0
  187. package/dist/core/operatorSurfaceReferral.js.map +1 -0
  188. package/dist/core/ownershipFollowsLiveWork.d.ts.map +1 -1
  189. package/dist/core/ownershipFollowsLiveWork.js +10 -1
  190. package/dist/core/ownershipFollowsLiveWork.js.map +1 -1
  191. package/dist/core/types.d.ts +15 -0
  192. package/dist/core/types.d.ts.map +1 -1
  193. package/dist/core/types.js.map +1 -1
  194. package/dist/core/worktreeDirtyCheck.d.ts.map +1 -1
  195. package/dist/core/worktreeDirtyCheck.js +2 -0
  196. package/dist/core/worktreeDirtyCheck.js.map +1 -1
  197. package/dist/data/stageBCertifiedSet.d.ts +9 -0
  198. package/dist/data/stageBCertifiedSet.d.ts.map +1 -1
  199. package/dist/data/stageBCertifiedSet.js +12 -0
  200. package/dist/data/stageBCertifiedSet.js.map +1 -1
  201. package/dist/data/standards-guard-index.json +1 -1
  202. package/dist/data/standards-guard-index.meta.json +2 -2
  203. package/dist/data/standards-registry.meta.json +1 -1
  204. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  205. package/dist/lifeline/TelegramLifeline.js +17 -3
  206. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  207. package/dist/messaging/attentionHubPolicy.d.ts.map +1 -1
  208. package/dist/messaging/attentionHubPolicy.js +1 -0
  209. package/dist/messaging/attentionHubPolicy.js.map +1 -1
  210. package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
  211. package/dist/monitoring/AgentWorktreeReaper.js +15 -0
  212. package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
  213. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.d.ts.map +1 -1
  214. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js +18 -9
  215. package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js.map +1 -1
  216. package/dist/monitoring/CodexArmSessionSweeper.d.ts.map +1 -1
  217. package/dist/monitoring/CodexArmSessionSweeper.js +11 -0
  218. package/dist/monitoring/CodexArmSessionSweeper.js.map +1 -1
  219. package/dist/monitoring/CrashLoopPauser.d.ts.map +1 -1
  220. package/dist/monitoring/CrashLoopPauser.js +8 -0
  221. package/dist/monitoring/CrashLoopPauser.js.map +1 -1
  222. package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
  223. package/dist/monitoring/DegradationReporter.js +7 -1
  224. package/dist/monitoring/DegradationReporter.js.map +1 -1
  225. package/dist/monitoring/DegradedTmuxGuard.d.ts +2 -0
  226. package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -1
  227. package/dist/monitoring/DegradedTmuxGuard.js +14 -0
  228. package/dist/monitoring/DegradedTmuxGuard.js.map +1 -1
  229. package/dist/monitoring/DurableOutputScrubber.d.ts.map +1 -1
  230. package/dist/monitoring/DurableOutputScrubber.js +7 -0
  231. package/dist/monitoring/DurableOutputScrubber.js.map +1 -1
  232. package/dist/monitoring/DurableVaultSession.d.ts.map +1 -1
  233. package/dist/monitoring/DurableVaultSession.js +15 -0
  234. package/dist/monitoring/DurableVaultSession.js.map +1 -1
  235. package/dist/monitoring/ExternalHogSentinel.d.ts +2 -0
  236. package/dist/monitoring/ExternalHogSentinel.d.ts.map +1 -1
  237. package/dist/monitoring/ExternalHogSentinel.js +27 -1
  238. package/dist/monitoring/ExternalHogSentinel.js.map +1 -1
  239. package/dist/monitoring/FailureLedger.d.ts.map +1 -1
  240. package/dist/monitoring/FailureLedger.js +38 -1
  241. package/dist/monitoring/FailureLedger.js.map +1 -1
  242. package/dist/monitoring/FeatureEvidenceLog.d.ts +5 -0
  243. package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -1
  244. package/dist/monitoring/FeatureEvidenceLog.js +25 -0
  245. package/dist/monitoring/FeatureEvidenceLog.js.map +1 -1
  246. package/dist/monitoring/GeminiCapacityEscalationMonitor.d.ts.map +1 -1
  247. package/dist/monitoring/GeminiCapacityEscalationMonitor.js +20 -2
  248. package/dist/monitoring/GeminiCapacityEscalationMonitor.js.map +1 -1
  249. package/dist/monitoring/GeminiLoopRunner.d.ts.map +1 -1
  250. package/dist/monitoring/GeminiLoopRunner.js +11 -1
  251. package/dist/monitoring/GeminiLoopRunner.js.map +1 -1
  252. package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
  253. package/dist/monitoring/GreenPrAutoMerger.js +11 -0
  254. package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
  255. package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
  256. package/dist/monitoring/GrowthDigestPublisher.js +16 -0
  257. package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
  258. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts +3 -0
  259. package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
  260. package/dist/monitoring/GrowthMilestoneAnalyst.js +45 -1
  261. package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
  262. package/dist/monitoring/McpProcessReaper.d.ts +2 -0
  263. package/dist/monitoring/McpProcessReaper.d.ts.map +1 -1
  264. package/dist/monitoring/McpProcessReaper.js +32 -0
  265. package/dist/monitoring/McpProcessReaper.js.map +1 -1
  266. package/dist/monitoring/MissingLoginSessionDetector.d.ts +2 -1
  267. package/dist/monitoring/MissingLoginSessionDetector.d.ts.map +1 -1
  268. package/dist/monitoring/MissingLoginSessionDetector.js +23 -0
  269. package/dist/monitoring/MissingLoginSessionDetector.js.map +1 -1
  270. package/dist/monitoring/OrchestratorPoller.d.ts +1 -0
  271. package/dist/monitoring/OrchestratorPoller.d.ts.map +1 -1
  272. package/dist/monitoring/OrchestratorPoller.js +13 -0
  273. package/dist/monitoring/OrchestratorPoller.js.map +1 -1
  274. package/dist/monitoring/OrphanedWorkSentinel.d.ts.map +1 -1
  275. package/dist/monitoring/OrphanedWorkSentinel.js +7 -0
  276. package/dist/monitoring/OrphanedWorkSentinel.js.map +1 -1
  277. package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
  278. package/dist/monitoring/PresenceProxy.js +9 -1
  279. package/dist/monitoring/PresenceProxy.js.map +1 -1
  280. package/dist/monitoring/ProcessFootprintMonitor.d.ts.map +1 -1
  281. package/dist/monitoring/ProcessFootprintMonitor.js +20 -2
  282. package/dist/monitoring/ProcessFootprintMonitor.js.map +1 -1
  283. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  284. package/dist/monitoring/PromiseBeacon.js +20 -0
  285. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  286. package/dist/monitoring/ReleaseReadinessSentinel.d.ts +2 -0
  287. package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
  288. package/dist/monitoring/ReleaseReadinessSentinel.js +26 -0
  289. package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
  290. package/dist/monitoring/RopeHealthMonitor.d.ts.map +1 -1
  291. package/dist/monitoring/RopeHealthMonitor.js +35 -1
  292. package/dist/monitoring/RopeHealthMonitor.js.map +1 -1
  293. package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
  294. package/dist/monitoring/SentinelNotifier.js +16 -0
  295. package/dist/monitoring/SentinelNotifier.js.map +1 -1
  296. package/dist/monitoring/SessionReaper.d.ts.map +1 -1
  297. package/dist/monitoring/SessionReaper.js +11 -2
  298. package/dist/monitoring/SessionReaper.js.map +1 -1
  299. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts +2 -0
  300. package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts.map +1 -1
  301. package/dist/monitoring/SingleMachineFailoverGapDetector.js +20 -0
  302. package/dist/monitoring/SingleMachineFailoverGapDetector.js.map +1 -1
  303. package/dist/monitoring/SpeakerElection.d.ts.map +1 -1
  304. package/dist/monitoring/SpeakerElection.js +8 -0
  305. package/dist/monitoring/SpeakerElection.js.map +1 -1
  306. package/dist/monitoring/StrandedTopicSentinel.d.ts +3 -0
  307. package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
  308. package/dist/monitoring/StrandedTopicSentinel.js +33 -0
  309. package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
  310. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  311. package/dist/native/instar-desktop-host +0 -0
  312. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.d.ts.map +1 -1
  313. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js +5 -2
  314. package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js.map +1 -1
  315. package/dist/recommended/RecommendedServicesLedger.d.ts +91 -0
  316. package/dist/recommended/RecommendedServicesLedger.d.ts.map +1 -0
  317. package/dist/recommended/RecommendedServicesLedger.js +193 -0
  318. package/dist/recommended/RecommendedServicesLedger.js.map +1 -0
  319. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts +14 -0
  320. package/dist/recommended/RecommendedServicesReplicatedStore.d.ts.map +1 -0
  321. package/dist/recommended/RecommendedServicesReplicatedStore.js +34 -0
  322. package/dist/recommended/RecommendedServicesReplicatedStore.js.map +1 -0
  323. package/dist/recommended/legacyDeclines.d.ts +11 -0
  324. package/dist/recommended/legacyDeclines.d.ts.map +1 -0
  325. package/dist/recommended/legacyDeclines.js +17 -0
  326. package/dist/recommended/legacyDeclines.js.map +1 -0
  327. package/dist/recommended/serviceIds.d.ts +3 -0
  328. package/dist/recommended/serviceIds.d.ts.map +1 -0
  329. package/dist/recommended/serviceIds.js +6 -0
  330. package/dist/recommended/serviceIds.js.map +1 -0
  331. package/dist/scaffold/templates.d.ts +2 -0
  332. package/dist/scaffold/templates.d.ts.map +1 -1
  333. package/dist/scaffold/templates.js +8 -0
  334. package/dist/scaffold/templates.js.map +1 -1
  335. package/dist/scheduler/JobResultTriage.d.ts.map +1 -1
  336. package/dist/scheduler/JobResultTriage.js +10 -0
  337. package/dist/scheduler/JobResultTriage.js.map +1 -1
  338. package/dist/scheduler/JobScheduler.d.ts.map +1 -1
  339. package/dist/scheduler/JobScheduler.js +12 -0
  340. package/dist/scheduler/JobScheduler.js.map +1 -1
  341. package/dist/scheduler/MentorOnboardingRunner.d.ts +3 -0
  342. package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
  343. package/dist/scheduler/MentorOnboardingRunner.js +24 -2
  344. package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
  345. package/dist/server/AgentServer.d.ts +2 -0
  346. package/dist/server/AgentServer.d.ts.map +1 -1
  347. package/dist/server/AgentServer.js +76 -15
  348. package/dist/server/AgentServer.js.map +1 -1
  349. package/dist/server/BootHealthBeacon.d.ts +3 -0
  350. package/dist/server/BootHealthBeacon.d.ts.map +1 -1
  351. package/dist/server/BootHealthBeacon.js +9 -0
  352. package/dist/server/BootHealthBeacon.js.map +1 -1
  353. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  354. package/dist/server/CapabilityIndex.js +10 -1
  355. package/dist/server/CapabilityIndex.js.map +1 -1
  356. package/dist/server/LifelineIngressGuard.d.ts.map +1 -1
  357. package/dist/server/LifelineIngressGuard.js +11 -0
  358. package/dist/server/LifelineIngressGuard.js.map +1 -1
  359. package/dist/server/PoolPollCache.d.ts +4 -0
  360. package/dist/server/PoolPollCache.d.ts.map +1 -1
  361. package/dist/server/PoolPollCache.js +33 -0
  362. package/dist/server/PoolPollCache.js.map +1 -1
  363. package/dist/server/machineRoutes.d.ts.map +1 -1
  364. package/dist/server/machineRoutes.js +6 -0
  365. package/dist/server/machineRoutes.js.map +1 -1
  366. package/dist/server/middleware.d.ts.map +1 -1
  367. package/dist/server/middleware.js +6 -0
  368. package/dist/server/middleware.js.map +1 -1
  369. package/dist/server/mobileConsoleTicket.d.ts +113 -0
  370. package/dist/server/mobileConsoleTicket.d.ts.map +1 -0
  371. package/dist/server/mobileConsoleTicket.js +405 -0
  372. package/dist/server/mobileConsoleTicket.js.map +1 -0
  373. package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
  374. package/dist/server/mobileConversationRoutes.js +20 -1
  375. package/dist/server/mobileConversationRoutes.js.map +1 -1
  376. package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
  377. package/dist/server/mobileMediaRoutes.js +3 -0
  378. package/dist/server/mobileMediaRoutes.js.map +1 -1
  379. package/dist/server/mobilePairingRoutes.d.ts +8 -2
  380. package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
  381. package/dist/server/mobilePairingRoutes.js +67 -6
  382. package/dist/server/mobilePairingRoutes.js.map +1 -1
  383. package/dist/server/mobileSessionTerminalRoutes.d.ts +128 -0
  384. package/dist/server/mobileSessionTerminalRoutes.d.ts.map +1 -0
  385. package/dist/server/mobileSessionTerminalRoutes.js +389 -0
  386. package/dist/server/mobileSessionTerminalRoutes.js.map +1 -0
  387. package/dist/server/recommendedServiceRoutes.d.ts +13 -0
  388. package/dist/server/recommendedServiceRoutes.d.ts.map +1 -0
  389. package/dist/server/recommendedServiceRoutes.js +49 -0
  390. package/dist/server/recommendedServiceRoutes.js.map +1 -0
  391. package/dist/server/routes.d.ts +2 -0
  392. package/dist/server/routes.d.ts.map +1 -1
  393. package/dist/server/routes.js +170 -4
  394. package/dist/server/routes.js.map +1 -1
  395. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  396. package/dist/testing/selfActionRegistry.js +36 -0
  397. package/dist/testing/selfActionRegistry.js.map +1 -1
  398. package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -1
  399. package/dist/threadline/A2ACheckInProxy.js +26 -15
  400. package/dist/threadline/A2ACheckInProxy.js.map +1 -1
  401. package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
  402. package/dist/threadline/AgentTrustManager.js +3 -0
  403. package/dist/threadline/AgentTrustManager.js.map +1 -1
  404. package/dist/threadline/InboundIdLedger.d.ts.map +1 -1
  405. package/dist/threadline/InboundIdLedger.js +18 -1
  406. package/dist/threadline/InboundIdLedger.js.map +1 -1
  407. package/dist/threadline/NegotiatorGate.d.ts.map +1 -1
  408. package/dist/threadline/NegotiatorGate.js +11 -0
  409. package/dist/threadline/NegotiatorGate.js.map +1 -1
  410. package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
  411. package/dist/threadline/PipeSessionSpawner.js +8 -0
  412. package/dist/threadline/PipeSessionSpawner.js.map +1 -1
  413. package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
  414. package/dist/threadline/ThreadlineRouter.js +13 -0
  415. package/dist/threadline/ThreadlineRouter.js.map +1 -1
  416. package/dist/threadline/pairingReplicationWiring.d.ts.map +1 -1
  417. package/dist/threadline/pairingReplicationWiring.js +9 -0
  418. package/dist/threadline/pairingReplicationWiring.js.map +1 -1
  419. package/dist/threadline/relayForward.d.ts.map +1 -1
  420. package/dist/threadline/relayForward.js +13 -2
  421. package/dist/threadline/relayForward.js.map +1 -1
  422. package/dist/threadline/relayUnknownSenderTrust.d.ts +0 -9
  423. package/dist/threadline/relayUnknownSenderTrust.d.ts.map +1 -1
  424. package/dist/threadline/relayUnknownSenderTrust.js +16 -0
  425. package/dist/threadline/relayUnknownSenderTrust.js.map +1 -1
  426. package/package.json +1 -1
  427. package/scripts/check-constitution-pairing.mjs +273 -0
  428. package/scripts/safe-merge.mjs +9 -0
  429. package/src/data/builtin-manifest.json +103 -103
  430. package/src/data/feature-ladders.json +113 -113
  431. package/src/data/stageBCertifiedSet.ts +12 -0
  432. package/src/data/standards-guard-index.json +1 -1
  433. package/src/data/standards-guard-index.meta.json +2 -2
  434. package/src/data/standards-registry.meta.json +1 -1
  435. package/src/data/state-coherence-registry.json +18 -0
  436. package/src/scaffold/templates.ts +9 -0
  437. package/upgrades/1.3.1650.md +105 -0
  438. package/upgrades/mobile-console-device-signin.eli16.md +5 -0
  439. package/upgrades/side-effects/cloud-key-internal-calls.md +116 -0
  440. package/upgrades/side-effects/constitution-alignment.eli16.md +11 -0
  441. package/upgrades/side-effects/constitution-alignment.md +69 -0
  442. package/upgrades/side-effects/feature-evidence-recording.eli16.md +3 -0
  443. package/upgrades/side-effects/feature-evidence-recording.md +66 -0
  444. package/upgrades/side-effects/feedback-reroute-admission-parity.md +77 -0
  445. package/upgrades/side-effects/mobile-console-device-signin.md +102 -0
  446. package/upgrades/side-effects/mobile-native-session-screen.md +88 -0
  447. package/upgrades/side-effects/operator-needs-first-screen.md +87 -0
  448. package/upgrades/side-effects/recommended-services-choices.md +50 -0
  449. package/upgrades/side-effects/rerouted-lifetime-active-process.md +63 -0
  450. package/upgrades/side-effects/undated-resurfacer-e2e-wait.eli16.md +5 -0
  451. package/upgrades/side-effects/undated-resurfacer-e2e-wait.md +9 -0
@@ -28,6 +28,7 @@ import { Router } from 'express';
28
28
  import { resolveDevAgentGate } from '../core/devAgentGate.js';
29
29
  import { arrivedOverLocalTls } from '../core/desktopTransport.js';
30
30
  import { PairingCodeStore, NONCE_PATTERN, buildPairLink, cleanText, codeTtlMs, pingAnswer, stableOrigin, } from '../core/MobilePairing.js';
31
+ import { featureEvidence } from '../monitoring/FeatureEvidenceLog.js';
31
32
  import { ConfirmationCodes, DeviceRegistry, displayCode, ReplayGuard, parseDevicePublicKey, verifyDeviceRequest, } from '../core/MobileDeviceKeys.js';
32
33
  import { isPeerUrlAllowedForCredentials } from './peerUrlGuard.js';
33
34
  import { poolPeerFetch } from './poolPeerFetch.js';
@@ -38,6 +39,7 @@ import { PairingInviteTelegram } from '../threadline/PairingInviteTelegram.js';
38
39
  import { APP_CONVERSATION_KEY_PATTERN, derivedEventId, hideCredentialSpans, removeAuthorityTokens } from '../core/appConversationText.js';
39
40
  import { deviceKeyHashOf } from '../core/AppRecordSignatures.js';
40
41
  import { buildSignedOrigin } from './mobileConversationRoutes.js';
42
+ import { mountConsoleTicketDeviceRoutes } from './mobileConsoleTicket.js';
41
43
  import { checkSignedFiles, claimMediaUploads, mediaRecordTooLarge, mirrorMediaToTelegram, preflightMediaAttachments, publishMediaMessage, signedFileHashParts, } from './mobileMediaSend.js';
42
44
  import { isExactStopMessage } from '../core/MessageSentinel.js';
43
45
  import { UserManager } from '../users/UserManager.js';
@@ -392,16 +394,26 @@ export class MobilePairingService {
392
394
  this.deviceRate.set(deviceId, arr);
393
395
  return true;
394
396
  }
395
- /** A rule's own per-minute bucket (media chunks), independent of the read allowance. */
396
- deviceBucketOk(deviceId, perMinute) {
397
+ /**
398
+ * A rule's own per-minute bucket, independent of the read allowance. Each named bucket counts
399
+ * separately (media chunks use 'default'; the session screen has its own two), and a key whose
400
+ * window has emptied is deleted, so the map holds only devices active in the last minute.
401
+ */
402
+ deviceBucketOk(deviceId, perMinute, bucket = 'default') {
397
403
  const t = this.now();
398
- const arr = (this.deviceBucket.get(deviceId) ?? []).filter((x) => t - x < 60_000);
404
+ const key = bucket === 'default' ? deviceId : `${deviceId}\u0000${bucket}`;
405
+ const arr = (this.deviceBucket.get(key) ?? []).filter((x) => t - x < 60_000);
399
406
  if (arr.length >= perMinute) {
400
- this.deviceBucket.set(deviceId, arr);
407
+ this.deviceBucket.set(key, arr);
401
408
  return false;
402
409
  }
403
410
  arr.push(t);
404
- this.deviceBucket.set(deviceId, arr);
411
+ this.deviceBucket.set(key, arr);
412
+ if (this.deviceBucket.size > 64) {
413
+ for (const [k, v] of this.deviceBucket)
414
+ if (!v.some((x) => t - x < 60_000))
415
+ this.deviceBucket.delete(k);
416
+ }
405
417
  return true;
406
418
  }
407
419
  /** Inbound Telegram text: void any pending device whose live code appears in it. */
@@ -609,12 +621,14 @@ export function mountPublicMobilePairingRoutes(app, svc) {
609
621
  const reqHost = normalizeRequestHost(req.headers.host);
610
622
  const eligible = svc.redeemHostEligible(reqHost);
611
623
  if (!arrivedOverLocalTls(req.secure, req.socket.remoteAddress, req.headers['x-forwarded-proto']) || !eligible) {
624
+ featureEvidence.recordAtMostEvery('mobilePairing', 'redeem|not-secure-address', 60_000, { kind: 'held', reason: 'redeem refused: not-secure-address' });
612
625
  res.status(403).json({ error: 'Pairing only works over this agent\'s secure address.' });
613
626
  return;
614
627
  }
615
628
  const body = (req.body ?? {});
616
629
  const publicKey = typeof body.devicePublicKey === 'string' ? body.devicePublicKey : '';
617
630
  if (!parseDevicePublicKey(publicKey)) {
631
+ featureEvidence.recordAtMostEvery('mobilePairing', 'redeem|bad-device-key', 60_000, { kind: 'held', reason: 'redeem refused: bad-device-key' });
618
632
  res.status(400).json({ error: 'A valid device public key is required.' });
619
633
  return;
620
634
  }
@@ -624,16 +638,19 @@ export function mountPublicMobilePairingRoutes(app, svc) {
624
638
  // session, which needs no lease.
625
639
  const approval = svc.approvalPath();
626
640
  if (!approval || (approval === 'telegram' && !svc.holdsLease())) {
641
+ featureEvidence.recordAtMostEvery('mobilePairing', 'redeem|approval-unavailable', 60_000, { kind: 'held', reason: 'redeem refused: approval-unavailable' });
627
642
  res.status(409).json({ error: 'approval-unavailable', detail: 'This agent cannot send you the confirmation code right now (no Telegram owner chat on this machine).' });
628
643
  return;
629
644
  }
630
645
  if (svc.devices.pairingPaused()) {
646
+ featureEvidence.recordAtMostEvery('mobilePairing', 'redeem|pairing-paused', 60_000, { kind: 'held', reason: 'redeem refused: pairing-paused' });
631
647
  res.status(429).json({ error: 'pairing-paused' });
632
648
  return;
633
649
  }
634
650
  // Take-and-delete happens synchronously inside redeem(), before any async work.
635
651
  const r = svc.codes.redeem(body.code, token);
636
652
  if (!r.ok) {
653
+ featureEvidence.recordAtMostEvery('mobilePairing', `redeem|${r.reason}`, 60_000, { kind: 'held', reason: `redeem refused: ${r.reason}` });
637
654
  if (r.reason === 'too-many-attempts') {
638
655
  res.status(429).json({ error: 'too-many-attempts' });
639
656
  return;
@@ -644,6 +661,7 @@ export function mountPublicMobilePairingRoutes(app, svc) {
644
661
  // §3.2 step 3: an honest phone sends to the link's own origin. A code with no bound origin
645
662
  // (minted before this change, in this process) keeps the old rule: the eligible host.
646
663
  if (r.bound && (r.bound.host !== reqHost || r.bound.kind !== eligible.kind)) {
664
+ featureEvidence.recordAtMostEvery('mobilePairing', 'redeem|wrong-origin', 60_000, { kind: 'held', reason: 'redeem refused: wrong-origin' });
647
665
  res.status(403).json({ error: 'That link has expired or was already used.' });
648
666
  return;
649
667
  }
@@ -653,11 +671,13 @@ export function mountPublicMobilePairingRoutes(app, svc) {
653
671
  }
654
672
  catch (err) {
655
673
  svc.deps.reportDegradation?.('MobilePairing.registryWrite', err);
674
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'redeem failed: registry write', context: { routeKind: eligible.kind } });
656
675
  res.status(500).json({ error: 'Could not record the device. Ask for a new link.' });
657
676
  return;
658
677
  }
659
678
  if (!created.ok) {
660
679
  const status = created.reason === 'duplicate-key' ? 409 : 429;
680
+ featureEvidence.record('mobilePairing', { kind: 'held', reason: `redeem refused: ${created.reason}`, context: { routeKind: eligible.kind, status } });
661
681
  res.status(status).json({ error: created.reason });
662
682
  return;
663
683
  }
@@ -672,6 +692,7 @@ export function mountPublicMobilePairingRoutes(app, svc) {
672
692
  svc.holdDashboardCode(device.id, code, Date.parse(device.expiresAt));
673
693
  // dashboard-console-default-and-pair-page §3.3: the code page on the host this phone just
674
694
  // redeemed on (already checked above: local TLS, an eligible host, the code's bound host).
695
+ featureEvidence.record('mobilePairing', { kind: 'fired', reason: 'redeemed: code held on dashboard', context: { deviceId: device.id, approval: 'dashboard', role: device.role ?? 'owner', routeKind: eligible.kind, codeFormat } });
675
696
  res.json({ deviceId: device.id, agentName: svc.deps.config.projectName, status: 'pending', approval: 'dashboard', codeFormat,
676
697
  codePageUrl: codePageUrlForDevice(reqHost, device.id) });
677
698
  return;
@@ -707,9 +728,11 @@ export function mountPublicMobilePairingRoutes(app, svc) {
707
728
  catch (err) {
708
729
  svc.deps.reportDegradation?.('MobilePairing.registryWrite', err);
709
730
  }
731
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'redeem failed: confirmation code not delivered', context: { deviceId: device.id, routeKind: eligible.kind } });
710
732
  res.status(409).json({ error: 'approval-unavailable', detail: 'I could not send you the confirmation code in Telegram. Open a private chat with the bot and send it any message, then ask me for a new link.' });
711
733
  return;
712
734
  }
735
+ featureEvidence.record('mobilePairing', { kind: 'fired', reason: 'redeemed: code sent by Telegram', context: { deviceId: device.id, approval: 'telegram', role: device.role ?? 'owner', routeKind: eligible.kind, codeFormat } });
713
736
  res.json({ deviceId: device.id, agentName: svc.deps.config.projectName, status: 'pending', approval: 'telegram', codeFormat });
714
737
  });
715
738
  }
@@ -1062,15 +1085,18 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1062
1085
  catch (err) {
1063
1086
  deps.reportDegradation?.('MobilePairing.registryWrite', err);
1064
1087
  }
1088
+ featureEvidence.record('mobilePairing', { kind: 'held', reason: 'confirm refused: approval-moved', context: { deviceId: d.id } });
1065
1089
  res.status(409).json({ error: 'approval-moved', detail: 'This pairing moved machines. Ask for a new link.' });
1066
1090
  return;
1067
1091
  }
1068
1092
  if (svc.devices.pairingPaused()) {
1093
+ featureEvidence.record('mobilePairing', { kind: 'held', reason: 'confirm refused: pairing-paused', context: { deviceId: d.id } });
1069
1094
  res.status(429).json({ error: 'pairing-paused' });
1070
1095
  return;
1071
1096
  }
1072
1097
  const check = svc.confirm.check(d.id, req.body?.code);
1073
1098
  if (check.result === 'none') {
1099
+ featureEvidence.record('mobilePairing', { kind: 'held', reason: 'confirm refused: expired', context: { deviceId: d.id } });
1074
1100
  res.status(409).json({ error: 'expired' });
1075
1101
  return;
1076
1102
  }
@@ -1088,6 +1114,7 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1088
1114
  }
1089
1115
  catch (err) {
1090
1116
  deps.reportDegradation?.('MobilePairing.keyLedger', err);
1117
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'confirm failed: key ledger write', context: { deviceId: d.id, approvedVia } });
1091
1118
  res.status(500).json({ error: 'Could not record the confirmation. Try again.' });
1092
1119
  return;
1093
1120
  }
@@ -1097,6 +1124,7 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1097
1124
  }
1098
1125
  catch (err) {
1099
1126
  deps.reportDegradation?.('MobilePairing.registryWrite', err);
1127
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'confirm failed: registry write', context: { deviceId: d.id, approvedVia } });
1100
1128
  res.status(500).json({ error: 'Could not record the confirmation. Try again.' });
1101
1129
  return;
1102
1130
  }
@@ -1106,9 +1134,11 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1106
1134
  for (const [n, id] of svc.declineNonces)
1107
1135
  if (id === d.id)
1108
1136
  svc.declineNonces.delete(n);
1137
+ featureEvidence.record('mobilePairing', { kind: 'fired', reason: 'confirmed', context: { deviceId: d.id, approvedVia, role: d.role ?? 'owner' } });
1109
1138
  res.json({ status: 'active' });
1110
1139
  return;
1111
1140
  }
1141
+ featureEvidence.record('mobilePairing', { kind: 'held', reason: 'confirm refused: wrong code', context: { deviceId: d.id, nowDeclined: after?.status === 'declined', pairingPaused: svc.devices.pairingPaused() } });
1112
1142
  if (svc.devices.pairingPaused()) {
1113
1143
  deps.raiseAttention?.('Phone pairing paused', 'Ten wrong pairing codes were entered in the last 24 hours, so phone pairing is paused for now. If you were not pairing a phone, someone may be guessing.');
1114
1144
  }
@@ -1121,6 +1151,8 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1121
1151
  }
1122
1152
  res.status(403).json({ error: 'wrong-code' });
1123
1153
  });
1154
+ // Console sign-in from an owner phone (docs/specs/mobile-console-device-signin.md).
1155
+ mountConsoleTicketDeviceRoutes(router, svc);
1124
1156
  // Revoke: bearer may revoke any device; a device only itself.
1125
1157
  router.post('/mobile/devices/:id/revoke', async (req, res) => {
1126
1158
  if (!svc.enabled()) {
@@ -1158,11 +1190,13 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1158
1190
  }
1159
1191
  catch (err) {
1160
1192
  deps.reportDegradation?.('MobilePairing.registryWrite', err);
1193
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'revoke failed: registry write', context: { deviceId: id, by: p.kind } });
1161
1194
  res.status(500).json({ error: 'Could not record the revocation. Try again.' });
1162
1195
  return;
1163
1196
  }
1164
1197
  if (held) {
1165
1198
  svc.confirm.drop(id);
1199
+ featureEvidence.record('mobilePairing', { kind: 'fired', reason: 'revoked here', context: { deviceId: id, by: p.kind, heldHere: true } });
1166
1200
  res.json({ revoked: true, machine: deps.selfMachineId ?? null });
1167
1201
  return;
1168
1202
  }
@@ -1172,9 +1206,11 @@ export function createMobilePairingRouter(svc, deps, poolCtx) {
1172
1206
  }
1173
1207
  const r = await forwardRevoke(poolCtx, id);
1174
1208
  if (r.confirmedBy) {
1209
+ featureEvidence.record('mobilePairing', { kind: 'fired', reason: 'revoked by a peer', context: { deviceId: id, by: p.kind, heldHere: false } });
1175
1210
  res.json({ revoked: true, machine: r.confirmedBy });
1176
1211
  return;
1177
1212
  }
1213
+ featureEvidence.record('mobilePairing', { kind: 'error', reason: 'revoke unconfirmed: no machine holding this phone answered', context: { deviceId: id, by: p.kind } });
1178
1214
  res.status(202).json({ pending: true, detail: 'No machine holding this phone confirmed yet. Until one does, the phone may still have access. Revoke it on the machine that serves its address for an immediate effect.' });
1179
1215
  });
1180
1216
  // ── Mobile push (docs/specs/mobile-push.md) ──
@@ -1733,6 +1769,8 @@ const UUID = APP_CONVERSATION_KEY_PATTERN;
1733
1769
  // `unassignedOk`: the route answers a phone whose person is no longer in the registry (people and
1734
1770
  // roles §3.4): only its own status, confirm and self-revoke. `conversationRef`: the route names a
1735
1771
  // conversation, so it must call the shared `mayUse` check (the coverage test reads this flag).
1772
+ // `ownerOnly`: only a phone whose person is the owner (403 owner-phone-required otherwise).
1773
+ // `bucket`: the name of the rule's own bucket (rules sharing a name share a count).
1736
1774
  export const DEVICE_ALLOWLIST = (() => {
1737
1775
  const active = new Set(['active']);
1738
1776
  return [
@@ -1775,7 +1813,18 @@ export const DEVICE_ALLOWLIST = (() => {
1775
1813
  { method: 'GET', re: new RegExp(`^/mobile/media/uploads/${UUID}$`), statuses: active, body: 'none' },
1776
1814
  { method: 'GET', re: /^\/mobile\/media\/[0-9a-f]{64}$/, statuses: active, body: 'none', conversationRef: true },
1777
1815
  { method: 'POST', re: /^\/mobile\/media\/purge$/, statuses: active, body: 'json', conversationRef: true },
1816
+ // Console sign-in from an owner phone (mobile-console-device-signin §3.1-3.2); each route
1817
+ // re-checks owner, local TLS and the feature switch itself.
1818
+ { method: 'POST', re: /^\/mobile\/device\/presence-key$/, statuses: active, body: 'json' },
1819
+ { method: 'POST', re: /^\/mobile\/console-ticket\/challenge$/, statuses: active, body: 'json' },
1820
+ { method: 'POST', re: /^\/mobile\/console-ticket$/, statuses: active, body: 'json' },
1778
1821
  { method: 'POST', re: /^\/mobile\/devices\/[^/]+\/revoke$/, statuses: new Set(['pending', 'active', 'declined', 'expired']), unassignedOk: true },
1822
+ // The native session screen (docs/specs/mobile-native-session-screen.md): read a session's pane
1823
+ // and type plain text into it. Owner phones only; each has its own bucket so polling and typing
1824
+ // never use up the read allowance the chat list needs. The path is lower-cased here; the router
1825
+ // reads the name with its case kept.
1826
+ { method: 'GET', re: /^\/sessions\/[a-z0-9_-]{1,200}\/output$/, statuses: active, body: 'none', ownerOnly: true, ownBucket: 90, bucket: 'session-output' },
1827
+ { method: 'POST', re: /^\/sessions\/[a-z0-9_-]{1,200}\/input$/, statuses: active, body: 'json', ownerOnly: true, ownBucket: 12, bucket: 'session-input' },
1779
1828
  ];
1780
1829
  })();
1781
1830
  /**
@@ -1837,6 +1886,9 @@ export function deviceAuthenticator(svc) {
1837
1886
  if (svc.ownNames) {
1838
1887
  const h = normalizeRequestHost(req.headers.host);
1839
1888
  if (!h || !svc.ownNames.accepts(h) || !arrivedOverLocalTls(req.secure, req.socket.remoteAddress, req.headers['x-forwarded-proto'])) {
1889
+ // The bar is about OWN names: a name that is not ours is someone knocking, not a refusal of a real route.
1890
+ const ownName = !!h && svc.ownNames.accepts(h);
1891
+ featureEvidence.recordAtMostEvery('mobilePairing.multiRoute', `host-refused|${ownName}`, 60_000, { kind: ownName ? 'error' : 'held', reason: ownName ? 'refused on an own name: not over local TLS' : 'refused: host is not an own name', context: { ownName, routeKind: ownName ? svc.ownNames.listed().find((n) => n.host === h)?.kind ?? 'unknown' : null } });
1840
1892
  return refuse(401, 'device-unauthorized');
1841
1893
  }
1842
1894
  host = h;
@@ -1851,10 +1903,13 @@ export function deviceAuthenticator(svc) {
1851
1903
  const ledgerRevoked = !!svc.keyLedger && svc.keyLedger.isRevoked(deviceKeyHashOf(d.publicKey), d.id);
1852
1904
  return { publicKey: d.publicKey, host: d.host, status: ledgerRevoked ? 'revoked' : d.status };
1853
1905
  }, rule.statuses, svc.replay, Date.now(), rule.sendRoute === true);
1906
+ if (!v.ok && host) {
1907
+ featureEvidence.recordAtMostEvery('mobilePairing.multiRoute', `signature-refused|${v.reason}|${host}`, 60_000, { kind: v.reason === 'rate-limited' ? 'held' : 'error', reason: `signature refused on an own name: ${v.reason}`, context: { signatureReason: v.reason, host, routeKind: svc.ownNames?.listed().find((n) => n.host === host)?.kind ?? 'unknown' } });
1908
+ }
1854
1909
  if (!v.ok)
1855
1910
  return refuse(v.reason === 'rate-limited' ? 429 : 401, v.reason === 'rate-limited' ? 'too-many-requests' : 'device-unauthorized');
1856
1911
  if (rule.ownBucket !== undefined) {
1857
- if (!svc.deviceBucketOk(v.deviceId, rule.ownBucket))
1912
+ if (!svc.deviceBucketOk(v.deviceId, rule.ownBucket, rule.bucket))
1858
1913
  return refuse(429, 'too-many-requests');
1859
1914
  }
1860
1915
  else if (!(rule.sendRoute && svc.nativeOn) && !svc.deviceRateOk(v.deviceId))
@@ -1869,6 +1924,8 @@ export function deviceAuthenticator(svc) {
1869
1924
  return refuse(403, 'person-unknown');
1870
1925
  }
1871
1926
  else {
1927
+ if (rule.ownerOnly && person.role !== 'owner')
1928
+ return refuse(403, 'owner-phone-required');
1872
1929
  req.instarDevicePerson = person;
1873
1930
  }
1874
1931
  req.instarPrincipal = { kind: 'device', deviceId: v.deviceId };
@@ -1877,6 +1934,10 @@ export function deviceAuthenticator(svc) {
1877
1934
  // The Host the signature was checked against (multi-route: one of this machine's own names;
1878
1935
  // otherwise the paired host). Signed records store THIS host, never the paired one.
1879
1936
  req.instarDeviceHost = host ?? svc.devices.get(v.deviceId)?.host ?? '';
1937
+ if (host) {
1938
+ // Per request by nature: one row a device and route an hour, carrying how many it stands for.
1939
+ featureEvidence.recordAtMostEvery('mobilePairing.multiRoute', `accepted|${v.deviceId}|${host}`, 60 * 60 * 1000, { kind: 'fired', reason: 'signature accepted on an own name', context: { deviceId: v.deviceId, host, routeKind: svc.ownNames?.listed().find((n) => n.host === host)?.kind ?? 'unknown', pairedHost: rec?.host === host } });
1940
+ }
1880
1941
  return 'ok';
1881
1942
  };
1882
1943
  }