@sema-agent/client-core 0.111.0 → 0.112.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 +75 -0
- package/README.md +15 -6
- package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
- package/dist/checkpointRowVerdict.d.ts +3 -0
- package/dist/checkpointRowVerdict.js +14 -1
- package/dist/consoleCaPin.d.ts +136 -0
- package/dist/consoleCaPin.js +827 -0
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/deviceRebind.js +3 -3
- package/dist/effectiveFacts.d.ts +9 -0
- package/dist/effectiveFacts.js +33 -0
- package/dist/engineAddress.d.ts +1 -0
- package/dist/engineAddress.js +4 -1
- package/dist/engineCredentialRelease.d.ts +54 -0
- package/dist/engineCredentialRelease.js +146 -0
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +1 -0
- package/dist/engineHealthFacts.d.ts +0 -11
- package/dist/engineHealthFacts.js +0 -21
- package/dist/engineHealthProbeVerdict.d.ts +1 -0
- package/dist/engineHealthProbeVerdict.js +21 -13
- package/dist/engineUnavailable.d.ts +3 -2
- package/dist/engineUnavailable.js +16 -12
- package/dist/engineUrl.js +4 -2
- package/dist/gateFailureCodes.js +2 -2
- package/dist/generated/sdkFactTables.d.ts +1 -0
- package/dist/generated/sdkFactTables.js +13 -0
- package/dist/generated/settingsSchemaFns.d.ts +1 -0
- package/dist/generated/settingsSchemaFns.js +3 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +38 -9
- package/dist/generated/settingsSchemaTables.d.ts +52 -0
- package/dist/generated/settingsSchemaTables.js +18 -0
- package/dist/generated/settingsSchemaTypes.d.ts +23 -13
- package/dist/generated/settingsSchemaUrlShape.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlShape.js +17 -0
- package/dist/hitl/decisionRefusal.d.ts +4 -0
- package/dist/hitl/decisionRefusal.js +12 -2
- package/dist/hitl/localAllowRedemption.d.ts +9 -6
- package/dist/hitl/localAllowRedemption.js +20 -0
- package/dist/hitl/parkOwnership.js +2 -1
- package/dist/hitl/parkResolver.js +7 -0
- package/dist/hitl/screenDecisionCards.js +3 -2
- package/dist/hitl/sessionPolicyWire.js +2 -2
- package/dist/hitl/standingRows.d.ts +4 -2
- package/dist/hitl/standingRows.js +10 -3
- package/dist/hooksReaderGenerations.js +1 -1
- package/dist/i18n/messages.en.d.ts +163 -0
- package/dist/i18n/messages.en.js +163 -0
- package/dist/i18n/messages.zh.js +174 -0
- package/dist/index.d.ts +30 -5
- package/dist/index.js +15 -2
- package/dist/liveModelCatalog.d.ts +4 -0
- package/dist/liveModelCatalog.js +10 -1
- package/dist/localConfig/documents.d.ts +61 -0
- package/dist/localConfig/documents.js +51 -0
- package/dist/localConfig/kernel.d.ts +149 -0
- package/dist/localConfig/kernel.js +597 -0
- package/dist/localConfig/mcp/edit.d.ts +161 -0
- package/dist/localConfig/mcp/edit.js +846 -0
- package/dist/localConfig/mcp/servers.d.ts +165 -0
- package/dist/localConfig/mcp/servers.js +776 -0
- package/dist/localConfig/mcp/views.d.ts +170 -0
- package/dist/localConfig/mcp/views.js +429 -0
- package/dist/localConfig/modelPool.d.ts +262 -0
- package/dist/localConfig/modelPool.js +1489 -0
- package/dist/localConfig/modelPoolWords.d.ts +13 -0
- package/dist/localConfig/modelPoolWords.js +20 -0
- package/dist/localConfig/receiptShape.d.ts +7 -0
- package/dist/localConfig/receiptShape.js +135 -0
- package/dist/localConfig/settingsWrite.d.ts +127 -0
- package/dist/localConfig/settingsWrite.js +237 -0
- package/dist/localConfig/skills.d.ts +124 -0
- package/dist/localConfig/skills.js +397 -0
- package/dist/localConfig/skillsWords.d.ts +10 -0
- package/dist/localConfig/skillsWords.js +5 -0
- package/dist/mcpProbeWire.js +2 -1
- package/dist/mcpWireCaps.js +1 -1
- package/dist/memoryVerbsWire.js +3 -2
- package/dist/model/onboardJudgement.d.ts +14 -4
- package/dist/model/onboardJudgement.js +91 -139
- package/dist/modelConfigGapNotice.d.ts +20 -0
- package/dist/modelConfigGapNotice.js +102 -0
- package/dist/modsKernelIdentity.js +2 -47
- package/dist/ownKey.d.ts +1 -0
- package/dist/ownKey.js +40 -8
- package/dist/permissionsDeclaration.d.ts +2 -1
- package/dist/permissionsDeclaration.js +31 -17
- package/dist/promptBlockedCopy.js +2 -2
- package/dist/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +12 -4
- package/dist/runLedgerSnapshot.js +3 -3
- package/dist/runPermissionModeSwitch.js +2 -3
- package/dist/seatContract.d.ts +154 -4
- package/dist/seatContract.js +228 -2
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +4 -1
- package/dist/sessionMemoryErase.js +2 -1
- package/dist/sha256Bytes.d.ts +1 -0
- package/dist/sha256Bytes.js +46 -0
- package/dist/skillOverrideChain.d.ts +83 -0
- package/dist/skillOverrideChain.js +378 -0
- package/dist/skillsWireCaps.d.ts +3 -0
- package/dist/skillsWireCaps.js +16 -1
- package/dist/turnFailurePresentation.js +4 -10
- package/docs/INTEGRATION-CLIENTS.md +614 -14
- package/package.json +3 -3
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
|
|
2
2
|
const HOOK_GUARD_EVENTS = ["PreToolUse", "PermissionRequest"];
|
|
3
3
|
const HOOK_SHELLS = ["bash", "powershell"];
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
command: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
const HOOK_ON_FAILURE_ACCEPTED = { continue: true, block: true };
|
|
5
|
+
const HOOK_ENTRY_FIELDS_READ = {
|
|
6
|
+
command: {
|
|
7
|
+
command: "text",
|
|
8
|
+
args: "argv?",
|
|
9
|
+
shell: "shell?",
|
|
10
|
+
async: "boolean?",
|
|
11
|
+
asyncRewake: "boolean?",
|
|
12
|
+
onFailure: "onFailure?",
|
|
13
|
+
if: "string?",
|
|
14
|
+
timeout: "seconds?",
|
|
15
|
+
statusMessage: "string?",
|
|
16
|
+
once: "boolean?",
|
|
17
|
+
rewakeMessage: "nonEmpty?",
|
|
18
|
+
rewakeSummary: "nonEmpty?",
|
|
19
|
+
cloud: "any?",
|
|
20
|
+
},
|
|
21
|
+
prompt: { prompt: "text", model: "string?", if: "string?", timeout: "seconds?", statusMessage: "string?", once: "boolean?", continueOnBlock: "boolean?" },
|
|
22
|
+
agent: { prompt: "text", model: "string?", if: "string?", timeout: "seconds?", statusMessage: "string?", once: "boolean?" },
|
|
23
|
+
http: { url: "text", headers: "stringRecord?", allowedEnvVars: "stringList?", onFailure: "onFailure?", if: "string?", timeout: "seconds?", statusMessage: "string?", once: "boolean?", cloud: "any?" },
|
|
24
|
+
mcp_tool: { server: "string", tool: "string", input: "record?", if: "string?", timeout: "seconds?", statusMessage: "string?", once: "boolean?" },
|
|
11
25
|
};
|
|
12
26
|
function hookShapeOf(v) {
|
|
13
27
|
try {
|
|
@@ -146,6 +160,8 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
|
|
|
146
160
|
switch (base) {
|
|
147
161
|
case "text":
|
|
148
162
|
return typeof value === "string" && value.length > 0 && !value.includes("\0");
|
|
163
|
+
case "nonEmpty":
|
|
164
|
+
return typeof value === "string" && value.length > 0;
|
|
149
165
|
case "string":
|
|
150
166
|
return typeof value === "string";
|
|
151
167
|
case "shell":
|
|
@@ -163,6 +179,19 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
|
|
|
163
179
|
if (typeof value[i] !== "string")
|
|
164
180
|
return false;
|
|
165
181
|
return true;
|
|
182
|
+
case "argv":
|
|
183
|
+
if (!hookIsArray(value))
|
|
184
|
+
return false;
|
|
185
|
+
for (let i = 0; i < value.length; i++) {
|
|
186
|
+
const arg = value[i];
|
|
187
|
+
if (typeof arg !== "string" || arg.includes("\0"))
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return true;
|
|
191
|
+
case "onFailure":
|
|
192
|
+
return typeof value === "string" && Object.hasOwn(HOOK_ON_FAILURE_ACCEPTED, value);
|
|
193
|
+
case "any":
|
|
194
|
+
return true;
|
|
166
195
|
case "record":
|
|
167
196
|
return hookIsRecord(value);
|
|
168
197
|
default: {
|
|
@@ -175,9 +204,9 @@ export const SETTINGS_CLASSIFY_HOOKS_CONFIG_CLOSURE = (HOOK_EVENTS) => {
|
|
|
175
204
|
if (!hookIsRecord(entry))
|
|
176
205
|
return {};
|
|
177
206
|
const type = Object.hasOwn(entry, "type") ? entry.type : undefined;
|
|
178
|
-
if (typeof type !== "string" || !Object.hasOwn(
|
|
207
|
+
if (typeof type !== "string" || !Object.hasOwn(HOOK_ENTRY_FIELDS_READ, type))
|
|
179
208
|
return { field: "type" };
|
|
180
|
-
const fields =
|
|
209
|
+
const fields = HOOK_ENTRY_FIELDS_READ[type];
|
|
181
210
|
const out = { type };
|
|
182
211
|
for (const field of Object.keys(fields)) {
|
|
183
212
|
const kind = fields[field];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const SETTINGS_ENGINE_OWNED_HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure", "PostToolBatch", "PreCompact", "PostCompact", "Stop", "StopFailure", "UserPromptSubmit"];
|
|
2
2
|
export declare const SETTINGS_SECRET_LITERAL_RE: RegExp;
|
|
3
3
|
export declare const SETTINGS_PRIVATE_KEY_PEM_HEADER: RegExp;
|
|
4
|
+
export declare const SETTINGS_SHA256_DIGEST_RE: RegExp;
|
|
4
5
|
export declare const SETTINGS_DEVICE_CODE_TTL_SECONDS = 900;
|
|
5
6
|
export declare const SETTINGS_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
6
7
|
export declare const SETTINGS_TIER_GROUP_NAME_RE: RegExp;
|
|
@@ -19,3 +20,54 @@ export declare const SETTINGS_WEB_ADMIN_TOKEN_ENV: Readonly<{
|
|
|
19
20
|
readonly tokenFile: "SEMA_WEB_ADMIN_TOKEN_FILE";
|
|
20
21
|
}>;
|
|
21
22
|
export declare const SETTINGS_NO_EXECUTION_TARGET_LANES: readonly ["none"];
|
|
23
|
+
export declare const SETTINGS_ROOT_DOCUMENT_UNREADABLE_REASONS: readonly ["bad_json", "bad_shape", "io"];
|
|
24
|
+
export declare const SETTINGS_UNIT_PLACES: Readonly<{
|
|
25
|
+
permissions: Readonly<{
|
|
26
|
+
path: readonly ["permissions"];
|
|
27
|
+
category: "permissions";
|
|
28
|
+
}>;
|
|
29
|
+
permissionMode: Readonly<{
|
|
30
|
+
path: readonly ["permissions", "defaultMode"];
|
|
31
|
+
category: "permissionMode";
|
|
32
|
+
reading: "permissionMode";
|
|
33
|
+
}>;
|
|
34
|
+
additionalDirectories: Readonly<{
|
|
35
|
+
path: readonly ["permissions", "additionalDirectories"];
|
|
36
|
+
category: "sandboxNetwork";
|
|
37
|
+
reading: "stringList";
|
|
38
|
+
}>;
|
|
39
|
+
sandbox: Readonly<{
|
|
40
|
+
path: readonly ["sandbox"];
|
|
41
|
+
category: "sandboxNetwork";
|
|
42
|
+
}>;
|
|
43
|
+
disableBypassPermissionsMode: Readonly<{
|
|
44
|
+
path: readonly ["permissions", "disableBypassPermissionsMode"];
|
|
45
|
+
category: "killSwitches";
|
|
46
|
+
reading: "killSwitch";
|
|
47
|
+
}>;
|
|
48
|
+
disableAutoMode: Readonly<{
|
|
49
|
+
path: readonly ["permissions", "disableAutoMode"];
|
|
50
|
+
category: "killSwitches";
|
|
51
|
+
reading: "killSwitch";
|
|
52
|
+
}>;
|
|
53
|
+
hooks: Readonly<{
|
|
54
|
+
path: readonly ["hooks"];
|
|
55
|
+
category: "hooks";
|
|
56
|
+
reading: "hooks";
|
|
57
|
+
}>;
|
|
58
|
+
env: Readonly<{
|
|
59
|
+
path: readonly ["env"];
|
|
60
|
+
category: "env";
|
|
61
|
+
reading: "envMap";
|
|
62
|
+
}>;
|
|
63
|
+
model: Readonly<{
|
|
64
|
+
path: readonly ["model"];
|
|
65
|
+
category: "model";
|
|
66
|
+
reading: "nonEmptyString";
|
|
67
|
+
}>;
|
|
68
|
+
outputStyle: Readonly<{
|
|
69
|
+
path: readonly ["outputStyle"];
|
|
70
|
+
category: "ui";
|
|
71
|
+
reading: "nonEmptyString";
|
|
72
|
+
}>;
|
|
73
|
+
}>;
|
|
@@ -11,6 +11,7 @@ export const SETTINGS_ENGINE_OWNED_HOOK_EVENTS = Object.freeze([
|
|
|
11
11
|
]);
|
|
12
12
|
export const SETTINGS_SECRET_LITERAL_RE = Object.freeze(/^(sk-|gh[opus]_|github_pat_|xox[baprse]-|xapp-|bearer\s|basic\s|eyJ[A-Za-z0-9_-]{10,}\.|AKIA[0-9A-Z]{12,}|AIza[0-9A-Za-z_-]{20,}|-----BEGIN[A-Z0-9 ]*PRIVATE KEY)/i);
|
|
13
13
|
export const SETTINGS_PRIVATE_KEY_PEM_HEADER = Object.freeze(/-----BEGIN[A-Z0-9 ]*PRIVATE KEY/i);
|
|
14
|
+
export const SETTINGS_SHA256_DIGEST_RE = Object.freeze(/^sha256:[0-9a-f]{64}$/);
|
|
14
15
|
export const SETTINGS_DEVICE_CODE_TTL_SECONDS = 900;
|
|
15
16
|
export const SETTINGS_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
16
17
|
export const SETTINGS_TIER_GROUP_NAME_RE = Object.freeze(/^[a-z0-9][a-z0-9._-]*$/i);
|
|
@@ -74,3 +75,20 @@ export const SETTINGS_WEB_ADMIN_TOKEN_ENV = Object.freeze({ token: "SEMA_WEB_ADM
|
|
|
74
75
|
export const SETTINGS_NO_EXECUTION_TARGET_LANES = Object.freeze([
|
|
75
76
|
"none",
|
|
76
77
|
]);
|
|
78
|
+
export const SETTINGS_ROOT_DOCUMENT_UNREADABLE_REASONS = Object.freeze([
|
|
79
|
+
"bad_json",
|
|
80
|
+
"bad_shape",
|
|
81
|
+
"io",
|
|
82
|
+
]);
|
|
83
|
+
export const SETTINGS_UNIT_PLACES = Object.freeze({
|
|
84
|
+
"permissions": Object.freeze({ path: Object.freeze(["permissions"]), category: "permissions" }),
|
|
85
|
+
"permissionMode": Object.freeze({ path: Object.freeze(["permissions", "defaultMode"]), category: "permissionMode", reading: "permissionMode" }),
|
|
86
|
+
"additionalDirectories": Object.freeze({ path: Object.freeze(["permissions", "additionalDirectories"]), category: "sandboxNetwork", reading: "stringList" }),
|
|
87
|
+
"sandbox": Object.freeze({ path: Object.freeze(["sandbox"]), category: "sandboxNetwork" }),
|
|
88
|
+
"disableBypassPermissionsMode": Object.freeze({ path: Object.freeze(["permissions", "disableBypassPermissionsMode"]), category: "killSwitches", reading: "killSwitch" }),
|
|
89
|
+
"disableAutoMode": Object.freeze({ path: Object.freeze(["permissions", "disableAutoMode"]), category: "killSwitches", reading: "killSwitch" }),
|
|
90
|
+
"hooks": Object.freeze({ path: Object.freeze(["hooks"]), category: "hooks", reading: "hooks" }),
|
|
91
|
+
"env": Object.freeze({ path: Object.freeze(["env"]), category: "env", reading: "envMap" }),
|
|
92
|
+
"model": Object.freeze({ path: Object.freeze(["model"]), category: "model", reading: "nonEmptyString" }),
|
|
93
|
+
"outputStyle": Object.freeze({ path: Object.freeze(["outputStyle"]), category: "ui", reading: "nonEmptyString" }),
|
|
94
|
+
});
|
|
@@ -3,35 +3,44 @@ declare const HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFa
|
|
|
3
3
|
type HookEventWord = (typeof HOOK_EVENTS)[number];
|
|
4
4
|
declare const HOOK_ENTRY_TYPES: readonly ["command", "prompt", "agent", "http", "mcp_tool"];
|
|
5
5
|
export type HookEntryType = (typeof HOOK_ENTRY_TYPES)[number];
|
|
6
|
+
declare const HOOK_ON_FAILURE_WORDS: readonly ["continue", "block"];
|
|
7
|
+
export type HookOnFailure = (typeof HOOK_ON_FAILURE_WORDS)[number];
|
|
6
8
|
declare const HOOK_SHELLS: readonly ["bash", "powershell"];
|
|
7
|
-
declare const HOOK_ENTRY_FIELDS: {
|
|
8
|
-
|
|
9
|
+
declare const HOOK_ENTRY_FIELDS: Readonly<{
|
|
10
|
+
command: Readonly<{
|
|
11
|
+
readonly rewakeMessage: "nonEmpty?";
|
|
12
|
+
readonly rewakeSummary: "nonEmpty?";
|
|
13
|
+
readonly cloud: "any?";
|
|
9
14
|
readonly if: "string?";
|
|
10
15
|
readonly timeout: "seconds?";
|
|
11
16
|
readonly statusMessage: "string?";
|
|
12
17
|
readonly once: "boolean?";
|
|
13
18
|
readonly command: "text";
|
|
19
|
+
readonly args: "argv?";
|
|
14
20
|
readonly shell: "shell?";
|
|
15
21
|
readonly async: "boolean?";
|
|
16
22
|
readonly asyncRewake: "boolean?";
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
readonly onFailure: "onFailure?";
|
|
24
|
+
}>;
|
|
25
|
+
prompt: Readonly<{
|
|
26
|
+
readonly continueOnBlock: "boolean?";
|
|
19
27
|
readonly if: "string?";
|
|
20
28
|
readonly timeout: "seconds?";
|
|
21
29
|
readonly statusMessage: "string?";
|
|
22
30
|
readonly once: "boolean?";
|
|
23
31
|
readonly prompt: "text";
|
|
24
32
|
readonly model: "string?";
|
|
25
|
-
}
|
|
26
|
-
|
|
33
|
+
}>;
|
|
34
|
+
agent: Readonly<{
|
|
27
35
|
readonly if: "string?";
|
|
28
36
|
readonly timeout: "seconds?";
|
|
29
37
|
readonly statusMessage: "string?";
|
|
30
38
|
readonly once: "boolean?";
|
|
31
39
|
readonly prompt: "text";
|
|
32
40
|
readonly model: "string?";
|
|
33
|
-
}
|
|
34
|
-
|
|
41
|
+
}>;
|
|
42
|
+
http: Readonly<{
|
|
43
|
+
readonly cloud: "any?";
|
|
35
44
|
readonly if: "string?";
|
|
36
45
|
readonly timeout: "seconds?";
|
|
37
46
|
readonly statusMessage: "string?";
|
|
@@ -39,8 +48,9 @@ declare const HOOK_ENTRY_FIELDS: {
|
|
|
39
48
|
readonly url: "text";
|
|
40
49
|
readonly headers: "stringRecord?";
|
|
41
50
|
readonly allowedEnvVars: "stringList?";
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
readonly onFailure: "onFailure?";
|
|
52
|
+
}>;
|
|
53
|
+
mcp_tool: Readonly<{
|
|
44
54
|
readonly if: "string?";
|
|
45
55
|
readonly timeout: "seconds?";
|
|
46
56
|
readonly statusMessage: "string?";
|
|
@@ -48,9 +58,9 @@ declare const HOOK_ENTRY_FIELDS: {
|
|
|
48
58
|
readonly server: "string";
|
|
49
59
|
readonly tool: "string";
|
|
50
60
|
readonly input: "record?";
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
type HookFieldBaseValue<B> = B extends "text" | "string" ? string : B extends "shell" ? (typeof HOOK_SHELLS)[number] : B extends "boolean" ? boolean : B extends "seconds" ? number : B extends "stringRecord" ? Record<string, string> : B extends "stringList" ? string[] : B extends "record" ? Record<string, unknown> : never;
|
|
61
|
+
}>;
|
|
62
|
+
}>;
|
|
63
|
+
type HookFieldBaseValue<B> = B extends "text" | "nonEmpty" | "string" ? string : B extends "shell" ? (typeof HOOK_SHELLS)[number] : B extends "onFailure" ? HookOnFailure : B extends "any" ? unknown : B extends "boolean" ? boolean : B extends "seconds" ? number : B extends "stringRecord" ? Record<string, string> : B extends "stringList" | "argv" ? string[] : B extends "record" ? Record<string, unknown> : never;
|
|
54
64
|
type HookFieldValue<K> = K extends `${infer B}?` ? HookFieldBaseValue<B> : HookFieldBaseValue<K>;
|
|
55
65
|
type Flat<O> = {
|
|
56
66
|
[K in keyof O]: O[K];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_URL_SHAPE_CLOSURE: (isHierarchicalUrl: (raw: string) => boolean) => any;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const SETTINGS_URL_SHAPE_CLOSURE = (isHierarchicalUrl) => {
|
|
2
|
+
const HTTP_URL_PARTS = ["userinfo", "query", "fragment"];
|
|
3
|
+
function httpUrlFlaws(raw, forbid) {
|
|
4
|
+
if (!isHierarchicalUrl(raw))
|
|
5
|
+
return ["not-http-url"];
|
|
6
|
+
const u = new URL(raw);
|
|
7
|
+
const hashAt = u.href.indexOf("#");
|
|
8
|
+
const present = {
|
|
9
|
+
userinfo: u.username !== "" || u.password !== "",
|
|
10
|
+
query: (hashAt < 0 ? u.href : u.href.slice(0, hashAt)).includes("?"),
|
|
11
|
+
fragment: hashAt >= 0,
|
|
12
|
+
};
|
|
13
|
+
const shape = u.protocol === "http:" || u.protocol === "https:" ? [] : ["not-http-url"];
|
|
14
|
+
return [...shape, ...HTTP_URL_PARTS.filter((p) => forbid.includes(p) && present[p])];
|
|
15
|
+
}
|
|
16
|
+
return { httpUrlFlaws };
|
|
17
|
+
};
|
|
@@ -5,7 +5,9 @@ import { type ProtocolErrorName, type ProtocolErrorNameReading } from '../wireFa
|
|
|
5
5
|
import type { DenyAttributionRefusalDetail } from '../wireRefusalCopy.js';
|
|
6
6
|
import { type DeliveredReading } from './attributionLadder.js';
|
|
7
7
|
import { type AnswerCapture, type UnansweredCapture } from '../engineWireFor.js';
|
|
8
|
+
import { type DecisionRefusalWayOut } from '../checkpointRowVerdict.js';
|
|
8
9
|
export declare const ASK_DECIDED_CODE = "conflict.ask_decided";
|
|
10
|
+
export type { DecisionRefusalWayOut } from '../checkpointRowVerdict.js';
|
|
9
11
|
export type DecisionRefusalStanding = 'settled-elsewhere' | 'ambiguous' | 'refused-pending';
|
|
10
12
|
export type { DecisionRefusalConflict } from './decisionConflict.js';
|
|
11
13
|
export { refusalCarrierOf, type RefusalCarrier } from './hitlBridge.js';
|
|
@@ -57,6 +59,7 @@ export interface DecisionRefusalReading {
|
|
|
57
59
|
readonly conflict?: DecisionRefusalConflict;
|
|
58
60
|
readonly unrecoverable?: true;
|
|
59
61
|
readonly acceptableForm?: {} | null;
|
|
62
|
+
readonly wayOut?: DecisionRefusalWayOut;
|
|
60
63
|
}
|
|
61
64
|
export declare function mintDecisionRefusalReading(err: {} | null | undefined, context?: RefusalRouteContext, attributionCarried?: boolean, delivered?: DeliveredReading, carried?: RefusalCarrier): DecisionRefusalReading;
|
|
62
65
|
export declare function readDecisionRefusalReading(err: {} | null | undefined, context?: RefusalRouteContext): DecisionRefusalReading;
|
|
@@ -67,6 +70,7 @@ export interface DecisionRefusalClassified {
|
|
|
67
70
|
readonly transient?: true;
|
|
68
71
|
readonly conflict?: DecisionRefusalConflict;
|
|
69
72
|
readonly unrecoverable?: true;
|
|
73
|
+
readonly wayOut?: DecisionRefusalWayOut;
|
|
70
74
|
}
|
|
71
75
|
export declare function classifyDecisionRefusal(err: unknown, context?: RefusalRouteContext): DecisionRefusalClassified | undefined;
|
|
72
76
|
export declare function classifyDeliveredDecisionRefusal(err: {} | null | undefined, delivered: DeliveredReading): DecisionRefusalClassified | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ASK_GONE, ASK_GONE_PARKED, RESUME_CONSTRAINT_REJECTED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, isDecideRowUnrevivableCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
1
|
+
import { ASK_GONE, ASK_GONE_PARKED, CORRUPT_ROW_ERROR_CODE, RESUME_CONSTRAINT_REJECTED, RESUME_PREFLIGHT_REJECTED, isDecideAlreadyResolvedCode, isDecideParkMovedCode, isDecideRowUnrevivableCode, refusalRetriableReading, refusalSaysStillPending } from '../engineErrorCodes.js';
|
|
2
2
|
import { isUiLanguage } from '../env/uiLanguage.js';
|
|
3
3
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
4
4
|
import { notPendingCauseReading, refusalCauseWordOf } from './approvalEndingCause.js';
|
|
@@ -10,6 +10,7 @@ import { guardedRead, ownDataField, readOwnDataValue } from '../ownKey.js';
|
|
|
10
10
|
import { PROTOCOL_ERROR_NAME, THROWN_SLOT_UNREADABLE, isDisplayableWireCode, isSlotCarrier, ownFoldedCodeBitsOf, protocolErrorNameReading, readErrorPresent, readErrorString, readRefusalField, readThrownSlot } from '../wireFailureShape.js';
|
|
11
11
|
import { attributionRefusalOf, carrierReadOf } from './attributionLadder.js';
|
|
12
12
|
import { CODE_UNREADABLE, ownReadingSlot } from '../engineWireFor.js';
|
|
13
|
+
import { isDecisionRefusalWayOut } from '../checkpointRowVerdict.js';
|
|
13
14
|
export const ASK_DECIDED_CODE = 'conflict.ask_decided';
|
|
14
15
|
const TRANSIENT_STATUSES = new Set([408, 425, 429, 502, 503, 504]);
|
|
15
16
|
export { refusalCarrierOf } from './hitlBridge.js';
|
|
@@ -32,7 +33,7 @@ const ROUTE_WORDS = { approval_decide: true, live_respond: true, ask_decide: tru
|
|
|
32
33
|
export const REFUSAL_ROUTES = Object.freeze(Object.keys(ROUTE_WORDS));
|
|
33
34
|
const PRIOR_REFUSAL_EVIDENCE = Object.freeze([
|
|
34
35
|
Object.freeze({
|
|
35
|
-
errorCode:
|
|
36
|
+
errorCode: CORRUPT_ROW_ERROR_CODE,
|
|
36
37
|
routes: Object.freeze(['plan_review', 'approval_decide', 'live_respond']),
|
|
37
38
|
evidence: 'server resume-legs.ts:1019 / :2752 / :2910 (resume context read, before the claim CAS at :1666 / :1457); plan_review resumePlanReview reads context before settling',
|
|
38
39
|
}),
|
|
@@ -223,10 +224,13 @@ export function mintDecisionRefusalReading(err, context, attributionCarried, del
|
|
|
223
224
|
const conflict = inRange && status === 409 && obj !== undefined ? isolated(() => decisionConflictOf(obj, captured, pn)) : undefined;
|
|
224
225
|
const unrecoverable = inRange && status !== undefined && Number.isInteger(status) && status >= 400 && status <= 599 && isDecideRowUnrevivableCode(errorCode);
|
|
225
226
|
const acceptableForm = errorCode === RESUME_CONSTRAINT_REJECTED && obj !== undefined ? isolated(() => readErrorPresent(obj, 'acceptableForm')) : undefined;
|
|
227
|
+
const wayOutRaw = inRange && status === 409 && obj !== undefined ? isolated(() => readErrorString(obj, 'wayOut')) : undefined;
|
|
228
|
+
const wayOut = isDecisionRefusalWayOut(wayOutRaw) ? wayOutRaw : undefined;
|
|
226
229
|
const transient = inRange &&
|
|
227
230
|
conflict !== 'grant_changed' &&
|
|
228
231
|
conflict !== 'row_integrity' &&
|
|
229
232
|
!unrecoverable &&
|
|
233
|
+
wayOut === undefined &&
|
|
230
234
|
(TRANSIENT_STATUSES.has(status) || retriable || (status === 404 && obj !== undefined && isolated(() => notPendingCauseReading(obj)) === 'other_replica'));
|
|
231
235
|
return Object.freeze({
|
|
232
236
|
...(status !== undefined ? { status } : {}),
|
|
@@ -246,6 +250,7 @@ export function mintDecisionRefusalReading(err, context, attributionCarried, del
|
|
|
246
250
|
...(conflict !== undefined ? { conflict } : {}),
|
|
247
251
|
...(unrecoverable ? { unrecoverable: true } : {}),
|
|
248
252
|
...(acceptableForm !== undefined ? { acceptableForm } : {}),
|
|
253
|
+
...(wayOut !== undefined ? { wayOut } : {}),
|
|
249
254
|
});
|
|
250
255
|
}
|
|
251
256
|
export function readDecisionRefusalReading(err, context) {
|
|
@@ -264,6 +269,7 @@ function classifiedOf(reading) {
|
|
|
264
269
|
const transient = ownDataField(reading, 'transient') === true;
|
|
265
270
|
const conflict = ownDataField(reading, 'conflict');
|
|
266
271
|
const unrecoverable = ownDataField(reading, 'unrecoverable') === true;
|
|
272
|
+
const wayOut = ownDataField(reading, 'wayOut');
|
|
267
273
|
return Object.freeze({
|
|
268
274
|
standing,
|
|
269
275
|
status,
|
|
@@ -271,6 +277,7 @@ function classifiedOf(reading) {
|
|
|
271
277
|
...(transient ? { transient: true } : {}),
|
|
272
278
|
...(typeof conflict === 'string' ? { conflict: conflict } : {}),
|
|
273
279
|
...(unrecoverable ? { unrecoverable: true } : {}),
|
|
280
|
+
...(isDecisionRefusalWayOut(wayOut) ? { wayOut } : {}),
|
|
274
281
|
});
|
|
275
282
|
}
|
|
276
283
|
catch {
|
|
@@ -312,6 +319,9 @@ export function decisionRefusalClosesOut(refusal, pending) {
|
|
|
312
319
|
const conflict = readThrownSlot(refusal, 'conflict', 'data');
|
|
313
320
|
if (conflict === 'grant_changed' || conflict === THROWN_SLOT_UNREADABLE)
|
|
314
321
|
return false;
|
|
322
|
+
const wayOut = readThrownSlot(refusal, 'wayOut', 'data');
|
|
323
|
+
if (wayOut === 'newer_worker' || wayOut === THROWN_SLOT_UNREADABLE)
|
|
324
|
+
return false;
|
|
315
325
|
return standing === 'ambiguous' || standing === 'refused-pending';
|
|
316
326
|
}
|
|
317
327
|
export function decisionStatusTag(status, errorCode) {
|
|
@@ -21,18 +21,21 @@ export interface LocalAllowOfferedFacts {
|
|
|
21
21
|
readonly scopeRoot: string | undefined;
|
|
22
22
|
readonly road: EngineCapState;
|
|
23
23
|
}
|
|
24
|
-
export
|
|
25
|
-
readonly subject: 'offered';
|
|
26
|
-
} & LocalAllowOfferedFacts) | {
|
|
27
|
-
readonly subject: 'declared';
|
|
24
|
+
export interface LocalAllowDeclaredFacts {
|
|
28
25
|
readonly source: HostSettingsLayer;
|
|
29
26
|
readonly workspace: WorkspaceTrustState | 'unreadable';
|
|
30
27
|
readonly managedRulesOnly: boolean | 'unreadable';
|
|
31
|
-
readonly rule: string;
|
|
32
28
|
readonly scopeRoot: string | undefined;
|
|
33
29
|
readonly store: ListAllPersistedRulesOutcome;
|
|
34
|
-
}
|
|
30
|
+
}
|
|
31
|
+
export type LocalAllowRedeemabilityInput = ({
|
|
32
|
+
readonly subject: 'offered';
|
|
33
|
+
} & LocalAllowOfferedFacts) | ({
|
|
34
|
+
readonly subject: 'declared';
|
|
35
|
+
readonly rule: string;
|
|
36
|
+
} & LocalAllowDeclaredFacts);
|
|
35
37
|
export declare function localAllowRedeemability(input: LocalAllowRedeemabilityInput): LocalAllowRedeemability;
|
|
38
|
+
export declare function localAllowLandingRedeemability(rule: {} | null | undefined, landing: {} | null | undefined): LocalAllowRedeemability;
|
|
36
39
|
export declare const LOCAL_ALLOW_REDEMPTION_REFUSALS: readonly ["managed_only", "no_scope_root", "rule_shape", "request_refused", "preview_mismatch", "engine_refused", "ticket_dead"];
|
|
37
40
|
export type LocalAllowRedemptionRefusal = (typeof LOCAL_ALLOW_REDEMPTION_REFUSALS)[number];
|
|
38
41
|
export declare const LOCAL_ALLOW_REDEMPTION_UNAVAILABLE_CAUSES: readonly ["road_closed", "road_unknown", "policy_unreadable", "input_unreadable", "prepare_failed"];
|
|
@@ -99,6 +99,26 @@ export function localAllowRedeemability(input) {
|
|
|
99
99
|
return unknownBecause('input_unreadable');
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
+
export function localAllowLandingRedeemability(rule, landing) {
|
|
103
|
+
try {
|
|
104
|
+
if (typeof rule !== 'string' || rule.trim() === '')
|
|
105
|
+
return unknownBecause('input_unreadable');
|
|
106
|
+
if (typeof landing !== 'object' || landing === null)
|
|
107
|
+
return unknownBecause('input_unreadable');
|
|
108
|
+
return localAllowRedeemability({
|
|
109
|
+
subject: 'declared',
|
|
110
|
+
rule,
|
|
111
|
+
source: readOwnDataValue(landing, 'source'),
|
|
112
|
+
workspace: readOwnDataValue(landing, 'workspace'),
|
|
113
|
+
managedRulesOnly: readOwnDataValue(landing, 'managedRulesOnly'),
|
|
114
|
+
scopeRoot: readOwnDataValue(landing, 'scopeRoot'),
|
|
115
|
+
store: readOwnDataValue(landing, 'store'),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return unknownBecause('input_unreadable');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
102
122
|
export const LOCAL_ALLOW_REDEMPTION_REFUSALS = Object.freeze([
|
|
103
123
|
'managed_only',
|
|
104
124
|
'no_scope_root',
|
|
@@ -4,6 +4,7 @@ import { hostSessionFor } from '../host.js';
|
|
|
4
4
|
import { DEFAULT_SESSION_KEY } from '../sessionSlot.js';
|
|
5
5
|
import { pendingRowIsOfSession } from './parkRowDelegation.js';
|
|
6
6
|
import { slotReadOf } from '../wireFailureShape.js';
|
|
7
|
+
import { safetyStopNamed } from './hitlBridge.js';
|
|
7
8
|
export function pendingRowIsOwnedByThisSession(row, deps) {
|
|
8
9
|
return ownershipVerdictOf(row, deps) === 'owned';
|
|
9
10
|
}
|
|
@@ -70,5 +71,5 @@ export function askQuestionsFromPending(pending) {
|
|
|
70
71
|
return usableAskQuestions(input.questions);
|
|
71
72
|
}
|
|
72
73
|
export function isHitlSafetyErrorLike(e) {
|
|
73
|
-
return typeof e === 'object' && e !== null && e
|
|
74
|
+
return typeof e === 'object' && e !== null && safetyStopNamed(e);
|
|
74
75
|
}
|
|
@@ -17,6 +17,7 @@ import { decideFailureNote } from '../decideFailureNote.js';
|
|
|
17
17
|
import { wireFailureTextsOf } from '../wireFailureShape.js';
|
|
18
18
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
19
19
|
import { refusedParkFromError } from '../resumeRefusalCopy.js';
|
|
20
|
+
import { decisionRefusalWayOutContent } from '../checkpointRowVerdict.js';
|
|
20
21
|
export const MAX_GATE_HOPS = 2;
|
|
21
22
|
export function nextHopBudget(prev, round) {
|
|
22
23
|
const total = (prev?.total ?? 0) + 1;
|
|
@@ -332,6 +333,10 @@ function failsoftWayOutOf(outcome) {
|
|
|
332
333
|
return 'speak';
|
|
333
334
|
if (outcome.kind === 'not_sent' && (outcome.cause === 'row_unresumable' || (outcome.cause === 'safety_stop' && outcome.safetyCode === 'binding_missing')))
|
|
334
335
|
return 'reason';
|
|
336
|
+
if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && outcome.refusal?.wayOut === 'newer_worker')
|
|
337
|
+
return 'newer_worker';
|
|
338
|
+
if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && outcome.refusal?.wayOut === 'cancel_run')
|
|
339
|
+
return 'cancel';
|
|
335
340
|
if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused' && (refusedParkFromError(outcome.refusal) !== null || outcome.refusal?.conflict === 'row_integrity'))
|
|
336
341
|
return 'cancel';
|
|
337
342
|
if (outcome.kind === 'unsettled' && outcome.cause === 'engine_refused')
|
|
@@ -348,6 +353,8 @@ function failsoftReasonSentence(park, failedReason, terminal, wayOut) {
|
|
|
348
353
|
return renderMessage(msg('approval.park.stillParked', { gate, reason: failedReason }));
|
|
349
354
|
if (wayOut === 'cancel')
|
|
350
355
|
return renderMessage(msg('approval.park.refusedNotResumable', { gate, reason: failedReason }));
|
|
356
|
+
if (wayOut === 'newer_worker')
|
|
357
|
+
return renderMessage(msg('approval.park.newerWorker', { gate, reason: failedReason, wayOut: decisionRefusalWayOutContent('newer_worker') ?? '' }));
|
|
351
358
|
return renderMessage(msg(wayOut === 'speak' ? 'approval.park.resume.speak' : 'approval.park.resume.card', { gate, reason: failedReason }));
|
|
352
359
|
}
|
|
353
360
|
function failsoftEvents(park, ctx, gateAbortedByUser, failedReason, terminal, noDecisionSurface, wayOut) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SCREEN_CARD_ORIGINS } from './gateIdentity.js';
|
|
2
2
|
import { convergeEndedEngineGeneration, } from '../engineGenerationConvergence.js';
|
|
3
3
|
import { checkpointRowVerdictOf } from '../checkpointRowVerdict.js';
|
|
4
|
+
import { CHECKPOINT_INVALID_OUTCOME, CHECKPOINT_UNSUPPORTED_VERSION } from '../engineErrorCodes.js';
|
|
4
5
|
import { planReviewCardFactsFrom } from '../planReviewCardFacts.js';
|
|
5
6
|
import { slotReadOf } from '../wireFailureShape.js';
|
|
6
7
|
import { PARK_GATE_KEY } from './screenCardCarriers.js';
|
|
@@ -291,8 +292,8 @@ function deepFreeze(v) {
|
|
|
291
292
|
}
|
|
292
293
|
return v;
|
|
293
294
|
}
|
|
294
|
-
const GOLD_LACKING = { kind: 'lacking', code:
|
|
295
|
-
const GOLD_DAMAGED = { kind: 'damaged', code:
|
|
295
|
+
const GOLD_LACKING = { kind: 'lacking', code: CHECKPOINT_UNSUPPORTED_VERSION, reason: 'version_newer', sentence: 'Newer engine.' };
|
|
296
|
+
const GOLD_DAMAGED = { kind: 'damaged', code: CHECKPOINT_INVALID_OUTCOME, reason: 'requirements_damaged', sentence: 'Row damaged.' };
|
|
296
297
|
function goldenCases() {
|
|
297
298
|
const ALL = ['park-approval', 'park-question', 'plan-review', 'host-reopen-question'];
|
|
298
299
|
const ready = (name, cards, rows, pick, over = {}) => {
|
|
@@ -3,7 +3,7 @@ import { wireFailureShapeOf } from '../wireFailureShape.js';
|
|
|
3
3
|
import { hostLog } from '../host.js';
|
|
4
4
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
5
5
|
import { ruleToolNameVerdictOf } from '../protocolSegment.js';
|
|
6
|
-
import { RULES_INERT_ENTRY, RULES_INVALID_SHAPE, isRulesRefusalCode } from '../engineErrorCodes.js';
|
|
6
|
+
import { CORRUPT_ROW_ERROR_CODE, RULES_INERT_ENTRY, RULES_INVALID_SHAPE, isRulesRefusalCode } from '../engineErrorCodes.js';
|
|
7
7
|
import { deniedEntryToolName } from '../engineToolDirectory.js';
|
|
8
8
|
import { rosterMountedNames } from '../rosterMountedNames.js';
|
|
9
9
|
import { CORE_ALLOW_ENTRY_INERT_REASONS, CORE_RULE_TOOL_NAME_VERDICTS } from '../generated/engineFactTables.js';
|
|
@@ -64,7 +64,7 @@ export function classifySessionPolicyFailure(e) {
|
|
|
64
64
|
}
|
|
65
65
|
if (errorCode === 'loosen_forbidden')
|
|
66
66
|
return { kind: 'loosen-forbidden', message };
|
|
67
|
-
if (errorCode ===
|
|
67
|
+
if (errorCode === CORRUPT_ROW_ERROR_CODE)
|
|
68
68
|
return { kind: 'store-corrupt', message };
|
|
69
69
|
if (errorCode === 'conflict')
|
|
70
70
|
return { kind: 'cas-conflict', message };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type PermissionsKeptReason } from '../permissionsDeclaration.js';
|
|
2
2
|
import type { PermissionsAllowGrantReading } from '../permissionsAllowGrantCapability.js';
|
|
3
|
-
import { type LocalAllowOfferedFacts } from './localAllowRedemption.js';
|
|
3
|
+
import { type LocalAllowDeclaredFacts, type LocalAllowOfferedFacts, type LocalAllowRedeemability } from './localAllowRedemption.js';
|
|
4
4
|
export type StandingRowWhy = 'given' | 'card_unreadable' | 'remember_refused' | 'remember_unreadable' | 'route_cannot_carry' | 'classes_unreadable' | 'not_deployment_list_question' | 'evidence_unreadable' | 'offers_unreadable' | 'engine_lane_closed' | 'args_unavailable' | 'grant_binding' | 'tool_name_unreadable' | 'rule_cannot_clear' | 'host_fact_missing' | 'card_face_absent' | 'face_not_generic' | 'rule_not_sent' | 'redemption_closed' | 'redemption_unknown';
|
|
5
5
|
export type StandingPersistentRow = 'engine_offer' | 'local_whole_tool' | 'none';
|
|
6
6
|
export interface StandingRowsWhy {
|
|
@@ -17,6 +17,7 @@ export interface StandingRows {
|
|
|
17
17
|
export interface StandingRowsHostFacts {
|
|
18
18
|
readonly wholeToolRuleSent?: boolean;
|
|
19
19
|
readonly readOnlyRedemption?: LocalAllowOfferedFacts;
|
|
20
|
+
readonly wholeToolLanding?: LocalAllowDeclaredFacts;
|
|
20
21
|
}
|
|
21
22
|
export declare function standingRowsOf(card: object | null | undefined, host?: StandingRowsHostFacts | null): StandingRows;
|
|
22
23
|
export declare function seatSessionRowOf(card: object | null | undefined, requestId: string | undefined): boolean;
|
|
@@ -31,6 +32,7 @@ export declare function rememberOfferable(card: object | null | undefined, host?
|
|
|
31
32
|
export interface LocalAllowRuleEnforcement {
|
|
32
33
|
readonly enforceable: boolean;
|
|
33
34
|
readonly engine: 'sent' | 'kept' | 'unreadable';
|
|
35
|
+
readonly redemption: LocalAllowRedeemability;
|
|
34
36
|
readonly keptReason?: PermissionsKeptReason;
|
|
35
37
|
}
|
|
36
|
-
export declare function localAllowRuleEnforceable(rule: string, caps: PermissionsAllowGrantReading): LocalAllowRuleEnforcement;
|
|
38
|
+
export declare function localAllowRuleEnforceable(rule: string, caps: PermissionsAllowGrantReading, landing?: LocalAllowDeclaredFacts): LocalAllowRuleEnforcement;
|
|
@@ -6,7 +6,7 @@ import { inSlotReadOf, inValueOf } from '../wireFailureShape.js';
|
|
|
6
6
|
import { toolPermissionRequestIdDomain } from '../seatContract.js';
|
|
7
7
|
import { permissionsDeclarationReport } from '../permissionsDeclaration.js';
|
|
8
8
|
import { readCardUnreadableEvidence, sessionAllowCardReadable, sessionAllowEligible } from './sessionAllowRoute.js';
|
|
9
|
-
import { localAllowRedeemability } from './localAllowRedemption.js';
|
|
9
|
+
import { localAllowLandingRedeemability, localAllowRedeemability } from './localAllowRedemption.js';
|
|
10
10
|
const UNREADABLE = Symbol('unreadable');
|
|
11
11
|
function ownData(v, key) {
|
|
12
12
|
try {
|
|
@@ -103,6 +103,11 @@ function persistentRowOf(card, host, evidenceUnreadable) {
|
|
|
103
103
|
return { row: 'none', why: 'host_fact_missing' };
|
|
104
104
|
if (!sent)
|
|
105
105
|
return { row: 'none', why: 'rule_not_sent' };
|
|
106
|
+
const judged = localAllowLandingRedeemability(tool, ownData(host, 'wholeToolLanding'));
|
|
107
|
+
if (judged.kind === 'not_redeemable')
|
|
108
|
+
return { row: 'none', why: 'redemption_closed' };
|
|
109
|
+
if (judged.kind === 'unknown')
|
|
110
|
+
return { row: 'none', why: 'redemption_unknown' };
|
|
106
111
|
return { row: 'local_whole_tool', why: 'given' };
|
|
107
112
|
}
|
|
108
113
|
function enginePremiseOf(card) {
|
|
@@ -214,7 +219,7 @@ export function rememberOfferable(card, host) {
|
|
|
214
219
|
deploymentList: SESSION_OFFER[rows.why.deploymentList],
|
|
215
220
|
});
|
|
216
221
|
}
|
|
217
|
-
export function localAllowRuleEnforceable(rule, caps) {
|
|
222
|
+
export function localAllowRuleEnforceable(rule, caps, landing) {
|
|
218
223
|
let engine = 'unreadable';
|
|
219
224
|
let keptReason;
|
|
220
225
|
if (typeof rule === 'string' && rule.trim() !== '') {
|
|
@@ -234,9 +239,11 @@ export function localAllowRuleEnforceable(rule, caps) {
|
|
|
234
239
|
engine = 'unreadable';
|
|
235
240
|
}
|
|
236
241
|
}
|
|
242
|
+
const redemption = localAllowLandingRedeemability(rule, landing);
|
|
237
243
|
return Object.freeze({
|
|
238
|
-
enforceable: engine === 'sent',
|
|
244
|
+
enforceable: engine === 'sent' && redemption.kind === 'redeemable',
|
|
239
245
|
engine,
|
|
246
|
+
redemption,
|
|
240
247
|
...(keptReason !== undefined ? { keptReason } : {}),
|
|
241
248
|
});
|
|
242
249
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { engineVersionTier } from './supportFloor.js';
|
|
2
2
|
const HOOKS_READER_GENERATIONS = Object.freeze([
|
|
3
|
-
Object.freeze({ from: '7.139.0', below: '7.147.0', notRead: Object.freeze(['onFailure']) }),
|
|
3
|
+
Object.freeze({ from: '7.139.0', below: '7.147.0', notRead: Object.freeze(['onFailure', 'rewakeMessage', 'rewakeSummary', 'cloud', 'continueOnBlock']) }),
|
|
4
4
|
]);
|
|
5
5
|
const HOOKS_READER_FAIL_CLOSED = Object.freeze([...new Set(HOOKS_READER_GENERATIONS.flatMap((g) => g.notRead))]);
|
|
6
6
|
export function hooksReaderNotReadKeys(serverVersion) {
|