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.
- package/dashboard/console/accounts.js +2 -1
- package/dashboard/console/agents-model.js +3 -3
- package/dashboard/console/agents.js +7 -4
- package/dashboard/console/console.css +1 -0
- package/dashboard/console/console.js +35 -4
- package/dashboard/console/costs-model.js +12 -0
- package/dashboard/console/costs.js +6 -3
- package/dashboard/console/development-model.js +9 -3
- package/dashboard/console/development.js +7 -4
- package/dashboard/console/home-model.js +30 -14
- package/dashboard/console/mandates.js +3 -3
- package/dashboard/console/needs-model.js +105 -0
- package/dashboard/console/plans.js +2 -1
- package/dashboard/console/secrets.js +2 -2
- package/dashboard/console/ticket-model.js +36 -0
- package/dashboard/console/ui.js +3 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/install.d.ts +9 -7
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +2 -19
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/reflect.d.ts.map +1 -1
- package/dist/commands/reflect.js +2 -0
- package/dist/commands/reflect.js.map +1 -1
- package/dist/commands/route.d.ts.map +1 -1
- package/dist/commands/route.js +2 -0
- package/dist/commands/route.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +315 -14
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/setClaudeKey.d.ts +8 -0
- package/dist/commands/setClaudeKey.d.ts.map +1 -0
- package/dist/commands/setClaudeKey.js +35 -0
- package/dist/commands/setClaudeKey.js.map +1 -0
- package/dist/core/AccountFollowMeOrchestrator.d.ts.map +1 -1
- package/dist/core/AccountFollowMeOrchestrator.js +4 -0
- package/dist/core/AccountFollowMeOrchestrator.js.map +1 -1
- package/dist/core/AppMediaStore.d.ts.map +1 -1
- package/dist/core/AppMediaStore.js +3 -0
- package/dist/core/AppMediaStore.js.map +1 -1
- package/dist/core/BackupManager.d.ts.map +1 -1
- package/dist/core/BackupManager.js +2 -0
- package/dist/core/BackupManager.js.map +1 -1
- package/dist/core/ClaudeCliIntelligenceProvider.d.ts.map +1 -1
- package/dist/core/ClaudeCliIntelligenceProvider.js +11 -3
- package/dist/core/ClaudeCliIntelligenceProvider.js.map +1 -1
- package/dist/core/ClaudeKeyHealth.d.ts +141 -0
- package/dist/core/ClaudeKeyHealth.d.ts.map +1 -0
- package/dist/core/ClaudeKeyHealth.js +467 -0
- package/dist/core/ClaudeKeyHealth.js.map +1 -0
- package/dist/core/CodexTaskContinuationStore.d.ts.map +1 -1
- package/dist/core/CodexTaskContinuationStore.js +7 -0
- package/dist/core/CodexTaskContinuationStore.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +11 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/Config.d.ts +8 -0
- package/dist/core/Config.d.ts.map +1 -1
- package/dist/core/Config.js +26 -0
- package/dist/core/Config.js.map +1 -1
- package/dist/core/CredentialSwapExecutor.d.ts.map +1 -1
- package/dist/core/CredentialSwapExecutor.js +10 -0
- package/dist/core/CredentialSwapExecutor.js.map +1 -1
- package/dist/core/DecisionQualityRecorderImpl.d.ts.map +1 -1
- package/dist/core/DecisionQualityRecorderImpl.js +6 -0
- package/dist/core/DecisionQualityRecorderImpl.js.map +1 -1
- package/dist/core/DiscoveryEvaluator.d.ts.map +1 -1
- package/dist/core/DiscoveryEvaluator.js +4 -0
- package/dist/core/DiscoveryEvaluator.js.map +1 -1
- package/dist/core/IdentityReannounceClaimant.d.ts.map +1 -1
- package/dist/core/IdentityReannounceClaimant.js +4 -0
- package/dist/core/IdentityReannounceClaimant.js.map +1 -1
- package/dist/core/IntelligenceRouter.d.ts.map +1 -1
- package/dist/core/IntelligenceRouter.js +9 -0
- package/dist/core/IntelligenceRouter.js.map +1 -1
- package/dist/core/JournalSyncApplier.d.ts +1 -0
- package/dist/core/JournalSyncApplier.d.ts.map +1 -1
- package/dist/core/JournalSyncApplier.js +48 -0
- package/dist/core/JournalSyncApplier.js.map +1 -1
- package/dist/core/LeaseCoordinator.d.ts +4 -0
- package/dist/core/LeaseCoordinator.d.ts.map +1 -1
- package/dist/core/LeaseCoordinator.js +64 -1
- package/dist/core/LeaseCoordinator.js.map +1 -1
- package/dist/core/MessagingToneGate.d.ts +11 -7
- package/dist/core/MessagingToneGate.d.ts.map +1 -1
- package/dist/core/MessagingToneGate.js +15 -1
- package/dist/core/MessagingToneGate.js.map +1 -1
- package/dist/core/MobileDeviceKeys.d.ts +10 -0
- package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
- package/dist/core/MobileDeviceKeys.js +17 -0
- package/dist/core/MobileDeviceKeys.js.map +1 -1
- package/dist/core/MultiMachineCoordinator.d.ts +12 -0
- package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
- package/dist/core/MultiMachineCoordinator.js +115 -3
- package/dist/core/MultiMachineCoordinator.js.map +1 -1
- package/dist/core/MutualSshRuntime.d.ts +1 -0
- package/dist/core/MutualSshRuntime.d.ts.map +1 -1
- package/dist/core/MutualSshRuntime.js +17 -1
- package/dist/core/MutualSshRuntime.js.map +1 -1
- package/dist/core/ObservedEndpointTracker.d.ts +1 -0
- package/dist/core/ObservedEndpointTracker.d.ts.map +1 -1
- package/dist/core/ObservedEndpointTracker.js +17 -0
- package/dist/core/ObservedEndpointTracker.js.map +1 -1
- package/dist/core/OverloadShedPlanner.d.ts.map +1 -1
- package/dist/core/OverloadShedPlanner.js +9 -0
- package/dist/core/OverloadShedPlanner.js.map +1 -1
- package/dist/core/OwnershipApplier.d.ts.map +1 -1
- package/dist/core/OwnershipApplier.js +7 -0
- package/dist/core/OwnershipApplier.js.map +1 -1
- package/dist/core/OwnershipReconciler.d.ts.map +1 -1
- package/dist/core/OwnershipReconciler.js +5 -0
- package/dist/core/OwnershipReconciler.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +8 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +76 -2
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/PrHandLease.d.ts.map +1 -1
- package/dist/core/PrHandLease.js +2 -0
- package/dist/core/PrHandLease.js.map +1 -1
- package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
- package/dist/core/ProactiveSwapMonitor.js +7 -0
- package/dist/core/ProactiveSwapMonitor.js.map +1 -1
- package/dist/core/ProjectRoundExecution.d.ts.map +1 -1
- package/dist/core/ProjectRoundExecution.js +3 -2
- package/dist/core/ProjectRoundExecution.js.map +1 -1
- package/dist/core/QueueDrainLoop.d.ts +7 -0
- package/dist/core/QueueDrainLoop.d.ts.map +1 -1
- package/dist/core/QueueDrainLoop.js +37 -1
- package/dist/core/QueueDrainLoop.js.map +1 -1
- package/dist/core/RemoteAckStore.d.ts.map +1 -1
- package/dist/core/RemoteAckStore.js +4 -0
- package/dist/core/RemoteAckStore.js.map +1 -1
- package/dist/core/ReplicatedStoreReconcilerWiring.d.ts.map +1 -1
- package/dist/core/ReplicatedStoreReconcilerWiring.js +1 -0
- package/dist/core/ReplicatedStoreReconcilerWiring.js.map +1 -1
- package/dist/core/SecretSync.d.ts +1 -0
- package/dist/core/SecretSync.d.ts.map +1 -1
- package/dist/core/SecretSync.js +16 -0
- package/dist/core/SecretSync.js.map +1 -1
- package/dist/core/SessionManager.d.ts +11 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +125 -14
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionPoolFailoverRunner.d.ts.map +1 -1
- package/dist/core/SessionPoolFailoverRunner.js +4 -0
- package/dist/core/SessionPoolFailoverRunner.js.map +1 -1
- package/dist/core/SleepWakeDetector.d.ts.map +1 -1
- package/dist/core/SleepWakeDetector.js +10 -0
- package/dist/core/SleepWakeDetector.js.map +1 -1
- package/dist/core/SubscriptionReloginStore.d.ts.map +1 -1
- package/dist/core/SubscriptionReloginStore.js +10 -1
- package/dist/core/SubscriptionReloginStore.js.map +1 -1
- package/dist/core/TopicPinMutation.d.ts.map +1 -1
- package/dist/core/TopicPinMutation.js +5 -0
- package/dist/core/TopicPinMutation.js.map +1 -1
- package/dist/core/UnjustifiedStopGate.d.ts.map +1 -1
- package/dist/core/UnjustifiedStopGate.js +22 -0
- package/dist/core/UnjustifiedStopGate.js.map +1 -1
- package/dist/core/WindowRunCadenceExecutor.d.ts.map +1 -1
- package/dist/core/WindowRunCadenceExecutor.js +20 -0
- package/dist/core/WindowRunCadenceExecutor.js.map +1 -1
- package/dist/core/claudeChildAuth.d.ts +68 -0
- package/dist/core/claudeChildAuth.d.ts.map +1 -0
- package/dist/core/claudeChildAuth.js +173 -0
- package/dist/core/claudeChildAuth.js.map +1 -0
- package/dist/core/claudeKeyProbe.d.ts +23 -0
- package/dist/core/claudeKeyProbe.d.ts.map +1 -0
- package/dist/core/claudeKeyProbe.js +68 -0
- package/dist/core/claudeKeyProbe.js.map +1 -0
- package/dist/core/codexDeviceLimitWiring.d.ts.map +1 -1
- package/dist/core/codexDeviceLimitWiring.js +12 -0
- package/dist/core/codexDeviceLimitWiring.js.map +1 -1
- package/dist/core/deliverToConversation.d.ts.map +1 -1
- package/dist/core/deliverToConversation.js +11 -0
- package/dist/core/deliverToConversation.js.map +1 -1
- package/dist/core/meteredCallEntry.d.ts.map +1 -1
- package/dist/core/meteredCallEntry.js +21 -0
- package/dist/core/meteredCallEntry.js.map +1 -1
- package/dist/core/nobodyPollingActuator.d.ts.map +1 -1
- package/dist/core/nobodyPollingActuator.js +5 -0
- package/dist/core/nobodyPollingActuator.js.map +1 -1
- package/dist/core/operatorSurfaceReferral.d.ts +18 -0
- package/dist/core/operatorSurfaceReferral.d.ts.map +1 -0
- package/dist/core/operatorSurfaceReferral.js +32 -0
- package/dist/core/operatorSurfaceReferral.js.map +1 -0
- package/dist/core/ownershipFollowsLiveWork.d.ts.map +1 -1
- package/dist/core/ownershipFollowsLiveWork.js +10 -1
- package/dist/core/ownershipFollowsLiveWork.js.map +1 -1
- package/dist/core/types.d.ts +15 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worktreeDirtyCheck.d.ts.map +1 -1
- package/dist/core/worktreeDirtyCheck.js +2 -0
- package/dist/core/worktreeDirtyCheck.js.map +1 -1
- package/dist/data/stageBCertifiedSet.d.ts +9 -0
- package/dist/data/stageBCertifiedSet.d.ts.map +1 -1
- package/dist/data/stageBCertifiedSet.js +12 -0
- package/dist/data/stageBCertifiedSet.js.map +1 -1
- package/dist/data/standards-guard-index.json +1 -1
- package/dist/data/standards-guard-index.meta.json +2 -2
- package/dist/data/standards-registry.meta.json +1 -1
- package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
- package/dist/lifeline/TelegramLifeline.js +17 -3
- package/dist/lifeline/TelegramLifeline.js.map +1 -1
- package/dist/messaging/attentionHubPolicy.d.ts.map +1 -1
- package/dist/messaging/attentionHubPolicy.js +1 -0
- package/dist/messaging/attentionHubPolicy.js.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.d.ts.map +1 -1
- package/dist/monitoring/AgentWorktreeReaper.js +15 -0
- package/dist/monitoring/AgentWorktreeReaper.js.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.d.ts.map +1 -1
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js +18 -9
- package/dist/monitoring/ApprenticeshipCycleSlaMonitor.js.map +1 -1
- package/dist/monitoring/CodexArmSessionSweeper.d.ts.map +1 -1
- package/dist/monitoring/CodexArmSessionSweeper.js +11 -0
- package/dist/monitoring/CodexArmSessionSweeper.js.map +1 -1
- package/dist/monitoring/CrashLoopPauser.d.ts.map +1 -1
- package/dist/monitoring/CrashLoopPauser.js +8 -0
- package/dist/monitoring/CrashLoopPauser.js.map +1 -1
- package/dist/monitoring/DegradationReporter.d.ts.map +1 -1
- package/dist/monitoring/DegradationReporter.js +7 -1
- package/dist/monitoring/DegradationReporter.js.map +1 -1
- package/dist/monitoring/DegradedTmuxGuard.d.ts +2 -0
- package/dist/monitoring/DegradedTmuxGuard.d.ts.map +1 -1
- package/dist/monitoring/DegradedTmuxGuard.js +14 -0
- package/dist/monitoring/DegradedTmuxGuard.js.map +1 -1
- package/dist/monitoring/DurableOutputScrubber.d.ts.map +1 -1
- package/dist/monitoring/DurableOutputScrubber.js +7 -0
- package/dist/monitoring/DurableOutputScrubber.js.map +1 -1
- package/dist/monitoring/DurableVaultSession.d.ts.map +1 -1
- package/dist/monitoring/DurableVaultSession.js +15 -0
- package/dist/monitoring/DurableVaultSession.js.map +1 -1
- package/dist/monitoring/ExternalHogSentinel.d.ts +2 -0
- package/dist/monitoring/ExternalHogSentinel.d.ts.map +1 -1
- package/dist/monitoring/ExternalHogSentinel.js +27 -1
- package/dist/monitoring/ExternalHogSentinel.js.map +1 -1
- package/dist/monitoring/FailureLedger.d.ts.map +1 -1
- package/dist/monitoring/FailureLedger.js +38 -1
- package/dist/monitoring/FailureLedger.js.map +1 -1
- package/dist/monitoring/FeatureEvidenceLog.d.ts +5 -0
- package/dist/monitoring/FeatureEvidenceLog.d.ts.map +1 -1
- package/dist/monitoring/FeatureEvidenceLog.js +25 -0
- package/dist/monitoring/FeatureEvidenceLog.js.map +1 -1
- package/dist/monitoring/GeminiCapacityEscalationMonitor.d.ts.map +1 -1
- package/dist/monitoring/GeminiCapacityEscalationMonitor.js +20 -2
- package/dist/monitoring/GeminiCapacityEscalationMonitor.js.map +1 -1
- package/dist/monitoring/GeminiLoopRunner.d.ts.map +1 -1
- package/dist/monitoring/GeminiLoopRunner.js +11 -1
- package/dist/monitoring/GeminiLoopRunner.js.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -1
- package/dist/monitoring/GreenPrAutoMerger.js +11 -0
- package/dist/monitoring/GreenPrAutoMerger.js.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.d.ts.map +1 -1
- package/dist/monitoring/GrowthDigestPublisher.js +16 -0
- package/dist/monitoring/GrowthDigestPublisher.js.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.d.ts +3 -0
- package/dist/monitoring/GrowthMilestoneAnalyst.d.ts.map +1 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.js +45 -1
- package/dist/monitoring/GrowthMilestoneAnalyst.js.map +1 -1
- package/dist/monitoring/McpProcessReaper.d.ts +2 -0
- package/dist/monitoring/McpProcessReaper.d.ts.map +1 -1
- package/dist/monitoring/McpProcessReaper.js +32 -0
- package/dist/monitoring/McpProcessReaper.js.map +1 -1
- package/dist/monitoring/MissingLoginSessionDetector.d.ts +2 -1
- package/dist/monitoring/MissingLoginSessionDetector.d.ts.map +1 -1
- package/dist/monitoring/MissingLoginSessionDetector.js +23 -0
- package/dist/monitoring/MissingLoginSessionDetector.js.map +1 -1
- package/dist/monitoring/OrchestratorPoller.d.ts +1 -0
- package/dist/monitoring/OrchestratorPoller.d.ts.map +1 -1
- package/dist/monitoring/OrchestratorPoller.js +13 -0
- package/dist/monitoring/OrchestratorPoller.js.map +1 -1
- package/dist/monitoring/OrphanedWorkSentinel.d.ts.map +1 -1
- package/dist/monitoring/OrphanedWorkSentinel.js +7 -0
- package/dist/monitoring/OrphanedWorkSentinel.js.map +1 -1
- package/dist/monitoring/PresenceProxy.d.ts.map +1 -1
- package/dist/monitoring/PresenceProxy.js +9 -1
- package/dist/monitoring/PresenceProxy.js.map +1 -1
- package/dist/monitoring/ProcessFootprintMonitor.d.ts.map +1 -1
- package/dist/monitoring/ProcessFootprintMonitor.js +20 -2
- package/dist/monitoring/ProcessFootprintMonitor.js.map +1 -1
- package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
- package/dist/monitoring/PromiseBeacon.js +20 -0
- package/dist/monitoring/PromiseBeacon.js.map +1 -1
- package/dist/monitoring/ReleaseReadinessSentinel.d.ts +2 -0
- package/dist/monitoring/ReleaseReadinessSentinel.d.ts.map +1 -1
- package/dist/monitoring/ReleaseReadinessSentinel.js +26 -0
- package/dist/monitoring/ReleaseReadinessSentinel.js.map +1 -1
- package/dist/monitoring/RopeHealthMonitor.d.ts.map +1 -1
- package/dist/monitoring/RopeHealthMonitor.js +35 -1
- package/dist/monitoring/RopeHealthMonitor.js.map +1 -1
- package/dist/monitoring/SentinelNotifier.d.ts.map +1 -1
- package/dist/monitoring/SentinelNotifier.js +16 -0
- package/dist/monitoring/SentinelNotifier.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +11 -2
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts +2 -0
- package/dist/monitoring/SingleMachineFailoverGapDetector.d.ts.map +1 -1
- package/dist/monitoring/SingleMachineFailoverGapDetector.js +20 -0
- package/dist/monitoring/SingleMachineFailoverGapDetector.js.map +1 -1
- package/dist/monitoring/SpeakerElection.d.ts.map +1 -1
- package/dist/monitoring/SpeakerElection.js +8 -0
- package/dist/monitoring/SpeakerElection.js.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.d.ts +3 -0
- package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.js +33 -0
- package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
- package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
- package/dist/native/instar-desktop-host +0 -0
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.d.ts.map +1 -1
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js +5 -2
- package/dist/providers/adapters/anthropic-headless/transport/oneShotCompletion.js.map +1 -1
- package/dist/recommended/RecommendedServicesLedger.d.ts +91 -0
- package/dist/recommended/RecommendedServicesLedger.d.ts.map +1 -0
- package/dist/recommended/RecommendedServicesLedger.js +193 -0
- package/dist/recommended/RecommendedServicesLedger.js.map +1 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.d.ts +14 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.d.ts.map +1 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.js +34 -0
- package/dist/recommended/RecommendedServicesReplicatedStore.js.map +1 -0
- package/dist/recommended/legacyDeclines.d.ts +11 -0
- package/dist/recommended/legacyDeclines.d.ts.map +1 -0
- package/dist/recommended/legacyDeclines.js +17 -0
- package/dist/recommended/legacyDeclines.js.map +1 -0
- package/dist/recommended/serviceIds.d.ts +3 -0
- package/dist/recommended/serviceIds.d.ts.map +1 -0
- package/dist/recommended/serviceIds.js +6 -0
- package/dist/recommended/serviceIds.js.map +1 -0
- package/dist/scaffold/templates.d.ts +2 -0
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +8 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/scheduler/JobResultTriage.d.ts.map +1 -1
- package/dist/scheduler/JobResultTriage.js +10 -0
- package/dist/scheduler/JobResultTriage.js.map +1 -1
- package/dist/scheduler/JobScheduler.d.ts.map +1 -1
- package/dist/scheduler/JobScheduler.js +12 -0
- package/dist/scheduler/JobScheduler.js.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.d.ts +3 -0
- package/dist/scheduler/MentorOnboardingRunner.d.ts.map +1 -1
- package/dist/scheduler/MentorOnboardingRunner.js +24 -2
- package/dist/scheduler/MentorOnboardingRunner.js.map +1 -1
- package/dist/server/AgentServer.d.ts +2 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +76 -15
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/BootHealthBeacon.d.ts +3 -0
- package/dist/server/BootHealthBeacon.d.ts.map +1 -1
- package/dist/server/BootHealthBeacon.js +9 -0
- package/dist/server/BootHealthBeacon.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +10 -1
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/LifelineIngressGuard.d.ts.map +1 -1
- package/dist/server/LifelineIngressGuard.js +11 -0
- package/dist/server/LifelineIngressGuard.js.map +1 -1
- package/dist/server/PoolPollCache.d.ts +4 -0
- package/dist/server/PoolPollCache.d.ts.map +1 -1
- package/dist/server/PoolPollCache.js +33 -0
- package/dist/server/PoolPollCache.js.map +1 -1
- package/dist/server/machineRoutes.d.ts.map +1 -1
- package/dist/server/machineRoutes.js +6 -0
- package/dist/server/machineRoutes.js.map +1 -1
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +6 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/mobileConsoleTicket.d.ts +113 -0
- package/dist/server/mobileConsoleTicket.d.ts.map +1 -0
- package/dist/server/mobileConsoleTicket.js +405 -0
- package/dist/server/mobileConsoleTicket.js.map +1 -0
- package/dist/server/mobileConversationRoutes.d.ts.map +1 -1
- package/dist/server/mobileConversationRoutes.js +20 -1
- package/dist/server/mobileConversationRoutes.js.map +1 -1
- package/dist/server/mobileMediaRoutes.d.ts.map +1 -1
- package/dist/server/mobileMediaRoutes.js +3 -0
- package/dist/server/mobileMediaRoutes.js.map +1 -1
- package/dist/server/mobilePairingRoutes.d.ts +8 -2
- package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
- package/dist/server/mobilePairingRoutes.js +67 -6
- package/dist/server/mobilePairingRoutes.js.map +1 -1
- package/dist/server/mobileSessionTerminalRoutes.d.ts +128 -0
- package/dist/server/mobileSessionTerminalRoutes.d.ts.map +1 -0
- package/dist/server/mobileSessionTerminalRoutes.js +389 -0
- package/dist/server/mobileSessionTerminalRoutes.js.map +1 -0
- package/dist/server/recommendedServiceRoutes.d.ts +13 -0
- package/dist/server/recommendedServiceRoutes.d.ts.map +1 -0
- package/dist/server/recommendedServiceRoutes.js +49 -0
- package/dist/server/recommendedServiceRoutes.js.map +1 -0
- package/dist/server/routes.d.ts +2 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +170 -4
- package/dist/server/routes.js.map +1 -1
- package/dist/testing/selfActionRegistry.d.ts.map +1 -1
- package/dist/testing/selfActionRegistry.js +36 -0
- package/dist/testing/selfActionRegistry.js.map +1 -1
- package/dist/threadline/A2ACheckInProxy.d.ts.map +1 -1
- package/dist/threadline/A2ACheckInProxy.js +26 -15
- package/dist/threadline/A2ACheckInProxy.js.map +1 -1
- package/dist/threadline/AgentTrustManager.d.ts.map +1 -1
- package/dist/threadline/AgentTrustManager.js +3 -0
- package/dist/threadline/AgentTrustManager.js.map +1 -1
- package/dist/threadline/InboundIdLedger.d.ts.map +1 -1
- package/dist/threadline/InboundIdLedger.js +18 -1
- package/dist/threadline/InboundIdLedger.js.map +1 -1
- package/dist/threadline/NegotiatorGate.d.ts.map +1 -1
- package/dist/threadline/NegotiatorGate.js +11 -0
- package/dist/threadline/NegotiatorGate.js.map +1 -1
- package/dist/threadline/PipeSessionSpawner.d.ts.map +1 -1
- package/dist/threadline/PipeSessionSpawner.js +8 -0
- package/dist/threadline/PipeSessionSpawner.js.map +1 -1
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +13 -0
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/pairingReplicationWiring.d.ts.map +1 -1
- package/dist/threadline/pairingReplicationWiring.js +9 -0
- package/dist/threadline/pairingReplicationWiring.js.map +1 -1
- package/dist/threadline/relayForward.d.ts.map +1 -1
- package/dist/threadline/relayForward.js +13 -2
- package/dist/threadline/relayForward.js.map +1 -1
- package/dist/threadline/relayUnknownSenderTrust.d.ts +0 -9
- package/dist/threadline/relayUnknownSenderTrust.d.ts.map +1 -1
- package/dist/threadline/relayUnknownSenderTrust.js +16 -0
- package/dist/threadline/relayUnknownSenderTrust.js.map +1 -1
- package/package.json +1 -1
- package/scripts/check-constitution-pairing.mjs +273 -0
- package/scripts/safe-merge.mjs +9 -0
- package/src/data/builtin-manifest.json +103 -103
- package/src/data/feature-ladders.json +113 -113
- package/src/data/stageBCertifiedSet.ts +12 -0
- package/src/data/standards-guard-index.json +1 -1
- package/src/data/standards-guard-index.meta.json +2 -2
- package/src/data/standards-registry.meta.json +1 -1
- package/src/data/state-coherence-registry.json +18 -0
- package/src/scaffold/templates.ts +9 -0
- package/upgrades/1.3.1650.md +105 -0
- package/upgrades/mobile-console-device-signin.eli16.md +5 -0
- package/upgrades/side-effects/cloud-key-internal-calls.md +116 -0
- package/upgrades/side-effects/constitution-alignment.eli16.md +11 -0
- package/upgrades/side-effects/constitution-alignment.md +69 -0
- package/upgrades/side-effects/feature-evidence-recording.eli16.md +3 -0
- package/upgrades/side-effects/feature-evidence-recording.md +66 -0
- package/upgrades/side-effects/feedback-reroute-admission-parity.md +77 -0
- package/upgrades/side-effects/mobile-console-device-signin.md +102 -0
- package/upgrades/side-effects/mobile-native-session-screen.md +88 -0
- package/upgrades/side-effects/operator-needs-first-screen.md +87 -0
- package/upgrades/side-effects/recommended-services-choices.md +50 -0
- package/upgrades/side-effects/rerouted-lifetime-active-process.md +63 -0
- package/upgrades/side-effects/undated-resurfacer-e2e-wait.eli16.md +5 -0
- package/upgrades/side-effects/undated-resurfacer-e2e-wait.md +9 -0
package/dist/server/routes.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { registerEcosystemIdeaRoutes } from './ecosystemIdeaRoutes.js';
|
|
2
|
+
import { registerRecommendedServiceRoutes } from './recommendedServiceRoutes.js';
|
|
3
|
+
import { isRetiredLegacyOffer } from '../recommended/legacyDeclines.js';
|
|
4
|
+
import { featureEvidence } from '../monitoring/FeatureEvidenceLog.js';
|
|
2
5
|
import { ISSUES_TOPIC_OFFSET } from '../messaging/telegramTopicSpace.js';
|
|
3
6
|
import { SlackOriginLedger, SlackOriginRecordingError } from '../messaging/slack/SlackOriginLedger.js';
|
|
4
7
|
import { slackOriginFooter, currentAgentDisplay, deviceOriginRow, effectiveDisplay, originEvidenceFromProducer, validateDeviceOriginRow, validateMessageOriginEvidence } from '../messaging/messageOrigin.js';
|
|
@@ -39,6 +42,7 @@ import { telegramFetch } from '../messaging/telegram-egress.js';
|
|
|
39
42
|
import { emergencyStopUserMessage } from '../messaging/shared/emergencyStopUserMessage.js';
|
|
40
43
|
import { isVerifiedChannelName, verifiedEntityName } from '../messaging/shared/channelIdentity.js';
|
|
41
44
|
import { execFileSync } from 'node:child_process';
|
|
45
|
+
import { activeClaudeKeyHealth } from '../core/ClaudeKeyHealth.js';
|
|
42
46
|
import { createHash, createHmac, timingSafeEqual, randomBytes, randomUUID } from 'node:crypto';
|
|
43
47
|
import { governor as selfActionGovernorSurface } from '../monitoring/selfaction/governor.js';
|
|
44
48
|
import { classifyActionClaim, classifyApprovalRequest, excerptAround } from '../core/action-claim.js';
|
|
@@ -390,6 +394,7 @@ import { credentialGuardMessage, detectOutboundCredential } from '../messaging/o
|
|
|
390
394
|
import { detectJargon } from '../core/JargonDetector.js';
|
|
391
395
|
import { detectRawFilePath } from '../core/raw-file-path.js';
|
|
392
396
|
import { detectParkedOnUser } from '../core/parked-on-user.js';
|
|
397
|
+
import { detectSurfaceReferral } from '../core/operatorSurfaceReferral.js';
|
|
393
398
|
import { detectAskWhenAuthorized } from '../core/ask-when-authorized.js';
|
|
394
399
|
import { detectInternalIdLeak } from '../core/internal-id-leak.js';
|
|
395
400
|
import { OutboundAdvisoryAudit, composeAdvisories, composeTimeClaimAdvisories, PREFLIGHT_TEXT_CAP, } from '../messaging/OutboundAdvisory.js';
|
|
@@ -3081,6 +3086,11 @@ export function createRoutes(ctx) {
|
|
|
3081
3086
|
// over. A guard that walls a credential in the message body while storing
|
|
3082
3087
|
// one from the reason field would be theatre.
|
|
3083
3088
|
const note = input.reason ? scrubForStore(input.reason).text.slice(0, 500) : undefined;
|
|
3089
|
+
featureEvidence.record('toneGate.advisoryMigration', {
|
|
3090
|
+
kind: 'fired',
|
|
3091
|
+
reason: `self-report-${reaction}`,
|
|
3092
|
+
context: { reaction, rule: rule.slice(0, 64), derivation: derivation ?? null, grade: reaction === 'override' ? 'wrong' : 'right', hasReason: !!note },
|
|
3093
|
+
});
|
|
3084
3094
|
// ── Off the send path ────────────────────────────────────────────────
|
|
3085
3095
|
// `upsertOutcome` is a synchronous better-sqlite3 transaction that
|
|
3086
3096
|
// recomputes the whole (decision_point, day) rollup twice over a window-
|
|
@@ -3285,6 +3295,25 @@ export function createRoutes(ctx) {
|
|
|
3285
3295
|
catch {
|
|
3286
3296
|
// @silent-fallback-ok — detector errors never override the authority; skip the signal (outbound-jargon-filepath-gap §2.3).
|
|
3287
3297
|
}
|
|
3298
|
+
// operator-needs-first-screen §6 — surface referral (B22). SIGNAL ONLY, and only for a
|
|
3299
|
+
// sender that can react to a nudge: a caller that treats any hold as final never sees it.
|
|
3300
|
+
// Fail-OPEN: a detector throw skips the signal, never withholds.
|
|
3301
|
+
if (options.liveArtefactSignals === true && kindForSignals === 'reply' && options.noReactionPossible !== true) {
|
|
3302
|
+
try {
|
|
3303
|
+
const sr = detectSurfaceReferral(text);
|
|
3304
|
+
if (sr.referral) {
|
|
3305
|
+
signals.surfaceReferral = {
|
|
3306
|
+
...(sr.phrase ? { phrase: sr.phrase } : {}),
|
|
3307
|
+
hasLink: sr.hasLink,
|
|
3308
|
+
hasOnScreenWords: sr.hasOnScreenWords,
|
|
3309
|
+
renderConfirmed: options.toneAdvisoryComplied === 'B22_SURFACE_REFERRAL',
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
catch {
|
|
3314
|
+
// @silent-fallback-ok — detector errors never override the authority; skip the signal.
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3288
3317
|
// C1+C2 §4.3 — parked-on-user (B19) + internal-id-leak (B20) signals.
|
|
3289
3318
|
// SIGNAL ONLY: the authority (B19/B20 rules) decides with carve-outs +
|
|
3290
3319
|
// fail-toward-sending. Fail-OPEN: a detector throw skips the signal.
|
|
@@ -4265,7 +4294,8 @@ export function createRoutes(ctx) {
|
|
|
4265
4294
|
let isDegraded = sessionExhausted
|
|
4266
4295
|
|| totalFailures >= 5
|
|
4267
4296
|
|| degradations.length > 0
|
|
4268
|
-
|| (llmReliability !== null && llmReliability.status !== 'ok')
|
|
4297
|
+
|| (llmReliability !== null && llmReliability.status !== 'ok')
|
|
4298
|
+
|| activeClaudeKeyHealth()?.status()?.status === 'dead';
|
|
4269
4299
|
const base = {
|
|
4270
4300
|
status: isDegraded ? 'degraded' : 'ok',
|
|
4271
4301
|
uptime: uptimeMs,
|
|
@@ -4286,6 +4316,9 @@ export function createRoutes(ctx) {
|
|
|
4286
4316
|
// (`bearerMatches`): byte-identical to the inline check it replaced.
|
|
4287
4317
|
const isAuthed = bearerMatches(req, ctx.config.authToken);
|
|
4288
4318
|
if (isAuthed) {
|
|
4319
|
+
const claudeKey = activeClaudeKeyHealth()?.status();
|
|
4320
|
+
if (claudeKey)
|
|
4321
|
+
base.claudeKey = claudeKey;
|
|
4289
4322
|
// job-cost-reduction §5.3: the stable feature ids behind degradationSummary.
|
|
4290
4323
|
// The narrative strings carry per-occurrence values, so they are evidence
|
|
4291
4324
|
// only; health-check keys its `degradation:<feature>` reasons on these.
|
|
@@ -7658,6 +7691,19 @@ export function createRoutes(ctx) {
|
|
|
7658
7691
|
: condition.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 80) || 'autonomous-goal';
|
|
7659
7692
|
const userFacing = typeof body.userFacing === 'boolean' ? body.userFacing : undefined;
|
|
7660
7693
|
const gate = ctx.liveTestGate.evaluate({ featureId, userFacing, goalText: condition, mode: ctx.liveTestGateMode });
|
|
7694
|
+
featureEvidence.record('monitoring.liveTestGate', {
|
|
7695
|
+
kind: gate.outcome !== 'allow' ? 'fired' : 'held',
|
|
7696
|
+
reason: gate.blocks ? `veto:${gate.outcome}` : gate.wouldBlock ? `would-veto:${gate.outcome}` : 'allowed',
|
|
7697
|
+
context: {
|
|
7698
|
+
outcome: gate.outcome,
|
|
7699
|
+
mode: gate.mode,
|
|
7700
|
+
wouldBlock: gate.wouldBlock,
|
|
7701
|
+
blocks: gate.blocks,
|
|
7702
|
+
// The fallback id is built from the goal text, so only a declared id is kept.
|
|
7703
|
+
declaredFeatureId: typeof body.featureId === 'string' && body.featureId ? body.featureId : null,
|
|
7704
|
+
userFacingDeclared: userFacing ?? null,
|
|
7705
|
+
},
|
|
7706
|
+
});
|
|
7661
7707
|
if (gate.outcome !== 'allow') {
|
|
7662
7708
|
if (gate.blocks) {
|
|
7663
7709
|
res.json({ met: false, reason: `live-test gate: ${gate.reason}`, liveTestGate: { outcome: gate.outcome, mode: gate.mode, overrode: true } });
|
|
@@ -7670,7 +7716,8 @@ export function createRoutes(ctx) {
|
|
|
7670
7716
|
return;
|
|
7671
7717
|
}
|
|
7672
7718
|
}
|
|
7673
|
-
catch {
|
|
7719
|
+
catch (gateErr) {
|
|
7720
|
+
featureEvidence.record('monitoring.liveTestGate', { kind: 'error', reason: 'gate-evaluate-failed', context: { mode: ctx.liveTestGateMode, errorName: gateErr instanceof Error ? gateErr.name : 'unknown' } });
|
|
7674
7721
|
// @silent-fallback-ok — a gate error must never trap a genuine completion
|
|
7675
7722
|
// (the completion judge is the primary authority); fall through to the verdict.
|
|
7676
7723
|
}
|
|
@@ -12309,6 +12356,7 @@ export function createRoutes(ctx) {
|
|
|
12309
12356
|
browserNonce: req.body?.browserNonce, videoCodec: req.body?.videoCodec,
|
|
12310
12357
|
client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true,
|
|
12311
12358
|
});
|
|
12359
|
+
featureEvidence.record('remoteDesktop', { kind: 'fired', reason: 'session-started-via-mesh', context: { route: 'mesh', machineId: String(req.body?.machineId ?? '').slice(0, 64), client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true } });
|
|
12312
12360
|
res.status(201).json(result);
|
|
12313
12361
|
return;
|
|
12314
12362
|
}
|
|
@@ -12321,9 +12369,11 @@ export function createRoutes(ctx) {
|
|
|
12321
12369
|
scopeConfirmed: req.body?.scopeConfirmed,
|
|
12322
12370
|
client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true,
|
|
12323
12371
|
});
|
|
12372
|
+
featureEvidence.record('remoteDesktop', { kind: 'fired', reason: 'session-started-direct', context: { route: 'direct', machineId: String(req.body?.machineId ?? '').slice(0, 64), client: req.body?.client === 'app' ? 'app' : 'browser', controlRecords: req.body?.controlRecords === true, telegramStepUp } });
|
|
12324
12373
|
res.status(201).json(result);
|
|
12325
12374
|
}
|
|
12326
12375
|
catch (error) {
|
|
12376
|
+
featureEvidence.record('remoteDesktop', { kind: 'error', reason: 'session-start-refused', context: { machineId: String(req.body?.machineId ?? '').slice(0, 64), telegramStepUp, errorName: error?.name ?? 'unknown' } });
|
|
12327
12377
|
res.status(403).json({ error: error.message });
|
|
12328
12378
|
}
|
|
12329
12379
|
});
|
|
@@ -13867,6 +13917,7 @@ export function createRoutes(ctx) {
|
|
|
13867
13917
|
if (typeof proposedUid === 'string' && proposedUid) {
|
|
13868
13918
|
const principal = ar.resolvePrincipal(proposedUid);
|
|
13869
13919
|
if (!principal || !principal.registered) {
|
|
13920
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: 'create refused: unknown-user', context: { status: 400 } });
|
|
13870
13921
|
res.status(400).json({ error: 'unknown-user — the grantee must be a registered Slack user' });
|
|
13871
13922
|
return;
|
|
13872
13923
|
}
|
|
@@ -13878,9 +13929,11 @@ export function createRoutes(ctx) {
|
|
|
13878
13929
|
reason: typeof b.reason === 'string' ? b.reason : undefined,
|
|
13879
13930
|
});
|
|
13880
13931
|
if (!result.ok) {
|
|
13932
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `create refused: ${result.error}`, context: { status: result.status } });
|
|
13881
13933
|
res.status(result.status).json({ error: result.error });
|
|
13882
13934
|
return;
|
|
13883
13935
|
}
|
|
13936
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: result.deduped ? 'create deduped' : 'created', context: { requestId: result.request.id, requestKind: result.request.kind, floorAction: result.request.proposal.floorAction, durationMs: result.request.proposal.durationMs, deduped: result.deduped ?? false } });
|
|
13884
13937
|
res.status(201).json({ id: result.request.id, deduped: result.deduped ?? false, request: decorateAuthReq(result.request) });
|
|
13885
13938
|
});
|
|
13886
13939
|
// List requests (filter ?status=pending). Each row carries the server-rendered card. Bearer.
|
|
@@ -13913,8 +13966,10 @@ export function createRoutes(ctx) {
|
|
|
13913
13966
|
res.status(503).json({ error: 'coordination mandate engine unavailable' });
|
|
13914
13967
|
return;
|
|
13915
13968
|
}
|
|
13916
|
-
if (!checkMandatePin(req, res))
|
|
13969
|
+
if (!checkMandatePin(req, res)) {
|
|
13970
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: 'approve refused: PIN gate', context: { requestId: req.params.id } });
|
|
13917
13971
|
return;
|
|
13972
|
+
}
|
|
13918
13973
|
const ar = ctx.authorizationRequests;
|
|
13919
13974
|
const result = ar.store.approve(req.params.id, {
|
|
13920
13975
|
execute: (proposal) => {
|
|
@@ -13953,9 +14008,11 @@ export function createRoutes(ctx) {
|
|
|
13953
14008
|
},
|
|
13954
14009
|
});
|
|
13955
14010
|
if (!result.ok) {
|
|
14011
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: result.status === 409 ? 'error' : 'held', reason: `approve refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
|
|
13956
14012
|
res.status(result.status).json({ error: result.error });
|
|
13957
14013
|
return;
|
|
13958
14014
|
}
|
|
14015
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: result.alreadyApproved ? 'already approved' : 'approved', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction, durationMs: result.request.proposal.durationMs, alreadyApproved: result.alreadyApproved ?? false } });
|
|
13959
14016
|
res.status(result.alreadyApproved ? 200 : 201).json({
|
|
13960
14017
|
approved: true, alreadyApproved: result.alreadyApproved ?? false, request: decorateAuthReq(result.request),
|
|
13961
14018
|
});
|
|
@@ -13969,9 +14026,11 @@ export function createRoutes(ctx) {
|
|
|
13969
14026
|
const reason = typeof (req.body ?? {}).denyReason === 'string' ? req.body.denyReason : '';
|
|
13970
14027
|
const result = ctx.authorizationRequests.store.deny(req.params.id, reason);
|
|
13971
14028
|
if (!result.ok) {
|
|
14029
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `deny refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
|
|
13972
14030
|
res.status(result.status).json({ error: result.error });
|
|
13973
14031
|
return;
|
|
13974
14032
|
}
|
|
14033
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: 'denied', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction } });
|
|
13975
14034
|
res.json({ denied: true, request: decorateAuthReq(result.request) });
|
|
13976
14035
|
});
|
|
13977
14036
|
// Proposing agent WITHDRAWS its own still-pending request (Bearer).
|
|
@@ -13982,9 +14041,11 @@ export function createRoutes(ctx) {
|
|
|
13982
14041
|
const agentName = (typeof b.createdByAgent === 'string' && b.createdByAgent) ? b.createdByAgent : 'agent';
|
|
13983
14042
|
const result = ctx.authorizationRequests.store.withdraw(req.params.id, agentName);
|
|
13984
14043
|
if (!result.ok) {
|
|
14044
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'held', reason: `withdraw refused: ${result.error}`, context: { requestId: req.params.id, status: result.status } });
|
|
13985
14045
|
res.status(result.status).json({ error: result.error });
|
|
13986
14046
|
return;
|
|
13987
14047
|
}
|
|
14048
|
+
featureEvidence.record('monitoring.authorizationRequests', { kind: 'fired', reason: 'withdrawn', context: { requestId: result.request.id, floorAction: result.request.proposal.floorAction } });
|
|
13988
14049
|
res.json({ withdrawn: true, request: decorateAuthReq(result.request) });
|
|
13989
14050
|
});
|
|
13990
14051
|
// ── ReviewExchange — autonomous code-review protocol (coordination-mandate spec §7 G2.3) ──
|
|
@@ -14867,6 +14928,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
14867
14928
|
const plan = ctx.feedbackTriage.store.createPlan({ action: 'ignore-live', payload: { enabled }, renderedText });
|
|
14868
14929
|
res.json({ action: 'ignore-live', ...plan });
|
|
14869
14930
|
});
|
|
14931
|
+
registerRecommendedServiceRoutes(router, { ledger: () => ctx.recommendedServicesLedger ?? null, checkPin: (req, res) => checkMandatePin(req, res) });
|
|
14870
14932
|
registerEcosystemIdeaRoutes(router, { ecosystem: () => ctx.ecosystemIdeas?.() ?? null, checkPin: (req, res) => checkMandatePin(req, res) });
|
|
14871
14933
|
router.post('/feedback-factory/triage/commit', (req, res) => {
|
|
14872
14934
|
if (triageUnavailable(res))
|
|
@@ -18143,6 +18205,10 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
18143
18205
|
const advisories = kind === 'automated'
|
|
18144
18206
|
? composeAdvisories(capped, { sessionClocks: activeClocks })
|
|
18145
18207
|
: composeTimeClaimAdvisories(capped, activeClocks);
|
|
18208
|
+
const timeClaimAdvisories = advisories.filter((a) => a.code === 'TIME_CLAIM').length;
|
|
18209
|
+
if (timeClaimAdvisories > 0) {
|
|
18210
|
+
featureEvidence.record('messaging.outboundAdvisory.timeClaim', { kind: 'fired', reason: 'TIME_CLAIM: claim contradicts the live session clock', context: { topicId: Number.isFinite(topic) ? topic : 0, senderKind: kind, jobSlug: typeof jobSlug === 'string' ? jobSlug : null, timeClaimAdvisories, activeClocks: activeClocks.length, chars: capped.length } });
|
|
18211
|
+
}
|
|
18146
18212
|
outboundAdvisoryAudit.recordPreflight({
|
|
18147
18213
|
topicId: Number.isFinite(topic) ? topic : 0,
|
|
18148
18214
|
// Non-automated (conversational-session) preflights carry no job slug —
|
|
@@ -18416,6 +18482,9 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
18416
18482
|
toneAdvisoryComplied,
|
|
18417
18483
|
// jev-signal-live: this reply path carries the acknowledge-and-override fields.
|
|
18418
18484
|
liveArtefactSignals: true,
|
|
18485
|
+
// A sentinel redrive has nobody to react to a nudge, and the recovery policy treats any 422
|
|
18486
|
+
// as final, so B22 must not hold it. A fabricated header does not buy this: it must match a queue row.
|
|
18487
|
+
noReactionPossible: typeof deliveryId === 'string' && /^[0-9a-f-]{16,64}$/i.test(deliveryId) && ctx.pendingRelayLookup?.(deliveryId) === true,
|
|
18419
18488
|
}))
|
|
18420
18489
|
return false;
|
|
18421
18490
|
ctx.telegramOrigin?.service.markCurrentSendPolicyReviewed();
|
|
@@ -19967,9 +20036,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
19967
20036
|
if (body.match === false) {
|
|
19968
20037
|
const ok = trustManager.markVerificationFailed(peerFp, 'Operator-asserted SAS mismatch (POST /threadline/pairing/:peerFp/verify)');
|
|
19969
20038
|
if (!ok) {
|
|
20039
|
+
featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'could-not-mark-verification-failed', context: { peerFp } });
|
|
19970
20040
|
res.status(409).json({ error: 'could not mark verification-failed for this pairing' });
|
|
19971
20041
|
return;
|
|
19972
20042
|
}
|
|
20043
|
+
featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'verification-failed: sas-mismatch', context: { peerFp, typedWords: Array.isArray(body.words) } });
|
|
19973
20044
|
// §3.2 / §3.7 — an operator-asserted SAS mismatch is a potential MITM and must
|
|
19974
20045
|
// raise ONE HIGH attention item, deduped per (peerFp) episode, NEVER coalesced
|
|
19975
20046
|
// (a re-attempt LOOP — repeated handshake-then-mismatch — collapses onto the SAME
|
|
@@ -20003,6 +20074,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
20003
20074
|
peerAcked: profile.peerAcked,
|
|
20004
20075
|
});
|
|
20005
20076
|
if (!ok) {
|
|
20077
|
+
featureEvidence.record('threadline.verifiedPairing', { kind: 'error', reason: 'confirm-refused: state-or-epoch', context: { peerFp, pairingState: profile.pairingState ?? null } });
|
|
20006
20078
|
res.status(409).json({ error: 'could not confirm pairing (state/epoch mismatch or not pending) — re-handshake required' });
|
|
20007
20079
|
return;
|
|
20008
20080
|
}
|
|
@@ -20874,16 +20946,19 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
20874
20946
|
let dropped = 0;
|
|
20875
20947
|
for (const intent of remoteAckStore.list()) {
|
|
20876
20948
|
if (intent.attempts >= REMOTE_ACK_GIVE_UP_ATTEMPTS) {
|
|
20949
|
+
featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'error', reason: 'ack intent given up after the attempt limit', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts, lastOutcome: intent.lastOutcome ?? null } });
|
|
20877
20950
|
remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
|
|
20878
20951
|
dropped += 1;
|
|
20879
20952
|
continue;
|
|
20880
20953
|
}
|
|
20881
20954
|
const disposition = await deliverRemoteAck(intent);
|
|
20882
20955
|
if (disposition === 'delivered') {
|
|
20956
|
+
featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'fired', reason: 'queued ack applied on the owner', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts } });
|
|
20883
20957
|
remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
|
|
20884
20958
|
delivered += 1;
|
|
20885
20959
|
}
|
|
20886
20960
|
else if (disposition === 'stale-superseded') {
|
|
20961
|
+
featureEvidence.record('multiMachine.seamlessness.ws41DurableAck', { kind: 'held', reason: 'queued ack superseded on the owner', context: { itemId: intent.itemId, targetMachineId: intent.targetMachineId, attempts: intent.attempts } });
|
|
20887
20962
|
remoteAckStore.resolve(intent.itemId, intent.targetMachineId);
|
|
20888
20963
|
dropped += 1;
|
|
20889
20964
|
}
|
|
@@ -25530,7 +25605,13 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
25530
25605
|
// bound, single-use, mesh-signed assertion of THAT user-authentication —
|
|
25531
25606
|
// never the raw credential (each machine's PIN secret never crosses).
|
|
25532
25607
|
if (ctx.poolLink) {
|
|
25533
|
-
|
|
25608
|
+
try {
|
|
25609
|
+
await proxyViewToHolder(req, res, req.params.id);
|
|
25610
|
+
}
|
|
25611
|
+
catch (err) {
|
|
25612
|
+
featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'error', reason: 'view proxy to the holder failed', context: { error: (err instanceof Error ? err.message : String(err)).slice(0, 80) } });
|
|
25613
|
+
throw err;
|
|
25614
|
+
}
|
|
25534
25615
|
return;
|
|
25535
25616
|
}
|
|
25536
25617
|
res.status(404).json({ error: 'View not found' });
|
|
@@ -25595,12 +25676,14 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
25595
25676
|
// labeled), never a fabricated/stale body. (The broader pool-cache
|
|
25596
25677
|
// unification is the tracked follow-up CMT-1416; this in-scope posture is
|
|
25597
25678
|
// the staleness-tag on the holder-resolution caching surface.)
|
|
25679
|
+
featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'declined: fronting machine load-shedding with no cached holder', context: { resolution: resolution.kind } });
|
|
25598
25680
|
res.status(503).setHeader('Retry-After', '5');
|
|
25599
25681
|
res.json({ error: 'Fronting machine busy (load-shed) — retry shortly' });
|
|
25600
25682
|
return;
|
|
25601
25683
|
}
|
|
25602
25684
|
if (resolution.kind === 'holder-offline') {
|
|
25603
25685
|
// §WS4.4 d: honest unavailable — NEVER a bare 404, never stale content.
|
|
25686
|
+
featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'holder offline: answered unavailable', context: { resolution: resolution.kind, stale: tagged.stale } });
|
|
25604
25687
|
tagStale();
|
|
25605
25688
|
res.status(503).setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
25606
25689
|
res.send('<!doctype html><meta charset="utf-8"><title>Temporarily unavailable</title>'
|
|
@@ -25620,17 +25703,24 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
25620
25703
|
const slot = await pl.proxy.withSlot(async () => pl.fetchFromHolder({ machineId: resolution.machineId, url: resolution.url }, viewId, method, assertion));
|
|
25621
25704
|
if (!slot.ok) {
|
|
25622
25705
|
// §WS4.4 c: over the in-flight cap — honest 503, never an unbounded queue.
|
|
25706
|
+
featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'held', reason: 'over the in-flight proxy cap', context: { holder: resolution.machineId, method } });
|
|
25623
25707
|
res.status(503).json({ error: 'Too many in-flight remote view requests — retry shortly' });
|
|
25624
25708
|
return;
|
|
25625
25709
|
}
|
|
25626
25710
|
const holderRes = slot.value;
|
|
25627
25711
|
if (holderRes.status === 404) {
|
|
25712
|
+
featureEvidence.record('multiMachine.seamlessness.ws44PoolLinks', { kind: 'error', reason: 'resolved holder no longer has the view', context: { holder: resolution.machineId, status: 404, stale: tagged.stale, method } });
|
|
25628
25713
|
// The memo may name a stale holder (view moved). Invalidate so the next
|
|
25629
25714
|
// request re-fans-out, and surface not-found honestly.
|
|
25630
25715
|
pl.proxy.invalidate(viewId);
|
|
25631
25716
|
res.status(404).json({ error: 'View not found' });
|
|
25632
25717
|
return;
|
|
25633
25718
|
}
|
|
25719
|
+
featureEvidence.recordAtMostEvery('multiMachine.seamlessness.ws44PoolLinks', `proxied|${holderRes.status}`, 10 * 60 * 1000, {
|
|
25720
|
+
kind: holderRes.status >= 500 || holderRes.status === 401 || holderRes.status === 403 ? 'error' : 'fired',
|
|
25721
|
+
reason: holderRes.status === 401 || holderRes.status === 403 ? 'holder refused the assertion' : `proxied view to the holder: ${holderRes.status}`,
|
|
25722
|
+
context: { holder: resolution.machineId, status: holderRes.status, stale: tagged.stale, method, userAuth },
|
|
25723
|
+
});
|
|
25634
25724
|
// §WS4.4 b: the HOLDER makes the authorization decision — relay its
|
|
25635
25725
|
// 401/403 (or any status) UNCHANGED. The fronting machine never substitutes
|
|
25636
25726
|
// its own decision. Stream the body straight through; never cache it.
|
|
@@ -28658,6 +28748,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
28658
28748
|
const full = String(req.query.full ?? '') === '1';
|
|
28659
28749
|
const bsk = new BootSelfKnowledge({ stateDir: ctx.config.stateDir, configPath });
|
|
28660
28750
|
const result = bsk.sessionContext(maxBytes, { full });
|
|
28751
|
+
featureEvidence.record('selfKnowledge.sessionContext', {
|
|
28752
|
+
kind: result.vaultState === 'decrypt-failed' ? 'error' : 'fired',
|
|
28753
|
+
reason: result.vaultState === 'decrypt-failed' ? 'vault-decrypt-failed' : result.present ? 'block-served' : 'nothing-to-serve',
|
|
28754
|
+
context: { present: result.present, nameCount: result.names.length, factCount: result.factCount, vaultState: result.vaultState, blockBytes: Buffer.byteLength(result.block, 'utf8'), maxBytes, full },
|
|
28755
|
+
});
|
|
28661
28756
|
console.log(`[boot-self-knowledge] served names=${result.names.length} facts=${result.factCount} vaultState=${result.vaultState} bytes=${Buffer.byteLength(result.block, 'utf8')}`);
|
|
28662
28757
|
if (result.vaultState === 'decrypt-failed') {
|
|
28663
28758
|
console.warn('[boot-self-knowledge] vault DECRYPT-FAILED — served hands-off warning block (not an empty vault)');
|
|
@@ -28665,6 +28760,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
28665
28760
|
res.json(result);
|
|
28666
28761
|
}
|
|
28667
28762
|
catch (err) {
|
|
28763
|
+
featureEvidence.record('selfKnowledge.sessionContext', { kind: 'error', reason: 'build-failed', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
28668
28764
|
res.status(500).json({ error: err instanceof Error ? err.message : 'Failed to build boot self-knowledge' });
|
|
28669
28765
|
}
|
|
28670
28766
|
});
|
|
@@ -29397,6 +29493,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
29397
29493
|
const entry = outbox.enqueue({ canonicalEmail: canonical, targetMachineId, principal, portable,
|
|
29398
29494
|
cutoffSeq: Number.isSafeInteger(args.revokesGrantSeq) ? args.revokesGrantSeq : null });
|
|
29399
29495
|
const after = await outbox.attemptNow(entry.key);
|
|
29496
|
+
featureEvidence.record('passkeys', { kind: after?.state === 'applied' ? 'fired' : 'held', reason: after?.state === 'applied' ? 'peer-revoke-applied' : 'peer-revoke-queued', context: { op, target: targetMachineId, outboxState: after?.state ?? 'pending' } });
|
|
29400
29497
|
appendPlaywrightAudit('passkey-revoke', 'passkeys', { target: targetMachineId, email: canonical ? 'set' : 'none', delivered: after?.state === 'applied', outbox: after?.state ?? 'pending', reason: after?.lastResult ?? null, dryRun: false });
|
|
29401
29498
|
res.status(after?.state === 'applied' ? 200 : 202).json({ op, target: targetMachineId, delivered: after?.state === 'applied', outbox: after ? { key: after.key, state: after.state, attempts: after.attempts, nextAttemptAt: after.nextAttemptAt, lastResult: after.lastResult ?? null } : null,
|
|
29402
29499
|
note: after?.state === 'applied' ? undefined : 'queued in the durable revoke outbox; re-delivered unchanged on backoff (1h, 6h, then daily) until the peer applies it' });
|
|
@@ -29408,12 +29505,14 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
29408
29505
|
auth.grants.recordIssuedPeerGrant({ canonicalEmail: canonical, targetMachineId, issuedAt: new Date().toISOString(), nonce: out.portable?.body.nonce ?? '',
|
|
29409
29506
|
...(Number.isSafeInteger(peerSeq) ? { targetLocalSeq: peerSeq } : {}) });
|
|
29410
29507
|
}
|
|
29508
|
+
featureEvidence.record('passkeys', { kind: out.ok ? 'fired' : 'error', reason: out.ok ? `peer-${op}-delivered` : `peer-${op}-failed: ${out.reason ?? 'unknown'}`, context: { op, target: targetMachineId, status: out.status ?? null } });
|
|
29411
29509
|
appendPlaywrightAudit(`passkey-${op}`, 'passkeys', { target: targetMachineId, email: canonical ? 'set' : 'none', delivered: out.ok, reason: out.reason ?? null, dryRun: false });
|
|
29412
29510
|
res.status(out.ok ? 200 : 502).json({ op, target: targetMachineId, delivered: out.ok, status: out.status, reason: out.reason ?? null, result: out.result ?? null });
|
|
29413
29511
|
return;
|
|
29414
29512
|
}
|
|
29415
29513
|
const body = mintPasskeyCellBody({ principal, canonicalEmail: canonical, targetMachineId, op, args });
|
|
29416
29514
|
const outcome = await applyLocalPasskeyCellAction(auth.deps, body);
|
|
29515
|
+
featureEvidence.record('passkeys', { kind: outcome.applied ? 'fired' : 'error', reason: outcome.applied ? `local-${op}-applied` : `local-${op}-refused: ${outcome.reason}`, context: { op, target: 'local' } });
|
|
29417
29516
|
appendPlaywrightAudit(`passkey-${op}`, 'passkeys', { target: 'local', email: canonical ? 'set' : 'none', applied: outcome.applied, reason: outcome.applied ? null : outcome.reason, dryRun: false });
|
|
29418
29517
|
res.status(outcome.applied ? 200 : (outcome.reason === 'issuer-bootstrap-required' ? 409 : 400)).json({ ...outcome, target: targetMachineId });
|
|
29419
29518
|
};
|
|
@@ -29968,6 +30067,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
29968
30067
|
return;
|
|
29969
30068
|
}
|
|
29970
30069
|
const r = buildPasskeyHealth(auth).recordOutcome({ canonicalEmail: email, outcome: outcome, origin: origin, reenrolled });
|
|
30070
|
+
featureEvidence.record('passkeys', { kind: outcome === 'ready' ? 'fired' : outcome === 'unknown' ? 'held' : 'error', reason: `proof-outcome: ${outcome}`, context: { outcome, origin, transition: r.transition ? `${r.transition.from}->${r.transition.to}` : null } });
|
|
29971
30071
|
appendPlaywrightAudit('passkey-health-outcome', 'passkeys', { outcome, origin, transition: r.transition ? `${r.transition.from}->${r.transition.to}` : null, dryRun: false });
|
|
29972
30072
|
res.json({ cell: r.cell, transition: r.transition, scheduleConfirmAt: r.scheduleConfirmAt });
|
|
29973
30073
|
}
|
|
@@ -30089,6 +30189,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
30089
30189
|
pauses.push('account-throttled-24h', 'machine-throttled-1h');
|
|
30090
30190
|
}
|
|
30091
30191
|
const recorded = health.recordOutcome({ canonicalEmail: canonical, outcome: result.outcome, origin: 'operator' });
|
|
30192
|
+
featureEvidence.record('passkeys', { kind: result.outcome === 'ready' ? 'fired' : result.outcome === 'unknown' ? 'held' : 'error', reason: `sign-in-proof: ${result.outcome}`, context: { outcome: result.outcome, reasonCode: result.reason ?? null, finalPageClass: result.finalPageClass ?? null, steps: result.steps.length, riskPage: !!result.riskPage, throttled: !!result.throttled } });
|
|
30092
30193
|
appendPlaywrightAudit('passkey-prove', 'passkeys', { outcome: result.outcome, reason: result.reason, page: result.finalPageClass, steps: result.steps.length, pauses: pauses.join(',') || null, transition: recorded.transition ? `${recorded.transition.from}->${recorded.transition.to}` : null, dryRun: false });
|
|
30093
30194
|
res.json({ outcome: result.outcome, reason: result.reason, finalPageClass: result.finalPageClass, observedAssertion: result.observedAssertion, singleCredential: result.singleCredential, signedInIdentity: result.signedInIdentity, riskPage: result.riskPage, throttled: result.throttled, steps: result.steps, teardown: result.teardown, pauses, cell: recorded.cell, transition: recorded.transition,
|
|
30094
30195
|
// Honest about the admission inputs this build does not publish yet (same wording as GET /passkeys/admission).
|
|
@@ -30113,10 +30214,12 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
30113
30214
|
try {
|
|
30114
30215
|
const auth = await buildPasskeyAuthorityAndSweep();
|
|
30115
30216
|
const outcome = await receivePasskeyCellMandate({ ...auth.deps, verify: { issuerPublicKeyPem: passkeyIssuerPublicKeyPem } }, portable);
|
|
30217
|
+
featureEvidence.record('passkeys', { kind: outcome.applied ? 'fired' : 'error', reason: outcome.applied ? `mandate-applied: ${outcome.op}` : `mandate-refused: ${outcome.reason}`, context: { op: outcome.op ?? null, applied: outcome.applied } });
|
|
30116
30218
|
appendPlaywrightAudit('passkey-cell-action', 'passkeys', { op: outcome.op, applied: outcome.applied, reason: outcome.applied ? null : outcome.reason, dryRun: false });
|
|
30117
30219
|
res.status(outcome.applied ? 200 : 403).json(outcome);
|
|
30118
30220
|
}
|
|
30119
30221
|
catch (err) {
|
|
30222
|
+
featureEvidence.record('passkeys', { kind: 'error', reason: 'mandate-authority-unreadable', context: { errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
30120
30223
|
res.status(500).json({ applied: false, reason: 'authority-unreadable', detail: err instanceof Error ? err.message : String(err) });
|
|
30121
30224
|
}
|
|
30122
30225
|
});
|
|
@@ -34296,6 +34399,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34296
34399
|
const { command, cwd, topicId, sessionName, intent, prNumber } = req.body ?? {};
|
|
34297
34400
|
if (typeof command !== 'string' || typeof cwd !== 'string' || typeof topicId !== 'number' || typeof sessionName !== 'string') {
|
|
34298
34401
|
// Malformed → fail-open (never block on a bad request).
|
|
34402
|
+
featureEvidence.record('monitoring.prHandLease', { kind: 'error', reason: 'bad-request-failopen', context: { dryRun } });
|
|
34299
34403
|
res.json({ decision: 'allow', reason: 'bad-request-failopen' });
|
|
34300
34404
|
return;
|
|
34301
34405
|
}
|
|
@@ -34308,6 +34412,19 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34308
34412
|
return;
|
|
34309
34413
|
}
|
|
34310
34414
|
const evalResult = ctx.prHandLease.evaluate(key, topicId, sessionName);
|
|
34415
|
+
const leaseRefuses = evalResult.decision === 'deny' || evalResult.decision === 'escalate';
|
|
34416
|
+
featureEvidence.record('monitoring.prHandLease', {
|
|
34417
|
+
kind: evalResult.reason === 'eval-error-failopen' ? 'error' : leaseRefuses ? 'fired' : 'held',
|
|
34418
|
+
reason: `${leaseRefuses && dryRun ? 'would-' : ''}${evalResult.decision}:${evalResult.reason}`,
|
|
34419
|
+
context: {
|
|
34420
|
+
decision: evalResult.decision,
|
|
34421
|
+
leaseReason: evalResult.reason,
|
|
34422
|
+
dryRun,
|
|
34423
|
+
topicId,
|
|
34424
|
+
holderTopicId: evalResult.holder?.holderTopicId ?? null,
|
|
34425
|
+
holderPr: evalResult.holder?.prNumber ?? null,
|
|
34426
|
+
},
|
|
34427
|
+
});
|
|
34311
34428
|
// Always (re)acquire/renew MY lease on the allow-because-mine / no-lease paths,
|
|
34312
34429
|
// and take over on a stale path — so a peer can see I hold it.
|
|
34313
34430
|
if (evalResult.decision === 'allow' && (evalResult.reason === 'own-topic' || evalResult.reason === 'no-lease')) {
|
|
@@ -34328,6 +34445,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34328
34445
|
}
|
|
34329
34446
|
catch (err) {
|
|
34330
34447
|
// Inner fail-open — never block a push on an internal error.
|
|
34448
|
+
featureEvidence.record('monitoring.prHandLease', { kind: 'error', reason: 'eval-error-failopen', context: { dryRun, errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
34331
34449
|
res.json({ decision: 'allow', reason: 'eval-error-failopen' });
|
|
34332
34450
|
}
|
|
34333
34451
|
});
|
|
@@ -34607,6 +34725,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34607
34725
|
attention: ctx.telegram,
|
|
34608
34726
|
});
|
|
34609
34727
|
if (!verdict.ok) {
|
|
34728
|
+
if (isMinted)
|
|
34729
|
+
featureEvidence.record('messaging.actionClaim.slack', { kind: 'held', reason: 'refused: conversation-bind-not-authorized', context: { topicId, lane, dryRun: slackDryRun } });
|
|
34610
34730
|
res.status(403).json({ error: 'conversation-bind-not-authorized', detail: verdict.detail });
|
|
34611
34731
|
return;
|
|
34612
34732
|
}
|
|
@@ -34622,6 +34742,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34622
34742
|
(c.externalKey.startsWith('actionclaim:') || c.externalKey.startsWith('timepromise:')));
|
|
34623
34743
|
const alreadyOpen = openForTopic.some((c) => c.externalKey === externalKey);
|
|
34624
34744
|
if (!alreadyOpen && openForTopic.length >= cap) {
|
|
34745
|
+
if (isMinted)
|
|
34746
|
+
featureEvidence.record('messaging.actionClaim.slack', { kind: 'held', reason: 'refused: per-topic-cap', context: { topicId, lane, dryRun: slackDryRun, openForTopic: openForTopic.length, cap } });
|
|
34625
34747
|
res.json({ observed: true, registered: false, reason: 'per-topic-cap', lane, ...(verb ? { verb } : {}), cap, activityNote });
|
|
34626
34748
|
return;
|
|
34627
34749
|
}
|
|
@@ -34648,6 +34770,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34648
34770
|
catch {
|
|
34649
34771
|
/* audit is observability */
|
|
34650
34772
|
}
|
|
34773
|
+
featureEvidence.record('messaging.actionClaim.slack', { kind: 'fired', reason: 'would register (dry run)', context: { topicId, lane, verb: verb ?? null, externalKey, bindVerdict: boundBy ?? 'legacy-open', dryRun: true, openForTopic: openForTopic.length, alreadyOpen } });
|
|
34651
34774
|
res.json({ observed: true, registered: false, dryRun: true, wouldRegister: true, lane, ...(verb ? { verb } : {}), externalKey, activityNote });
|
|
34652
34775
|
return;
|
|
34653
34776
|
}
|
|
@@ -34666,6 +34789,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34666
34789
|
// Lane B passes NO beacon fields — record()'s internal auto-arm sets
|
|
34667
34790
|
// beaconEnabled + cadence from the SAME detectTimePromise (§4.2 fold).
|
|
34668
34791
|
});
|
|
34792
|
+
if (isMinted)
|
|
34793
|
+
featureEvidence.record('messaging.actionClaim.slack', { kind: 'fired', reason: 'registered', context: { topicId, lane, verb: verb ?? null, commitmentId: commitment.id, bindVerdict: boundBy ?? 'legacy-open', dryRun: false, beaconEnabled: commitment.beaconEnabled ?? false, alreadyOpen } });
|
|
34669
34794
|
res.json({
|
|
34670
34795
|
observed: true,
|
|
34671
34796
|
registered: true,
|
|
@@ -34679,6 +34804,8 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
34679
34804
|
}
|
|
34680
34805
|
catch (err) {
|
|
34681
34806
|
// Signal-only: never surface a failure as a block. Audit via the 500-free path.
|
|
34807
|
+
if (isMinted)
|
|
34808
|
+
featureEvidence.record('messaging.actionClaim.slack', { kind: 'error', reason: 'record-failed', context: { topicId, lane, verb: verb ?? null, errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
34682
34809
|
res.json({ observed: true, registered: false, reason: 'record-failed', detail: err instanceof Error ? err.message : String(err) });
|
|
34683
34810
|
}
|
|
34684
34811
|
});
|
|
@@ -37622,6 +37749,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
37622
37749
|
// No trust manager (relay off, relay standby, or trust init failed):
|
|
37623
37750
|
// there is no authority to consult, so today's handling stands. Counted.
|
|
37624
37751
|
localRouteTrustCounters.noTrustManager++;
|
|
37752
|
+
featureEvidence.recordAtMostEvery('threadline.localRouteTrust', 'no-trust-manager', 60 * 60 * 1000, { kind: 'held', reason: 'no-trust-manager', context: { dryRun: trustMode.dryRun } });
|
|
37625
37753
|
}
|
|
37626
37754
|
else {
|
|
37627
37755
|
let verdict = null;
|
|
@@ -37636,6 +37764,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
37636
37764
|
}
|
|
37637
37765
|
catch (trustErr) {
|
|
37638
37766
|
localRouteTrustCounters.lookupErrors++;
|
|
37767
|
+
featureEvidence.record('threadline.localRouteTrust', { kind: 'error', reason: 'trust-lookup-failed', context: { dryRun: trustMode.dryRun, senderRegistered: !!senderRegistryFp } });
|
|
37639
37768
|
console.warn(`[relay-agent-trust] lookup failed: ${trustErr instanceof Error ? trustErr.message : String(trustErr)}`);
|
|
37640
37769
|
if (!trustMode.dryRun) {
|
|
37641
37770
|
// Enforcing and the authority cannot answer: refuse, retryable —
|
|
@@ -37646,6 +37775,15 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
37646
37775
|
}
|
|
37647
37776
|
if (verdict) {
|
|
37648
37777
|
localRouteTrustCounters.evaluated++;
|
|
37778
|
+
// Per message, so one row per sender, operation and verdict per hour. A refusal of
|
|
37779
|
+
// a registry-known same-machine agent is the failure this rollout watches for.
|
|
37780
|
+
const localTrustEvidenceVerdict = verdict.allowed ? 'allowed' : trustMode.dryRun ? 'would-refuse' : 'refuse';
|
|
37781
|
+
const localTrustEvidenceFailure = !verdict.allowed && verdict.identitySource === 'registry';
|
|
37782
|
+
featureEvidence.recordAtMostEvery('threadline.localRouteTrust', `${verdict.fingerprint ?? 'no-fp'}|${verdict.identitySource}|${verdict.operation.slice(0, 48)}|${localTrustEvidenceVerdict}`, 60 * 60 * 1000, {
|
|
37783
|
+
kind: localTrustEvidenceFailure ? 'error' : 'fired',
|
|
37784
|
+
reason: localTrustEvidenceFailure ? `${localTrustEvidenceVerdict}-registered-sender` : localTrustEvidenceVerdict,
|
|
37785
|
+
context: { level: verdict.level, operation: verdict.operation.slice(0, 48), identitySource: verdict.identitySource, fingerprint: verdict.fingerprint, dryRun: trustMode.dryRun },
|
|
37786
|
+
});
|
|
37649
37787
|
if (verdict.allowed) {
|
|
37650
37788
|
localRouteTrustCounters.allowed++;
|
|
37651
37789
|
// Enforcing: the router is told the resolved level instead of the
|
|
@@ -39747,6 +39885,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
39747
39885
|
backupRouteCounters.fingerprintLocal++;
|
|
39748
39886
|
fingerprintRouteCounted = true;
|
|
39749
39887
|
console.log(backupLogLine('fingerprint-local', msgId, localPostPeerFp, outcome));
|
|
39888
|
+
featureEvidence.recordAtMostEvery('threadline.backupRoutes', `fingerprint-local|${localPostPeerFp}|${accepted}`, 5 * 60 * 1000, {
|
|
39889
|
+
kind: accepted ? 'fired' : 'error',
|
|
39890
|
+
reason: accepted ? 'fingerprint-local-delivered' : 'fingerprint-local-not-accepted',
|
|
39891
|
+
context: { path: 'fingerprint-local', peerFp: localPostPeerFp, messageId: msgId, status: localResp.status },
|
|
39892
|
+
});
|
|
39750
39893
|
}
|
|
39751
39894
|
// Persist our OWN outbound leg into the thread history so
|
|
39752
39895
|
// getThread()/threadline_history return BOTH halves of the
|
|
@@ -40037,9 +40180,11 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
40037
40180
|
if (fallthrough.marked) {
|
|
40038
40181
|
backupRouteCounters.markedFallthrough++;
|
|
40039
40182
|
console.log(backupLogLine('marked-fallthrough', msgId, localPostPeerFp || resolvedId, fallthrough.outcome));
|
|
40183
|
+
featureEvidence.recordAtMostEvery('threadline.backupRoutes', `marked-fallthrough|${fallthrough.outcome}`, 10 * 60 * 1000, { kind: 'fired', reason: `marked-fallthrough: ${fallthrough.outcome}`, context: { path: 'marked-fallthrough', peerFp: localPostPeerFp || resolvedId, messageId: msgId, outcome: fallthrough.outcome } });
|
|
40040
40184
|
}
|
|
40041
40185
|
else {
|
|
40042
40186
|
backupRouteCounters.unmarkedFallthroughAfterPost++;
|
|
40187
|
+
featureEvidence.recordAtMostEvery('threadline.backupRoutes', `unmarked-fallthrough|${fallthrough.outcome}`, 10 * 60 * 1000, { kind: 'held', reason: `unmarked-fallthrough: ${fallthrough.outcome}`, context: { path: 'unmarked-fallthrough', peerFp: localPostPeerFp || resolvedId, messageId: msgId, outcome: fallthrough.outcome } });
|
|
40043
40188
|
}
|
|
40044
40189
|
}
|
|
40045
40190
|
const relayLegResend = Boolean(fallthrough?.marked || (forwardedRequest && req.body?.resend === true));
|
|
@@ -41062,6 +41207,10 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
41062
41207
|
});
|
|
41063
41208
|
// ── Phase 2: State Machine, Consent, Events ─────────────────────
|
|
41064
41209
|
router.post('/features/:id/surface', (req, res) => {
|
|
41210
|
+
if (isRetiredLegacyOffer(req.params.id)) {
|
|
41211
|
+
res.status(409).json({ error: { code: 'OFFER_RETIRED', message: 'This offer now goes through recommended services.' } });
|
|
41212
|
+
return;
|
|
41213
|
+
}
|
|
41065
41214
|
if (!ctx.featureRegistry) {
|
|
41066
41215
|
res.status(501).json({ error: 'FeatureRegistry not initialized' });
|
|
41067
41216
|
return;
|
|
@@ -42773,6 +42922,7 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
42773
42922
|
// enforces (a non-move is a recorded 200 'aborted', never a misleading PASS).
|
|
42774
42923
|
const t = await transfer(telegramTopicId, targetMachine);
|
|
42775
42924
|
if (!t.seatMoved) {
|
|
42925
|
+
featureEvidence.record('monitoring.liveTestRunner', { kind: 'held', reason: 'capstone-aborted-seat-did-not-move', context: { targetMachine, blockedSurfaces: blockedSurfaces.length, hasSlack: Boolean(slackChannelId) } });
|
|
42776
42926
|
res.status(200).json({ ok: true, seatMoved: false, capstone: 'aborted', reason: t.detail ?? 'seat did not move', blockedSurfaces });
|
|
42777
42927
|
return;
|
|
42778
42928
|
}
|
|
@@ -42781,9 +42931,25 @@ document.getElementById('mcpForm').addEventListener('submit', async function (e)
|
|
|
42781
42931
|
const matrix = buildMultiMachineCapstoneMatrix({ featureId, targetMachine, telegramTopicId, slackChannelId, message, timeoutMs });
|
|
42782
42932
|
const harness = ctx.liveTestRunnerCtx.makeHarness(driver);
|
|
42783
42933
|
const result = await harness.run(matrix, runId ? { runId } : {});
|
|
42934
|
+
const scenarioVerdict = (v) => result.artifact.scenarios.filter((s) => s.verdict === v).length;
|
|
42935
|
+
featureEvidence.record('monitoring.liveTestRunner', {
|
|
42936
|
+
kind: 'fired',
|
|
42937
|
+
reason: 'capstone-ran',
|
|
42938
|
+
context: {
|
|
42939
|
+
targetMachine,
|
|
42940
|
+
runId: result.artifact.runId,
|
|
42941
|
+
scenarios: result.artifact.scenarios.length,
|
|
42942
|
+
passed: scenarioVerdict('PASS'),
|
|
42943
|
+
failed: scenarioVerdict('FAIL'),
|
|
42944
|
+
blocked: scenarioVerdict('BLOCKED'),
|
|
42945
|
+
blockedSurfaces: blockedSurfaces.length,
|
|
42946
|
+
surfaces: result.artifact.surfaces.join(','),
|
|
42947
|
+
},
|
|
42948
|
+
});
|
|
42784
42949
|
res.json({ ok: true, seatMoved: true, capstone: 'ran', artifact: result.artifact, entry: result.entry, blockedSurfaces });
|
|
42785
42950
|
}
|
|
42786
42951
|
catch (err) {
|
|
42952
|
+
featureEvidence.record('monitoring.liveTestRunner', { kind: 'error', reason: 'capstone-run-failed', context: { targetMachine, errorName: err instanceof Error ? err.name : 'unknown' } });
|
|
42787
42953
|
// A genuine internal error surfaces LOUDLY as a 500 with the reason — never a
|
|
42788
42954
|
// fabricated PASS, never a swallowed run. This is the honest error path.
|
|
42789
42955
|
res.status(500).json({ error: `capstone run failed: ${err instanceof Error ? err.message : String(err)}` });
|