@sema-agent/client-core 0.99.0 → 0.101.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +572 -0
- package/README.md +174 -114
- package/dist/adapt/arms.js +109 -50
- package/dist/adapt/panelTasks.d.ts +2 -1
- package/dist/adapt/panelTasks.js +32 -9
- package/dist/adapt/textStream.d.ts +1 -1
- package/dist/adapt/textStream.js +58 -32
- package/dist/adapt/toolCards.js +9 -8
- package/dist/adapt.js +7 -1
- package/dist/adapter/activeRunSelfHeal.d.ts +31 -2
- package/dist/adapter/activeRunSelfHeal.js +162 -13
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
- package/dist/adapter/downstream/eventToSdkMessage.js +157 -20
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +219 -39
- package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
- package/dist/adapter/downstream/wiringManifestView.js +1 -0
- package/dist/adapter/runStream.d.ts +4 -4
- package/dist/adapter/runStream.js +184 -42
- package/dist/adapter/types.d.ts +2 -0
- package/dist/agentsWireCaps.d.ts +9 -7
- package/dist/agentsWireCaps.js +101 -17
- package/dist/approvalDecidedByCapability.js +2 -2
- package/dist/approvalFrameFamilies.d.ts +33 -0
- package/dist/approvalFrameFamilies.js +120 -0
- package/dist/approvalsStreamLiveCapability.js +2 -2
- package/dist/attachmentsWireCaps.js +41 -13
- package/dist/callerCwdCapability.js +2 -2
- package/dist/centerWiringCapability.js +2 -2
- package/dist/clockReading.d.ts +2 -0
- package/dist/clockReading.js +4 -0
- package/dist/cloudConfigWireCaps.d.ts +28 -5
- package/dist/cloudConfigWireCaps.js +334 -103
- package/dist/compactionStatus.d.ts +34 -0
- package/dist/compactionStatus.js +196 -0
- package/dist/coreValuePorts.d.ts +12 -2
- package/dist/coreValuePorts.js +9 -0
- package/dist/decideFailureNote.js +8 -6
- package/dist/decideReceipt.js +2 -2
- package/dist/deviceExecutorManagementCapability.js +2 -2
- package/dist/deviceFlowPolling.js +1 -1
- package/dist/disableSkillsWire.d.ts +1 -1
- package/dist/disableSkillsWire.js +4 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +215 -13
- package/dist/engineAgentPanelStore.d.ts +7 -4
- package/dist/engineCapReader.js +1 -1
- package/dist/engineConfigDrift.js +1 -1
- package/dist/engineErrorCodes.d.ts +23 -6
- package/dist/engineErrorCodes.js +36 -11
- package/dist/engineGenerationConvergence.d.ts +39 -0
- package/dist/engineGenerationConvergence.js +95 -0
- package/dist/engineGenerationPort.d.ts +61 -0
- package/dist/engineGenerationPort.js +144 -0
- package/dist/engineHealthFacts.d.ts +23 -0
- package/dist/engineHealthFacts.js +92 -0
- package/dist/engineIdentity.d.ts +4 -0
- package/dist/engineIdentity.js +11 -0
- package/dist/engineNoticeCodes.d.ts +2 -5
- package/dist/engineRowRef.js +4 -0
- package/dist/engineSessionMessages.js +2 -2
- package/dist/engineToolDirectory.d.ts +3 -0
- package/dist/engineToolDirectory.js +6 -4
- package/dist/engineWireFor.d.ts +99 -0
- package/dist/engineWireFor.js +248 -6
- package/dist/engineWireTarget.d.ts +1 -0
- package/dist/engineWireTarget.js +8 -0
- package/dist/env/uiLanguage.js +1 -1
- package/dist/errorSupplementRoles.d.ts +3 -0
- package/dist/errorSupplementRoles.js +37 -0
- package/dist/eventLeg.d.ts +1 -7
- package/dist/eventLeg.js +7 -8
- package/dist/executionLaneCapability.js +2 -2
- package/dist/fileHistoryCaptureCapability.d.ts +0 -3
- package/dist/fileHistoryCaptureCapability.js +3 -7
- package/dist/finalVerifyWire.d.ts +6 -3
- package/dist/finalVerifyWire.js +6 -23
- package/dist/flagInput.d.ts +4 -0
- package/dist/flagInput.js +24 -0
- package/dist/fleet/fleetLedger.js +5 -2
- package/dist/fleet/fleetProjection.d.ts +1 -0
- package/dist/fleet/fleetProjection.js +15 -2
- package/dist/gateVocabulary.js +3 -0
- package/dist/generated/engineFactTables.d.ts +7 -2
- package/dist/generated/engineFactTables.js +79 -0
- package/dist/generated/engineNoticeTables.js +15 -0
- package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
- package/dist/generated/settingsSchemaActiveTiers.js +14 -0
- package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
- package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
- package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
- package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
- package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
- package/dist/generated/settingsSchemaDefaultModel.js +25 -0
- package/dist/generated/settingsSchemaFns.d.ts +66 -0
- package/dist/generated/settingsSchemaFns.js +38 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.js +156 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
- package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
- package/dist/generated/settingsSchemaSettingsSources.js +58 -0
- package/dist/generated/settingsSchemaTables.d.ts +3 -0
- package/dist/generated/settingsSchemaTables.js +18 -0
- package/dist/generated/settingsSchemaTypes.d.ts +28 -0
- package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlPattern.js +183 -0
- package/dist/headlessPermissionModeWire.d.ts +18 -2
- package/dist/headlessPermissionModeWire.js +30 -19
- package/dist/hitl/allowRuleShadow.js +9 -7
- package/dist/hitl/approvalCardReading.d.ts +3 -0
- package/dist/hitl/approvalCardReading.js +17 -0
- package/dist/hitl/approvalCardReasons.js +2 -2
- package/dist/hitl/approvalCompleteParked.js +1 -1
- package/dist/hitl/approvalDelivery.d.ts +87 -0
- package/dist/hitl/approvalDelivery.js +193 -0
- package/dist/hitl/approvalHolds.d.ts +14 -0
- package/dist/hitl/approvalHolds.js +41 -0
- package/dist/hitl/approvalResolution.d.ts +11 -0
- package/dist/hitl/approvalResolution.js +50 -11
- package/dist/hitl/askClassPair.d.ts +8 -2
- package/dist/hitl/askClassPair.js +31 -4
- package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
- package/dist/hitl/askParkAutoReopenBlock.js +117 -0
- package/dist/hitl/askParkRowRouting.js +4 -1
- package/dist/hitl/attributionLadder.d.ts +62 -0
- package/dist/hitl/attributionLadder.js +138 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
- package/dist/hitl/automaticAnswerVerdict.js +46 -11
- package/dist/hitl/crashConverged.js +2 -2
- package/dist/hitl/decisionConflict.d.ts +6 -2
- package/dist/hitl/decisionConflict.js +24 -9
- package/dist/hitl/decisionLedger.d.ts +55 -0
- package/dist/hitl/decisionLedger.js +156 -0
- package/dist/hitl/decisionRefusal.d.ts +21 -10
- package/dist/hitl/decisionRefusal.js +100 -55
- package/dist/hitl/decisionSend.d.ts +116 -0
- package/dist/hitl/decisionSend.js +563 -0
- package/dist/hitl/frameRouter.d.ts +1 -0
- package/dist/hitl/frameRouter.js +9 -2
- package/dist/hitl/hitlBridge.d.ts +18 -6
- package/dist/hitl/hitlBridge.js +59 -43
- package/dist/hitl/livePendingAsk.js +4 -3
- package/dist/hitl/noAllowCause.js +1 -1
- package/dist/hitl/parkResolver.js +3 -2
- package/dist/hitl/persistedRulesWire.js +1 -0
- package/dist/hitl/planReviewWire.d.ts +4 -0
- package/dist/hitl/planReviewWire.js +104 -106
- package/dist/hitl/resumeRunningCard.d.ts +3 -2
- package/dist/hitl/resumeRunningCard.js +17 -11
- package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
- package/dist/hitl/sessionPolicyDeliverable.js +65 -35
- package/dist/hitl/sessionPolicyWire.d.ts +13 -3
- package/dist/hitl/sessionPolicyWire.js +81 -16
- package/dist/hitl/standingRows.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +9 -10
- package/dist/hitl/toolApprovalWire.js +103 -151
- package/dist/hookMatcherVerdict.d.ts +2 -0
- package/dist/hookMatcherVerdict.js +12 -0
- package/dist/hooksCompactTransition.d.ts +19 -0
- package/dist/hooksCompactTransition.js +41 -0
- package/dist/hooksWireCaps.d.ts +1 -1
- package/dist/hooksWireCaps.js +202 -203
- package/dist/host.d.ts +1 -14
- package/dist/host.js +0 -8
- package/dist/hostCallbackGuard.d.ts +1 -0
- package/dist/hostCallbackGuard.js +1 -1
- package/dist/hostSettingsSource.d.ts +172 -0
- package/dist/hostSettingsSource.js +675 -0
- package/dist/hostTurnSettings.d.ts +114 -19
- package/dist/hostTurnSettings.js +966 -68
- package/dist/httpHookPolicy.d.ts +37 -0
- package/dist/httpHookPolicy.js +176 -0
- package/dist/humanTurn.d.ts +4 -2
- package/dist/humanTurn.js +40 -10
- package/dist/humanTurnRead.js +4 -3
- package/dist/humanTurnSentences.d.ts +10 -0
- package/dist/humanTurnSentences.js +74 -0
- package/dist/i18n/messages.en.d.ts +313 -0
- package/dist/i18n/messages.en.js +326 -13
- package/dist/i18n/messages.zh.js +341 -13
- package/dist/i18n/translate.js +3 -3
- package/dist/index.d.ts +85 -15
- package/dist/index.js +53 -12
- package/dist/inheritEnvCapability.d.ts +4 -1
- package/dist/inheritEnvCapability.js +38 -17
- package/dist/inheritEnvWire.d.ts +2 -1
- package/dist/inheritEnvWire.js +11 -5
- package/dist/injectionLaneNotice.d.ts +5 -0
- package/dist/injectionLaneNotice.js +46 -0
- package/dist/interactiveToolsWire.d.ts +4 -2
- package/dist/interactiveToolsWire.js +5 -5
- package/dist/jsonFaithful.d.ts +20 -0
- package/dist/jsonFaithful.js +152 -0
- package/dist/limitsWire.d.ts +7 -2
- package/dist/limitsWire.js +19 -13
- package/dist/liveInitToolFace.d.ts +6 -1
- package/dist/liveInitToolFace.js +5 -3
- package/dist/liveModelCatalog.d.ts +22 -0
- package/dist/liveModelCatalog.js +132 -18
- package/dist/mcpPanel.js +3 -1
- package/dist/mcpProbeCapability.js +2 -2
- package/dist/mcpReconnect.js +2 -2
- package/dist/mcpStatusSupersetKeys.d.ts +24 -0
- package/dist/mcpStatusSupersetKeys.js +45 -0
- package/dist/mcpToolToggles.d.ts +6 -0
- package/dist/mcpToolToggles.js +47 -0
- package/dist/mcpWireCaps.d.ts +48 -4
- package/dist/mcpWireCaps.js +338 -99
- package/dist/mcpWireTransport.d.ts +4 -0
- package/dist/mcpWireTransport.js +18 -0
- package/dist/memoryComplianceCapability.js +2 -2
- package/dist/memoryOriginCapability.js +2 -2
- package/dist/model/catalogDefault.d.ts +24 -0
- package/dist/model/catalogDefault.js +4 -0
- package/dist/model/liveCatalogShape.js +5 -4
- package/dist/model/modelsPolicy.js +4 -3
- package/dist/model/onboardJudgement.d.ts +1 -0
- package/dist/model/onboardJudgement.js +1 -1
- package/dist/model/subagentModelWord.js +2 -2
- package/dist/modelCapabilityProbe.d.ts +2 -1
- package/dist/modelCapabilityProbe.js +16 -15
- package/dist/modelIdentityResolvability.d.ts +12 -1
- package/dist/modelIdentityResolvability.js +69 -28
- package/dist/modsKernelIdentity.d.ts +10 -0
- package/dist/modsKernelIdentity.js +103 -0
- package/dist/modsKernelTransit.d.ts +8 -0
- package/dist/modsKernelTransit.js +6 -0
- package/dist/notifications.d.ts +30 -12
- package/dist/notifications.js +241 -53
- package/dist/outputStyleSeatCapability.js +2 -2
- package/dist/ownKey.d.ts +37 -0
- package/dist/ownKey.js +238 -2
- package/dist/panelReduce.d.ts +5 -0
- package/dist/panelReduce.js +45 -13
- package/dist/panelStateHolder.d.ts +1 -0
- package/dist/panelStateHolder.js +10 -1
- package/dist/peerFrames.d.ts +1 -1
- package/dist/peerFrames.js +6 -2
- package/dist/peerLaneCapability.js +2 -2
- package/dist/permissionModesCapability.js +4 -4
- package/dist/permissionRuleIssue.d.ts +2 -1
- package/dist/permissionRuleIssue.js +24 -21
- package/dist/permissionRulesWriteCapability.js +2 -2
- package/dist/permissionsAllowGrantCapability.js +2 -2
- package/dist/permissionsDeclaration.d.ts +43 -4
- package/dist/permissionsDeclaration.js +102 -35
- package/dist/pluginHooksWire.d.ts +20 -4
- package/dist/pluginHooksWire.js +101 -60
- package/dist/prepareRefusal.d.ts +9 -0
- package/dist/prepareRefusal.js +90 -0
- package/dist/printInitToolFace.js +2 -2
- package/dist/printModelStatus.js +1 -1
- package/dist/projectMemory.d.ts +32 -0
- package/dist/projectMemory.js +70 -0
- package/dist/promptBlockedCopy.d.ts +2 -1
- package/dist/promptBlockedCopy.js +2 -1
- package/dist/promptDelivery.d.ts +23 -3
- package/dist/promptDelivery.js +169 -30
- package/dist/providerRejection.d.ts +19 -1
- package/dist/providerRejection.js +75 -4
- package/dist/queuedDelivery.d.ts +48 -0
- package/dist/queuedDelivery.js +233 -0
- package/dist/reattachWindow.d.ts +94 -0
- package/dist/reattachWindow.js +127 -0
- package/dist/request/printNotification.d.ts +1 -1
- package/dist/request/printNotification.js +5 -1
- package/dist/request/submissionIdentity.d.ts +37 -0
- package/dist/request/submissionIdentity.js +65 -0
- package/dist/request/taskRequest.d.ts +22 -14
- package/dist/request/taskRequest.js +312 -202
- package/dist/resultFrameKeys.d.ts +1 -0
- package/dist/resultFrameKeys.js +4 -1
- package/dist/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +22 -4
- package/dist/retryStatus.d.ts +26 -0
- package/dist/retryStatus.js +133 -28
- package/dist/rewindArchiveCapability.js +2 -2
- package/dist/rewindEngineAction.d.ts +2 -0
- package/dist/rewindEngineAction.js +23 -1
- package/dist/rowKind.d.ts +36 -0
- package/dist/rowKind.js +97 -0
- package/dist/ruleCompileVerdict.d.ts +18 -0
- package/dist/ruleCompileVerdict.js +67 -2
- package/dist/ruleReadings.d.ts +58 -0
- package/dist/ruleReadings.js +132 -0
- package/dist/ruleRefusalSentence.d.ts +8 -0
- package/dist/ruleRefusalSentence.js +64 -0
- package/dist/runCancelContext.d.ts +0 -1
- package/dist/runCancelContext.js +1 -2
- package/dist/runTerminal.d.ts +5 -0
- package/dist/runTerminal.js +52 -17
- package/dist/sandboxWire.d.ts +3 -2
- package/dist/sandboxWire.js +59 -27
- package/dist/scenarioRefusal.d.ts +2 -1
- package/dist/scenarioRefusal.js +6 -6
- package/dist/scenarioSkills.d.ts +20 -0
- package/dist/scenarioSkills.js +72 -0
- package/dist/scenarioWire.d.ts +5 -2
- package/dist/scenarioWire.js +9 -9
- package/dist/sealedKeyCapability.js +2 -2
- package/dist/seam.d.ts +26 -9
- package/dist/seam.js +44 -4
- package/dist/seatContract.d.ts +62 -9
- package/dist/seatContract.js +70 -25
- package/dist/selfOrchestrationDenial.js +1 -1
- package/dist/sessionPolicyCapability.js +2 -2
- package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
- package/dist/sessionRulesChildrenReadLive.js +5 -0
- package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
- package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
- package/dist/sessionSyncFileHistoryCapability.js +2 -2
- package/dist/settingsCredentialKeyPaths.d.ts +8 -0
- package/dist/settingsCredentialKeyPaths.js +274 -0
- package/dist/settingsHooksSalvage.d.ts +1 -0
- package/dist/settingsHooksSalvage.js +7 -1
- package/dist/settingsLayerAdmission.d.ts +4 -0
- package/dist/settingsLayerAdmission.js +16 -0
- package/dist/skillToolListsCapability.js +6 -5
- package/dist/skillsWireCaps.d.ts +14 -3
- package/dist/skillsWireCaps.js +48 -18
- package/dist/slashCommandGate.d.ts +24 -0
- package/dist/slashCommandGate.js +74 -0
- package/dist/slashCommandTable.d.ts +14 -0
- package/dist/slashCommandTable.js +99 -0
- package/dist/sqlEngineCapability.js +2 -2
- package/dist/steerPriorityCapability.js +2 -2
- package/dist/storePostureCapability.js +2 -2
- package/dist/subagent/agentStateDetail.js +1 -1
- package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
- package/dist/subagent/engineDelegatedPrompt.js +38 -7
- package/dist/subagent/engineRowStopGate.js +2 -2
- package/dist/subagent/engineSubagentResume.js +3 -3
- package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
- package/dist/subagent/engineTaskHandleWire.js +10 -0
- package/dist/subagentContentStore.d.ts +1 -0
- package/dist/subagentContentStore.js +135 -27
- package/dist/submitFailure.d.ts +8 -0
- package/dist/submitFailure.js +17 -0
- package/dist/supportFloor.d.ts +1 -0
- package/dist/supportFloor.js +7 -0
- package/dist/terminationIntent.d.ts +55 -0
- package/dist/terminationIntent.js +352 -0
- package/dist/toolHistoryMismatch.d.ts +8 -0
- package/dist/toolHistoryMismatch.js +37 -6
- package/dist/toolResult.d.ts +13 -3
- package/dist/toolResult.js +158 -9
- package/dist/toolResultContent.d.ts +13 -0
- package/dist/toolResultContent.js +82 -7
- package/dist/toolRoster.d.ts +18 -0
- package/dist/toolRoster.js +64 -0
- package/dist/toolsFlagNames.d.ts +8 -0
- package/dist/toolsFlagNames.js +110 -0
- package/dist/turnFailurePresentation.js +41 -96
- package/dist/usageLimitAutoResume.d.ts +74 -0
- package/dist/usageLimitAutoResume.js +227 -0
- package/dist/userAttachmentEnvelope.js +1 -1
- package/dist/userAttachmentSeat.js +5 -5
- package/dist/userInvokedSkillsCapability.js +2 -2
- package/dist/webSearchBackendCapability.js +2 -2
- package/dist/wireErrorTriage.js +99 -50
- package/dist/wireFailureShape.d.ts +25 -1
- package/dist/wireFailureShape.js +92 -5
- package/dist/wireRefusalCopy.d.ts +75 -18
- package/dist/wireRefusalCopy.js +532 -148
- package/dist/wiringFleetDoctor.d.ts +3 -0
- package/dist/wiringFleetDoctor.js +21 -0
- package/dist/workflow.d.ts +2 -1
- package/dist/workflow.js +38 -1
- package/dist/workflowClient.d.ts +2 -7
- package/dist/workflowsJournalCapability.js +2 -2
- package/dist/writeProtectionCapability.js +2 -2
- package/docs/INTEGRATION-CLIENTS.md +1013 -190
- package/package.json +15 -4
package/dist/hostTurnSettings.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { SETTINGS_CLASSIFY_HOOKS_CONFIG } from './generated/settingsSchemaFns.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { hostLog } from './host.js';
|
|
3
|
+
import { layerNotAppliedRefusesTurn, salvageSettingsHooksEntries } from './settingsHooksSalvage.js';
|
|
4
|
+
import { ADOPTED_LAYERS, HOST_SETTINGS_LAYERS, HostSettingsSourceShapeError, permissionRulesOf, MANAGED_READING_DISPOSITIONS, adoptHostSettingsRead, mintHostSettingsSession, readHostSettingsOnce, remintSameContent, sessionSnapshotOf, settingsValueOf, sourceOfRead, } from './hostSettingsSource.js';
|
|
5
|
+
import { hooksWirePlan } from './hooksWireCaps.js';
|
|
6
|
+
import { submissionSurfaceOf } from './request/submissionIdentity.js';
|
|
7
|
+
import { displayUntrusted } from './displayUntrusted.js';
|
|
8
|
+
import { resolveWebSearchVerdict, webSearchVerdictMessage } from './webSearchWireCaps.js';
|
|
9
|
+
import { fileHistoryTightenVerdict, fileHistoryUnjudgedRefusal } from './fileHistoryCaptureCapability.js';
|
|
10
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
11
|
+
import { newRulePortsProjection, projectPermissionsDeclaration, rulePortsMissingOf, WIRE_RULE_TRUST_ORDER } from './permissionsDeclaration.js';
|
|
12
|
+
import { assemblyRefusalOf } from './wireFailureShape.js';
|
|
13
|
+
import { layerAdmitted } from './settingsLayerAdmission.js';
|
|
14
|
+
import { appendOwnElement, ownDataField } from './ownKey.js';
|
|
15
|
+
export const HOST_SUPPLIED_KEYS = Object.freeze(['settings.hooks', 'settings.resolved', 'settings.webSearch', 'settings.outputStyle', 'memory', 'fileHistory']);
|
|
4
16
|
export const HOST_SETTING_CAUSES = Object.freeze([
|
|
5
17
|
'carried',
|
|
6
18
|
'entries_dropped',
|
|
@@ -10,19 +22,33 @@ export const HOST_SETTING_CAUSES = Object.freeze([
|
|
|
10
22
|
'empty',
|
|
11
23
|
'no_source',
|
|
12
24
|
'host_port_missing',
|
|
25
|
+
'value_malformed',
|
|
26
|
+
'held_previous',
|
|
27
|
+
'policy_withheld',
|
|
13
28
|
]);
|
|
14
|
-
export const HOST_SETTING_DISPOSITIONS = Object.freeze(['carry', 'carry_partial', 'withhold_notice', 'refuse_turn', 'unwired', 'nothing_to_carry']);
|
|
29
|
+
export const HOST_SETTING_DISPOSITIONS = Object.freeze(['carry', 'carry_partial', 'withhold_notice', 'withhold_by_policy', 'hold_for_consent', 'refuse_turn', 'unwired', 'nothing_to_carry']);
|
|
15
30
|
const HOST_SETTING_NOTICE_TEXT = {
|
|
16
31
|
'HS-UNWIRED': (what) => `This app has not connected ${what} from your settings, so it is not sent with your requests.`,
|
|
17
32
|
'HS-MANAGED-REJECTED': () => 'Managed settings: the hooks your administrator configured could not be loaded, so requests are not sent until the managed settings are fixed.',
|
|
18
|
-
'HS-PROJECTION': () =>
|
|
33
|
+
'HS-PROJECTION': (sentence) => (sentence === '' ? renderMessage(msg('session.hostSettings.projectionUnchecked')) : sentence),
|
|
19
34
|
'HS-SOURCE-UNREADABLE': (what) => `This app could not read ${what} from your settings, so the request is not sent. Reload your settings and try again.`,
|
|
35
|
+
'HS-WEBSEARCH-MALFORMED': (sentence) => sentence,
|
|
36
|
+
'HS-SWITCH-MALFORMED': () => renderMessage(msg('session.hostSettings.memorySwitchMalformed')),
|
|
37
|
+
'HS-FILEHISTORY-UNJUDGED': (sentence) => sentence,
|
|
38
|
+
'HS-FILEHISTORY-RESTORE': () => renderMessage(msg('session.hostSettings.fileHistoryRestoreConflict')),
|
|
39
|
+
'HS-MANAGED-UNREADABLE': () => renderMessage(msg('session.hostSettings.managedUnreadable')),
|
|
40
|
+
'HS-LAYER-NOT-LOADED': (sentence) => sentence,
|
|
41
|
+
'HS-HELD-PREVIOUS': () => renderMessage(msg('session.hostSettings.heldPrevious')),
|
|
42
|
+
'HS-STYLE-MISSING': (what) => renderMessage(msg('session.hostSettings.styleMissing', { name: what })),
|
|
43
|
+
'HS-STYLE-SAFE': () => renderMessage(msg('session.hostSettings.styleSafeMode')),
|
|
20
44
|
};
|
|
21
45
|
const KEY_NOUN = {
|
|
22
46
|
'settings.hooks': 'the hooks',
|
|
23
47
|
'settings.resolved': 'the permission rules',
|
|
24
48
|
'settings.webSearch': 'the web search setup',
|
|
25
49
|
'settings.outputStyle': 'the output style',
|
|
50
|
+
memory: 'auto-memory',
|
|
51
|
+
fileHistory: 'file checkpoints',
|
|
26
52
|
};
|
|
27
53
|
const BASE_DISPOSITION = {
|
|
28
54
|
carried: 'carry',
|
|
@@ -33,6 +59,9 @@ const BASE_DISPOSITION = {
|
|
|
33
59
|
empty: 'nothing_to_carry',
|
|
34
60
|
no_source: 'nothing_to_carry',
|
|
35
61
|
host_port_missing: 'unwired',
|
|
62
|
+
value_malformed: 'refuse_turn',
|
|
63
|
+
held_previous: 'carry',
|
|
64
|
+
policy_withheld: 'withhold_by_policy',
|
|
36
65
|
};
|
|
37
66
|
const freeze = (o) => Object.freeze(o);
|
|
38
67
|
const mint = (o) => o;
|
|
@@ -48,18 +77,6 @@ function readSource(sources, key) {
|
|
|
48
77
|
return { kind: 'threw' };
|
|
49
78
|
}
|
|
50
79
|
}
|
|
51
|
-
function unwrap(v, field) {
|
|
52
|
-
if (v === 'none')
|
|
53
|
-
return { kind: 'none' };
|
|
54
|
-
try {
|
|
55
|
-
if (typeof v !== 'object' || v === null || Array.isArray(v) || !Object.hasOwn(v, field))
|
|
56
|
-
return { kind: 'bad' };
|
|
57
|
-
return { kind: 'value', value: v[field] };
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return { kind: 'bad' };
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
80
|
const isRecordShape = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
64
81
|
function hooksPassJudge(wire) {
|
|
65
82
|
try {
|
|
@@ -69,8 +86,11 @@ function hooksPassJudge(wire) {
|
|
|
69
86
|
return false;
|
|
70
87
|
}
|
|
71
88
|
}
|
|
89
|
+
class HostSourceShapeError extends TypeError {
|
|
90
|
+
code = 'host_source_shape';
|
|
91
|
+
}
|
|
72
92
|
function badSource(key, want) {
|
|
73
|
-
return new
|
|
93
|
+
return new HostSourceShapeError(`hostTurnSettings: sources.${key.replace(/^settings\./, '')} must be 'none' or ${want} — got something else (the value is not echoed).`);
|
|
74
94
|
}
|
|
75
95
|
const missingArm = (key) => ({
|
|
76
96
|
row: freeze({ key, cause: 'host_port_missing', disposition: BASE_DISPOSITION.host_port_missing }),
|
|
@@ -81,41 +101,50 @@ const unreadableArm = (key) => ({
|
|
|
81
101
|
notices: [notice('HS-SOURCE-UNREADABLE', 'turn', KEY_NOUN[key])],
|
|
82
102
|
});
|
|
83
103
|
const noSourceArm = (key) => ({ row: freeze({ key, cause: 'no_source', disposition: BASE_DISPOSITION.no_source }), notices: [] });
|
|
104
|
+
const emptyArm = (key) => ({ row: freeze({ key, cause: 'empty', disposition: BASE_DISPOSITION.empty }), notices: [] });
|
|
84
105
|
const carriedArm = (key, value) => ({ row: freeze({ key, cause: 'carried', disposition: BASE_DISPOSITION.carried }), notices: [], carried: value });
|
|
85
|
-
function hooksArm(src) {
|
|
106
|
+
function hooksArm(src, side) {
|
|
86
107
|
const key = 'settings.hooks';
|
|
87
108
|
if (src.kind === 'missing')
|
|
88
109
|
return missingArm(key);
|
|
89
110
|
if (src.kind === 'threw')
|
|
90
111
|
return unreadableArm(key);
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
112
|
+
const facts = src.value;
|
|
113
|
+
if (facts === 'none')
|
|
93
114
|
return noSourceArm(key);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const plan = u.value;
|
|
97
|
-
let wire;
|
|
98
|
-
let salvageRows;
|
|
99
|
-
let closedBy;
|
|
115
|
+
let hasPlan;
|
|
116
|
+
let hasSettings;
|
|
100
117
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
if (!isRecordShape(facts))
|
|
119
|
+
throw badSource(key, "the hooks plan facts ({ baseUrl?, engineOwnedByThisShell?, shellHookEvents?, … }) — since 0.101.0 the entry builds the plan from the settings it reads");
|
|
120
|
+
hasPlan = Object.hasOwn(facts, 'plan');
|
|
121
|
+
hasSettings = Object.hasOwn(facts, 'settings');
|
|
104
122
|
}
|
|
105
|
-
catch {
|
|
106
|
-
|
|
123
|
+
catch (e) {
|
|
124
|
+
if (e instanceof HostSourceShapeError)
|
|
125
|
+
throw e;
|
|
126
|
+
return unreadableArm(key);
|
|
107
127
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
128
|
+
if (hasPlan || hasSettings)
|
|
129
|
+
throw badSource(key, "the hooks plan facts — since 0.101.0 do not pass { plan } (the entry builds the plan) nor settings (pass it once as the entry's settings)");
|
|
130
|
+
if (side.kind === 'missing')
|
|
131
|
+
return missingArm(key);
|
|
132
|
+
if (side.kind === 'none')
|
|
133
|
+
return noSourceArm(key);
|
|
134
|
+
const plan = hooksWirePlan({ ...facts, settings: sourceOfRead(side.read) });
|
|
135
|
+
const wire = plan.wire;
|
|
136
|
+
const rows = plan.settingsSalvage;
|
|
137
|
+
const layersOf = (outcome) => rows.filter((r) => r.outcome === outcome).map((r) => r.source);
|
|
138
|
+
const refusingRejected = layersOf('rejected').filter(layerNotAppliedRefusesTurn);
|
|
139
|
+
const refusingPartial = layersOf('loaded-partial').filter(layerNotAppliedRefusesTurn);
|
|
140
|
+
if (refusingRejected.length > 0 || refusingPartial.length > 0) {
|
|
112
141
|
return {
|
|
113
|
-
row: freeze({ key, cause:
|
|
142
|
+
row: freeze({ key, cause: refusingRejected.length > 0 ? 'source_rejected' : 'entries_dropped', disposition: 'refuse_turn', layers: freeze([...new Set([...refusingRejected, ...refusingPartial])]) }),
|
|
114
143
|
notices: [notice('HS-MANAGED-REJECTED', 'turn')],
|
|
115
144
|
plan,
|
|
116
145
|
};
|
|
117
146
|
}
|
|
118
|
-
if (closedBy === 'governance_unreadable')
|
|
147
|
+
if (plan.closedBy === 'governance_unreadable')
|
|
119
148
|
return { ...unreadableArm(key), plan };
|
|
120
149
|
if (wire !== undefined && !hooksPassJudge(wire)) {
|
|
121
150
|
return { row: freeze({ key, cause: 'projection_failed', disposition: BASE_DISPOSITION.projection_failed }), notices: [notice('HS-PROJECTION', 'turn')], plan };
|
|
@@ -129,23 +158,372 @@ function hooksArm(src) {
|
|
|
129
158
|
return { row: freeze({ key, cause, disposition: carried !== undefined ? 'carry_partial' : 'withhold_notice', layers }), notices: [], carried, plan };
|
|
130
159
|
}
|
|
131
160
|
if (carried === undefined)
|
|
132
|
-
return {
|
|
161
|
+
return { ...emptyArm(key), plan };
|
|
133
162
|
return { ...carriedArm(key, carried), plan };
|
|
134
163
|
}
|
|
135
|
-
function
|
|
164
|
+
function webSearchArm(src, side) {
|
|
165
|
+
const key = 'settings.webSearch';
|
|
166
|
+
if (src.kind === 'missing')
|
|
167
|
+
return missingArm(key);
|
|
168
|
+
if (src.kind === 'threw')
|
|
169
|
+
return unreadableArm(key);
|
|
170
|
+
const v = src.value;
|
|
171
|
+
if (v === 'none')
|
|
172
|
+
return noSourceArm(key);
|
|
173
|
+
let env;
|
|
174
|
+
let apiKeyFor;
|
|
175
|
+
try {
|
|
176
|
+
if (!isRecordShape(v) || !Object.hasOwn(v, 'env') || Object.hasOwn(v, 'settings') || Object.hasOwn(v, 'section')) {
|
|
177
|
+
throw badSource(key, "{ env, apiKeyFor? } with the environment (since 0.101.0 the webSearch section comes from the settings the entry reads — do not pass section)");
|
|
178
|
+
}
|
|
179
|
+
env = v.env;
|
|
180
|
+
apiKeyFor = v.apiKeyFor;
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
if (e instanceof HostSourceShapeError)
|
|
184
|
+
throw e;
|
|
185
|
+
return unreadableArm(key);
|
|
186
|
+
}
|
|
187
|
+
if (!isRecordShape(env))
|
|
188
|
+
throw badSource(key, '{ env } where env is the environment record (pass {} where there is none)');
|
|
189
|
+
if (apiKeyFor !== undefined && typeof apiKeyFor !== 'function')
|
|
190
|
+
throw badSource(key, '{ env, apiKeyFor? } where apiKeyFor is a function');
|
|
191
|
+
if (side.kind === 'missing')
|
|
192
|
+
return missingArm(key);
|
|
193
|
+
const section = side.kind === 'read' ? settingsValueOf(side.read, 'webSearch') : undefined;
|
|
194
|
+
const verdict = resolveWebSearchVerdict(env, section, apiKeyFor);
|
|
195
|
+
if (verdict.kind === 'absent')
|
|
196
|
+
return emptyArm(key);
|
|
197
|
+
if (verdict.kind === 'honored')
|
|
198
|
+
return carriedArm(key, freeze({ ...verdict.settings }));
|
|
199
|
+
return {
|
|
200
|
+
row: freeze({ key, cause: 'value_malformed', disposition: BASE_DISPOSITION.value_malformed }),
|
|
201
|
+
notices: [notice('HS-WEBSEARCH-MALFORMED', 'turn', webSearchVerdictMessage(verdict, 'submit') ?? '')],
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function memoryArm(src, side, judge) {
|
|
205
|
+
const key = 'memory';
|
|
206
|
+
if (src.kind === 'missing')
|
|
207
|
+
return missingArm(key);
|
|
208
|
+
if (src.kind === 'threw')
|
|
209
|
+
return unreadableArm(key);
|
|
210
|
+
const v = src.value;
|
|
211
|
+
if (v === 'none')
|
|
212
|
+
return noSourceArm(key);
|
|
213
|
+
let flag;
|
|
214
|
+
try {
|
|
215
|
+
if (!isRecordShape(v) || Object.hasOwn(v, 'settingsMemory'))
|
|
216
|
+
throw badSource(key, '{ flag? } with the --memory flag word (since 0.101.0 the memory section comes from the settings the entry reads — do not pass settingsMemory)');
|
|
217
|
+
flag = v.flag;
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
if (e instanceof HostSourceShapeError)
|
|
221
|
+
throw e;
|
|
222
|
+
return unreadableArm(key);
|
|
223
|
+
}
|
|
224
|
+
if (judge({ flag }))
|
|
225
|
+
return carriedArm(key, 'off');
|
|
226
|
+
if (side.kind === 'missing')
|
|
227
|
+
return missingArm(key);
|
|
228
|
+
const settingsMemory = side.kind === 'read' ? settingsValueOf(side.read, 'memory') : undefined;
|
|
229
|
+
let bySettings;
|
|
230
|
+
try {
|
|
231
|
+
bySettings = judge({ settingsMemory });
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return { row: freeze({ key, cause: 'value_malformed', disposition: 'withhold_notice' }), notices: [notice('HS-SWITCH-MALFORMED', 'session')] };
|
|
235
|
+
}
|
|
236
|
+
if (bySettings)
|
|
237
|
+
return carriedArm(key, 'off');
|
|
238
|
+
return emptyArm(key);
|
|
239
|
+
}
|
|
240
|
+
const UNOBSERVED_READING = Object.freeze({ kind: 'unobserved' });
|
|
241
|
+
function fileHistoryReadingSnapshot(reading) {
|
|
242
|
+
try {
|
|
243
|
+
if (typeof reading !== 'object' || reading === null)
|
|
244
|
+
return UNOBSERVED_READING;
|
|
245
|
+
const kind = reading.kind;
|
|
246
|
+
if (kind === 'present') {
|
|
247
|
+
const word = reading.word;
|
|
248
|
+
return Object.freeze({ kind, word });
|
|
249
|
+
}
|
|
250
|
+
return Object.freeze({ kind });
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return UNOBSERVED_READING;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function fileHistoryArm(src) {
|
|
257
|
+
const key = 'fileHistory';
|
|
258
|
+
if (src.kind === 'missing')
|
|
259
|
+
return missingArm(key);
|
|
260
|
+
if (src.kind === 'threw')
|
|
261
|
+
return unreadableArm(key);
|
|
262
|
+
const v = src.value;
|
|
263
|
+
if (v === 'none')
|
|
264
|
+
return noSourceArm(key);
|
|
265
|
+
let reading;
|
|
266
|
+
let captureOff;
|
|
267
|
+
try {
|
|
268
|
+
if (!isRecordShape(v) || !Object.hasOwn(v, 'captureOff'))
|
|
269
|
+
throw badSource(key, '{ reading, captureOff } with the engine capability reading and the switch');
|
|
270
|
+
reading = v.reading;
|
|
271
|
+
captureOff = v.captureOff;
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
if (e instanceof HostSourceShapeError)
|
|
275
|
+
throw e;
|
|
276
|
+
return unreadableArm(key);
|
|
277
|
+
}
|
|
278
|
+
if (typeof captureOff !== 'boolean')
|
|
279
|
+
throw badSource(key, '{ reading, captureOff } where captureOff is a boolean');
|
|
280
|
+
const snap = fileHistoryReadingSnapshot(reading);
|
|
281
|
+
const verdict = fileHistoryTightenVerdict(snap, captureOff);
|
|
282
|
+
if (verdict === 'declare')
|
|
283
|
+
return carriedArm(key, 'disabled');
|
|
284
|
+
if (verdict === 'unjudged') {
|
|
285
|
+
return {
|
|
286
|
+
row: freeze({ key, cause: 'value_malformed', disposition: 'refuse_turn' }),
|
|
287
|
+
notices: [notice('HS-FILEHISTORY-UNJUDGED', 'turn', fileHistoryUnjudgedRefusal(snap, true) ?? fileHistoryUnjudgedRefusal(UNOBSERVED_READING, true) ?? '')],
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return emptyArm(key);
|
|
291
|
+
}
|
|
292
|
+
function outputStyleArm(src, side) {
|
|
293
|
+
const key = 'settings.outputStyle';
|
|
294
|
+
if (src.kind === 'missing')
|
|
295
|
+
return missingArm(key);
|
|
296
|
+
if (src.kind === 'threw')
|
|
297
|
+
return unreadableArm(key);
|
|
298
|
+
const v = src.value;
|
|
299
|
+
if (v === 'none')
|
|
300
|
+
return noSourceArm(key);
|
|
301
|
+
let readBody;
|
|
302
|
+
try {
|
|
303
|
+
if (!isRecordShape(v) || Object.hasOwn(v, 'name'))
|
|
304
|
+
throw badSource(key, '{ readBody(name) } (since 0.101.0 the style name comes from the settings the entry reads — do not pass name)');
|
|
305
|
+
readBody = v.readBody;
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
if (e instanceof HostSourceShapeError)
|
|
309
|
+
throw e;
|
|
310
|
+
return unreadableArm(key);
|
|
311
|
+
}
|
|
312
|
+
if (typeof readBody !== 'function')
|
|
313
|
+
throw badSource(key, '{ readBody(name) } where readBody is a method');
|
|
314
|
+
if (side.kind === 'missing')
|
|
315
|
+
return missingArm(key);
|
|
316
|
+
if (side.kind === 'none')
|
|
317
|
+
return noSourceArm(key);
|
|
318
|
+
const name = settingsValueOf(side.read, 'outputStyle');
|
|
319
|
+
if (typeof name !== 'string' || name === '')
|
|
320
|
+
return emptyArm(key);
|
|
321
|
+
if (side.read.startup === 'safe') {
|
|
322
|
+
return { row: freeze({ key, cause: 'policy_withheld', disposition: BASE_DISPOSITION.policy_withheld }), notices: [notice('HS-STYLE-SAFE', 'diagnostic')] };
|
|
323
|
+
}
|
|
324
|
+
let body;
|
|
325
|
+
try {
|
|
326
|
+
body = readBody.call(v, name);
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
body = undefined;
|
|
330
|
+
}
|
|
331
|
+
const state = ownDataOf(body, 'state');
|
|
332
|
+
const text = state.ok && state.value === 'present' ? ownDataOf(body, 'body') : undefined;
|
|
333
|
+
const reminder = state.ok && state.value === 'present' ? ownDataOf(body, 'turnReminder') : undefined;
|
|
334
|
+
if (text !== undefined && text.ok && typeof text.value === 'string' && reminder !== undefined && reminder.ok && (reminder.value === undefined || typeof reminder.value === 'string')) {
|
|
335
|
+
const facts = freeze({ name, body: text.value, ...(reminder.value !== undefined ? { turnReminder: reminder.value } : {}) });
|
|
336
|
+
return { ...carriedArm(key, name), facts };
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
row: freeze({ key, cause: 'source_unreadable', disposition: 'withhold_notice' }),
|
|
340
|
+
notices: [notice('HS-STYLE-MISSING', 'session', displayUntrusted(name))],
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function stringListOf(v) {
|
|
344
|
+
if (v === undefined)
|
|
345
|
+
return [];
|
|
346
|
+
try {
|
|
347
|
+
if (!Array.isArray(v))
|
|
348
|
+
return undefined;
|
|
349
|
+
const ld = Object.getOwnPropertyDescriptor(v, 'length');
|
|
350
|
+
if (ld === undefined || !Object.hasOwn(ld, 'value') || typeof ld.value !== 'number' || !Number.isSafeInteger(ld.value) || ld.value < 0 || ld.value > 100_000)
|
|
351
|
+
return undefined;
|
|
352
|
+
const len = ld.value;
|
|
353
|
+
const out = [];
|
|
354
|
+
for (let i = 0; i < len; i++) {
|
|
355
|
+
const d = Object.getOwnPropertyDescriptor(v, i);
|
|
356
|
+
if (d === undefined || !Object.hasOwn(d, 'value') || typeof d.value !== 'string')
|
|
357
|
+
return undefined;
|
|
358
|
+
appendOwnElement(out, d.value);
|
|
359
|
+
}
|
|
360
|
+
return out;
|
|
361
|
+
}
|
|
362
|
+
catch {
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function permissionMemberAdmitted(layer, read, bucket) {
|
|
367
|
+
return layerAdmitted(layer, read.trust, 'permissions', bucket);
|
|
368
|
+
}
|
|
369
|
+
function allowAdmittedFor(read) {
|
|
370
|
+
const disp = MANAGED_READING_DISPOSITIONS[read.managed];
|
|
371
|
+
const policyDoc = read.layers.policySettings.doc;
|
|
372
|
+
const managedOnlySwitch = disp.ruleScope === 'by-switch' && policyDoc !== null && managedOnlySwitchOn(policyDoc);
|
|
373
|
+
const degrade = disp.ruleScope === 'degrade';
|
|
374
|
+
return (layer) => {
|
|
375
|
+
if (degrade || managedOnlySwitch)
|
|
376
|
+
return false;
|
|
377
|
+
try {
|
|
378
|
+
const doc = read.layers[layer].doc;
|
|
379
|
+
if (doc !== null && salvageSettingsHooksEntries(doc).outcome === 'rejected')
|
|
380
|
+
return false;
|
|
381
|
+
return layerAdmitted(layer, read.trust, 'permissions', 'allow');
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function badPermissionsSource() {
|
|
389
|
+
return new HostSourceShapeError(`hostTurnSettings: sources.resolved must be 'none' or { allowGrantReading, cliArg?, session?, clientOwnedServers?, serverVersion? } — since 0.101.0 the permission rules of the settings files come from the settings the entry reads; do not pass snapshot — got something else (the value is not echoed).`);
|
|
390
|
+
}
|
|
391
|
+
function permissionsArm(src, side, adoption) {
|
|
392
|
+
const key = 'settings.resolved';
|
|
136
393
|
if (src.kind === 'missing')
|
|
137
394
|
return missingArm(key);
|
|
138
395
|
if (src.kind === 'threw')
|
|
139
396
|
return unreadableArm(key);
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
397
|
+
const v = src.value;
|
|
398
|
+
if (v === 'none')
|
|
142
399
|
return noSourceArm(key);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
400
|
+
let allowGrantReading;
|
|
401
|
+
let cliAllow;
|
|
402
|
+
let cliDeny;
|
|
403
|
+
let sesDeny;
|
|
404
|
+
let sesAsk;
|
|
405
|
+
let owned;
|
|
406
|
+
let ownedRaw;
|
|
407
|
+
let serverVersion;
|
|
408
|
+
try {
|
|
409
|
+
if (!isRecordShape(v) || Object.hasOwn(v, 'snapshot') || !Object.hasOwn(v, 'allowGrantReading'))
|
|
410
|
+
throw badPermissionsSource();
|
|
411
|
+
const sver = ownDataOf(v, 'serverVersion');
|
|
412
|
+
serverVersion = sver.ok && typeof sver.value === 'string' ? sver.value : undefined;
|
|
413
|
+
const g = ownDataOf(v, 'allowGrantReading');
|
|
414
|
+
const c = ownDataOf(v, 'cliArg');
|
|
415
|
+
const se = ownDataOf(v, 'session');
|
|
416
|
+
const o = ownDataOf(v, 'clientOwnedServers');
|
|
417
|
+
if (!g.ok || !c.ok || !se.ok || !o.ok)
|
|
418
|
+
return unreadableArm(key);
|
|
419
|
+
allowGrantReading = g.value;
|
|
420
|
+
const cv = c.value;
|
|
421
|
+
const sv = se.value;
|
|
422
|
+
if (cv !== undefined && !isRecordShape(cv))
|
|
423
|
+
throw badPermissionsSource();
|
|
424
|
+
if (sv !== undefined && !isRecordShape(sv))
|
|
425
|
+
throw badPermissionsSource();
|
|
426
|
+
const ca = cv === undefined ? { ok: true, value: undefined } : ownDataOf(cv, 'allow');
|
|
427
|
+
const cd = cv === undefined ? { ok: true, value: undefined } : ownDataOf(cv, 'deny');
|
|
428
|
+
const sd = sv === undefined ? { ok: true, value: undefined } : ownDataOf(sv, 'deny');
|
|
429
|
+
const sa = sv === undefined ? { ok: true, value: undefined } : ownDataOf(sv, 'ask');
|
|
430
|
+
if (!ca.ok || !cd.ok || !sd.ok || !sa.ok)
|
|
431
|
+
return unreadableArm(key);
|
|
432
|
+
cliAllow = stringListOf(ca.value);
|
|
433
|
+
cliDeny = stringListOf(cd.value);
|
|
434
|
+
sesDeny = stringListOf(sd.value);
|
|
435
|
+
sesAsk = stringListOf(sa.value);
|
|
436
|
+
ownedRaw = o.value;
|
|
437
|
+
owned = o.value === undefined ? undefined : stringListOf(o.value);
|
|
438
|
+
}
|
|
439
|
+
catch (e) {
|
|
440
|
+
if (e instanceof HostSourceShapeError)
|
|
441
|
+
throw e;
|
|
442
|
+
return unreadableArm(key);
|
|
443
|
+
}
|
|
444
|
+
if (cliAllow === undefined || cliDeny === undefined || sesDeny === undefined || sesAsk === undefined || (owned === undefined && ownedRaw !== undefined))
|
|
445
|
+
throw badPermissionsSource();
|
|
446
|
+
if (side.kind === 'missing')
|
|
447
|
+
return missingArm(key);
|
|
448
|
+
const buckets = { deny: [], ask: [], allow: [] };
|
|
449
|
+
const origins = { deny: new Map(), ask: new Map(), allow: new Map() };
|
|
450
|
+
const rank = (o) => WIRE_RULE_TRUST_ORDER.indexOf(o);
|
|
451
|
+
const add = (bucket, rule, origin) => {
|
|
452
|
+
const prev = origins[bucket].get(rule);
|
|
453
|
+
if (prev === undefined) {
|
|
454
|
+
appendOwnElement(buckets[bucket], rule);
|
|
455
|
+
origins[bucket].set(rule, origin);
|
|
456
|
+
}
|
|
457
|
+
else if (rank(origin) < rank(prev))
|
|
458
|
+
origins[bucket].set(rule, origin);
|
|
459
|
+
};
|
|
460
|
+
let projectionError;
|
|
461
|
+
const portsProjection = newRulePortsProjection();
|
|
462
|
+
if (side.kind === 'read') {
|
|
463
|
+
const read = side.read;
|
|
464
|
+
const disp = MANAGED_READING_DISPOSITIONS[read.managed];
|
|
465
|
+
const policyDoc = read.layers.policySettings.doc;
|
|
466
|
+
const managedOnlySwitch = disp.ruleScope === 'by-switch' && policyDoc !== null && managedOnlySwitchOn(policyDoc);
|
|
467
|
+
const degrade = disp.ruleScope === 'degrade';
|
|
468
|
+
try {
|
|
469
|
+
for (const bucket of Object.keys(buckets)) {
|
|
470
|
+
if (bucket === 'allow' && degrade)
|
|
471
|
+
continue;
|
|
472
|
+
if (permissionMemberAdmitted('policySettings', read, bucket))
|
|
473
|
+
for (const r of permissionRulesOf(policyDoc, bucket))
|
|
474
|
+
add(bucket, r, 'policySettings');
|
|
475
|
+
}
|
|
476
|
+
if (!managedOnlySwitch) {
|
|
477
|
+
for (const l of ADOPTED_LAYERS) {
|
|
478
|
+
for (const bucket of ['deny', 'ask'])
|
|
479
|
+
if (permissionMemberAdmitted(l, read, bucket))
|
|
480
|
+
for (const r of permissionRulesOf(read.layers[l].doc, bucket))
|
|
481
|
+
add(bucket, r, l);
|
|
482
|
+
if (!degrade && permissionMemberAdmitted(l, read, 'allow'))
|
|
483
|
+
for (const r of adoption?.allowByLayer[l] ?? [])
|
|
484
|
+
add('allow', r, l);
|
|
485
|
+
}
|
|
486
|
+
for (const bucket of ['deny', 'ask'])
|
|
487
|
+
for (const r of adoption?.extraTighten[bucket] ?? [])
|
|
488
|
+
if (permissionMemberAdmitted(r.layer, read, bucket))
|
|
489
|
+
add(bucket, r.rule, r.layer);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
catch (error) {
|
|
493
|
+
projectionError = freeze({ error: error });
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
for (const r of cliAllow)
|
|
497
|
+
add('allow', r, 'cliArg');
|
|
498
|
+
for (const r of sesDeny)
|
|
499
|
+
add('deny', r, 'session');
|
|
500
|
+
for (const r of sesAsk)
|
|
501
|
+
add('ask', r, 'session');
|
|
502
|
+
let declared;
|
|
503
|
+
if (projectionError === undefined) {
|
|
504
|
+
try {
|
|
505
|
+
const d = projectPermissionsDeclaration({ deny: buckets.deny, ask: buckets.ask, allow: buckets.allow, origins, cliDeny, settingsRead: 'clean', ...(owned !== undefined && owned.length > 0 ? { clientOwnedServers: owned } : {}), ...(serverVersion !== undefined ? { serverVersion } : {}) }, allowGrantReading, portsProjection);
|
|
506
|
+
declared = d.permissions !== undefined ? { permissions: d.permissions } : undefined;
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
projectionError = freeze({ error: error });
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (projectionError !== undefined)
|
|
513
|
+
return { row: freeze({ key, cause: 'projection_failed', disposition: BASE_DISPOSITION.projection_failed }), notices: [projectionRefusedNotice(projectionError.error, portsProjection)], refusalCause: projectionError };
|
|
514
|
+
if (declared === undefined)
|
|
515
|
+
return emptyArm(key);
|
|
516
|
+
return carriedArm(key, declared);
|
|
517
|
+
}
|
|
518
|
+
function projectionRefusedNotice(error, projection) {
|
|
519
|
+
const ports = rulePortsMissingOf(error, projection);
|
|
520
|
+
if (ports !== undefined && ports.length > 0)
|
|
521
|
+
return notice('HS-PROJECTION', 'turn', renderMessage(msg('session.hostSettings.projectionUncheckedPortsMissing', { ports: ports.join(' / ') })));
|
|
522
|
+
if (assemblyRefusalOf(error)?.cause === 'judge_unanswerable')
|
|
523
|
+
return notice('HS-PROJECTION', 'turn', renderMessage(msg('session.hostSettings.projectionUncheckedJudgeFailed')));
|
|
524
|
+
return notice('HS-PROJECTION', 'turn');
|
|
148
525
|
}
|
|
526
|
+
const REFUSAL_CAUSE = Symbol('hostTurnSettings.refusalCause');
|
|
149
527
|
const RESOLVED_DEFERRED_ERROR = Symbol('hostTurnSettings.resolvedDeferredError');
|
|
150
528
|
export function rethrowHostResolvedDeferred(product) {
|
|
151
529
|
const rec = product;
|
|
@@ -155,7 +533,60 @@ export function rethrowHostResolvedDeferred(product) {
|
|
|
155
533
|
if (box !== undefined)
|
|
156
534
|
throw box.error;
|
|
157
535
|
}
|
|
158
|
-
|
|
536
|
+
function sessionOf(previous) {
|
|
537
|
+
const s = sessionSnapshotOf(previous);
|
|
538
|
+
if (s === undefined)
|
|
539
|
+
throw new HostSourceShapeError('hostTurnSettings: previous must be the session of the previous product of this session (product.session) or absent — got something else (the value is not echoed).');
|
|
540
|
+
return s;
|
|
541
|
+
}
|
|
542
|
+
const NON_MANAGED_LAYERS = HOST_SETTINGS_LAYERS.filter((l) => l !== 'policySettings');
|
|
543
|
+
function fnv1a(text) {
|
|
544
|
+
let h = 0x811c9dc5;
|
|
545
|
+
for (let i = 0; i < text.length; i++) {
|
|
546
|
+
h ^= text.charCodeAt(i);
|
|
547
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
548
|
+
}
|
|
549
|
+
return h.toString(16).padStart(8, '0');
|
|
550
|
+
}
|
|
551
|
+
function notLoadedLayers(read, plan) {
|
|
552
|
+
const out = [];
|
|
553
|
+
for (const layer of NON_MANAGED_LAYERS) {
|
|
554
|
+
const snap = read.layers[layer];
|
|
555
|
+
if (!snap.enabled)
|
|
556
|
+
continue;
|
|
557
|
+
const down = snap.carriers.filter((c) => c.status === 'unreadable' || c.status === 'not-loaded');
|
|
558
|
+
if (snap.malformed || down.length > 0) {
|
|
559
|
+
appendOwnElement(out, { layer, how: 'unreadable', key: JSON.stringify([layer, 'unreadable', down.map((c) => [c.id, c.status])]) });
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
if (plan?.settingsSalvage.some((r) => r.source === layer && r.outcome === 'rejected') === true) {
|
|
563
|
+
appendOwnElement(out, { layer, how: 'rejected', key: JSON.stringify([layer, 'rejected', fnv1a(JSON.stringify(snap.doc))]) });
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return out;
|
|
567
|
+
}
|
|
568
|
+
function notLoadedSentence(n, form) {
|
|
569
|
+
const layer = msg(`session.hostSettings.layer.${n.layer}`);
|
|
570
|
+
return renderMessage(msg(form === 'hold' ? `session.hostSettings.layerNotLoaded.hold.${n.how}` : 'session.hostSettings.layerNotLoaded.sent.unreadable', { layer }));
|
|
571
|
+
}
|
|
572
|
+
function settingsSideOf(input) {
|
|
573
|
+
let given;
|
|
574
|
+
let has;
|
|
575
|
+
try {
|
|
576
|
+
has = typeof input === 'object' && input !== null && Object.hasOwn(input, 'settings');
|
|
577
|
+
given = has ? input.settings : undefined;
|
|
578
|
+
}
|
|
579
|
+
catch {
|
|
580
|
+
throw new HostSettingsSourceShapeError('hostTurnSettings: reading input.settings threw — pass the HostSettingsSource for this turn, or \'none\'.');
|
|
581
|
+
}
|
|
582
|
+
if (!has || given === undefined)
|
|
583
|
+
return { kind: 'missing' };
|
|
584
|
+
if (given === 'none')
|
|
585
|
+
return { kind: 'none' };
|
|
586
|
+
return { kind: 'read', read: readHostSettingsOnce(given, 'hostTurnSettings') };
|
|
587
|
+
}
|
|
588
|
+
export function buildHostTurnSettings(input, judges) {
|
|
589
|
+
const materialize = judges.materialize;
|
|
159
590
|
let sources;
|
|
160
591
|
let sourcesThrew = false;
|
|
161
592
|
try {
|
|
@@ -165,8 +596,28 @@ export function buildHostTurnSettings(input, materialize) {
|
|
|
165
596
|
sourcesThrew = true;
|
|
166
597
|
}
|
|
167
598
|
const read = (key) => (sourcesThrew ? { kind: 'threw' } : readSource(sources, key));
|
|
168
|
-
|
|
169
|
-
let
|
|
599
|
+
let identityIn;
|
|
600
|
+
let previousIn;
|
|
601
|
+
try {
|
|
602
|
+
identityIn = input.identity;
|
|
603
|
+
previousIn = input.previous;
|
|
604
|
+
}
|
|
605
|
+
catch {
|
|
606
|
+
throw new HostSourceShapeError('hostTurnSettings: reading input.identity / input.previous threw (the value is not echoed).');
|
|
607
|
+
}
|
|
608
|
+
const surface = submissionSurfaceOf(identityIn);
|
|
609
|
+
if (surface === undefined)
|
|
610
|
+
throw new HostSourceShapeError('hostTurnSettings: identity must be the submission identity of this turn ({ surface, origin, tools }) — got something else (the value is not echoed).');
|
|
611
|
+
const session = sessionOf(previousIn);
|
|
612
|
+
const rawSide = settingsSideOf(input);
|
|
613
|
+
if (rawSide.kind === 'read')
|
|
614
|
+
for (const line of rawSide.read.debug)
|
|
615
|
+
hostLog('debug', line);
|
|
616
|
+
const adoption = rawSide.kind === 'read' ? adoptHostSettingsRead(rawSide.read, session, allowAdmittedFor(rawSide.read)) : undefined;
|
|
617
|
+
const side = adoption !== undefined ? { kind: 'read', read: adoption.read } : rawSide;
|
|
618
|
+
const nextSession = adoption?.session ?? remintSameContent(session);
|
|
619
|
+
const resolvedArm = permissionsArm(read('resolved'), side, adoption);
|
|
620
|
+
let resolvedCarried = resolvedArm.carried;
|
|
170
621
|
let resolvedError;
|
|
171
622
|
if (resolvedCarried !== undefined) {
|
|
172
623
|
try {
|
|
@@ -176,25 +627,182 @@ export function buildHostTurnSettings(input, materialize) {
|
|
|
176
627
|
resolvedError = freeze({ error });
|
|
177
628
|
}
|
|
178
629
|
}
|
|
179
|
-
const hooks = hooksArm(read('hooks'));
|
|
180
|
-
const webSearch =
|
|
181
|
-
const outputStyle =
|
|
182
|
-
const
|
|
630
|
+
const hooks = hooksArm(read('hooks'), side);
|
|
631
|
+
const webSearch = webSearchArm(read('webSearch'), side);
|
|
632
|
+
const outputStyle = outputStyleArm(read('outputStyle'), side);
|
|
633
|
+
const memory = memoryArm(read('memory'), side, judges.memoryOffDeclared);
|
|
634
|
+
const fileHistory = fileHistoryArm(read('fileHistory'));
|
|
635
|
+
let resolved = resolvedArm;
|
|
636
|
+
let armsByKey = [hooks, resolved, webSearch, outputStyle, memory, fileHistory];
|
|
637
|
+
if (side.kind === 'read' && MANAGED_READING_DISPOSITIONS[side.read.managed].commit === 'refuse') {
|
|
638
|
+
let said = false;
|
|
639
|
+
const managedArm = (a) => {
|
|
640
|
+
if (a.row.cause === 'host_port_missing' || a.row.cause === 'no_source')
|
|
641
|
+
return a;
|
|
642
|
+
const out = { row: freeze({ key: a.row.key, cause: 'source_unreadable', disposition: 'refuse_turn', layers: freeze(['policySettings']) }), notices: said ? [] : [notice('HS-MANAGED-UNREADABLE', 'turn')] };
|
|
643
|
+
said = true;
|
|
644
|
+
return out;
|
|
645
|
+
};
|
|
646
|
+
const hooksM = managedArm(hooks);
|
|
647
|
+
resolved = managedArm(resolved);
|
|
648
|
+
armsByKey = [{ ...hooksM, ...(hooks.plan !== undefined ? { plan: hooks.plan } : {}) }, resolved, managedArm(webSearch), outputStyle, memory, fileHistory];
|
|
649
|
+
}
|
|
650
|
+
if (adoption?.overflow === true) {
|
|
651
|
+
const over = (a) => (a.row.cause === 'host_port_missing' || a.row.cause === 'no_source' || a.row.disposition === 'refuse_turn' ? a : unreadableArm(a.row.key));
|
|
652
|
+
armsByKey = [{ ...over(armsByKey[0]), ...(hooks.plan !== undefined ? { plan: hooks.plan } : {}) }, over(armsByKey[1]), armsByKey[2], armsByKey[3], armsByKey[4], armsByKey[5]];
|
|
653
|
+
}
|
|
654
|
+
const heldLayer = (l) => adoption !== undefined && !adoption.trusted && (session.baseline?.loaded.some((k) => k.startsWith(`${l}|`)) ?? false);
|
|
655
|
+
const notLoaded = side.kind === 'read' ? notLoadedLayers(side.read, hooks.plan).filter((n) => !heldLayer(n.layer)) : [];
|
|
656
|
+
let consentKey;
|
|
657
|
+
const notLoadedNotices = [];
|
|
658
|
+
if (notLoaded.length > 0) {
|
|
659
|
+
const key = `hs1-${fnv1a(JSON.stringify(notLoaded.map((n) => n.key)))}`;
|
|
660
|
+
const ask = surface === 'interactive' && !session.consented.includes(key);
|
|
661
|
+
const layers = freeze(notLoaded.map((n) => n.layer));
|
|
662
|
+
const cause = notLoaded.some((n) => n.how === 'unreadable') ? 'source_unreadable' : 'source_rejected';
|
|
663
|
+
const reshape = (a) => {
|
|
664
|
+
const d = a.row.disposition;
|
|
665
|
+
if (d === 'refuse_turn' || d === 'unwired' || a.row.cause === 'no_source')
|
|
666
|
+
return a;
|
|
667
|
+
const disposition = ask ? 'hold_for_consent' : a.carried !== undefined ? 'carry_partial' : 'withhold_notice';
|
|
668
|
+
return { ...a, row: freeze({ key: a.row.key, cause, disposition, layers }) };
|
|
669
|
+
};
|
|
670
|
+
const before = armsByKey;
|
|
671
|
+
armsByKey = [{ ...reshape(before[0]), ...(hooks.plan !== undefined ? { plan: hooks.plan } : {}) }, reshape(before[1]), before[2], before[3], before[4], before[5]];
|
|
672
|
+
if (ask && armsByKey.slice(0, 2).some((a) => a.row.disposition === 'hold_for_consent'))
|
|
673
|
+
consentKey = key;
|
|
674
|
+
for (const n of notLoaded) {
|
|
675
|
+
if (consentKey !== undefined)
|
|
676
|
+
appendOwnElement(notLoadedNotices, notice('HS-LAYER-NOT-LOADED', 'turn', notLoadedSentence(n, 'hold')));
|
|
677
|
+
else if (n.how === 'unreadable')
|
|
678
|
+
appendOwnElement(notLoadedNotices, notice('HS-LAYER-NOT-LOADED', 'session', notLoadedSentence(n, 'sent')));
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
const heldNotices = [];
|
|
682
|
+
let held;
|
|
683
|
+
if (adoption?.held !== undefined) {
|
|
684
|
+
held = freeze({ wouldDrop: adoption.held.wouldDrop, version: nextSession.version });
|
|
685
|
+
const mark = (a) => (a.row.disposition === 'carry' && a.row.cause === 'carried' ? { ...a, row: freeze({ ...a.row, cause: 'held_previous' }) } : a);
|
|
686
|
+
armsByKey = [{ ...mark(armsByKey[0]), ...(hooks.plan !== undefined ? { plan: hooks.plan } : {}) }, mark(armsByKey[1]), armsByKey[2], armsByKey[3], armsByKey[4], armsByKey[5]];
|
|
687
|
+
appendOwnElement(heldNotices, notice('HS-HELD-PREVIOUS', 'diagnostic'));
|
|
688
|
+
}
|
|
689
|
+
const arms = armsByKey;
|
|
183
690
|
const rows = freeze(arms.map((a) => a.row));
|
|
184
|
-
const notices = freeze(arms.flatMap((a) => a.notices));
|
|
691
|
+
const notices = freeze([...arms.flatMap((a) => a.notices), ...notLoadedNotices, ...heldNotices]);
|
|
185
692
|
const refusal = arms.find((a) => a.row.disposition === 'refuse_turn');
|
|
186
|
-
const verdict = refusal
|
|
693
|
+
const verdict = refusal !== undefined
|
|
694
|
+
? freeze({ kind: 'refuse', notice: refusal.notices[0] ?? notices.find((n) => n.plane === 'turn') ?? notice('HS-PROJECTION', 'turn') })
|
|
695
|
+
: consentKey !== undefined
|
|
696
|
+
? freeze({ kind: 'hold', consentKey, notice: notLoadedNotices[0] })
|
|
697
|
+
: freeze({ kind: 'send' });
|
|
698
|
+
const carriedOf = (i) => {
|
|
699
|
+
const a = arms[i];
|
|
700
|
+
return a.row.disposition === 'carry' || a.row.disposition === 'carry_partial' || a.row.disposition === 'hold_for_consent' ? a.carried : undefined;
|
|
701
|
+
};
|
|
702
|
+
const hooksCarried = carriedOf(0);
|
|
703
|
+
const resolvedOut = arms[1]?.row.disposition === 'carry' || arms[1]?.row.disposition === 'carry_partial' || arms[1]?.row.disposition === 'hold_for_consent' ? resolvedCarried : undefined;
|
|
187
704
|
const carried = freeze({
|
|
188
|
-
...(
|
|
189
|
-
...(
|
|
190
|
-
...(
|
|
191
|
-
...(
|
|
705
|
+
...(hooksCarried !== undefined ? { hooks: hooksCarried } : {}),
|
|
706
|
+
...(resolvedOut !== undefined ? { resolved: resolvedOut } : {}),
|
|
707
|
+
...(carriedOf(2) !== undefined ? { webSearch: carriedOf(2) } : {}),
|
|
708
|
+
...(carriedOf(3) !== undefined ? { outputStyle: carriedOf(3) } : {}),
|
|
709
|
+
...(carriedOf(4) !== undefined ? { memory: 'off' } : {}),
|
|
710
|
+
...(carriedOf(5) !== undefined ? { fileHistory: 'disabled' } : {}),
|
|
192
711
|
});
|
|
193
|
-
const
|
|
194
|
-
|
|
712
|
+
const styleFacts = arms[3]?.row.disposition === 'carry' ? outputStyle.facts : undefined;
|
|
713
|
+
const product = { verdict, rows, notices, hooks: hooks.plan, carried, session: nextSession, outputStyle: styleFacts, held };
|
|
714
|
+
if (resolvedError !== undefined && resolvedOut !== undefined)
|
|
195
715
|
Object.defineProperty(product, RESOLVED_DEFERRED_ERROR, { value: resolvedError, enumerable: false });
|
|
716
|
+
const resolvedFinal = arms[1];
|
|
717
|
+
if (resolvedFinal?.refusalCause !== undefined && resolvedFinal.row.cause === 'projection_failed' && resolvedFinal.row.disposition === 'refuse_turn') {
|
|
718
|
+
Object.defineProperty(product, REFUSAL_CAUSE, { value: freeze({ key: resolvedFinal.row.key, error: resolvedFinal.refusalCause.error }), enumerable: false });
|
|
719
|
+
}
|
|
720
|
+
if (adoption?.held?.candidate !== undefined)
|
|
721
|
+
Object.defineProperty(product, ACCEPT_CANDIDATE, { value: adoption.held.candidate, enumerable: false });
|
|
196
722
|
return mint(freeze(product));
|
|
197
723
|
}
|
|
724
|
+
export function hostSettingsConsent(product) {
|
|
725
|
+
const snap = hostTurnSettingsOf(product);
|
|
726
|
+
if (snap === undefined || snap === UNWIRED_HOST_TURN_SETTINGS)
|
|
727
|
+
throw new HostSourceShapeError('hostSettingsConsent: pass the product returned by hostTurnSettings() for this turn (the value is not echoed).');
|
|
728
|
+
const p = snap;
|
|
729
|
+
if (p.verdict.kind !== 'hold')
|
|
730
|
+
return product;
|
|
731
|
+
const key = p.verdict.consentKey;
|
|
732
|
+
const rows = freeze(p.rows.map((r) => r.disposition !== 'hold_for_consent'
|
|
733
|
+
? r
|
|
734
|
+
: freeze({ ...r, disposition: (Object.hasOwn(p.carried, carriedKeyOf(r.key)) ? 'carry_partial' : 'withhold_notice') })));
|
|
735
|
+
const notices = freeze(p.notices.filter((n) => !(n.id === 'HS-LAYER-NOT-LOADED' && n.plane === 'turn')));
|
|
736
|
+
const session = mintHostSettingsSession(p.session.parent, [...p.session.consented, key], p.session.baseline);
|
|
737
|
+
if (session === undefined)
|
|
738
|
+
return product;
|
|
739
|
+
return mint(freeze({ verdict: freeze({ kind: 'send' }), rows, notices, hooks: p.hooks, carried: p.carried, session, outputStyle: p.outputStyle, held: p.held }));
|
|
740
|
+
}
|
|
741
|
+
const ACCEPT_CANDIDATE = Symbol('hostTurnSettings.acceptCandidate');
|
|
742
|
+
export function hostSettingsAcceptCurrent(product, confirmation) {
|
|
743
|
+
const c = captureConfirmation(confirmation);
|
|
744
|
+
if (c === undefined)
|
|
745
|
+
throw new HostSourceShapeError('hostSettingsAcceptCurrent: confirmation must be { version, deny, ask } — the session version of the product the user saw (held.version) and the deny / ask rules the user confirmed to stop sending (the value is not echoed).');
|
|
746
|
+
let candidate;
|
|
747
|
+
let held;
|
|
748
|
+
try {
|
|
749
|
+
if (typeof product !== 'object' || product === null)
|
|
750
|
+
return undefined;
|
|
751
|
+
const d = Object.getOwnPropertyDescriptor(product, ACCEPT_CANDIDATE);
|
|
752
|
+
candidate = d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
|
|
753
|
+
const h = Object.getOwnPropertyDescriptor(product, 'held');
|
|
754
|
+
held = h !== undefined && Object.hasOwn(h, 'value') ? h.value : undefined;
|
|
755
|
+
}
|
|
756
|
+
catch {
|
|
757
|
+
return undefined;
|
|
758
|
+
}
|
|
759
|
+
if (candidate === undefined || !isRecordShape(held))
|
|
760
|
+
return undefined;
|
|
761
|
+
const h = held;
|
|
762
|
+
if (h.version !== c.version)
|
|
763
|
+
return undefined;
|
|
764
|
+
const wd = h.wouldDrop;
|
|
765
|
+
if (!isRecordShape(wd) || !Array.isArray(wd.deny) || !Array.isArray(wd.ask))
|
|
766
|
+
return undefined;
|
|
767
|
+
if (!wd.deny.every((r) => typeof r === 'string' && c.deny.includes(r)))
|
|
768
|
+
return undefined;
|
|
769
|
+
if (!wd.ask.every((r) => typeof r === 'string' && c.ask.includes(r)))
|
|
770
|
+
return undefined;
|
|
771
|
+
return candidate;
|
|
772
|
+
}
|
|
773
|
+
function captureConfirmation(v) {
|
|
774
|
+
const version = ownDataOf(v, 'version');
|
|
775
|
+
const deny = ownDataOf(v, 'deny');
|
|
776
|
+
const ask = ownDataOf(v, 'ask');
|
|
777
|
+
if (!version.ok || !deny.ok || !ask.ok || typeof version.value !== 'string' || version.value.length === 0)
|
|
778
|
+
return undefined;
|
|
779
|
+
const strs = (x) => {
|
|
780
|
+
try {
|
|
781
|
+
if (!Array.isArray(x))
|
|
782
|
+
return undefined;
|
|
783
|
+
const ld = Object.getOwnPropertyDescriptor(x, 'length');
|
|
784
|
+
if (ld === undefined || !Object.hasOwn(ld, 'value') || typeof ld.value !== 'number' || !Number.isSafeInteger(ld.value) || ld.value < 0 || ld.value > 100_000)
|
|
785
|
+
return undefined;
|
|
786
|
+
const len = ld.value;
|
|
787
|
+
const out = [];
|
|
788
|
+
for (let i = 0; i < len; i++) {
|
|
789
|
+
const d = Object.getOwnPropertyDescriptor(x, i);
|
|
790
|
+
if (d === undefined || !Object.hasOwn(d, 'value') || typeof d.value !== 'string')
|
|
791
|
+
return undefined;
|
|
792
|
+
appendOwnElement(out, d.value);
|
|
793
|
+
}
|
|
794
|
+
return out;
|
|
795
|
+
}
|
|
796
|
+
catch {
|
|
797
|
+
return undefined;
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
const dn = strs(deny.value);
|
|
801
|
+
const ak = strs(ask.value);
|
|
802
|
+
if (dn === undefined || ak === undefined)
|
|
803
|
+
return undefined;
|
|
804
|
+
return freeze({ version: version.value, deny: freeze(dn), ask: freeze(ak) });
|
|
805
|
+
}
|
|
198
806
|
export function hostSettingsSelfCheck(product) {
|
|
199
807
|
try {
|
|
200
808
|
const rows = product.rows;
|
|
@@ -207,17 +815,19 @@ export function hostSettingsSelfCheck(product) {
|
|
|
207
815
|
continue;
|
|
208
816
|
seen.add(r.key);
|
|
209
817
|
if (r.disposition === 'unwired' && HOST_SUPPLIED_KEYS.includes(r.key))
|
|
210
|
-
out
|
|
818
|
+
appendOwnElement(out, r.key);
|
|
211
819
|
}
|
|
212
820
|
for (const k of HOST_SUPPLIED_KEYS)
|
|
213
821
|
if (!seen.has(k) && !out.includes(k))
|
|
214
|
-
out
|
|
822
|
+
appendOwnElement(out, k);
|
|
215
823
|
return freeze(out);
|
|
216
824
|
}
|
|
217
825
|
catch {
|
|
218
826
|
return HOST_SUPPLIED_KEYS;
|
|
219
827
|
}
|
|
220
828
|
}
|
|
829
|
+
export const hostProjectionNotice = () => notice('HS-PROJECTION', 'turn');
|
|
830
|
+
export const hostFileHistoryRestoreNotice = () => notice('HS-FILEHISTORY-RESTORE', 'turn');
|
|
221
831
|
export class HostSettingsRefused extends Error {
|
|
222
832
|
notice;
|
|
223
833
|
constructor(n) {
|
|
@@ -260,25 +870,36 @@ export function hostTurnSettingsOf(v, depth = 'full') {
|
|
|
260
870
|
const p = view;
|
|
261
871
|
const rows = p.rows;
|
|
262
872
|
const carried = p.carried;
|
|
263
|
-
const subs = HOST_SUPPLIED_KEYS.map(
|
|
873
|
+
const subs = HOST_SUPPLIED_KEYS.map(carriedKeyOf);
|
|
264
874
|
if (Object.keys(carried).some((k) => !subs.includes(k)))
|
|
265
875
|
return undefined;
|
|
876
|
+
if (carried.memory !== undefined && carried.memory !== 'off')
|
|
877
|
+
return undefined;
|
|
878
|
+
if (carried.fileHistory !== undefined && carried.fileHistory !== 'disabled')
|
|
879
|
+
return undefined;
|
|
266
880
|
let refuses = false;
|
|
881
|
+
let holds = false;
|
|
267
882
|
for (const [i, r] of rows.entries()) {
|
|
268
883
|
const disposition = r.disposition;
|
|
269
884
|
if (!HOST_SETTING_DISPOSITIONS.includes(disposition))
|
|
270
885
|
return undefined;
|
|
271
886
|
if (disposition === 'refuse_turn')
|
|
272
887
|
refuses = true;
|
|
888
|
+
if (disposition === 'hold_for_consent')
|
|
889
|
+
holds = true;
|
|
890
|
+
if (r.cause === 'projection_failed' && disposition !== 'refuse_turn')
|
|
891
|
+
return undefined;
|
|
273
892
|
const sub = subs[i] ?? '';
|
|
274
893
|
const has = Object.hasOwn(carried, sub) && carried[sub] !== undefined;
|
|
275
|
-
if (has !== CARRYING.has(disposition))
|
|
894
|
+
if (disposition !== 'hold_for_consent' && has !== CARRYING.has(disposition))
|
|
276
895
|
return undefined;
|
|
277
896
|
}
|
|
278
897
|
const verdict = p.verdict;
|
|
279
|
-
if (verdict.kind !== (refuses ? 'refuse' : 'send'))
|
|
898
|
+
if (verdict.kind !== (refuses ? 'refuse' : holds ? 'hold' : 'send'))
|
|
899
|
+
return undefined;
|
|
900
|
+
if ((refuses || holds) && !(isRecordShape(verdict.notice) && typeof verdict.notice.text === 'string'))
|
|
280
901
|
return undefined;
|
|
281
|
-
if (refuses &&
|
|
902
|
+
if (!refuses && holds && typeof verdict.consentKey !== 'string')
|
|
282
903
|
return undefined;
|
|
283
904
|
if (Object.hasOwn(carried, 'hooks') && carried.hooks !== undefined && !hooksPassJudge(carried.hooks))
|
|
284
905
|
return undefined;
|
|
@@ -288,4 +909,281 @@ export function hostTurnSettingsOf(v, depth = 'full') {
|
|
|
288
909
|
return undefined;
|
|
289
910
|
}
|
|
290
911
|
}
|
|
291
|
-
|
|
912
|
+
function wireFormOf(v) {
|
|
913
|
+
const text = JSON.stringify(v);
|
|
914
|
+
return text === undefined ? undefined : JSON.parse(text);
|
|
915
|
+
}
|
|
916
|
+
function sameJson(a, b) {
|
|
917
|
+
if (a === b)
|
|
918
|
+
return true;
|
|
919
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
920
|
+
return false;
|
|
921
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
922
|
+
return false;
|
|
923
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
924
|
+
return a.length === b.length && a.every((x, i) => sameJson(x, b[i]));
|
|
925
|
+
const ra = a;
|
|
926
|
+
const rb = b;
|
|
927
|
+
const ka = Object.keys(ra);
|
|
928
|
+
if (ka.length !== Object.keys(rb).length)
|
|
929
|
+
return false;
|
|
930
|
+
return ka.every((k) => Object.hasOwn(rb, k) && sameJson(ra[k], rb[k]));
|
|
931
|
+
}
|
|
932
|
+
function groupHead(g) {
|
|
933
|
+
if (!isRecordShape(g))
|
|
934
|
+
return undefined;
|
|
935
|
+
const head = {};
|
|
936
|
+
for (const k of Object.keys(g))
|
|
937
|
+
if (k !== 'hooks')
|
|
938
|
+
head[k] = g[k];
|
|
939
|
+
return head;
|
|
940
|
+
}
|
|
941
|
+
export function intersectHostHooks(sent, now) {
|
|
942
|
+
try {
|
|
943
|
+
return intersectHostHooksUnguarded(sent, now);
|
|
944
|
+
}
|
|
945
|
+
catch {
|
|
946
|
+
return { hooks: undefined, dropped: 0, judged: false };
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
function intersectHostHooksUnguarded(sentIn, nowIn) {
|
|
950
|
+
const sent = wireFormOf(sentIn);
|
|
951
|
+
const now = nowIn === undefined ? undefined : wireFormOf(nowIn);
|
|
952
|
+
const entriesOf = (cfg) => {
|
|
953
|
+
if (!isRecordShape(cfg))
|
|
954
|
+
return 0;
|
|
955
|
+
let n = 0;
|
|
956
|
+
for (const ev of Object.keys(cfg)) {
|
|
957
|
+
const groups = cfg[ev];
|
|
958
|
+
if (!Array.isArray(groups))
|
|
959
|
+
continue;
|
|
960
|
+
for (const g of groups)
|
|
961
|
+
if (isRecordShape(g) && Array.isArray(g.hooks))
|
|
962
|
+
n += g.hooks.length;
|
|
963
|
+
}
|
|
964
|
+
return n;
|
|
965
|
+
};
|
|
966
|
+
const total = entriesOf(sent);
|
|
967
|
+
if (!isRecordShape(sent))
|
|
968
|
+
return { hooks: undefined, dropped: 0, judged: true };
|
|
969
|
+
if (!isRecordShape(now))
|
|
970
|
+
return { hooks: undefined, dropped: total, judged: true };
|
|
971
|
+
const out = {};
|
|
972
|
+
let kept = 0;
|
|
973
|
+
for (const ev of Object.keys(sent)) {
|
|
974
|
+
const groups = sent[ev];
|
|
975
|
+
const nowGroups = now[ev];
|
|
976
|
+
if (!Array.isArray(groups) || !Array.isArray(nowGroups))
|
|
977
|
+
continue;
|
|
978
|
+
const pool = nowGroups.map((g) => ({ head: groupHead(g), left: isRecordShape(g) && Array.isArray(g.hooks) ? [...g.hooks] : [] }));
|
|
979
|
+
const evOut = [];
|
|
980
|
+
for (const g of groups) {
|
|
981
|
+
const head = groupHead(g);
|
|
982
|
+
if (head === undefined || !isRecordShape(g) || !Array.isArray(g.hooks))
|
|
983
|
+
continue;
|
|
984
|
+
const keep = [];
|
|
985
|
+
for (const entry of g.hooks) {
|
|
986
|
+
for (const slot of pool) {
|
|
987
|
+
if (slot.head === undefined || !sameJson(slot.head, head))
|
|
988
|
+
continue;
|
|
989
|
+
const at = slot.left.findIndex((x) => sameJson(x, entry));
|
|
990
|
+
if (at < 0)
|
|
991
|
+
continue;
|
|
992
|
+
slot.left.splice(at, 1);
|
|
993
|
+
appendOwnElement(keep, entry);
|
|
994
|
+
break;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (keep.length > 0)
|
|
998
|
+
appendOwnElement(evOut, { ...head, hooks: keep });
|
|
999
|
+
kept += keep.length;
|
|
1000
|
+
}
|
|
1001
|
+
if (evOut.length > 0)
|
|
1002
|
+
out[ev] = evOut;
|
|
1003
|
+
}
|
|
1004
|
+
const hooks = Object.keys(out).length > 0 ? out : undefined;
|
|
1005
|
+
return { hooks, dropped: total - kept, judged: hooks === undefined || hooksPassJudge(hooks) };
|
|
1006
|
+
}
|
|
1007
|
+
function ownDataOf(o, k) {
|
|
1008
|
+
if (typeof o !== 'object' || o === null)
|
|
1009
|
+
return { ok: false };
|
|
1010
|
+
try {
|
|
1011
|
+
return { ok: true, value: ownDataField(o, k) };
|
|
1012
|
+
}
|
|
1013
|
+
catch {
|
|
1014
|
+
return { ok: false };
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
function managedOnlySwitchOn(policyDoc) {
|
|
1018
|
+
const r = ownDataOf(policyDoc, 'allowManagedPermissionRulesOnly');
|
|
1019
|
+
return r.ok && r.value === true;
|
|
1020
|
+
}
|
|
1021
|
+
function noticeCopyOf(n) {
|
|
1022
|
+
const id = ownDataOf(n, 'id');
|
|
1023
|
+
const plane = ownDataOf(n, 'plane');
|
|
1024
|
+
const text = ownDataOf(n, 'text');
|
|
1025
|
+
if (!id.ok || !plane.ok || !text.ok || typeof id.value !== 'string' || typeof plane.value !== 'string' || typeof text.value !== 'string')
|
|
1026
|
+
return undefined;
|
|
1027
|
+
return freeze({ id: id.value, plane: plane.value, text: text.value });
|
|
1028
|
+
}
|
|
1029
|
+
function turnNoticesOf(product) {
|
|
1030
|
+
try {
|
|
1031
|
+
return turnNoticesUnguarded(product);
|
|
1032
|
+
}
|
|
1033
|
+
catch {
|
|
1034
|
+
return undefined;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
function turnNoticesUnguarded(product) {
|
|
1038
|
+
const ns = ownDataOf(product, 'notices');
|
|
1039
|
+
if (!ns.ok || !Array.isArray(ns.value))
|
|
1040
|
+
return undefined;
|
|
1041
|
+
const len = ownDataOf(ns.value, 'length');
|
|
1042
|
+
if (!len.ok || typeof len.value !== 'number')
|
|
1043
|
+
return undefined;
|
|
1044
|
+
const out = [];
|
|
1045
|
+
for (let i = 0; i < len.value; i++) {
|
|
1046
|
+
const e = ownDataOf(ns.value, String(i));
|
|
1047
|
+
const copy = e.ok ? noticeCopyOf(e.value) : undefined;
|
|
1048
|
+
if (copy === undefined)
|
|
1049
|
+
return undefined;
|
|
1050
|
+
if (copy.plane === 'turn')
|
|
1051
|
+
appendOwnElement(out, copy);
|
|
1052
|
+
}
|
|
1053
|
+
return freeze(out);
|
|
1054
|
+
}
|
|
1055
|
+
function deepFreeze(v) {
|
|
1056
|
+
if (typeof v === 'object' && v !== null) {
|
|
1057
|
+
for (const x of Object.values(v))
|
|
1058
|
+
deepFreeze(x);
|
|
1059
|
+
Object.freeze(v);
|
|
1060
|
+
}
|
|
1061
|
+
return v;
|
|
1062
|
+
}
|
|
1063
|
+
export function hostIntakeSnapshotOf(product, onResolved) {
|
|
1064
|
+
try {
|
|
1065
|
+
return intakeSnapshotUnguarded(product, onResolved);
|
|
1066
|
+
}
|
|
1067
|
+
catch {
|
|
1068
|
+
return undefined;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
function intakeSnapshotUnguarded(product, onResolved) {
|
|
1072
|
+
if (product === UNWIRED_HOST_TURN_SETTINGS) {
|
|
1073
|
+
return freeze({
|
|
1074
|
+
carried: freeze({}),
|
|
1075
|
+
refuses: false,
|
|
1076
|
+
dispositions: freeze(Object.fromEntries(HOST_SUPPLIED_KEYS.map((k) => [k, 'unwired']))),
|
|
1077
|
+
refusingKeys: freeze([]),
|
|
1078
|
+
turnNotices: freeze([]),
|
|
1079
|
+
notice: undefined,
|
|
1080
|
+
refusalCause: undefined,
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
const c = ownDataOf(product, 'carried');
|
|
1084
|
+
if (!c.ok || !isRecordShape(c.value))
|
|
1085
|
+
return undefined;
|
|
1086
|
+
const carriedIn = c.value;
|
|
1087
|
+
const subs = HOST_SUPPLIED_KEYS.map(carriedKeyOf);
|
|
1088
|
+
let keys;
|
|
1089
|
+
try {
|
|
1090
|
+
keys = Reflect.ownKeys(carriedIn);
|
|
1091
|
+
}
|
|
1092
|
+
catch {
|
|
1093
|
+
return undefined;
|
|
1094
|
+
}
|
|
1095
|
+
if (keys.some((k) => typeof k !== 'string' || !subs.includes(k)))
|
|
1096
|
+
return undefined;
|
|
1097
|
+
const values = {};
|
|
1098
|
+
const resolvedR = ownDataOf(carriedIn, 'resolved');
|
|
1099
|
+
if (!resolvedR.ok)
|
|
1100
|
+
return undefined;
|
|
1101
|
+
onResolved?.(resolvedR.value);
|
|
1102
|
+
if (resolvedR.value !== undefined)
|
|
1103
|
+
values.resolved = resolvedR.value;
|
|
1104
|
+
for (const sub of subs.filter((x) => x !== 'resolved')) {
|
|
1105
|
+
const r = ownDataOf(carriedIn, sub);
|
|
1106
|
+
if (!r.ok)
|
|
1107
|
+
return undefined;
|
|
1108
|
+
const copy = deepFreeze(wireFormOf(r.value));
|
|
1109
|
+
if (copy !== undefined)
|
|
1110
|
+
values[sub] = copy;
|
|
1111
|
+
}
|
|
1112
|
+
const rowsR = ownDataOf(product, 'rows');
|
|
1113
|
+
if (!rowsR.ok || !Array.isArray(rowsR.value) || rowsR.value.length !== HOST_SUPPLIED_KEYS.length)
|
|
1114
|
+
return undefined;
|
|
1115
|
+
let refuses = false;
|
|
1116
|
+
let anyRefuse = false;
|
|
1117
|
+
const refusingKeys = [];
|
|
1118
|
+
const dispositions = {};
|
|
1119
|
+
for (const [i, key] of HOST_SUPPLIED_KEYS.entries()) {
|
|
1120
|
+
const rowR = ownDataOf(rowsR.value, String(i));
|
|
1121
|
+
if (!rowR.ok)
|
|
1122
|
+
return undefined;
|
|
1123
|
+
const k = ownDataOf(rowR.value, 'key');
|
|
1124
|
+
const d = ownDataOf(rowR.value, 'disposition');
|
|
1125
|
+
if (!k.ok || !d.ok || k.value !== key || !HOST_SETTING_DISPOSITIONS.includes(d.value))
|
|
1126
|
+
return undefined;
|
|
1127
|
+
const cause = ownDataOf(rowR.value, 'cause');
|
|
1128
|
+
if (!cause.ok || (cause.value === 'projection_failed' && d.value !== 'refuse_turn'))
|
|
1129
|
+
return undefined;
|
|
1130
|
+
if (d.value === 'refuse_turn' || d.value === 'hold_for_consent') {
|
|
1131
|
+
refuses = true;
|
|
1132
|
+
appendOwnElement(refusingKeys, key);
|
|
1133
|
+
}
|
|
1134
|
+
if (d.value === 'refuse_turn')
|
|
1135
|
+
anyRefuse = true;
|
|
1136
|
+
dispositions[key] = d.value;
|
|
1137
|
+
if (d.value !== 'hold_for_consent' && (values[carriedKeyOf(key)] !== undefined) !== CARRYING.has(d.value))
|
|
1138
|
+
return undefined;
|
|
1139
|
+
}
|
|
1140
|
+
if (values.memory !== undefined && values.memory !== 'off')
|
|
1141
|
+
return undefined;
|
|
1142
|
+
if (values.fileHistory !== undefined && values.fileHistory !== 'disabled')
|
|
1143
|
+
return undefined;
|
|
1144
|
+
if (values.hooks !== undefined && !hooksPassJudge(values.hooks))
|
|
1145
|
+
return undefined;
|
|
1146
|
+
const v = ownDataOf(product, 'verdict');
|
|
1147
|
+
if (!v.ok)
|
|
1148
|
+
return undefined;
|
|
1149
|
+
const kind = ownDataOf(v.value, 'kind');
|
|
1150
|
+
if (!kind.ok || kind.value !== (anyRefuse ? 'refuse' : refuses ? 'hold' : 'send'))
|
|
1151
|
+
return undefined;
|
|
1152
|
+
const noticeR = refuses ? ownDataOf(v.value, 'notice') : undefined;
|
|
1153
|
+
const notice = noticeR === undefined ? undefined : ((noticeR.ok ? noticeCopyOf(noticeR.value) : undefined) ?? hostProjectionNotice());
|
|
1154
|
+
return freeze({
|
|
1155
|
+
carried: freeze(values),
|
|
1156
|
+
refuses,
|
|
1157
|
+
dispositions: freeze(dispositions),
|
|
1158
|
+
refusingKeys: freeze(refusingKeys),
|
|
1159
|
+
turnNotices: turnNoticesOf(product),
|
|
1160
|
+
notice,
|
|
1161
|
+
refusalCause: anyRefuse ? refusalCauseOf(product) : undefined,
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
function refusalCauseOf(product) {
|
|
1165
|
+
try {
|
|
1166
|
+
const d = Object.getOwnPropertyDescriptor(product, REFUSAL_CAUSE);
|
|
1167
|
+
return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
|
|
1168
|
+
}
|
|
1169
|
+
catch {
|
|
1170
|
+
return undefined;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
export function hostSettingsRefusedError(n, intake, firstSeatedKey) {
|
|
1174
|
+
const e = new HostSettingsRefused(n);
|
|
1175
|
+
const cause = intake.refusalCause;
|
|
1176
|
+
if (cause !== undefined && firstSeatedKey === cause.key && n.id === 'HS-PROJECTION')
|
|
1177
|
+
Object.defineProperty(e, 'cause', { value: cause.error, writable: true, enumerable: false, configurable: true });
|
|
1178
|
+
return e;
|
|
1179
|
+
}
|
|
1180
|
+
const UNWIRED_IDENTITY = Object.freeze({ surface: 'print', origin: 'user', tools: 'full' });
|
|
1181
|
+
export const UNWIRED_HOST_TURN_SETTINGS = buildHostTurnSettings({ sources: {}, identity: UNWIRED_IDENTITY }, {
|
|
1182
|
+
materialize: (snapshot) => snapshot,
|
|
1183
|
+
memoryOffDeclared: () => false,
|
|
1184
|
+
});
|
|
1185
|
+
function carriedKeyOf(k) {
|
|
1186
|
+
return k.startsWith('settings.') ? k.slice('settings.'.length) : k;
|
|
1187
|
+
}
|
|
1188
|
+
const _armsPin = [true, true, true, true];
|
|
1189
|
+
void _armsPin;
|