@sema-agent/client-core 0.100.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 +395 -0
- package/README.md +164 -117
- package/dist/adapt/arms.js +51 -16
- package/dist/adapt/textStream.js +7 -4
- package/dist/adapt/toolCards.js +9 -8
- package/dist/adapt.js +7 -1
- package/dist/adapter/activeRunSelfHeal.d.ts +24 -2
- package/dist/adapter/activeRunSelfHeal.js +108 -6
- package/dist/adapter/downstream/eventToSdkMessage.js +33 -12
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +209 -39
- package/dist/adapter/runStream.d.ts +4 -4
- package/dist/adapter/runStream.js +158 -43
- package/dist/agentsWireCaps.d.ts +2 -7
- package/dist/agentsWireCaps.js +1 -2
- 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 +19 -5
- package/dist/cloudConfigWireCaps.js +193 -56
- package/dist/coreValuePorts.d.ts +12 -2
- package/dist/coreValuePorts.js +9 -0
- package/dist/decideFailureNote.js +5 -3
- 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 +65 -8
- package/dist/engineCapReader.js +1 -1
- package/dist/engineConfigDrift.js +1 -1
- package/dist/engineErrorCodes.d.ts +14 -5
- package/dist/engineErrorCodes.js +27 -6
- 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 +3 -0
- package/dist/engineSessionMessages.js +2 -2
- package/dist/engineToolDirectory.js +2 -2
- 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/executionLaneCapability.js +2 -2
- package/dist/fileHistoryCaptureCapability.js +3 -3
- 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 -3
- package/dist/generated/engineFactTables.js +52 -0
- package/dist/generated/engineNoticeTables.js +12 -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 +54 -0
- package/dist/generated/settingsSchemaFns.js +26 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +1 -7
- 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 +2 -0
- package/dist/generated/settingsSchemaTables.js +13 -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 +7 -5
- package/dist/hitl/approvalCardReading.d.ts +3 -0
- package/dist/hitl/approvalCardReading.js +17 -0
- 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/approvalResolution.d.ts +11 -0
- package/dist/hitl/approvalResolution.js +50 -11
- package/dist/hitl/askClassPair.d.ts +6 -0
- package/dist/hitl/askClassPair.js +30 -3
- 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 +42 -3
- package/dist/hitl/attributionLadder.js +79 -8
- 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/decisionRefusal.d.ts +20 -10
- package/dist/hitl/decisionRefusal.js +99 -54
- package/dist/hitl/decisionSend.d.ts +3 -0
- package/dist/hitl/decisionSend.js +87 -103
- 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 +41 -37
- 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 +59 -30
- 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 +62 -29
- 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 +72 -54
- 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 +73 -17
- package/dist/hostTurnSettings.js +594 -97
- package/dist/httpHookPolicy.d.ts +37 -0
- package/dist/httpHookPolicy.js +176 -0
- package/dist/humanTurn.d.ts +2 -1
- package/dist/humanTurn.js +37 -7
- 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 +184 -2
- package/dist/i18n/messages.en.js +187 -5
- package/dist/i18n/messages.zh.js +197 -5
- package/dist/i18n/translate.js +3 -3
- package/dist/index.d.ts +69 -15
- package/dist/index.js +45 -13
- package/dist/inheritEnvCapability.d.ts +3 -1
- package/dist/inheritEnvCapability.js +31 -17
- package/dist/inheritEnvWire.d.ts +2 -1
- package/dist/inheritEnvWire.js +11 -5
- 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 +1 -1
- package/dist/mcpProbeCapability.js +2 -2
- package/dist/mcpStatusSupersetKeys.d.ts +24 -0
- package/dist/mcpStatusSupersetKeys.js +45 -0
- package/dist/mcpToolToggles.js +2 -1
- package/dist/mcpWireCaps.d.ts +39 -1
- package/dist/mcpWireCaps.js +254 -50
- 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.js +6 -6
- package/dist/modelIdentityResolvability.d.ts +10 -1
- package/dist/modelIdentityResolvability.js +62 -39
- 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 +11 -0
- package/dist/ownKey.js +164 -3
- package/dist/panelReduce.js +1 -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.js +2 -0
- 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 +92 -53
- package/dist/prepareRefusal.d.ts +3 -2
- package/dist/prepareRefusal.js +27 -9
- 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 +12 -4
- package/dist/request/taskRequest.js +221 -152
- package/dist/resultFrameKeys.d.ts +1 -0
- package/dist/resultFrameKeys.js +4 -1
- package/dist/retryStatus.d.ts +8 -0
- package/dist/retryStatus.js +57 -9
- 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 +4 -0
- package/dist/ruleRefusalSentence.js +9 -3
- 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 +1 -1
- package/dist/sandboxWire.js +4 -6
- package/dist/scenarioRefusal.js +1 -1
- 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 +2 -0
- package/dist/seam.js +2 -2
- package/dist/seatContract.d.ts +46 -1
- package/dist/seatContract.js +49 -19
- 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.js +60 -5
- 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 -0
- package/dist/skillsWireCaps.js +47 -16
- 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/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/turnFailurePresentation.js +27 -90
- 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 +24 -1
- package/dist/wireRefusalCopy.js +253 -32
- 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 +607 -181
- package/package.json +14 -3
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { appendOwnElement } from './ownKey.js';
|
|
2
|
+
import { SETTINGS_WORKSPACE_TRUST_STATES } from './generated/settingsSchemaTables.js';
|
|
3
|
+
import { jsonFaithfulCost, materializeJsonFaithful } from './jsonFaithful.js';
|
|
4
|
+
import { faultText } from './hostCallbackGuard.js';
|
|
5
|
+
export const HOST_SETTINGS_LAYERS = Object.freeze(['policySettings', 'userSettings', 'projectSettings', 'localSettings', 'flagSettings']);
|
|
6
|
+
export const MANAGED_POLICY_STATES = Object.freeze(['absent', 'in-effect', 'in-effect-pieces', 'unreadable-covered', 'unreadable-uncovered', 'remote-unknown']);
|
|
7
|
+
export const HOST_STARTUP_MODES = Object.freeze(['safe', 'bare', 'none']);
|
|
8
|
+
export const HOST_SETTINGS_CARRIER_STATUSES = Object.freeze(['loaded', 'loaded-partial', 'empty', 'absent', 'unreadable', 'not-loaded']);
|
|
9
|
+
export const HOST_SETTINGS_EMPTY_KINDS = Object.freeze(['zero-byte', 'whitespace', 'empty-object']);
|
|
10
|
+
const MEMBERS = ['readLayer', 'workspaceTrust', 'managedPolicyReading', 'startupMode', 'enabledPluginHooks', 'sessionHooks'];
|
|
11
|
+
export class HostSettingsSourceShapeError extends TypeError {
|
|
12
|
+
code = 'host_settings_source_shape';
|
|
13
|
+
}
|
|
14
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
15
|
+
function shortShape(v) {
|
|
16
|
+
try {
|
|
17
|
+
if (v === null)
|
|
18
|
+
return 'null';
|
|
19
|
+
if (typeof v === 'string')
|
|
20
|
+
return JSON.stringify(v.length > 40 ? `${v.slice(0, 40)}…` : v);
|
|
21
|
+
return Array.isArray(v) ? 'array' : typeof v;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return 'unreadable';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function isRecordSafe(v) {
|
|
28
|
+
try {
|
|
29
|
+
return isRecord(v);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function ownData(o, k) {
|
|
36
|
+
try {
|
|
37
|
+
if (typeof o !== 'object' || o === null)
|
|
38
|
+
return { ok: false };
|
|
39
|
+
const d = Object.getOwnPropertyDescriptor(o, k);
|
|
40
|
+
if (d === undefined)
|
|
41
|
+
return { ok: true, value: undefined };
|
|
42
|
+
if (!Object.hasOwn(d, 'value'))
|
|
43
|
+
return { ok: false };
|
|
44
|
+
return { ok: true, value: d.value };
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { ok: false };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export const SETTINGS_READ_BUDGET = 250_000;
|
|
51
|
+
export const HOST_SETTINGS_STATE_BUDGET = 4 * SETTINGS_READ_BUDGET;
|
|
52
|
+
export const SETTINGS_MAX_CARRIERS_PER_LAYER = 1024;
|
|
53
|
+
export const SETTINGS_MAX_ISSUES_PER_CARRIER = 4096;
|
|
54
|
+
const SESSION_CALLBACK_LEAF = (captured, key) => key === 'callback' && (captured.type === 'callback' || captured.type === 'function');
|
|
55
|
+
function sessionFunctionsAtRegistrations(v, path = []) {
|
|
56
|
+
if (typeof v === 'function') {
|
|
57
|
+
return path.length === 8 && path[0] === 'sources' && typeof path[1] === 'number' && path[2] === 'hooks' && typeof path[3] === 'string' &&
|
|
58
|
+
typeof path[4] === 'number' && path[5] === 'hooks' && typeof path[6] === 'number' && path[7] === 'callback';
|
|
59
|
+
}
|
|
60
|
+
if (v === null || typeof v !== 'object')
|
|
61
|
+
return true;
|
|
62
|
+
if (Array.isArray(v))
|
|
63
|
+
return v.every((x, i) => sessionFunctionsAtRegistrations(x, [...path, i]));
|
|
64
|
+
return Object.keys(v).every((k) => sessionFunctionsAtRegistrations(v[k], [...path, k]));
|
|
65
|
+
}
|
|
66
|
+
function captureSettingsValue(v, budget, kind = 'settings') {
|
|
67
|
+
try {
|
|
68
|
+
const guard = kind === 'state' ? { budget } : { budget, visited: new WeakSet() };
|
|
69
|
+
const r = materializeJsonFaithful(v, 'settings', new Set(), kind === 'session' ? { guard, functionLeaf: SESSION_CALLBACK_LEAF } : kind === 'state' ? { guard, undefinedIsBad: true } : { guard });
|
|
70
|
+
if ('bad' in r)
|
|
71
|
+
return { ok: false };
|
|
72
|
+
if (kind === 'session' && !sessionFunctionsAtRegistrations(r.value))
|
|
73
|
+
return { ok: false };
|
|
74
|
+
return { ok: true, value: deepFreeze(r.value) };
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return { ok: false };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function ownArrayItems(v, max, budget) {
|
|
81
|
+
try {
|
|
82
|
+
if (!Array.isArray(v))
|
|
83
|
+
return undefined;
|
|
84
|
+
if (--budget.left < 0)
|
|
85
|
+
return undefined;
|
|
86
|
+
const ld = Object.getOwnPropertyDescriptor(v, 'length');
|
|
87
|
+
if (ld === undefined || !Object.hasOwn(ld, 'value') || typeof ld.value !== 'number' || !Number.isSafeInteger(ld.value) || ld.value < 0 || ld.value > max)
|
|
88
|
+
return undefined;
|
|
89
|
+
const len = ld.value;
|
|
90
|
+
const out = [];
|
|
91
|
+
for (let i = 0; i < len; i++) {
|
|
92
|
+
budget.left -= 2;
|
|
93
|
+
if (budget.left < 0)
|
|
94
|
+
return undefined;
|
|
95
|
+
const d = Object.getOwnPropertyDescriptor(v, i);
|
|
96
|
+
if (d === undefined || !Object.hasOwn(d, 'value'))
|
|
97
|
+
return undefined;
|
|
98
|
+
appendOwnElement(out, d.value);
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function deepFreeze(v) {
|
|
107
|
+
if (typeof v === 'object' && v !== null && !Object.isFrozen(v)) {
|
|
108
|
+
for (const k of Reflect.ownKeys(v))
|
|
109
|
+
deepFreeze(v[k]);
|
|
110
|
+
Object.freeze(v);
|
|
111
|
+
}
|
|
112
|
+
return v;
|
|
113
|
+
}
|
|
114
|
+
const MALFORMED_LAYER = (layer) => Object.freeze({
|
|
115
|
+
layer,
|
|
116
|
+
enabled: true,
|
|
117
|
+
outcome: 'unreadable',
|
|
118
|
+
doc: null,
|
|
119
|
+
carriers: Object.freeze([Object.freeze({ id: `${layer}|reading`, status: 'unreadable' })]),
|
|
120
|
+
issues: Object.freeze([]),
|
|
121
|
+
malformed: true,
|
|
122
|
+
});
|
|
123
|
+
export function combineCarrierStatuses(carriers) {
|
|
124
|
+
const has = (st) => carriers.some((c) => c.status === st);
|
|
125
|
+
if (has('unreadable'))
|
|
126
|
+
return 'unreadable';
|
|
127
|
+
if (has('not-loaded'))
|
|
128
|
+
return 'not-loaded';
|
|
129
|
+
if (has('loaded-partial'))
|
|
130
|
+
return 'loaded-partial';
|
|
131
|
+
if (has('loaded'))
|
|
132
|
+
return 'loaded';
|
|
133
|
+
if (has('empty'))
|
|
134
|
+
return 'empty';
|
|
135
|
+
return 'absent';
|
|
136
|
+
}
|
|
137
|
+
function carrierOf(c, budget) {
|
|
138
|
+
budget.left -= 8;
|
|
139
|
+
if (budget.left < 0)
|
|
140
|
+
return undefined;
|
|
141
|
+
const id = ownData(c, 'id');
|
|
142
|
+
const st = ownData(c, 'status');
|
|
143
|
+
const ek = ownData(c, 'emptyKind');
|
|
144
|
+
const is = ownData(c, 'issues');
|
|
145
|
+
if (!id.ok || !st.ok || !ek.ok || !is.ok || typeof id.value !== 'string' || id.value.length === 0)
|
|
146
|
+
return undefined;
|
|
147
|
+
const status = HOST_SETTINGS_CARRIER_STATUSES.find((x) => x === st.value);
|
|
148
|
+
if (status === undefined)
|
|
149
|
+
return undefined;
|
|
150
|
+
let emptyKind;
|
|
151
|
+
if (status === 'empty') {
|
|
152
|
+
emptyKind = HOST_SETTINGS_EMPTY_KINDS.find((x) => x === ek.value);
|
|
153
|
+
if (emptyKind === undefined)
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
else if (ek.value !== undefined)
|
|
157
|
+
return undefined;
|
|
158
|
+
let issues;
|
|
159
|
+
if (is.value !== undefined) {
|
|
160
|
+
const items = ownArrayItems(is.value, SETTINGS_MAX_ISSUES_PER_CARRIER, budget);
|
|
161
|
+
if (items === undefined || !items.every((x) => typeof x === 'string'))
|
|
162
|
+
return undefined;
|
|
163
|
+
issues = Object.freeze(items);
|
|
164
|
+
}
|
|
165
|
+
if (status === 'loaded-partial' && (issues === undefined || issues.length === 0))
|
|
166
|
+
return undefined;
|
|
167
|
+
return Object.freeze({ id: id.value, status, ...(emptyKind !== undefined ? { emptyKind } : {}), ...(issues !== undefined ? { issues } : {}) });
|
|
168
|
+
}
|
|
169
|
+
function layerSnapshotOf(layer, r, budget) {
|
|
170
|
+
budget.left -= 3;
|
|
171
|
+
if (budget.left < 0)
|
|
172
|
+
return MALFORMED_LAYER(layer);
|
|
173
|
+
const en = ownData(r, 'enabled');
|
|
174
|
+
if (!en.ok || typeof en.value !== 'boolean')
|
|
175
|
+
return MALFORMED_LAYER(layer);
|
|
176
|
+
if (!en.value) {
|
|
177
|
+
return Object.freeze({ layer, enabled: false, outcome: 'absent', doc: null, carriers: Object.freeze([]), issues: Object.freeze([]), malformed: false });
|
|
178
|
+
}
|
|
179
|
+
const docIn = ownData(r, 'doc');
|
|
180
|
+
const cs = ownData(r, 'carriers');
|
|
181
|
+
if (!docIn.ok || !(docIn.value === null || isRecordSafe(docIn.value)) || !cs.ok)
|
|
182
|
+
return MALFORMED_LAYER(layer);
|
|
183
|
+
let docCopy = null;
|
|
184
|
+
if (docIn.value !== null) {
|
|
185
|
+
const c = captureSettingsValue(docIn.value, budget);
|
|
186
|
+
if (!c.ok || !isRecord(c.value))
|
|
187
|
+
return MALFORMED_LAYER(layer);
|
|
188
|
+
docCopy = c.value;
|
|
189
|
+
}
|
|
190
|
+
const doc = { ok: true, value: docCopy };
|
|
191
|
+
const carriers = [];
|
|
192
|
+
const items = ownArrayItems(cs.value, SETTINGS_MAX_CARRIERS_PER_LAYER, budget);
|
|
193
|
+
if (items === undefined)
|
|
194
|
+
return MALFORMED_LAYER(layer);
|
|
195
|
+
const seenIds = new Set();
|
|
196
|
+
for (const item of items) {
|
|
197
|
+
const c = carrierOf(item, budget);
|
|
198
|
+
if (c === undefined || seenIds.has(c.id))
|
|
199
|
+
return MALFORMED_LAYER(layer);
|
|
200
|
+
seenIds.add(c.id);
|
|
201
|
+
appendOwnElement(carriers, c);
|
|
202
|
+
}
|
|
203
|
+
const outcome = combineCarrierStatuses(carriers);
|
|
204
|
+
const anyLoaded = carriers.some((c) => c.status === 'loaded' || c.status === 'loaded-partial');
|
|
205
|
+
let docKeys;
|
|
206
|
+
try {
|
|
207
|
+
docKeys = doc.value === null ? 0 : Reflect.ownKeys(doc.value).length;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return MALFORMED_LAYER(layer);
|
|
211
|
+
}
|
|
212
|
+
if (anyLoaded ? doc.value === null : docKeys > 0)
|
|
213
|
+
return MALFORMED_LAYER(layer);
|
|
214
|
+
const issues = carriers.flatMap((c) => (c.issues ?? []).map((x) => JSON.stringify([c.id, x])));
|
|
215
|
+
return Object.freeze({
|
|
216
|
+
layer,
|
|
217
|
+
enabled: true,
|
|
218
|
+
outcome,
|
|
219
|
+
doc: doc.value,
|
|
220
|
+
carriers: Object.freeze(carriers),
|
|
221
|
+
issues: Object.freeze(issues),
|
|
222
|
+
malformed: false,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
export function readHostSettingsOnce(source, who) {
|
|
226
|
+
if (typeof source === 'object' && source !== null) {
|
|
227
|
+
const replayed = REPLAYS.get(source);
|
|
228
|
+
if (replayed !== undefined)
|
|
229
|
+
return replayed;
|
|
230
|
+
}
|
|
231
|
+
if (!isRecordSafe(source) && typeof source !== 'function') {
|
|
232
|
+
throw new HostSettingsSourceShapeError(`${who}: settings must be a HostSettingsSource (an object with ${MEMBERS.join(' / ')}) — got ${shortShape(source)}.`);
|
|
233
|
+
}
|
|
234
|
+
const methods = {};
|
|
235
|
+
for (const name of MEMBERS) {
|
|
236
|
+
let m;
|
|
237
|
+
try {
|
|
238
|
+
m = source[name];
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
throw new HostSettingsSourceShapeError(`${who}: reading the settings source member ${name} threw — every member of HostSettingsSource is required and must be a method.`);
|
|
242
|
+
}
|
|
243
|
+
if (typeof m !== 'function') {
|
|
244
|
+
throw new HostSettingsSourceShapeError(`${who}: the settings source member ${name} is ${m === undefined ? 'missing' : `not a method (got ${shortShape(m)})`} — every member of HostSettingsSource is required (answer 'none' / { state: 'absent' } where there is nothing).`);
|
|
245
|
+
}
|
|
246
|
+
methods[name] = m;
|
|
247
|
+
}
|
|
248
|
+
const call = (name, ...args) => {
|
|
249
|
+
try {
|
|
250
|
+
return { ok: true, value: methods[name].call(source, ...args) };
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
return { ok: false, err };
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
const debug = [];
|
|
257
|
+
const budget = { left: SETTINGS_READ_BUDGET };
|
|
258
|
+
const layers = {};
|
|
259
|
+
for (const layer of HOST_SETTINGS_LAYERS) {
|
|
260
|
+
const r = call('readLayer', layer);
|
|
261
|
+
if (!r.ok) {
|
|
262
|
+
appendOwnElement(debug, `hostSettings: readLayer(${layer}) threw — this layer is read as unreadable: ${faultText(r.err)}`);
|
|
263
|
+
layers[layer] = MALFORMED_LAYER(layer);
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
let snap;
|
|
267
|
+
try {
|
|
268
|
+
snap = layerSnapshotOf(layer, r.value, budget);
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
snap = MALFORMED_LAYER(layer);
|
|
272
|
+
}
|
|
273
|
+
if (snap.malformed)
|
|
274
|
+
appendOwnElement(debug, `hostSettings: readLayer(${layer}) returned a malformed reading — this layer is read as unreadable`);
|
|
275
|
+
layers[layer] = snap;
|
|
276
|
+
}
|
|
277
|
+
let trust = 'unreadable';
|
|
278
|
+
{
|
|
279
|
+
const r = call('workspaceTrust');
|
|
280
|
+
if (!r.ok)
|
|
281
|
+
appendOwnElement(debug, `hostSettings: workspaceTrust() threw — hooks are not projected this turn (trust unknown): ${faultText(r.err)}`);
|
|
282
|
+
else {
|
|
283
|
+
const w = SETTINGS_WORKSPACE_TRUST_STATES.find((x) => x === r.value);
|
|
284
|
+
if (w === undefined)
|
|
285
|
+
appendOwnElement(debug, `hostSettings: workspaceTrust() returned ${shortShape(r.value)}, none of ${SETTINGS_WORKSPACE_TRUST_STATES.join(' / ')} — hooks are not projected this turn (trust unknown)`);
|
|
286
|
+
else
|
|
287
|
+
trust = w;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
let managed = 'unreadable-uncovered';
|
|
291
|
+
{
|
|
292
|
+
const r = call('managedPolicyReading');
|
|
293
|
+
if (!r.ok)
|
|
294
|
+
appendOwnElement(debug, `hostSettings: managedPolicyReading() threw — read as unreadable-uncovered: ${faultText(r.err)}`);
|
|
295
|
+
else {
|
|
296
|
+
const st = ownData(r.value, 'state');
|
|
297
|
+
const w = st.ok ? MANAGED_POLICY_STATES.find((x) => x === st.value) : undefined;
|
|
298
|
+
if (w === undefined)
|
|
299
|
+
appendOwnElement(debug, `hostSettings: managedPolicyReading() state is ${st.ok ? shortShape(st.value) : 'unreadable'}, none of ${MANAGED_POLICY_STATES.join(' / ')} — read as unreadable-uncovered`);
|
|
300
|
+
else
|
|
301
|
+
managed = w;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
let startup = 'none';
|
|
305
|
+
{
|
|
306
|
+
const r = call('startupMode');
|
|
307
|
+
if (!r.ok)
|
|
308
|
+
appendOwnElement(debug, `hostSettings: startupMode() threw — read as 'none' (hooks not narrowed): ${faultText(r.err)}`);
|
|
309
|
+
else {
|
|
310
|
+
const w = HOST_STARTUP_MODES.find((x) => x === r.value);
|
|
311
|
+
if (w === undefined)
|
|
312
|
+
appendOwnElement(debug, `hostSettings: startupMode() returned ${shortShape(r.value)}, none of ${HOST_STARTUP_MODES.join(' / ')} — read as 'none' (hooks not narrowed)`);
|
|
313
|
+
else
|
|
314
|
+
startup = w;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
let plugins = Object.freeze({ state: 'failed' });
|
|
318
|
+
{
|
|
319
|
+
const r = call('enabledPluginHooks');
|
|
320
|
+
if (!r.ok)
|
|
321
|
+
appendOwnElement(debug, `hostSettings: enabledPluginHooks() threw — no plugin hooks projected this turn: ${faultText(r.err)}`);
|
|
322
|
+
else if (r.value === 'none')
|
|
323
|
+
plugins = Object.freeze({ state: 'absent' });
|
|
324
|
+
else {
|
|
325
|
+
const c = isRecordSafe(r.value) ? captureSettingsValue(r.value, budget) : { ok: false };
|
|
326
|
+
const ps = c.ok ? ownData(c.value, 'plugins') : { ok: false };
|
|
327
|
+
if (c.ok && ps.ok && Array.isArray(ps.value))
|
|
328
|
+
plugins = Object.freeze({ state: 'present', reading: c.value });
|
|
329
|
+
else
|
|
330
|
+
appendOwnElement(debug, 'hostSettings: enabledPluginHooks() returned a malformed reading — no plugin hooks projected this turn');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
let sessionHooks = Object.freeze({ state: 'failed' });
|
|
334
|
+
{
|
|
335
|
+
const r = call('sessionHooks');
|
|
336
|
+
if (!r.ok)
|
|
337
|
+
appendOwnElement(debug, `hostSettings: sessionHooks() threw — no session hooks judged this turn: ${faultText(r.err)}`);
|
|
338
|
+
else if (r.value === 'none')
|
|
339
|
+
sessionHooks = Object.freeze({ state: 'absent' });
|
|
340
|
+
else {
|
|
341
|
+
const c = isRecordSafe(r.value) ? captureSettingsValue(r.value, budget, 'session') : { ok: false };
|
|
342
|
+
const sources = c.ok ? ownData(c.value, 'sources') : { ok: false };
|
|
343
|
+
if (sources.ok && Array.isArray(sources.value))
|
|
344
|
+
sessionHooks = Object.freeze({ state: 'present', sources: sources.value });
|
|
345
|
+
else
|
|
346
|
+
appendOwnElement(debug, 'hostSettings: sessionHooks() returned a malformed reading — no session hooks judged this turn');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return Object.freeze({ layers: Object.freeze(layers), trust, managed, startup, plugins, sessionHooks, debug: Object.freeze(debug) });
|
|
350
|
+
}
|
|
351
|
+
const REPLAYS = new WeakMap();
|
|
352
|
+
export function sourceOfRead(read) {
|
|
353
|
+
const quiet = read.debug.length === 0 ? read : Object.freeze({ ...read, debug: Object.freeze([]) });
|
|
354
|
+
const src = Object.freeze({
|
|
355
|
+
readLayer: (layer) => {
|
|
356
|
+
const snap = quiet.layers[layer];
|
|
357
|
+
return { enabled: snap.enabled, doc: snap.doc, carriers: snap.carriers };
|
|
358
|
+
},
|
|
359
|
+
workspaceTrust: () => {
|
|
360
|
+
if (quiet.trust === 'unreadable')
|
|
361
|
+
throw new HostSettingsSourceShapeError('hostSettings: replayed workspace trust reading was unreadable');
|
|
362
|
+
return quiet.trust;
|
|
363
|
+
},
|
|
364
|
+
managedPolicyReading: () => ({ state: quiet.managed }),
|
|
365
|
+
startupMode: () => quiet.startup,
|
|
366
|
+
enabledPluginHooks: () => (quiet.plugins.reading ?? 'none'),
|
|
367
|
+
sessionHooks: () => (quiet.sessionHooks.sources !== undefined ? { sources: quiet.sessionHooks.sources } : 'none'),
|
|
368
|
+
});
|
|
369
|
+
REPLAYS.set(src, quiet);
|
|
370
|
+
return src;
|
|
371
|
+
}
|
|
372
|
+
export function settingsValueOf(read, key) {
|
|
373
|
+
let out;
|
|
374
|
+
for (const layer of CC_MERGE_ORDER) {
|
|
375
|
+
const doc = read.layers[layer].doc;
|
|
376
|
+
if (doc === null)
|
|
377
|
+
continue;
|
|
378
|
+
const v = ownData(doc, key);
|
|
379
|
+
if (v.ok && v.value !== undefined)
|
|
380
|
+
out = v.value;
|
|
381
|
+
}
|
|
382
|
+
return out;
|
|
383
|
+
}
|
|
384
|
+
export function mergedBooleanOf(read, key) {
|
|
385
|
+
let out;
|
|
386
|
+
for (const layer of CC_MERGE_ORDER) {
|
|
387
|
+
const doc = read.layers[layer].doc;
|
|
388
|
+
if (doc === null)
|
|
389
|
+
continue;
|
|
390
|
+
const v = ownData(doc, key);
|
|
391
|
+
if (v.ok && typeof v.value === 'boolean')
|
|
392
|
+
out = v.value;
|
|
393
|
+
}
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
export const CC_MERGE_ORDER = Object.freeze(['userSettings', 'projectSettings', 'localSettings', 'flagSettings', 'policySettings']);
|
|
397
|
+
export function nonManagedLayerDown(read) {
|
|
398
|
+
return HOST_SETTINGS_LAYERS.some((l) => {
|
|
399
|
+
if (l === 'policySettings')
|
|
400
|
+
return false;
|
|
401
|
+
const snap = read.layers[l];
|
|
402
|
+
return snap.malformed || snap.outcome === 'unreadable' || snap.outcome === 'not-loaded';
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
export const ADOPTED_LAYERS = Object.freeze(['userSettings', 'projectSettings', 'localSettings', 'flagSettings']);
|
|
406
|
+
const GENESIS_VERSION = '0';
|
|
407
|
+
export const parentVersionOf = (session) => (session.version === GENESIS_VERSION ? null : session.version);
|
|
408
|
+
function canonicalOf(v) {
|
|
409
|
+
if (v === null || typeof v !== 'object')
|
|
410
|
+
return JSON.stringify(v) ?? 'null';
|
|
411
|
+
if (Array.isArray(v))
|
|
412
|
+
return `[${v.map(canonicalOf).join(',')}]`;
|
|
413
|
+
const keys = Object.keys(v).sort();
|
|
414
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalOf(v[k])}`).join(',')}}`;
|
|
415
|
+
}
|
|
416
|
+
function fingerprint64(text) {
|
|
417
|
+
let a = 0x811c9dc5;
|
|
418
|
+
let b = 0x050c5d1f;
|
|
419
|
+
for (let i = 0; i < text.length; i++) {
|
|
420
|
+
const c = text.charCodeAt(i);
|
|
421
|
+
a = Math.imul(a ^ c, 0x01000193) >>> 0;
|
|
422
|
+
b = Math.imul(b ^ c, 0x01000193) >>> 0;
|
|
423
|
+
b = (b ^ (b >>> 13)) >>> 0;
|
|
424
|
+
}
|
|
425
|
+
return a.toString(16).padStart(8, '0') + b.toString(16).padStart(8, '0');
|
|
426
|
+
}
|
|
427
|
+
const VERSION_SHAPE = /^[1-9][0-9]{0,15}\.[0-9a-f]{16}$/;
|
|
428
|
+
const generationOf = (version) => (version === null ? 0 : Number(version.slice(0, version.indexOf('.'))));
|
|
429
|
+
const versionFor = (parent, consented, baseline) => `${generationOf(parent) + 1}.${fingerprint64(canonicalOf({ parent, consented, baseline }))}`;
|
|
430
|
+
export function mintHostSettingsSession(parent, consented, baseline) {
|
|
431
|
+
const c = Object.freeze([...consented]);
|
|
432
|
+
if (jsonFaithfulCost({ version: '', parent, consented: c, baseline }) > HOST_SETTINGS_STATE_BUDGET)
|
|
433
|
+
return undefined;
|
|
434
|
+
return Object.freeze({ version: versionFor(parent, c, baseline), parent, consented: c, baseline });
|
|
435
|
+
}
|
|
436
|
+
export function remintSameContent(session) {
|
|
437
|
+
return mintHostSettingsSession(parentVersionOf(session), session.consented, session.baseline) ?? session;
|
|
438
|
+
}
|
|
439
|
+
export function hostSettingsSessionFollows(stored, next) {
|
|
440
|
+
const sv = stored === undefined ? { ok: true, value: null } : ownData(stored, 'version');
|
|
441
|
+
const np = ownData(next, 'parent');
|
|
442
|
+
return sv.ok && np.ok && (sv.value === null || typeof sv.value === 'string') && sv.value === np.value;
|
|
443
|
+
}
|
|
444
|
+
export const FIRST_SESSION = Object.freeze({ version: GENESIS_VERSION, parent: null, consented: Object.freeze([]), baseline: null });
|
|
445
|
+
const isStringArray = (v) => Array.isArray(v) && v.every((x) => typeof x === 'string');
|
|
446
|
+
const keysWithin = (v, allowed) => typeof v === 'object' && v !== null && Object.keys(v).every((k) => allowed.includes(k));
|
|
447
|
+
const freezeArr = (a) => Object.freeze([...a]);
|
|
448
|
+
export function sessionSnapshotOf(previous) {
|
|
449
|
+
if (previous === undefined)
|
|
450
|
+
return FIRST_SESSION;
|
|
451
|
+
const c = captureSettingsValue(previous, { left: HOST_SETTINGS_STATE_BUDGET }, 'state');
|
|
452
|
+
if (!c.ok || !isRecord(c.value))
|
|
453
|
+
return undefined;
|
|
454
|
+
const v = c.value;
|
|
455
|
+
if (!keysWithin(v, ['version', 'parent', 'consented', 'baseline']))
|
|
456
|
+
return undefined;
|
|
457
|
+
const version = v.version;
|
|
458
|
+
const parent = v.parent;
|
|
459
|
+
if (typeof version !== 'string' || !VERSION_SHAPE.test(version) || !(parent === null || (typeof parent === 'string' && VERSION_SHAPE.test(parent))) || !isStringArray(v.consented))
|
|
460
|
+
return undefined;
|
|
461
|
+
const verified = (baseline) => {
|
|
462
|
+
const s = mintHostSettingsSession(parent, v.consented, baseline);
|
|
463
|
+
return s !== undefined && s.version === version ? s : undefined;
|
|
464
|
+
};
|
|
465
|
+
if (v.baseline === null)
|
|
466
|
+
return verified(null);
|
|
467
|
+
const b = v.baseline;
|
|
468
|
+
if (!isRecord(b) || !isRecord(b.docs) || !isStringArray(b.loaded) || !isStringArray(b.issues) || !isRecord(b.cleanAllow) || !isRecord(b.cleanCarriers) || !isRecord(b.protecting))
|
|
469
|
+
return undefined;
|
|
470
|
+
if (!keysWithin(b, ['docs', 'loaded', 'issues', 'cleanAllow', 'cleanCarriers', 'protecting']) || !keysWithin(b.docs, ADOPTED_LAYERS) || !keysWithin(b.cleanAllow, ADOPTED_LAYERS) ||
|
|
471
|
+
!keysWithin(b.cleanCarriers, ADOPTED_LAYERS) || !keysWithin(b.protecting, ['deny', 'ask']))
|
|
472
|
+
return undefined;
|
|
473
|
+
const docs = {};
|
|
474
|
+
const cleanAllow = {};
|
|
475
|
+
const cleanCarriers = {};
|
|
476
|
+
for (const l of ADOPTED_LAYERS) {
|
|
477
|
+
const d = b.docs[l];
|
|
478
|
+
if (!(d === null || isRecord(d)))
|
|
479
|
+
return undefined;
|
|
480
|
+
docs[l] = d;
|
|
481
|
+
const a = b.cleanAllow[l];
|
|
482
|
+
const cc = b.cleanCarriers[l];
|
|
483
|
+
if (!isStringArray(a) || !isStringArray(cc))
|
|
484
|
+
return undefined;
|
|
485
|
+
cleanAllow[l] = a;
|
|
486
|
+
cleanCarriers[l] = cc;
|
|
487
|
+
}
|
|
488
|
+
const rulesOf = (x) => {
|
|
489
|
+
if (!Array.isArray(x))
|
|
490
|
+
return undefined;
|
|
491
|
+
const out = [];
|
|
492
|
+
for (const r of x) {
|
|
493
|
+
if (!isRecord(r) || !keysWithin(r, ['layer', 'rule']) || typeof r.rule !== 'string' || !ADOPTED_LAYERS.includes(r.layer))
|
|
494
|
+
return undefined;
|
|
495
|
+
appendOwnElement(out, Object.freeze({ layer: r.layer, rule: r.rule }));
|
|
496
|
+
}
|
|
497
|
+
return Object.freeze(out);
|
|
498
|
+
};
|
|
499
|
+
const pd = rulesOf(b.protecting.deny);
|
|
500
|
+
const pa = rulesOf(b.protecting.ask);
|
|
501
|
+
if (pd === undefined || pa === undefined)
|
|
502
|
+
return undefined;
|
|
503
|
+
const baseline = Object.freeze({
|
|
504
|
+
docs: Object.freeze(docs),
|
|
505
|
+
loaded: freezeArr(b.loaded),
|
|
506
|
+
issues: freezeArr(b.issues),
|
|
507
|
+
cleanAllow: Object.freeze(cleanAllow),
|
|
508
|
+
cleanCarriers: Object.freeze(cleanCarriers),
|
|
509
|
+
protecting: Object.freeze({ deny: pd, ask: pa }),
|
|
510
|
+
});
|
|
511
|
+
return verified(baseline);
|
|
512
|
+
}
|
|
513
|
+
const LOADED = new Set(['loaded', 'loaded-partial']);
|
|
514
|
+
export function permissionRulesOf(doc, bucket) {
|
|
515
|
+
if (doc === null)
|
|
516
|
+
return [];
|
|
517
|
+
const p = ownData(doc, 'permissions');
|
|
518
|
+
if (!p.ok || !isRecord(p.value))
|
|
519
|
+
return [];
|
|
520
|
+
const b = ownData(p.value, bucket);
|
|
521
|
+
return b.ok && Array.isArray(b.value) ? b.value.filter((x) => typeof x === 'string') : [];
|
|
522
|
+
}
|
|
523
|
+
function overflowOf(read, session) {
|
|
524
|
+
return Object.freeze({ read, session: remintSameContent(session), trusted: false, clean: false, extraTighten: NO_EXTRA, allowByLayer: emptyByLayer(), overflow: true });
|
|
525
|
+
}
|
|
526
|
+
const carrierKeysOf = (read, layer) => read.layers[layer].carriers.map((c) => c.id);
|
|
527
|
+
export function adoptHostSettingsRead(read, session, allowAdmitted = () => true) {
|
|
528
|
+
const B = session.baseline;
|
|
529
|
+
const stackIssues = ADOPTED_LAYERS.flatMap((l) => read.layers[l].issues.map((x) => `${l}|${x}`));
|
|
530
|
+
const loadedNow = ADOPTED_LAYERS.flatMap((l) => read.layers[l].malformed ? [] : read.layers[l].carriers.filter((c) => LOADED.has(c.status) || (c.status === 'empty' && c.emptyKind === 'empty-object')).map((c) => `${l}|${c.id}`));
|
|
531
|
+
const anyMalformed = ADOPTED_LAYERS.some((l) => read.layers[l].malformed);
|
|
532
|
+
const carrierState = new Map();
|
|
533
|
+
for (const l of ADOPTED_LAYERS)
|
|
534
|
+
for (const c of read.layers[l].carriers)
|
|
535
|
+
carrierState.set(`${l}|${c.id}`, c);
|
|
536
|
+
let trusted = true;
|
|
537
|
+
if (B !== null) {
|
|
538
|
+
const newIssue = stackIssues.some((x) => !B.issues.includes(x));
|
|
539
|
+
const lost = B.loaded.some((k) => {
|
|
540
|
+
const layer = k.slice(0, k.indexOf('|'));
|
|
541
|
+
if (read.layers[layer].malformed)
|
|
542
|
+
return true;
|
|
543
|
+
const c = carrierState.get(k);
|
|
544
|
+
if (c === undefined)
|
|
545
|
+
return true;
|
|
546
|
+
if (LOADED.has(c.status))
|
|
547
|
+
return false;
|
|
548
|
+
return !(c.status === 'empty' && c.emptyKind === 'empty-object');
|
|
549
|
+
});
|
|
550
|
+
trusted = !newIssue && !lost && !anyMalformed;
|
|
551
|
+
}
|
|
552
|
+
const anyDown = ADOPTED_LAYERS.some((l) => read.layers[l].carriers.some((c) => c.status === 'unreadable' || c.status === 'not-loaded' || c.status === 'loaded-partial'));
|
|
553
|
+
const clean = trusted && stackIssues.length === 0 && !anyDown && !anyMalformed;
|
|
554
|
+
const currentAllow = (l) => (allowAdmitted(l) ? permissionRulesOf(read.layers[l].doc, 'allow') : []);
|
|
555
|
+
const allowByLayer = {};
|
|
556
|
+
for (const l of ADOPTED_LAYERS) {
|
|
557
|
+
if (clean)
|
|
558
|
+
allowByLayer[l] = freezeArr(currentAllow(l));
|
|
559
|
+
else if (B === null)
|
|
560
|
+
allowByLayer[l] = Object.freeze([]);
|
|
561
|
+
else {
|
|
562
|
+
const sameCarriers = sameSet(B.cleanCarriers[l], carrierKeysOf(read, l));
|
|
563
|
+
allowByLayer[l] = sameCarriers ? freezeArr(currentAllow(l).filter((r) => B.cleanAllow[l].includes(r))) : Object.freeze([]);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const docsNow = {};
|
|
567
|
+
for (const l of ADOPTED_LAYERS)
|
|
568
|
+
docsNow[l] = read.layers[l].doc;
|
|
569
|
+
const voided = (B0) => {
|
|
570
|
+
const allow = {};
|
|
571
|
+
const carriers = {};
|
|
572
|
+
for (const l of ADOPTED_LAYERS) {
|
|
573
|
+
const same = sameSet(B0.cleanCarriers[l], carrierKeysOf(read, l));
|
|
574
|
+
allow[l] = same ? B0.cleanAllow[l] : Object.freeze([]);
|
|
575
|
+
carriers[l] = same ? B0.cleanCarriers[l] : Object.freeze([]);
|
|
576
|
+
}
|
|
577
|
+
return { allow: Object.freeze(allow), carriers: Object.freeze(carriers) };
|
|
578
|
+
};
|
|
579
|
+
const history = B === null ? undefined : voided(B);
|
|
580
|
+
const cleanAllowNext = clean ? Object.freeze({ ...allowByLayer }) : history?.allow ?? emptyByLayer();
|
|
581
|
+
const cleanCarriersNext = clean ? Object.freeze(Object.fromEntries(ADOPTED_LAYERS.map((l) => [l, freezeArr(carrierKeysOf(read, l))]))) : history?.carriers ?? emptyByLayer();
|
|
582
|
+
if (trusted) {
|
|
583
|
+
const baseline = Object.freeze({
|
|
584
|
+
docs: Object.freeze(docsNow),
|
|
585
|
+
loaded: freezeArr(loadedNow),
|
|
586
|
+
issues: freezeArr(stackIssues),
|
|
587
|
+
cleanAllow: cleanAllowNext,
|
|
588
|
+
cleanCarriers: cleanCarriersNext,
|
|
589
|
+
protecting: Object.freeze({ deny: Object.freeze([]), ask: Object.freeze([]) }),
|
|
590
|
+
});
|
|
591
|
+
const s = mintHostSettingsSession(parentVersionOf(session), session.consented, baseline);
|
|
592
|
+
if (s === undefined)
|
|
593
|
+
return overflowOf(read, session);
|
|
594
|
+
return Object.freeze({ read, session: s, trusted, clean, extraTighten: NO_EXTRA, allowByLayer: Object.freeze(allowByLayer) });
|
|
595
|
+
}
|
|
596
|
+
const base = B;
|
|
597
|
+
const inBase = (bucket, r) => permissionRulesOf(base.docs[r.layer], bucket).includes(r.rule);
|
|
598
|
+
const extra = (bucket) => {
|
|
599
|
+
const out = [];
|
|
600
|
+
const seen = new Set();
|
|
601
|
+
const push = (r) => {
|
|
602
|
+
const k = `${r.layer}|${r.rule}`;
|
|
603
|
+
if (seen.has(k) || inBase(bucket, r))
|
|
604
|
+
return;
|
|
605
|
+
seen.add(k);
|
|
606
|
+
appendOwnElement(out, Object.freeze(r));
|
|
607
|
+
};
|
|
608
|
+
for (const l of ADOPTED_LAYERS)
|
|
609
|
+
for (const rule of permissionRulesOf(read.layers[l].doc, bucket))
|
|
610
|
+
push({ layer: l, rule });
|
|
611
|
+
for (const r of base.protecting[bucket])
|
|
612
|
+
push(r);
|
|
613
|
+
return Object.freeze(out);
|
|
614
|
+
};
|
|
615
|
+
const extraTighten = Object.freeze({ deny: extra('deny'), ask: extra('ask') });
|
|
616
|
+
const baseline = Object.freeze({
|
|
617
|
+
docs: base.docs,
|
|
618
|
+
loaded: freezeArr([...new Set([...base.loaded, ...loadedNow])]),
|
|
619
|
+
issues: base.issues,
|
|
620
|
+
cleanAllow: cleanAllowNext,
|
|
621
|
+
cleanCarriers: cleanCarriersNext,
|
|
622
|
+
protecting: extraTighten,
|
|
623
|
+
});
|
|
624
|
+
const effectiveLayers = {};
|
|
625
|
+
for (const l of HOST_SETTINGS_LAYERS) {
|
|
626
|
+
const snap = read.layers[l];
|
|
627
|
+
effectiveLayers[l] = l === 'policySettings' ? snap : Object.freeze({ ...snap, doc: base.docs[l] });
|
|
628
|
+
}
|
|
629
|
+
const effective = Object.freeze({ ...read, layers: Object.freeze(effectiveLayers), current: read, debug: Object.freeze([]) });
|
|
630
|
+
const sentNow = (bucket) => new Set([...ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(base.docs[l], bucket)), ...extraTighten[bucket].map((r) => r.rule)]);
|
|
631
|
+
const readNow = (bucket) => new Set(ADOPTED_LAYERS.flatMap((l) => permissionRulesOf(read.layers[l].doc, bucket)));
|
|
632
|
+
const drop = (bucket) => Object.freeze([...sentNow(bucket)].filter((r) => !readNow(bucket).has(r)).sort());
|
|
633
|
+
const wouldDrop = Object.freeze({ deny: drop('deny'), ask: drop('ask') });
|
|
634
|
+
const acceptable = !stackIssues.some((x) => !base.issues.includes(x)) && !anyMalformed && !ADOPTED_LAYERS.some((l) => read.layers[l].carriers.some((c) => c.status === 'unreadable' || c.status === 'not-loaded'));
|
|
635
|
+
const s = mintHostSettingsSession(parentVersionOf(session), session.consented, baseline);
|
|
636
|
+
if (s === undefined)
|
|
637
|
+
return overflowOf(read, session);
|
|
638
|
+
const candidate = acceptable
|
|
639
|
+
? mintHostSettingsSession(s.version, session.consented, Object.freeze({
|
|
640
|
+
docs: Object.freeze(docsNow),
|
|
641
|
+
loaded: freezeArr(loadedNow),
|
|
642
|
+
issues: freezeArr(stackIssues),
|
|
643
|
+
cleanAllow: cleanAllowNext,
|
|
644
|
+
cleanCarriers: cleanCarriersNext,
|
|
645
|
+
protecting: Object.freeze({ deny: Object.freeze([]), ask: Object.freeze([]) }),
|
|
646
|
+
}))
|
|
647
|
+
: undefined;
|
|
648
|
+
return Object.freeze({
|
|
649
|
+
read: effective,
|
|
650
|
+
session: s,
|
|
651
|
+
trusted,
|
|
652
|
+
clean,
|
|
653
|
+
extraTighten,
|
|
654
|
+
allowByLayer: Object.freeze(allowByLayer),
|
|
655
|
+
held: Object.freeze({ wouldDrop, ...(candidate !== undefined ? { candidate } : {}) }),
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
const NO_EXTRA = Object.freeze({ deny: Object.freeze([]), ask: Object.freeze([]) });
|
|
659
|
+
const emptyByLayer = () => {
|
|
660
|
+
const out = {};
|
|
661
|
+
for (const l of ADOPTED_LAYERS)
|
|
662
|
+
out[l] = Object.freeze([]);
|
|
663
|
+
return Object.freeze(out);
|
|
664
|
+
};
|
|
665
|
+
const sameSet = (a, b) => a.length === b.length && a.every((x) => b.includes(x));
|
|
666
|
+
export const MANAGED_READING_DISPOSITIONS = Object.freeze({
|
|
667
|
+
absent: Object.freeze({ commit: 'proceed', ruleScope: 'all-sources', hooksRestriction: 'use-read', httpList: 'use-read' }),
|
|
668
|
+
'in-effect': Object.freeze({ commit: 'proceed', ruleScope: 'by-switch', hooksRestriction: 'use-read', httpList: 'use-read' }),
|
|
669
|
+
'in-effect-pieces': Object.freeze({ commit: 'proceed', ruleScope: 'degrade', hooksRestriction: 'use-read', httpList: 'use-read' }),
|
|
670
|
+
'unreadable-covered': Object.freeze({ commit: 'refuse', ruleScope: 'degrade', hooksRestriction: 'held-restrictions', httpList: 'use-read' }),
|
|
671
|
+
'unreadable-uncovered': Object.freeze({ commit: 'refuse', ruleScope: 'degrade', hooksRestriction: 'withhold', httpList: 'withhold' }),
|
|
672
|
+
'remote-unknown': Object.freeze({ commit: 'proceed', ruleScope: 'degrade', hooksRestriction: 'withhold', httpList: 'withhold' }),
|
|
673
|
+
});
|
|
674
|
+
const _hostSettingsPins = [true, true, true, true, true, true, true];
|
|
675
|
+
void _hostSettingsPins;
|