@sema-agent/client-core 0.97.1 → 0.99.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 +607 -0
- package/README.md +96 -46
- package/dist/adapt/arms.d.ts +1 -0
- package/dist/adapt/arms.js +188 -53
- package/dist/adapt/ids.d.ts +12 -1
- package/dist/adapt/ids.js +59 -8
- package/dist/adapt/instanceLedger.d.ts +50 -0
- package/dist/adapt/instanceLedger.js +147 -0
- package/dist/adapt/panelTasks.d.ts +1 -1
- package/dist/adapt/panelTasks.js +2 -2
- package/dist/adapt/textStream.d.ts +1 -0
- package/dist/adapt/textStream.js +24 -7
- package/dist/adapt/toolCards.d.ts +27 -5
- package/dist/adapt/toolCards.js +39 -6
- package/dist/adapt/wireShapes.js +6 -2
- package/dist/adapt.d.ts +2 -0
- package/dist/adapt.js +8 -3
- package/dist/adapter/activeRunSelfHeal.d.ts +9 -3
- package/dist/adapter/activeRunSelfHeal.js +205 -313
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +2 -5
- package/dist/adapter/downstream/eventToSdkMessage.js +77 -36
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -4
- package/dist/adapter/downstream/turnUsageToModelUsage.d.ts +5 -2
- package/dist/adapter/downstream/turnUsageToModelUsage.js +2 -0
- package/dist/adapter/runStream.js +79 -48
- package/dist/adapter/types.d.ts +4 -4
- package/dist/adapter/types.js +2 -1
- package/dist/agentSession/backgroundView.js +2 -1
- package/dist/agentSession/engineAgentRegistryRead.d.ts +2 -2
- package/dist/agentSession/engineAgentRegistryRead.js +12 -13
- package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
- package/dist/agentsWireCaps.d.ts +8 -11
- package/dist/agentsWireCaps.js +196 -194
- package/dist/approvalDecidedByCapability.d.ts +0 -4
- package/dist/approvalDecidedByCapability.js +0 -6
- package/dist/approvalsStreamLiveCapability.d.ts +0 -4
- package/dist/approvalsStreamLiveCapability.js +0 -6
- package/dist/assistantInbox.d.ts +34 -0
- package/dist/assistantInbox.js +118 -0
- package/dist/centerWiringCapability.js +9 -1
- package/dist/clientSlice.d.ts +0 -9
- package/dist/clientSlice.js +0 -3
- package/dist/cloudConfigWireCaps.d.ts +5 -3
- package/dist/cloudConfigWireCaps.js +106 -64
- package/dist/compensations.js +1 -1
- package/dist/connectorStatus.d.ts +21 -0
- package/dist/connectorStatus.js +112 -0
- package/dist/controlRouter.d.ts +18 -3
- package/dist/controlRouter.js +106 -67
- package/dist/coreValuePorts.d.ts +29 -4
- package/dist/coreValuePorts.js +10 -0
- package/dist/corruptSessionCopy.d.ts +2 -1
- package/dist/corruptSessionCopy.js +3 -3
- package/dist/decideReceipt.d.ts +2 -2
- package/dist/decideReceipt.js +5 -2
- package/dist/declared/supportFloorDeclared.js +3 -3
- package/dist/detachWire.js +3 -2
- package/dist/deviceExecutorManagementCapability.d.ts +0 -4
- package/dist/deviceExecutorManagementCapability.js +0 -6
- package/dist/deviceRebind.d.ts +49 -1
- package/dist/deviceRebind.js +221 -3
- package/dist/devicesFace.d.ts +34 -0
- package/dist/devicesFace.js +90 -0
- package/dist/displayUntrusted.d.ts +2 -0
- package/dist/displayUntrusted.js +253 -76
- package/dist/engineAgentAbsence.d.ts +1 -1
- package/dist/engineAgentPanelStore.d.ts +12 -4
- package/dist/engineAgentPanelStore.js +16 -11
- package/dist/engineCapReader.d.ts +2 -5
- package/dist/engineCapReader.js +8 -10
- package/dist/engineCapsCache.d.ts +12 -0
- package/dist/engineCapsCache.js +76 -18
- package/dist/engineCapsChange.d.ts +2 -0
- package/dist/engineCapsChange.js +9 -0
- package/dist/engineClosedSets.d.ts +1 -0
- package/dist/engineClosedSets.js +4 -1
- package/dist/engineErrorCodes.d.ts +11 -3
- package/dist/engineErrorCodes.js +11 -8
- package/dist/engineIdentity.d.ts +1 -0
- package/dist/engineIdentity.js +8 -0
- package/dist/engineRowRef.d.ts +28 -0
- package/dist/engineRowRef.js +114 -0
- package/dist/engineSessionMessages.d.ts +68 -0
- package/dist/engineSessionMessages.js +370 -0
- package/dist/engineTargetSeat.d.ts +27 -0
- package/dist/engineTargetSeat.js +199 -0
- package/dist/engineToolDirectory.d.ts +0 -9
- package/dist/engineToolDirectory.js +1 -94
- package/dist/engineUrl.d.ts +18 -0
- package/dist/engineUrl.js +52 -0
- package/dist/engineWireFor.js +3 -8
- package/dist/env/uiLanguage.d.ts +11 -1
- package/dist/env/uiLanguage.js +38 -2
- package/dist/eventLeg.d.ts +100 -0
- package/dist/eventLeg.js +305 -0
- package/dist/executionLaneCapability.d.ts +0 -4
- package/dist/executionLaneCapability.js +3 -16
- package/dist/fileHistoryCaptureCapability.d.ts +2 -5
- package/dist/fileHistoryCaptureCapability.js +13 -21
- package/dist/fileHistoryLegNotice.d.ts +2 -1
- package/dist/fileHistoryLegNotice.js +3 -3
- package/dist/fleet/fleetLedger.d.ts +0 -3
- package/dist/fleet/fleetLedger.js +21 -36
- package/dist/fleet/fleetProjection.d.ts +2 -2
- package/dist/fleet/fleetProjection.js +10 -8
- package/dist/frameBinding.d.ts +8 -0
- package/dist/frameBinding.js +35 -0
- package/dist/gateFailureCodes.d.ts +2 -0
- package/dist/gateFailureCodes.js +15 -0
- package/dist/gateOutcome.d.ts +3 -1
- package/dist/gateOutcome.js +41 -8
- package/dist/gateVocabulary.d.ts +10 -4
- package/dist/gateVocabulary.js +107 -47
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +22 -3
- package/dist/generated/engineFactTables.js +51 -4
- package/dist/generated/engineNoticeTables.js +18 -3
- package/dist/generated/settingsSchemaFns.d.ts +6 -0
- package/dist/generated/settingsSchemaFns.js +57 -0
- package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
- package/dist/generated/settingsSchemaTables.d.ts +1 -0
- package/dist/generated/settingsSchemaTables.js +4 -0
- package/dist/generated/settingsSchemaTypes.d.ts +105 -0
- package/dist/generated/settingsSchemaTypes.js +1 -0
- package/dist/generated/toolNameTables.d.ts +1 -0
- package/dist/generated/toolNameTables.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +8 -2
- package/dist/hitl/allowRuleShadow.js +36 -29
- package/dist/hitl/approvalCardReading.d.ts +15 -0
- package/dist/hitl/approvalCardReading.js +154 -0
- package/dist/hitl/approvalCardReasons.d.ts +14 -0
- package/dist/hitl/approvalCardReasons.js +119 -0
- package/dist/hitl/approvalHolds.d.ts +50 -15
- package/dist/hitl/approvalHolds.js +177 -27
- package/dist/hitl/approvalResolution.d.ts +51 -26
- package/dist/hitl/approvalResolution.js +86 -122
- package/dist/hitl/approvalsFeed.js +6 -18
- package/dist/hitl/askClassPair.d.ts +2 -0
- package/dist/hitl/askClassPair.js +17 -0
- package/dist/hitl/askGateWire.d.ts +20 -2
- package/dist/hitl/askGateWire.js +50 -1
- package/dist/hitl/askParkRowRouting.d.ts +5 -0
- package/dist/hitl/askParkRowRouting.js +32 -1
- package/dist/hitl/askSettlementLine.d.ts +28 -0
- package/dist/hitl/askSettlementLine.js +99 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +3 -2
- package/dist/hitl/automaticAnswerVerdict.js +29 -13
- package/dist/hitl/crashConverged.d.ts +11 -20
- package/dist/hitl/crashConverged.js +56 -0
- package/dist/hitl/crashConvergedNotice.d.ts +6 -3
- package/dist/hitl/crashConvergedNotice.js +48 -24
- package/dist/hitl/decisionConflict.js +3 -10
- package/dist/hitl/decisionRefusal.d.ts +40 -1
- package/dist/hitl/decisionRefusal.js +199 -42
- package/dist/hitl/frameRouter.d.ts +5 -2
- package/dist/hitl/frameRouter.js +27 -24
- package/dist/hitl/gateLedger.d.ts +2 -0
- package/dist/hitl/gateLedger.js +50 -13
- package/dist/hitl/hitlBridge.d.ts +2 -2
- package/dist/hitl/hitlBridge.js +13 -10
- package/dist/hitl/livePendingAsk.d.ts +3 -3
- package/dist/hitl/livePendingAsk.js +7 -18
- package/dist/hitl/parkResolver.d.ts +2 -24
- package/dist/hitl/parkResolver.js +61 -97
- package/dist/hitl/persistedRulesWire.d.ts +25 -0
- package/dist/hitl/persistedRulesWire.js +104 -2
- package/dist/hitl/planReviewWire.d.ts +31 -13
- package/dist/hitl/planReviewWire.js +120 -78
- package/dist/hitl/refusedToolNameProse.d.ts +0 -1
- package/dist/hitl/refusedToolNameProse.js +0 -3
- package/dist/hitl/replayedApproval.d.ts +4 -3
- package/dist/hitl/replayedApproval.js +7 -4
- package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
- package/dist/hitl/sessionPolicyDeliverable.js +48 -7
- package/dist/hitl/sessionPolicyWire.d.ts +34 -21
- package/dist/hitl/sessionPolicyWire.js +179 -70
- package/dist/hitl/standingRows.d.ts +20 -2
- package/dist/hitl/standingRows.js +69 -8
- package/dist/hitl/suspendedReopen.d.ts +2 -1
- package/dist/hitl/suspendedReopen.js +7 -10
- package/dist/hitl/toolApprovalWire.d.ts +103 -156
- package/dist/hitl/toolApprovalWire.js +661 -411
- package/dist/hookMatcherVerdict.d.ts +6 -1
- package/dist/hookMatcherVerdict.js +14 -7
- package/dist/hooksWireCaps.d.ts +2 -2
- package/dist/hooksWireCaps.js +174 -81
- package/dist/host.d.ts +21 -0
- package/dist/hostTurnSettings.d.ts +71 -0
- package/dist/hostTurnSettings.js +291 -0
- package/dist/humanTurn.d.ts +14 -1
- package/dist/humanTurn.js +100 -12
- package/dist/humanTurnRead.d.ts +2 -0
- package/dist/humanTurnRead.js +22 -1
- package/dist/i18n/messages.en.d.ts +703 -0
- package/dist/i18n/messages.en.js +701 -0
- package/dist/i18n/messages.zh.d.ts +3 -0
- package/dist/i18n/messages.zh.js +837 -0
- package/dist/i18n/translate.d.ts +25 -0
- package/dist/i18n/translate.js +127 -0
- package/dist/index.d.ts +78 -29
- package/dist/index.js +54 -18
- package/dist/inheritEnvCapability.d.ts +32 -0
- package/dist/inheritEnvCapability.js +104 -0
- package/dist/inheritEnvWire.d.ts +3 -2
- package/dist/inheritEnvWire.js +12 -14
- package/dist/interactiveHalt.js +17 -6
- package/dist/liveModelCatalog.d.ts +3 -3
- package/dist/liveModelCatalog.js +15 -13
- package/dist/liveQuestionStore.d.ts +2 -21
- package/dist/mcpLiveness.d.ts +2 -1
- package/dist/mcpPanel.d.ts +10 -1
- package/dist/mcpPanel.js +40 -13
- package/dist/mcpProbeCapability.d.ts +2 -1
- package/dist/mcpProbeCapability.js +7 -11
- package/dist/mcpProbeWire.d.ts +9 -2
- package/dist/mcpProbeWire.js +6 -1
- package/dist/mcpWireCaps.d.ts +47 -2
- package/dist/mcpWireCaps.js +164 -16
- package/dist/memoryEntriesWire.d.ts +4 -9
- package/dist/memoryEntriesWire.js +5 -10
- package/dist/model/modelSupplyRules.d.ts +0 -2
- package/dist/model/modelSupplyRules.js +3 -12
- package/dist/model/modelsPolicy.d.ts +0 -5
- package/dist/model/modelsPolicy.js +6 -36
- package/dist/model/onboardJudgement.d.ts +93 -0
- package/dist/model/onboardJudgement.js +415 -0
- package/dist/model/subagentModelWord.d.ts +31 -0
- package/dist/model/subagentModelWord.js +261 -0
- package/dist/model/tierVocabulary.d.ts +2 -0
- package/dist/model/tierVocabulary.js +17 -5
- package/dist/modelCapabilityProbe.d.ts +64 -0
- package/dist/modelCapabilityProbe.js +600 -0
- package/dist/modelIdentityResolvability.d.ts +3 -0
- package/dist/modelIdentityResolvability.js +26 -17
- package/dist/notifications.d.ts +6 -0
- package/dist/notifications.js +71 -23
- package/dist/outputStyleSeatCapability.d.ts +0 -3
- package/dist/outputStyleSeatCapability.js +0 -3
- package/dist/ownKey.d.ts +22 -0
- package/dist/ownKey.js +94 -3
- package/dist/panelReduce.d.ts +21 -10
- package/dist/panelReduce.js +728 -550
- package/dist/panelStateHolder.d.ts +3 -7
- package/dist/panelStateHolder.js +14 -130
- package/dist/peerLaneCapability.d.ts +0 -4
- package/dist/peerLaneCapability.js +0 -6
- package/dist/permissionRuleIssue.js +2 -0
- package/dist/permissionRulesWriteCapability.d.ts +2 -5
- package/dist/permissionRulesWriteCapability.js +8 -12
- package/dist/permissionWireCaps.d.ts +2 -2
- package/dist/permissionWireCaps.js +2 -0
- package/dist/permissionsAllowGrantCapability.d.ts +0 -4
- package/dist/permissionsAllowGrantCapability.js +0 -6
- package/dist/permissionsDeclaration.d.ts +0 -11
- package/dist/permissionsDeclaration.js +60 -53
- package/dist/pluginHooksWire.d.ts +46 -3
- package/dist/pluginHooksWire.js +219 -16
- package/dist/preemptWire.d.ts +44 -0
- package/dist/preemptWire.js +83 -0
- package/dist/printModelStatus.d.ts +63 -0
- package/dist/printModelStatus.js +155 -0
- package/dist/printToolResultFrame.js +15 -4
- package/dist/replayBody.d.ts +3 -0
- package/dist/replayBody.js +14 -0
- package/dist/request/taskRequest.d.ts +11 -6
- package/dist/request/taskRequest.js +112 -19
- package/dist/resumeRefusalCopy.d.ts +13 -9
- package/dist/resumeRefusalCopy.js +81 -118
- package/dist/retryStatus.d.ts +45 -0
- package/dist/retryStatus.js +185 -1
- package/dist/rewindArchiveCapability.d.ts +0 -4
- package/dist/rewindArchiveCapability.js +2 -10
- package/dist/rewindArchiveReading.d.ts +0 -1
- package/dist/rewindArchiveReading.js +0 -3
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +4 -2
- package/dist/runReattachPolicy.d.ts +31 -0
- package/dist/runReattachPolicy.js +46 -0
- package/dist/runTerminal.d.ts +3 -6
- package/dist/runTerminal.js +8 -9
- package/dist/sandboxWire.d.ts +3 -1
- package/dist/sandboxWire.js +76 -27
- package/dist/scenarioRefusal.d.ts +9 -0
- package/dist/scenarioRefusal.js +111 -0
- package/dist/scenarioWire.js +1 -1
- package/dist/seam.d.ts +48 -2
- package/dist/seam.js +25 -4
- package/dist/seatContract.d.ts +311 -18
- package/dist/seatContract.js +824 -100
- package/dist/selfOrchestrationDenial.js +7 -19
- package/dist/sessionIdSegment.d.ts +6 -0
- package/dist/sessionIdSegment.js +24 -0
- package/dist/sessionMemoryStatus.js +6 -11
- package/dist/sessionPolicyCapability.d.ts +2 -5
- package/dist/sessionPolicyCapability.js +8 -12
- package/dist/sessionSyncFileHistoryCapability.d.ts +0 -3
- package/dist/sessionSyncFileHistoryCapability.js +0 -3
- package/dist/settingsHooksSalvage.d.ts +44 -0
- package/dist/settingsHooksSalvage.js +211 -0
- package/dist/skillToolListsCapability.d.ts +2 -4
- package/dist/skillToolListsCapability.js +8 -9
- package/dist/sqlEngineCapability.d.ts +0 -4
- package/dist/sqlEngineCapability.js +0 -6
- package/dist/sseIdleTriage.js +3 -2
- package/dist/steerPriorityCapability.d.ts +0 -3
- package/dist/steerPriorityCapability.js +0 -3
- package/dist/streamDrainingLegs.d.ts +4 -0
- package/dist/streamDrainingLegs.js +6 -1
- package/dist/subagent/engineCompactWire.d.ts +0 -1
- package/dist/subagent/engineCompactWire.js +7 -5
- package/dist/subagent/engineSubagentResume.js +15 -9
- package/dist/subagent/engineTaskHandleWire.js +4 -7
- package/dist/subagentContentStore.d.ts +3 -0
- package/dist/subagentContentStore.js +22 -10
- package/dist/submitReopen.d.ts +24 -0
- package/dist/submitReopen.js +75 -0
- package/dist/terminalStatuses.d.ts +3 -0
- package/dist/terminalStatuses.js +10 -2
- package/dist/toolHistoryMismatch.js +3 -2
- package/dist/toolResult.d.ts +10 -1
- package/dist/toolResult.js +34 -6
- package/dist/toolRoster.d.ts +3 -4
- package/dist/toolRoster.js +21 -22
- package/dist/turnFailurePresentation.d.ts +39 -0
- package/dist/turnFailurePresentation.js +402 -0
- package/dist/usageAnalytics.js +6 -11
- package/dist/userAttachmentEnvelope.d.ts +1 -0
- package/dist/userAttachmentEnvelope.js +37 -7
- package/dist/userAttachmentSeat.d.ts +21 -0
- package/dist/userAttachmentSeat.js +75 -0
- package/dist/userInvokedSkillsCapability.d.ts +11 -4
- package/dist/userInvokedSkillsCapability.js +31 -10
- package/dist/webSearchBackendCapability.d.ts +0 -4
- package/dist/webSearchBackendCapability.js +0 -6
- package/dist/wireErrorTriage.d.ts +7 -0
- package/dist/wireErrorTriage.js +26 -23
- package/dist/wireFailureShape.d.ts +62 -5
- package/dist/wireFailureShape.js +106 -5
- package/dist/wireRefusalCopy.d.ts +25 -3
- package/dist/wireRefusalCopy.js +74 -80
- package/dist/workflowsJournalCapability.d.ts +2 -5
- package/dist/workflowsJournalCapability.js +8 -12
- package/dist/writeProtectionCapability.d.ts +0 -4
- package/dist/writeProtectionCapability.js +0 -6
- package/docs/INTEGRATION-CLIENTS.md +1775 -56
- package/package.json +6 -5
- package/dist/attachmentSeatCapability.d.ts +0 -12
- package/dist/attachmentSeatCapability.js +0 -23
- package/dist/hitl/approvalOutcomeNote.d.ts +0 -10
- package/dist/hitl/approvalOutcomeNote.js +0 -29
- package/dist/sessionReadRedactionCapability.d.ts +0 -13
- package/dist/sessionReadRedactionCapability.js +0 -35
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { CONFIG_LEGACY_TOOL_NAME
|
|
1
|
+
import { CONFIG_LEGACY_TOOL_NAME } from '../engineErrorCodes.js';
|
|
2
2
|
import { rosterMountedNames } from '../rosterMountedNames.js';
|
|
3
3
|
import { ruleCompileVerdict } from '../ruleCompileVerdict.js';
|
|
4
|
+
import { readRuleEntry } from '../coreValuePorts.js';
|
|
5
|
+
import { readOwnDataValue } from '../ownKey.js';
|
|
4
6
|
import { ruleToolNameVerdictOf } from '../protocolSegment.js';
|
|
5
|
-
import { PREFIXES_IN_PROSE, REFUSED_NAME_CLASSES, REFUSED_NAME_FIX
|
|
7
|
+
import { PREFIXES_IN_PROSE, REFUSED_NAME_CLASSES, REFUSED_NAME_FIX } from './refusedToolNameProse.js';
|
|
6
8
|
import { CORE_PROTOCOL_PREFIXES } from '../generated/toolNameTables.js';
|
|
7
9
|
const COVERING_NAMESPACE_PREFIXES = CORE_PROTOCOL_PREFIXES;
|
|
8
10
|
const WITHHELD_NOTICE = {
|
|
@@ -90,8 +92,9 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
|
|
|
90
92
|
continue;
|
|
91
93
|
}
|
|
92
94
|
let why = withheldWhyOf(r);
|
|
95
|
+
const engineAsked = why === undefined;
|
|
93
96
|
let currentName;
|
|
94
|
-
if (
|
|
97
|
+
if (engineAsked) {
|
|
95
98
|
const verdict = ruleToolNameVerdictOf(r);
|
|
96
99
|
if (verdict.kind === 'unknown')
|
|
97
100
|
return unreadable();
|
|
@@ -103,6 +106,17 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
|
|
|
103
106
|
else if (verdict.kind === 'unmintable_segment')
|
|
104
107
|
why = 'not_a_tool_name';
|
|
105
108
|
}
|
|
109
|
+
let inertReason;
|
|
110
|
+
if (engineAsked) {
|
|
111
|
+
const reading = entryReadingOf(r);
|
|
112
|
+
if (reading === 'unknown')
|
|
113
|
+
return unreadable();
|
|
114
|
+
if (reading !== 'row') {
|
|
115
|
+
inertReason = reading.reason;
|
|
116
|
+
if (why === undefined)
|
|
117
|
+
why = reading.why;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
106
120
|
if (why === undefined) {
|
|
107
121
|
const grammar = ruleCompileVerdict(r, 'deny').kind;
|
|
108
122
|
if (grammar === 'unknown')
|
|
@@ -115,13 +129,42 @@ export function sessionPolicyDeliverable(behavior, rules, opts) {
|
|
|
115
129
|
if (why === undefined)
|
|
116
130
|
exact.push(r);
|
|
117
131
|
else {
|
|
118
|
-
withheld.push(
|
|
132
|
+
withheld.push({
|
|
133
|
+
rule: r,
|
|
134
|
+
why,
|
|
135
|
+
...(why === 'legacy_tool_name' && currentName !== undefined ? { currentName } : {}),
|
|
136
|
+
...(inertReason !== undefined ? { inertReason } : {}),
|
|
137
|
+
});
|
|
119
138
|
}
|
|
120
139
|
}
|
|
121
|
-
|
|
140
|
+
const blocking = withheld.some((w) => w.inertReason === undefined);
|
|
141
|
+
if (blocking || exact.length === 0)
|
|
122
142
|
return { deliverable: {}, withheld };
|
|
123
143
|
return { deliverable: { toolDeny: exact }, withheld };
|
|
124
144
|
}
|
|
145
|
+
function entryReadingOf(rule) {
|
|
146
|
+
try {
|
|
147
|
+
const reading = readRuleEntry(rule, 'deny');
|
|
148
|
+
if (typeof reading !== 'object' || reading === null)
|
|
149
|
+
return 'unknown';
|
|
150
|
+
const kind = readOwnDataValue(reading, 'kind');
|
|
151
|
+
if (kind === 'row') {
|
|
152
|
+
const compiled = readOwnDataValue(reading, 'compiled');
|
|
153
|
+
return typeof compiled === 'object' && compiled !== null ? 'row' : 'unknown';
|
|
154
|
+
}
|
|
155
|
+
if (kind !== 'inert')
|
|
156
|
+
return 'unknown';
|
|
157
|
+
const reason = readOwnDataValue(reading, 'reason');
|
|
158
|
+
if (reason === 'grammar' || reason === 'content_unsupported')
|
|
159
|
+
return { why: 'not_a_tool_name', reason };
|
|
160
|
+
if (reason === 'wildcard_all' || reason === 'namespace_wildcard')
|
|
161
|
+
return { why: 'wildcard', reason };
|
|
162
|
+
return 'unknown';
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return 'unknown';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
125
168
|
export function sessionPolicyWithheldNotice(why) {
|
|
126
169
|
return typeof why === 'string' && Object.hasOwn(WITHHELD_NOTICE, why)
|
|
127
170
|
? WITHHELD_NOTICE[why]
|
|
@@ -132,7 +175,5 @@ const LEGACY_TOOL_NAME_FAILURE_NOTE = `This run did not start: a tool rule appli
|
|
|
132
175
|
export function legacyToolNameFailureNoteOf(code) {
|
|
133
176
|
if (code === CONFIG_LEGACY_TOOL_NAME)
|
|
134
177
|
return LEGACY_TOOL_NAME_FAILURE_NOTE;
|
|
135
|
-
if (code === RULES_LEGACY_TOOL_NAME)
|
|
136
|
-
return RULES_LEGACY_TOOL_NAME_WRITE_NOTE;
|
|
137
178
|
return undefined;
|
|
138
179
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { SessionPermissionRules, StoredSessionRules } from '@sema-agent/sdk';
|
|
2
|
+
import type { UiLanguage } from '../env/uiLanguage.js';
|
|
2
3
|
import type { SessionPolicyReading } from '../sessionPolicyCapability.js';
|
|
3
4
|
import type { ToolRosterView } from '../toolRoster.js';
|
|
4
|
-
import { CORE_RULE_TOOL_NAME_VERDICTS } from '../generated/engineFactTables.js';
|
|
5
|
+
import { CORE_ALLOW_ENTRY_INERT_REASONS, CORE_RULE_TOOL_NAME_VERDICTS } from '../generated/engineFactTables.js';
|
|
5
6
|
export type LegacyToolNameVerdict = Exclude<(typeof CORE_RULE_TOOL_NAME_VERDICTS)[number], 'current'>;
|
|
7
|
+
export type SessionRuleInertReason = (typeof CORE_ALLOW_ENTRY_INERT_REASONS)[number];
|
|
6
8
|
export interface SessionPolicyFacade {
|
|
7
9
|
getPolicy(sessionId: string, opts?: {
|
|
8
10
|
signal?: AbortSignal;
|
|
@@ -41,10 +43,16 @@ export type SessionPolicyFailure = {
|
|
|
41
43
|
kind: 'request-rejected';
|
|
42
44
|
message: string;
|
|
43
45
|
} | {
|
|
44
|
-
kind: '
|
|
46
|
+
kind: 'earlier-grammar';
|
|
47
|
+
message: string;
|
|
48
|
+
field?: 'toolAllow';
|
|
49
|
+
entry?: string;
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'inert-entry';
|
|
45
52
|
message: string;
|
|
46
53
|
field?: SessionPolicyRemovedEntry['field'];
|
|
47
|
-
|
|
54
|
+
entry?: string;
|
|
55
|
+
reason?: SessionRuleInertReason;
|
|
48
56
|
verdict?: LegacyToolNameVerdict;
|
|
49
57
|
currentName?: string;
|
|
50
58
|
} | {
|
|
@@ -58,11 +66,12 @@ export type SessionPolicyFailure = {
|
|
|
58
66
|
message: string;
|
|
59
67
|
};
|
|
60
68
|
export declare function classifySessionPolicyFailure(e: unknown): SessionPolicyFailure;
|
|
61
|
-
export type SessionPolicyMalformedWhy = 'envelope' | 'rev' | 'rule_field';
|
|
69
|
+
export type SessionPolicyMalformedWhy = 'envelope' | 'rev' | 'rule_field' | 'grammar_stamp';
|
|
62
70
|
export type SessionPolicyReadOutcome = {
|
|
63
71
|
kind: 'present';
|
|
64
72
|
rev: number;
|
|
65
73
|
rules: SessionPermissionRules;
|
|
74
|
+
grammar?: number;
|
|
66
75
|
} | {
|
|
67
76
|
kind: 'malformed';
|
|
68
77
|
why: SessionPolicyMalformedWhy;
|
|
@@ -82,6 +91,11 @@ export interface SessionPolicyTightenRequest {
|
|
|
82
91
|
}
|
|
83
92
|
export type SessionPolicyTightenUnknownWhy = 'face_unavailable' | 'session_not_found' | 'session_ownerless' | 'unauthorized' | 'request_rejected' | 'store_corrupt' | 'read_unreadable' | 'read_failed' | 'write_refused' | 'write_indeterminate' | 'write_receipt_unreadable' | 'write_receipt_mismatch';
|
|
84
93
|
export declare const SESSION_POLICY_TIGHTEN_UNKNOWN_WHY: readonly SessionPolicyTightenUnknownWhy[];
|
|
94
|
+
export type SessionPolicyEarlierGrammarRefusal = {
|
|
95
|
+
kind: 'refused';
|
|
96
|
+
why: 'earlier_grammar_rows';
|
|
97
|
+
entries: readonly SessionPolicyRemovedEntry[];
|
|
98
|
+
};
|
|
85
99
|
export type SessionPolicyTightenOutcome = {
|
|
86
100
|
kind: 'written';
|
|
87
101
|
rev: number;
|
|
@@ -94,23 +108,27 @@ export type SessionPolicyTightenOutcome = {
|
|
|
94
108
|
} | {
|
|
95
109
|
kind: 'capability_absent';
|
|
96
110
|
why: 'not_reported' | 'absent';
|
|
97
|
-
} | {
|
|
98
|
-
kind: '
|
|
99
|
-
|
|
100
|
-
field?: SessionPolicyRemovedEntry['field'];
|
|
101
|
-
name?: string;
|
|
102
|
-
verdict?: LegacyToolNameVerdict;
|
|
103
|
-
currentName?: string;
|
|
111
|
+
} | SessionPolicyEarlierGrammarRefusal | ({
|
|
112
|
+
kind: 'inert_entry';
|
|
113
|
+
} & SessionPolicyInertEntryRefusal & {
|
|
104
114
|
alreadyInRecord?: boolean;
|
|
105
|
-
} | {
|
|
115
|
+
}) | {
|
|
106
116
|
kind: 'unknown';
|
|
107
117
|
why: SessionPolicyTightenUnknownWhy;
|
|
108
118
|
message?: string;
|
|
109
119
|
};
|
|
120
|
+
export interface SessionPolicyInertEntryRefusal {
|
|
121
|
+
message: string;
|
|
122
|
+
field?: SessionPolicyRemovedEntry['field'];
|
|
123
|
+
entry?: string;
|
|
124
|
+
reason?: SessionRuleInertReason;
|
|
125
|
+
verdict?: LegacyToolNameVerdict;
|
|
126
|
+
currentName?: string;
|
|
127
|
+
}
|
|
110
128
|
export declare function tightenSessionPolicy(facade: SessionPolicyFacade, req: SessionPolicyTightenRequest, opts?: {
|
|
111
129
|
signal?: AbortSignal;
|
|
112
130
|
}): Promise<SessionPolicyTightenOutcome>;
|
|
113
|
-
export declare function sessionPolicyTightenNotice(outcome: SessionPolicyTightenOutcome): string;
|
|
131
|
+
export declare function sessionPolicyTightenNotice(outcome: SessionPolicyTightenOutcome, lang?: UiLanguage): string;
|
|
114
132
|
export declare function sessionPolicyReadNotice(outcome: Exclude<SessionPolicyReadOutcome, {
|
|
115
133
|
kind: 'present';
|
|
116
134
|
}> | {
|
|
@@ -153,14 +171,9 @@ export type SessionPolicyRemovalOutcome = {
|
|
|
153
171
|
kind: 'write_unconfirmed';
|
|
154
172
|
why: Extract<SessionPolicyTightenUnknownWhy, 'write_indeterminate' | 'write_receipt_unreadable' | 'write_receipt_mismatch'>;
|
|
155
173
|
message?: string;
|
|
156
|
-
} | {
|
|
157
|
-
kind: '
|
|
158
|
-
|
|
159
|
-
field?: SessionPolicyRemovedEntry['field'];
|
|
160
|
-
name?: string;
|
|
161
|
-
verdict?: LegacyToolNameVerdict;
|
|
162
|
-
currentName?: string;
|
|
163
|
-
};
|
|
174
|
+
} | SessionPolicyEarlierGrammarRefusal | ({
|
|
175
|
+
kind: 'inert_entry';
|
|
176
|
+
} & SessionPolicyInertEntryRefusal);
|
|
164
177
|
export type SessionPolicyRosterRequiredWhy = 'absent' | 'unreadable';
|
|
165
178
|
export declare function removeRefusedSessionRules(facade: SessionPolicyFacade, sessionId: string, roster: ToolRosterView | undefined, opts?: {
|
|
166
179
|
signal?: AbortSignal;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { wireFailureShapeOf } from '../wireFailureShape.js';
|
|
2
2
|
import { hostLog } from '../host.js';
|
|
3
|
+
import { msg, renderMessage } from '../i18n/translate.js';
|
|
3
4
|
import { ruleToolNameVerdictOf } from '../protocolSegment.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { RULES_INERT_ENTRY, RULES_INVALID_SHAPE, isRulesRefusalCode } from '../engineErrorCodes.js';
|
|
6
|
+
import { deniedEntryToolName } from '../engineToolDirectory.js';
|
|
6
7
|
import { rosterMountedNames } from '../rosterMountedNames.js';
|
|
7
|
-
import { CORE_RULE_TOOL_NAME_VERDICTS } from '../generated/engineFactTables.js';
|
|
8
|
+
import { CORE_ALLOW_ENTRY_INERT_REASONS, CORE_RULE_TOOL_NAME_VERDICTS } from '../generated/engineFactTables.js';
|
|
9
|
+
const EARLIER_GRAMMAR_REASON = 'earlier_grammar';
|
|
10
|
+
const _inertReasonPin = true;
|
|
11
|
+
void _inertReasonPin;
|
|
12
|
+
function isSessionRuleInertReason(v) {
|
|
13
|
+
return typeof v === 'string' && CORE_ALLOW_ENTRY_INERT_REASONS.includes(v);
|
|
14
|
+
}
|
|
8
15
|
function isLegacyToolNameVerdict(v) {
|
|
9
16
|
return typeof v === 'string' && v !== 'current' && CORE_RULE_TOOL_NAME_VERDICTS.includes(v);
|
|
10
17
|
}
|
|
@@ -12,25 +19,43 @@ const RULE_FIELD_PRESENCE = {
|
|
|
12
19
|
toolAllow: true,
|
|
13
20
|
toolDeny: true,
|
|
14
21
|
allowDirs: true,
|
|
15
|
-
commandAllow: true,
|
|
16
|
-
commandDeny: true,
|
|
17
22
|
};
|
|
23
|
+
const RECORD_META_KEYS = Object.freeze(['rev', 'gen', 'grammar']);
|
|
24
|
+
const _metaKeysPin = true;
|
|
25
|
+
void _metaKeysPin;
|
|
18
26
|
export const SESSION_POLICY_RULE_FIELDS = Object.freeze(Object.keys(RULE_FIELD_PRESENCE));
|
|
27
|
+
function foreignRecordKeysOf(record) {
|
|
28
|
+
return Object.getOwnPropertyNames(record).filter((key) => !SESSION_POLICY_RULE_FIELDS.includes(key) && !RECORD_META_KEYS.includes(key));
|
|
29
|
+
}
|
|
30
|
+
function recordKeyLabel(key) {
|
|
31
|
+
return /^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(key) ? `"${key}"` : 'unnamed';
|
|
32
|
+
}
|
|
19
33
|
const MAX_RULE_ENTRIES = 10_000;
|
|
20
34
|
export function classifySessionPolicyFailure(e) {
|
|
21
|
-
const { status, errorCode, message, bodyField,
|
|
35
|
+
const { status, errorCode, message, bodyField, bodyVerdict, bodyCurrentName, bodyEntry, bodyReason } = wireFailureShapeOf(e);
|
|
22
36
|
if (errorCode === undefined || errorCode === '')
|
|
23
37
|
return { kind: 'no-verdict', message };
|
|
24
|
-
if (errorCode ===
|
|
38
|
+
if (errorCode === RULES_INERT_ENTRY && bodyReason === EARLIER_GRAMMAR_REASON && status !== undefined && status >= 400 && status < 500) {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'earlier-grammar',
|
|
41
|
+
message,
|
|
42
|
+
...(bodyField === 'toolAllow' ? { field: bodyField } : {}),
|
|
43
|
+
...(bodyEntry !== undefined && bodyEntry !== '' ? { entry: bodyEntry } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (errorCode === RULES_INERT_ENTRY && status !== undefined && status >= 400 && status < 500) {
|
|
25
47
|
return {
|
|
26
|
-
kind: '
|
|
48
|
+
kind: 'inert-entry',
|
|
27
49
|
message,
|
|
28
50
|
...(bodyField === 'toolDeny' || bodyField === 'toolAllow' ? { field: bodyField } : {}),
|
|
29
|
-
...(
|
|
51
|
+
...(bodyEntry !== undefined && bodyEntry !== '' ? { entry: bodyEntry } : {}),
|
|
52
|
+
...(isSessionRuleInertReason(bodyReason) ? { reason: bodyReason } : {}),
|
|
30
53
|
...(isLegacyToolNameVerdict(bodyVerdict) ? { verdict: bodyVerdict } : {}),
|
|
31
54
|
...(bodyCurrentName !== undefined && bodyCurrentName !== '' ? { currentName: bodyCurrentName } : {}),
|
|
32
55
|
};
|
|
33
56
|
}
|
|
57
|
+
if (errorCode === RULES_INVALID_SHAPE && status !== undefined && status >= 400 && status < 500)
|
|
58
|
+
return { kind: 'request-rejected', message };
|
|
34
59
|
if (isRulesRefusalCode(errorCode) && status !== undefined && status >= 400 && status < 500)
|
|
35
60
|
return { kind: 'error', message };
|
|
36
61
|
if (status === 501 || errorCode === 'capability.session_store_required') {
|
|
@@ -95,6 +120,21 @@ function narrowStoredRecord(body) {
|
|
|
95
120
|
if (typeof rev !== 'number' || !Number.isSafeInteger(rev) || rev < 0) {
|
|
96
121
|
return { ok: false, why: 'rev', detail: 'policy record carries no readable version stamp' };
|
|
97
122
|
}
|
|
123
|
+
let grammarSlot;
|
|
124
|
+
try {
|
|
125
|
+
grammarSlot = Object.getOwnPropertyDescriptor(envelope, 'grammar');
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return { ok: false, why: 'grammar_stamp', detail: 'policy record’s rule-grammar stamp could not be read' };
|
|
129
|
+
}
|
|
130
|
+
let grammar;
|
|
131
|
+
if (grammarSlot !== undefined) {
|
|
132
|
+
const v = Object.hasOwn(grammarSlot, 'value') ? grammarSlot.value : undefined;
|
|
133
|
+
if (typeof v !== 'number' || !Number.isSafeInteger(v) || v < 0) {
|
|
134
|
+
return { ok: false, why: 'grammar_stamp', detail: 'policy record carries a rule-grammar stamp that is not a whole number of 0 or more' };
|
|
135
|
+
}
|
|
136
|
+
grammar = v;
|
|
137
|
+
}
|
|
98
138
|
const rules = {};
|
|
99
139
|
for (const field of SESSION_POLICY_RULE_FIELDS) {
|
|
100
140
|
if (!Object.hasOwn(envelope, field))
|
|
@@ -107,7 +147,19 @@ function narrowStoredRecord(body) {
|
|
|
107
147
|
return { ok: false, why: 'rule_field', detail: read.detail };
|
|
108
148
|
rules[field] = read.list;
|
|
109
149
|
}
|
|
110
|
-
|
|
150
|
+
for (const key of foreignRecordKeysOf(envelope)) {
|
|
151
|
+
const slot = Object.getOwnPropertyDescriptor(envelope, key);
|
|
152
|
+
if (slot === undefined)
|
|
153
|
+
continue;
|
|
154
|
+
if (!Object.hasOwn(slot, 'value') || Array.isArray(slot.value)) {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
why: 'rule_field',
|
|
158
|
+
detail: `policy record carries a rule field this client does not read (${recordKeyLabel(key)}) — refusing to treat it as readable, since writing the record back would drop that field`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { ok: true, rev, rules, grammar };
|
|
111
163
|
}
|
|
112
164
|
export async function readSessionPolicy(facade, sessionId, opts) {
|
|
113
165
|
let body;
|
|
@@ -126,7 +178,7 @@ export async function readSessionPolicy(facade, sessionId, opts) {
|
|
|
126
178
|
}
|
|
127
179
|
if (!read.ok)
|
|
128
180
|
return { kind: 'malformed', why: read.why, detail: read.detail };
|
|
129
|
-
return { kind: 'present', rev: read.rev, rules: read.rules };
|
|
181
|
+
return { kind: 'present', rev: read.rev, rules: read.rules, ...(read.grammar !== undefined ? { grammar: read.grammar } : {}) };
|
|
130
182
|
}
|
|
131
183
|
export function tightenedSessionRules(prior, add) {
|
|
132
184
|
const p = narrowRulesInput(prior, 'prior');
|
|
@@ -159,6 +211,10 @@ function narrowRulesInput(raw, side) {
|
|
|
159
211
|
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
160
212
|
throw new TypeError(`tightenedSessionRules: "${side}" must be a rules record object`);
|
|
161
213
|
}
|
|
214
|
+
const foreign = foreignRecordKeysOf(raw);
|
|
215
|
+
if (foreign.length > 0) {
|
|
216
|
+
throw new TypeError(`tightenedSessionRules: "${side}" carries a key that is not a rule field (${recordKeyLabel(foreign[0] ?? '')}) — it would not be written, so the record is refused instead of written without it`);
|
|
217
|
+
}
|
|
162
218
|
const out = {};
|
|
163
219
|
for (const field of SESSION_POLICY_RULE_FIELDS) {
|
|
164
220
|
if (!Object.hasOwn(raw, field))
|
|
@@ -173,10 +229,13 @@ function narrowRulesInput(raw, side) {
|
|
|
173
229
|
}
|
|
174
230
|
return out;
|
|
175
231
|
}
|
|
176
|
-
function receiptMismatch(sent, receipt, sentRev, receiptRev) {
|
|
232
|
+
function receiptMismatch(sent, receipt, sentRev, receiptRev, sentGrammar, receiptGrammar) {
|
|
177
233
|
if (receiptRev <= sentRev) {
|
|
178
234
|
return `policy write receipt did not advance the version stamp (sent with ${sentRev}, receipt says ${receiptRev})`;
|
|
179
235
|
}
|
|
236
|
+
if (sentGrammar !== undefined && (receiptGrammar === undefined || receiptGrammar < sentGrammar)) {
|
|
237
|
+
return `policy write receipt does not carry the rule-grammar stamp that was sent (sent ${sentGrammar}, receipt ${receiptGrammar === undefined ? 'carries none' : `says ${receiptGrammar}`}) — the stored entries may now read differently`;
|
|
238
|
+
}
|
|
180
239
|
for (const field of SESSION_POLICY_RULE_FIELDS) {
|
|
181
240
|
const s = Object.hasOwn(sent, field) ? sent[field] : undefined;
|
|
182
241
|
if (s === undefined)
|
|
@@ -227,32 +286,66 @@ function unknownFrom(failure, leg) {
|
|
|
227
286
|
return { kind: 'unknown', why: leg === 'read' ? 'read_failed' : 'write_indeterminate', message };
|
|
228
287
|
case 'loosen-forbidden':
|
|
229
288
|
case 'cas-conflict':
|
|
230
|
-
case '
|
|
289
|
+
case 'earlier-grammar':
|
|
290
|
+
case 'inert-entry':
|
|
231
291
|
case 'error':
|
|
232
292
|
return { kind: 'unknown', why: leg === 'read' ? 'read_failed' : 'write_refused', message };
|
|
233
293
|
}
|
|
234
294
|
}
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
295
|
+
function alreadyInRecordOf(field, entry, prior, add) {
|
|
296
|
+
if (field === undefined || entry === undefined)
|
|
297
|
+
return undefined;
|
|
298
|
+
const inPrior = Object.hasOwn(prior, field) ? prior[field] : undefined;
|
|
299
|
+
const inAdd = Object.hasOwn(add, field) ? add[field] : undefined;
|
|
300
|
+
if (inPrior !== undefined && inPrior.includes(entry))
|
|
301
|
+
return true;
|
|
302
|
+
if (inAdd !== undefined && inAdd.includes(entry))
|
|
303
|
+
return false;
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
function inertEntryRefusalOf(failure) {
|
|
307
|
+
const { field, entry, reason, verdict, currentName } = failure;
|
|
246
308
|
return {
|
|
247
|
-
kind: 'legacy_tool_name',
|
|
248
309
|
message: failure.message,
|
|
249
310
|
...(field !== undefined ? { field } : {}),
|
|
250
|
-
...(
|
|
311
|
+
...(entry !== undefined ? { entry } : {}),
|
|
312
|
+
...(reason !== undefined ? { reason } : {}),
|
|
251
313
|
...(verdict !== undefined ? { verdict } : {}),
|
|
252
314
|
...(currentName !== undefined ? { currentName } : {}),
|
|
253
|
-
...(alreadyInRecord !== undefined ? { alreadyInRecord } : {}),
|
|
254
315
|
};
|
|
255
316
|
}
|
|
317
|
+
function earlierGrammarEntriesOf(prior, outgoing) {
|
|
318
|
+
const priorAllow = Object.hasOwn(prior, 'toolAllow') ? prior.toolAllow : undefined;
|
|
319
|
+
const outAllow = Object.hasOwn(outgoing, 'toolAllow') ? outgoing.toolAllow : undefined;
|
|
320
|
+
if (priorAllow === undefined || outAllow === undefined)
|
|
321
|
+
return [];
|
|
322
|
+
const carried = new Set(outAllow);
|
|
323
|
+
const seen = new Set();
|
|
324
|
+
const out = [];
|
|
325
|
+
for (const rule of priorAllow) {
|
|
326
|
+
if (seen.has(rule) || !carried.has(rule))
|
|
327
|
+
continue;
|
|
328
|
+
const name = deniedEntryToolName(rule);
|
|
329
|
+
if (name === undefined || name === rule)
|
|
330
|
+
continue;
|
|
331
|
+
seen.add(rule);
|
|
332
|
+
out.push({ field: 'toolAllow', rule });
|
|
333
|
+
}
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
function earlierGrammarOutcome(failure) {
|
|
337
|
+
return {
|
|
338
|
+
kind: 'refused',
|
|
339
|
+
why: 'earlier_grammar_rows',
|
|
340
|
+
entries: Object.hasOwn(failure, 'field') && Object.hasOwn(failure, 'entry') && failure.field !== undefined && failure.entry !== undefined ? [{ field: failure.field, rule: failure.entry }] : [],
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function rulesWithStamp(rules, grammar) {
|
|
344
|
+
return grammar === undefined ? rules : { ...rules, grammar };
|
|
345
|
+
}
|
|
346
|
+
function grammarStampOf(read) {
|
|
347
|
+
return Object.hasOwn(read, 'grammar') ? read.grammar : undefined;
|
|
348
|
+
}
|
|
256
349
|
async function attemptTighten(facade, req, opts) {
|
|
257
350
|
const read = await readSessionPolicy(facade, req.sessionId, opts);
|
|
258
351
|
if (read.kind === 'failed')
|
|
@@ -261,9 +354,15 @@ async function attemptTighten(facade, req, opts) {
|
|
|
261
354
|
return { done: { kind: 'unknown', why: 'read_unreadable', message: read.detail } };
|
|
262
355
|
}
|
|
263
356
|
const rules = tightenedSessionRules(read.rules, req.add);
|
|
357
|
+
const stamp = grammarStampOf(read);
|
|
358
|
+
if (stamp === undefined) {
|
|
359
|
+
const earlier = earlierGrammarEntriesOf(read.rules, rules);
|
|
360
|
+
if (earlier.length > 0)
|
|
361
|
+
return { done: { kind: 'refused', why: 'earlier_grammar_rows', entries: earlier } };
|
|
362
|
+
}
|
|
264
363
|
let receipt;
|
|
265
364
|
try {
|
|
266
|
-
receipt = await facade.putPolicy(req.sessionId, { rules, expectedRev: read.rev }, opts);
|
|
365
|
+
receipt = await facade.putPolicy(req.sessionId, { rules: rulesWithStamp(rules, stamp), expectedRev: read.rev }, opts);
|
|
267
366
|
}
|
|
268
367
|
catch (e) {
|
|
269
368
|
const failure = classifySessionPolicyFailure(e);
|
|
@@ -271,8 +370,12 @@ async function attemptTighten(facade, req, opts) {
|
|
|
271
370
|
return { done: { kind: 'loosen_forbidden', message: failure.message } };
|
|
272
371
|
if (failure.kind === 'cas-conflict')
|
|
273
372
|
return { retryAtRev: read.rev };
|
|
274
|
-
if (failure.kind === '
|
|
275
|
-
return { done:
|
|
373
|
+
if (failure.kind === 'earlier-grammar')
|
|
374
|
+
return { done: earlierGrammarOutcome(failure) };
|
|
375
|
+
if (failure.kind === 'inert-entry') {
|
|
376
|
+
const alreadyInRecord = alreadyInRecordOf(failure.field, failure.entry, read.rules, req.add);
|
|
377
|
+
return { done: { kind: 'inert_entry', ...inertEntryRefusalOf(failure), ...(alreadyInRecord !== undefined ? { alreadyInRecord } : {}) } };
|
|
378
|
+
}
|
|
276
379
|
return { done: unknownFrom(failure, 'write') };
|
|
277
380
|
}
|
|
278
381
|
let narrowed;
|
|
@@ -285,7 +388,7 @@ async function attemptTighten(facade, req, opts) {
|
|
|
285
388
|
if (!narrowed.ok) {
|
|
286
389
|
return { done: { kind: 'unknown', why: 'write_receipt_unreadable', message: narrowed.detail } };
|
|
287
390
|
}
|
|
288
|
-
const mismatch = receiptMismatch(rules, narrowed.rules, read.rev, narrowed.rev);
|
|
391
|
+
const mismatch = receiptMismatch(rules, narrowed.rules, read.rev, narrowed.rev, stamp, narrowed.grammar);
|
|
289
392
|
if (mismatch !== null)
|
|
290
393
|
return { done: { kind: 'unknown', why: 'write_receipt_mismatch', message: mismatch } };
|
|
291
394
|
return { done: { kind: 'written', rev: narrowed.rev } };
|
|
@@ -309,46 +412,48 @@ export async function tightenSessionPolicy(facade, req, opts) {
|
|
|
309
412
|
return second.done;
|
|
310
413
|
return { kind: 'conflict', rev: second.retryAtRev };
|
|
311
414
|
}
|
|
312
|
-
|
|
415
|
+
const earlierGrammarNote = (lang) => renderMessage(msg('rules.sessionPolicy.tighten.earlierGrammar'), lang);
|
|
416
|
+
export function sessionPolicyTightenNotice(outcome, lang) {
|
|
417
|
+
const say = (key, params) => renderMessage(msg(key, params), lang);
|
|
313
418
|
switch (outcome.kind) {
|
|
314
419
|
case 'written':
|
|
315
|
-
return
|
|
420
|
+
return say('rules.sessionPolicy.tighten.written', { rev: outcome.rev });
|
|
316
421
|
case 'conflict':
|
|
317
|
-
return '
|
|
422
|
+
return say('rules.sessionPolicy.tighten.conflict');
|
|
318
423
|
case 'loosen_forbidden':
|
|
319
|
-
return '
|
|
424
|
+
return say('rules.sessionPolicy.tighten.loosenForbidden');
|
|
320
425
|
case 'capability_absent':
|
|
321
|
-
return outcome.why === 'absent'
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
case '
|
|
325
|
-
return
|
|
426
|
+
return outcome.why === 'absent' ? say('rules.sessionPolicy.tighten.capabilityAbsent') : say('rules.sessionPolicy.tighten.capabilityNotReported');
|
|
427
|
+
case 'refused':
|
|
428
|
+
return earlierGrammarNote(lang);
|
|
429
|
+
case 'inert_entry':
|
|
430
|
+
return say('rules.sessionPolicy.tighten.inertEntry');
|
|
326
431
|
case 'unknown':
|
|
327
432
|
switch (outcome.why) {
|
|
328
433
|
case 'face_unavailable':
|
|
329
|
-
return '
|
|
434
|
+
return say('rules.sessionPolicy.tighten.unknown.faceUnavailable');
|
|
330
435
|
case 'session_not_found':
|
|
331
|
-
return '
|
|
436
|
+
return say('rules.sessionPolicy.tighten.unknown.sessionNotFound');
|
|
332
437
|
case 'session_ownerless':
|
|
333
|
-
return '
|
|
438
|
+
return say('rules.sessionPolicy.tighten.unknown.sessionOwnerless');
|
|
334
439
|
case 'unauthorized':
|
|
335
|
-
return '
|
|
440
|
+
return say('rules.sessionPolicy.tighten.unknown.unauthorized');
|
|
336
441
|
case 'request_rejected':
|
|
337
|
-
return '
|
|
442
|
+
return say('rules.sessionPolicy.tighten.unknown.requestRejected');
|
|
338
443
|
case 'store_corrupt':
|
|
339
|
-
return '
|
|
444
|
+
return say('rules.sessionPolicy.tighten.unknown.storeCorrupt');
|
|
340
445
|
case 'read_unreadable':
|
|
341
|
-
return '
|
|
446
|
+
return say('rules.sessionPolicy.tighten.unknown.readUnreadable');
|
|
342
447
|
case 'read_failed':
|
|
343
|
-
return '
|
|
448
|
+
return say('rules.sessionPolicy.tighten.unknown.readFailed');
|
|
344
449
|
case 'write_refused':
|
|
345
|
-
return '
|
|
450
|
+
return say('rules.sessionPolicy.tighten.unknown.writeRefused');
|
|
346
451
|
case 'write_indeterminate':
|
|
347
|
-
return '
|
|
452
|
+
return say('rules.sessionPolicy.tighten.unknown.writeIndeterminate');
|
|
348
453
|
case 'write_receipt_unreadable':
|
|
349
|
-
return '
|
|
454
|
+
return say('rules.sessionPolicy.tighten.unknown.writeReceiptUnreadable');
|
|
350
455
|
case 'write_receipt_mismatch':
|
|
351
|
-
return '
|
|
456
|
+
return say('rules.sessionPolicy.tighten.unknown.writeReceiptMismatch');
|
|
352
457
|
}
|
|
353
458
|
}
|
|
354
459
|
}
|
|
@@ -371,8 +476,10 @@ function readFailureSentence(kind) {
|
|
|
371
476
|
return 'This session is not readable from here — it may not exist, or it may belong to someone else (the engine answers both the same way, so this client cannot tell which) — so its rule record cannot be shown. Check that you are connected to the engine and the session you meant, or continue in a new session.';
|
|
372
477
|
case 'request-rejected':
|
|
373
478
|
return 'The engine rejected the request to read this session’s rule record as malformed, so it could not be read. Sending the same request again will not change that; check which session was asked for.';
|
|
374
|
-
case '
|
|
375
|
-
return 'The engine answered this read with a refusal
|
|
479
|
+
case 'earlier-grammar':
|
|
480
|
+
return 'The engine answered this read with a refusal that only applies to writing back rules saved under an earlier rule grammar, so this session’s rule record could not be read. Try again; if it keeps happening, whoever runs the engine needs to look at it.';
|
|
481
|
+
case 'inert-entry':
|
|
482
|
+
return 'The engine answered this read with a refusal that only applies to writing a rule entry it reads as matching nothing, so this session’s rule record could not be read. Try again; if it keeps happening, whoever runs the engine needs to look at it.';
|
|
376
483
|
case 'unauthorized':
|
|
377
484
|
return 'This call could not present a verifiable identity, so this session’s rule record could not be read.';
|
|
378
485
|
case 'error':
|
|
@@ -389,6 +496,8 @@ function readMalformedSentence(why) {
|
|
|
389
496
|
return 'The engine’s answer for this session’s rule record carried no usable version, so this version will not show it — a record it cannot place may still hold restrictions that are in effect. Try again.';
|
|
390
497
|
case 'rule_field':
|
|
391
498
|
return 'One of the lists in this session’s rule record came back in a form this version cannot read, so none of the record is shown rather than part of it — a partly shown record could leave out restrictions that are in effect.';
|
|
499
|
+
case 'grammar_stamp':
|
|
500
|
+
return 'The engine’s answer for this session’s rule record carried a rule-grammar mark this version cannot read, so it will not show the record — the same entry can mean different things in different grammars, so what it allows is not known. Try again; if it keeps happening, this version and the engine may be out of step.';
|
|
392
501
|
}
|
|
393
502
|
}
|
|
394
503
|
function ownRead(o, key) {
|
|
@@ -492,9 +601,15 @@ async function attemptRemoval(facade, sessionId, mounted, opts) {
|
|
|
492
601
|
const { next, removed } = judged;
|
|
493
602
|
if (removed.length === 0)
|
|
494
603
|
return { done: { kind: 'nothing_to_remove', rev: read.rev } };
|
|
604
|
+
const stamp = grammarStampOf(read);
|
|
605
|
+
if (stamp === undefined) {
|
|
606
|
+
const earlier = earlierGrammarEntriesOf(read.rules, next);
|
|
607
|
+
if (earlier.length > 0)
|
|
608
|
+
return { done: { kind: 'refused', why: 'earlier_grammar_rows', entries: earlier } };
|
|
609
|
+
}
|
|
495
610
|
let receipt;
|
|
496
611
|
try {
|
|
497
|
-
receipt = await facade.putPolicy(sessionId, { rules: next, expectedRev: read.rev }, opts);
|
|
612
|
+
receipt = await facade.putPolicy(sessionId, { rules: rulesWithStamp(next, stamp), expectedRev: read.rev }, opts);
|
|
498
613
|
}
|
|
499
614
|
catch (e) {
|
|
500
615
|
const failure = classifySessionPolicyFailure(e);
|
|
@@ -502,18 +617,10 @@ async function attemptRemoval(facade, sessionId, mounted, opts) {
|
|
|
502
617
|
return { done: { kind: 'loosen_forbidden', message: failure.message, refused: removed } };
|
|
503
618
|
if (failure.kind === 'cas-conflict')
|
|
504
619
|
return { retryAtRev: read.rev };
|
|
505
|
-
if (failure.kind === '
|
|
506
|
-
return {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
message: failure.message,
|
|
510
|
-
...(failure.field !== undefined ? { field: failure.field } : {}),
|
|
511
|
-
...(failure.name !== undefined ? { name: failure.name } : {}),
|
|
512
|
-
...(failure.verdict !== undefined ? { verdict: failure.verdict } : {}),
|
|
513
|
-
...(failure.currentName !== undefined ? { currentName: failure.currentName } : {}),
|
|
514
|
-
},
|
|
515
|
-
};
|
|
516
|
-
}
|
|
620
|
+
if (failure.kind === 'earlier-grammar')
|
|
621
|
+
return { done: earlierGrammarOutcome(failure) };
|
|
622
|
+
if (failure.kind === 'inert-entry')
|
|
623
|
+
return { done: { kind: 'inert_entry', ...inertEntryRefusalOf(failure) } };
|
|
517
624
|
return { done: removalFailed(failure, 'write') };
|
|
518
625
|
}
|
|
519
626
|
let narrowed;
|
|
@@ -525,7 +632,7 @@ async function attemptRemoval(facade, sessionId, mounted, opts) {
|
|
|
525
632
|
}
|
|
526
633
|
if (!narrowed.ok)
|
|
527
634
|
return { done: { kind: 'write_unconfirmed', why: 'write_receipt_unreadable', message: narrowed.detail } };
|
|
528
|
-
const mismatch = receiptMismatch(next, narrowed.rules, read.rev, narrowed.rev) ??
|
|
635
|
+
const mismatch = receiptMismatch(next, narrowed.rules, read.rev, narrowed.rev, stamp, narrowed.grammar) ??
|
|
529
636
|
(removed.some((e) => {
|
|
530
637
|
const r = Object.hasOwn(narrowed.rules, e.field) ? narrowed.rules[e.field] : undefined;
|
|
531
638
|
return r !== undefined && r.includes(e.rule);
|
|
@@ -609,8 +716,10 @@ export function sessionPolicyRemovalNotice(outcome) {
|
|
|
609
716
|
}
|
|
610
717
|
case 'write_unconfirmed':
|
|
611
718
|
return 'The removal was sent but no clear answer came back from the engine — it may already be in effect. Run the removal again: it re-reads the record, and reports nothing left to remove if it did take effect.';
|
|
612
|
-
case '
|
|
613
|
-
return
|
|
719
|
+
case 'refused':
|
|
720
|
+
return earlierGrammarNote();
|
|
721
|
+
case 'inert_entry':
|
|
722
|
+
return 'Nothing was changed: the engine refused to write this session’s rule record back, because an entry this removal keeps reads as matching nothing (the engine’s own error text names the entry and why). This removal only takes out names the engine refuses to start a run with, so it leaves that entry for a person to correct or remove; while the record holds it, it cannot be written, so the entries this removal meant to take out stay in it as well.';
|
|
614
723
|
default:
|
|
615
724
|
return generic;
|
|
616
725
|
}
|