@everfur/cli 0.9.1 → 0.9.2
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/dist/{chunk-FWEDPKKK.js → chunk-5GXXNW3F.js} +3 -3
- package/dist/{chunk-FLW4ZANY.js → chunk-G7CJK7Z5.js} +237 -52
- package/dist/{chunk-JURZYOMH.js → chunk-LH4AWYCB.js} +1 -1
- package/dist/{chunk-VUXILRME.js → chunk-VSZ4RPKA.js} +7 -7
- package/dist/{chunk-LALDS2WR.js → chunk-WL42DEHE.js} +1 -1
- package/dist/everfur-mcp-hosted.js +4 -4
- package/dist/everfur-mcp-http.js +3 -3
- package/dist/everfur-mcp.js +2 -2
- package/dist/everfur.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { hostnameOf, listen, close, writeJson, serveStatelessMcp } from './chunk-
|
|
4
|
-
import { createHostedTokenVerifier, tokenBucketOf, isAccessTokenShaped, buildServer, MCP_SCOPE, tenantContextOf, sendTestUserRef, hostedVerifyUserRef, REVOKED_AUTHORIZATION_REMEDY, SYNTHETIC_USER_REF_PREFIX } from './chunk-
|
|
5
|
-
import { BASE_URL_ENV_VAR, resolveEndpoint, fetchTransport, systemClock, createApiClient, withPrefix, ephemeralCredential, validateContractText, isJsonObject, describeFailure } from './chunk-
|
|
3
|
+
import { hostnameOf, listen, close, writeJson, serveStatelessMcp } from './chunk-LH4AWYCB.js';
|
|
4
|
+
import { createHostedTokenVerifier, tokenBucketOf, isAccessTokenShaped, buildServer, MCP_SCOPE, tenantContextOf, sendTestUserRef, hostedVerifyUserRef, REVOKED_AUTHORIZATION_REMEDY, SYNTHETIC_USER_REF_PREFIX } from './chunk-G7CJK7Z5.js';
|
|
5
|
+
import { BASE_URL_ENV_VAR, resolveEndpoint, fetchTransport, systemClock, createApiClient, withPrefix, ephemeralCredential, validateContractText, isJsonObject, describeFailure } from './chunk-VSZ4RPKA.js';
|
|
6
6
|
import { createServer } from 'http';
|
|
7
7
|
import { InvalidTokenError, TooManyRequestsError, TemporarilyUnavailableError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
|
|
8
8
|
import { isIP } from 'net';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { ENVIRONMENTS, ENVELOPE_SHAPE, SURFACES, VERIFY_IDENTITY_MODES, digestOfProjection, ephemeralCredential, refusal, API_BASE_URL_BY_ENVIRONMENT, fetchContract, NO_CONTRACT_CACHE, systemClock, fetchTransport, describeFailure, loadDecisionSpaceFromContract, uuidFromKey, resolveEndpoint, createApiClient, createContractProvider, nodeContractCache, CLI_VERSION, withPrefix, isJsonObject, REFUSAL_POLICY, error_explanation_v1_schema_default, verification_v1_schema_default, diagnosis_v1_schema_default, plan_v1_schema_default, NEXT_ACTIONS, IDENTITY_QUESTION, IDENTITY_TREE, CAPABILITY_QUESTION, CAPABILITIES_TREE, WEB_EMBEDDING_QUESTION, PLATFORM_TREE, loadDecisionSpace, nodeFileSystem, expandCapabilities, detectThemeFromText, planIntegration, parseOrigin, parseLoaderUrl, isEverfurLoaderHost, EVERFUR_LOADER_HOSTS, resolveCredential, PARTNER_KEY, runVerification, themePropFromSource, normalizeSurfaces, failedResult, buildSupportBundle, chooseWidgetAuth, DIAGNOSTICS_PATH, diagnoseFailure, parseDiagnostics, buildDiagnosisDocument, toolCodeExplanation, resolveOffline, resolveWithoutRegistry, knownCodes, loadErrorRegistryFromContract, loadErrorRegistry, resolveAfterRegistryMiss, TOOL_CODES, registryAlsoIn, buildExplanationDocument, nextActionFor, CLAIMS_INBOUND_SECRET, WEBHOOK_SIGNING_SECRET, detectProject, BASE_URL_ENV_VAR, checkTenantMode, isWorkspaceRootEvidence, plannableCapabilities, blockedCapabilities, offlineDocument, toolCodeMeaning, SESSION_TOKEN, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, secretKeyHostProblem, ALLOW_CUSTOM_API_HOST_ENV_VAR, PARTNER_SECRET_KEY, SESSION_MINT_TREE, BACKEND_LANGUAGE_QUESTION, ALL_CAPABILITIES, WEBHOOK_PUBLIC_PATH, WEBHOOK_RECEIVER_PATH, TransportError, webhookRouteFile, importPath, hmacSha256, hmacSha256Hex, API_BASE_URL_PLACEHOLDER } from './chunk-
|
|
3
|
+
import { ENVIRONMENTS, ENVELOPE_SHAPE, SURFACES, VERIFY_IDENTITY_MODES, digestOfProjection, ephemeralCredential, refusal, API_BASE_URL_BY_ENVIRONMENT, fetchContract, NO_CONTRACT_CACHE, systemClock, fetchTransport, describeFailure, loadDecisionSpaceFromContract, uuidFromKey, resolveEndpoint, createApiClient, createContractProvider, nodeContractCache, CLI_VERSION, withPrefix, isJsonObject, REFUSAL_POLICY, error_explanation_v1_schema_default, verification_v1_schema_default, diagnosis_v1_schema_default, plan_v1_schema_default, NEXT_ACTIONS, IDENTITY_QUESTION, IDENTITY_TREE, CAPABILITY_QUESTION, CAPABILITIES_TREE, WEB_EMBEDDING_QUESTION, PLATFORM_TREE, loadDecisionSpace, nodeFileSystem, expandCapabilities, detectThemeFromText, planIntegration, parseOrigin, parseLoaderUrl, isEverfurLoaderHost, EVERFUR_LOADER_HOSTS, resolveCredential, PARTNER_KEY, runVerification, themePropFromSource, normalizeSurfaces, failedResult, buildSupportBundle, chooseWidgetAuth, DIAGNOSTICS_PATH, diagnoseFailure, parseDiagnostics, buildDiagnosisDocument, toolCodeExplanation, resolveOffline, resolveWithoutRegistry, knownCodes, loadErrorRegistryFromContract, loadErrorRegistry, resolveAfterRegistryMiss, TOOL_CODES, registryAlsoIn, buildExplanationDocument, nextActionFor, CLAIMS_INBOUND_SECRET, WEBHOOK_SIGNING_SECRET, detectProject, BASE_URL_ENV_VAR, checkTenantMode, isWorkspaceRootEvidence, plannableCapabilities, blockedCapabilities, offlineDocument, toolCodeMeaning, SESSION_TOKEN, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, errorCodeOf, secretKeyHostProblem, ALLOW_CUSTOM_API_HOST_ENV_VAR, PARTNER_SECRET_KEY, SESSION_MINT_TREE, BACKEND_LANGUAGE_QUESTION, ALL_CAPABILITIES, WEBHOOK_PUBLIC_PATH, WEBHOOK_RECEIVER_PATH, TransportError, webhookRouteFile, importPath, hmacSha256, hmacSha256Hex, API_BASE_URL_PLACEHOLDER } from './chunk-VSZ4RPKA.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
6
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -588,7 +588,7 @@ var PLAN_INPUT_SHAPE = {
|
|
|
588
588
|
"For a remote MCP: the text of the project's tailwind.config.{js,ts}, the CSS that declares its theme (a Tailwind v4 @theme block or :root custom properties), or a React Native theme or colours file, so the plan can match the generated surface to the project's own theme. Read statically and never executed. With project_root the project is read from disk instead; this argument, when given, wins. The plan refuses to guess a theme it cannot read and names the missing facts in its match-theme step."
|
|
589
589
|
),
|
|
590
590
|
capabilities: z.array(CAPABILITY).optional().describe(
|
|
591
|
-
'Which Everfur capabilities this integration uses, as the contract names them. The ids the contract can plan today are "chat", "entitlements", "events", "notifications", "photo", "records", "records-clinic" and "televet"; "animations", "health-plan", "records-push", "records-transfer", "server-pets", "texting" and "video" are blocked today and a plan refuses them with the reason. Pass ["all"] for every plannable capability. The loaded contract is the authority: an UNKNOWN_OPTION refusal lists its exact ids. The plan holds no credential, so everfur_verify_integration (not this tool) is the fail-closed check of what the tenant actually has. The native setup an in-app vet call needs (the Daily modules, an Expo config plugin, a clean prebuild, camera and microphone declarations, and a warning naming the missing-native-module error Expo Go produces) is planned only when the generated React Native file mounts that call; a plan whose file mounts only the vet visit button installs none of it. Omit if unknown; the tool will refuse and list the ids.'
|
|
591
|
+
'Which Everfur capabilities this integration uses, as the contract names them. The ids the contract can plan today are "chat", "entitlements", "events", "notifications", "photo", "records", "records-clinic" and "televet"; "animations", "claims", "health-plan", "records-push", "records-transfer", "server-pets", "texting" and "video" are blocked today and a plan refuses them with the reason. Pass ["all"] for every plannable capability. The loaded contract is the authority: an UNKNOWN_OPTION refusal lists its exact ids. The plan holds no credential, so everfur_verify_integration (not this tool) is the fail-closed check of what the tenant actually has. The native setup an in-app vet call needs (the Daily modules, an Expo config plugin, a clean prebuild, camera and microphone declarations, and a warning naming the missing-native-module error Expo Go produces) is planned only when the generated React Native file mounts that call; a plan whose file mounts only the vet visit button installs none of it. Omit if unknown; the tool will refuse and list the ids.'
|
|
592
592
|
),
|
|
593
593
|
identity_mode: IDENTITY_MODE.optional().describe('anonymous = no backend, scoped to the device. partner-user-ref = your backend mints a session against your own user id. shopify-app-proxy = a Shopify storefront, where Shopify vouches for the signed-in customer and no partner backend mints. "personalized" is accepted as an alias for partner-user-ref.'),
|
|
594
594
|
session_mint_language: MINT_LANGUAGE.optional().describe("Backend language that will mint sessions. Only meaningful when identity_mode is partner-user-ref."),
|
|
@@ -800,10 +800,11 @@ async function planIntegrationTool(args, context, ports = {}) {
|
|
|
800
800
|
);
|
|
801
801
|
}
|
|
802
802
|
if (plan.status === "blocked") {
|
|
803
|
+
const claims = (args.capabilities ?? []).some((value) => /claim/i.test(value));
|
|
803
804
|
return refusal(
|
|
804
805
|
"CAPABILITIES_BLOCKED",
|
|
805
|
-
"Everything this integration asked for is blocked by the contract, so nothing can be built today. Each reason and who owns it are below; no plan works around a blocked surface.",
|
|
806
|
-
{ blocked: plan.blocked, warnings: plan.warnings, plan, next_call: null }
|
|
806
|
+
"Everything this integration asked for is blocked by the contract, so nothing can be built today. Each reason and who owns it are below; no plan works around a blocked surface." + (claims ? " A claims integration is planned by everfur_plan_claims_integration, which needs no project." : ""),
|
|
807
|
+
{ blocked: plan.blocked, warnings: plan.warnings, plan, next_call: null, ...claims ? { see_also: "everfur_plan_claims_integration" } : {} }
|
|
807
808
|
);
|
|
808
809
|
}
|
|
809
810
|
const ready = mode.warning === null ? plan : { ...plan, warnings: [...plan.warnings, mode.warning] };
|
|
@@ -1187,9 +1188,9 @@ var EXPLAIN_ERROR_OUTPUT_SHAPE = {
|
|
|
1187
1188
|
};
|
|
1188
1189
|
var INBOUND_DOOR_PREFIX = "/partners/claims/inbound/";
|
|
1189
1190
|
var INBOUND_SANDBOX_ROUTE = "/partners/sandbox/claims-inbound";
|
|
1190
|
-
var RESERVED_CLAIM_IDS = Object.freeze(["inbound"]);
|
|
1191
|
+
var RESERVED_CLAIM_IDS = Object.freeze(["inbound", "batches", "profiles", "pets", "outcomes"]);
|
|
1191
1192
|
function isReservedClaimId(value) {
|
|
1192
|
-
return RESERVED_CLAIM_IDS.includes(value);
|
|
1193
|
+
return RESERVED_CLAIM_IDS.includes(value.toLowerCase());
|
|
1193
1194
|
}
|
|
1194
1195
|
var INBOUND_TOKEN_PATTERN = /^[A-Za-z0-9_-]{43}$/;
|
|
1195
1196
|
var INBOUND_SECRET_ENV = "EVERFUR_CLAIMS_INBOUND_SECRET";
|
|
@@ -1385,6 +1386,38 @@ var PII_KEY_PATTERNS = Object.freeze([
|
|
|
1385
1386
|
function foldKey(key) {
|
|
1386
1387
|
return key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1387
1388
|
}
|
|
1389
|
+
var OWNER_CONTEXT_WORDS = Object.freeze([
|
|
1390
|
+
"owner",
|
|
1391
|
+
"holder",
|
|
1392
|
+
"policyholder",
|
|
1393
|
+
"customer",
|
|
1394
|
+
"member",
|
|
1395
|
+
"insured",
|
|
1396
|
+
"client",
|
|
1397
|
+
"parent",
|
|
1398
|
+
"guardian",
|
|
1399
|
+
"contact",
|
|
1400
|
+
"billing",
|
|
1401
|
+
"payer",
|
|
1402
|
+
"payee",
|
|
1403
|
+
"account"
|
|
1404
|
+
]);
|
|
1405
|
+
var OWNER_SUFFIXES = Object.freeze(["s", "info", "details", "data", "profile"]);
|
|
1406
|
+
function isOwnerContextKey(key) {
|
|
1407
|
+
const folded = foldKey(key);
|
|
1408
|
+
if (OWNER_CONTEXT_WORDS.includes(folded)) return true;
|
|
1409
|
+
return OWNER_SUFFIXES.some((suffix) => folded.endsWith(suffix) && OWNER_CONTEXT_WORDS.includes(folded.slice(0, -suffix.length)));
|
|
1410
|
+
}
|
|
1411
|
+
function isRefKey(key) {
|
|
1412
|
+
const lowered = key.toLowerCase();
|
|
1413
|
+
if (lowered === "id" || lowered === "ref" || /^.+[_.-](?:id|ref)$/.test(lowered)) return true;
|
|
1414
|
+
return /^.*[a-z0-9](?:Id|ID|Ref|REF)$/.test(key);
|
|
1415
|
+
}
|
|
1416
|
+
function ownerPathProblem(keys) {
|
|
1417
|
+
if (!keys.some(isOwnerContextKey)) return null;
|
|
1418
|
+
const last = keys[keys.length - 1];
|
|
1419
|
+
return last !== void 0 && isRefKey(last) ? null : "a source path under an owner key (owner, holder, customer, contact, ...) may only read an id or ref key";
|
|
1420
|
+
}
|
|
1388
1421
|
function isPiiKey(key) {
|
|
1389
1422
|
const folded = foldKey(key);
|
|
1390
1423
|
return folded.length > 0 && PII_KEY_PATTERNS.some((pattern) => pattern.test(folded));
|
|
@@ -1965,7 +1998,7 @@ var INBOUND_CODES = Object.freeze([
|
|
|
1965
1998
|
409,
|
|
1966
1999
|
"stop",
|
|
1967
2000
|
"The sandbox tenant already has its inbound endpoint, and it has one at most. Its URL and secret were shown once, when it was created. Nothing was created.",
|
|
1968
|
-
`Set ${INBOUND_URL_ENV} from where it was saved. For a new secret call ${SETUP} with rotate_secret: true, for a new URL with rotate_token: true.
|
|
2001
|
+
`Set ${INBOUND_URL_ENV} from where it was saved. For a new secret call ${SETUP} with rotate_secret: true, for a new URL with rotate_token: true. To start over on a sandbox tenant, delete_endpoint: true and create again.`
|
|
1969
2002
|
),
|
|
1970
2003
|
inbound(
|
|
1971
2004
|
"events_invalid",
|
|
@@ -4574,7 +4607,7 @@ function rotateDetail() {
|
|
|
4574
4607
|
return `Secret rotation with no downtime: after a rotation the previous secret keeps verifying for previous_valid_seconds (default ${DEFAULT_PREVIOUS_VALID_SECONDS}, at most ${MAX_PREVIOUS_VALID_SECONDS}), so both are accepted while the claims system switches. Sandbox: ${SETUP2} with rotate_secret: true and secret_env_file ${LOCAL_ONLY} writes the new ${INBOUND_SECRET_ENV} to that file (never returned) and answers previous_secret_expires_at; put the new secret in the claims system's secrets store and switch the webhook to it before that time, then confirm with ${SAMPLES2}. previous_valid_seconds 0 cuts the old secret at once: only for a leak. A planned rotation while the previous secret of an earlier one is still valid answers 409 rotation_in_progress: wait for previous_secret_expires_at, or rotate with 0. URL token rotation: if the inbound URL leaks (a log line, a ticket, the chat), rotate its token with ${SETUP2} with rotate_token: true and secret_env_file ${LOCAL_ONLY}; it writes the new ${INBOUND_URL_ENV} to that file (never returned). The old URL answers 404 at once, with no overlap, so put the new URL in the claims system right away; the secret and the signing are unchanged. Live: ask Everfur for a secret rotation with the window wanted, or a token rotation; the new secret or URL is handed over once through a secure channel, and the same switch-over applies.`;
|
|
4575
4608
|
}
|
|
4576
4609
|
function goLiveDetail() {
|
|
4577
|
-
return `Live setup is done by Everfur; the MCP never touches the live account. (1) Ask Everfur for the live endpoint, with the same signing config as the sandbox one, which must be hmac with signed_payload timestamp_body (a live endpoint refuses any other signing: 422 signing_mode_sandbox_only), and for the reviewed sandbox mapping (its active version) to be made active on the live account. (2) Everfur hands over the live URL and shared secret once, through a secure channel: put them in the claims system's secrets store for its production environment, never in an MCP configuration, an env file in a repository or the chat. (3) Everfur switches the inbound webhook on for the live account; until then the live URL answers a plain 404. (4) Point the production webhook at the live URL with the same event types, signing and retry settings as the sandbox. (5) Watch the first real events: the claims system's delivery log shows 202 (or 200 duplicate) for each; any other status is explained by ${EXPLAIN}. A 202 is received, not yet applied
|
|
4610
|
+
return `Live setup is done by Everfur; the MCP never touches the live account. (1) Ask Everfur for the live endpoint, with the same signing config as the sandbox one, which must be hmac with signed_payload timestamp_body (a live endpoint refuses any other signing: 422 signing_mode_sandbox_only), and for the reviewed sandbox mapping (its active version) to be made active on the live account. (2) Everfur hands over the live URL and shared secret once, through a secure channel: put them in the claims system's secrets store for its production environment, never in an MCP configuration, an env file in a repository or the chat. (3) Everfur switches the inbound webhook on for the live account; until then the live URL answers a plain 404. (4) Point the production webhook at the live URL with the same event types, signing and retry settings as the sandbox. (5) Watch the first real events: the claims system's delivery log shows 202 (or 200 duplicate) for each; any other status is explained by ${EXPLAIN}. A 202 is received, not yet applied: the claims system's own servers read the live event log with the live secret key (GET /api/v1/partners/claims/inbound/events, the same view read_event_log shows for the sandbox; never through the MCP), so watch the first events reach applied there and the claims appear in the claims portal. (6) Tell Everfur before changing the event format, so the mapping changes with it.`;
|
|
4578
4611
|
}
|
|
4579
4612
|
function portalDetail() {
|
|
4580
4613
|
return `Every claim the events file lands in the Everfur claims portal for the insurer's adjusters; ask Everfur for the adjusters' portal access. Evidence carries its sources (document, page and quoted text), with invoice lines, coverage gaps and the pre-existing check against past claims from profile events. Opening a claim moves it to in_review; asking for more records moves it to records_requested, answered by a documents_added event with packet_complete true. The adjuster records the decision (${list(DECISIONS)}), the amount paid in cents and a reason; Everfur never decides a claim. In the sandbox every claim runs straight to evidence_ready. Results can also be sent back to the insurer's own systems by the optional outbound webhooks (the optional section).`;
|
|
@@ -5021,7 +5054,7 @@ function checkMappingDocument(document) {
|
|
|
5021
5054
|
extraKeys(kind, ["path", "values"], "kind", at);
|
|
5022
5055
|
const path = kind["path"];
|
|
5023
5056
|
if (typeof path !== "string") at("kind.path", "kind.path is required");
|
|
5024
|
-
else
|
|
5057
|
+
else sourcePathProblem(path, "forbidden", [], "kind.path", at);
|
|
5025
5058
|
const values = kind["values"];
|
|
5026
5059
|
if (!isObject(values) || Object.keys(values).length === 0 || Object.keys(values).length > MAX_KIND_VALUES) {
|
|
5027
5060
|
at("kind.values", `kind.values maps 1 to ${MAX_KIND_VALUES} native values to a kind`);
|
|
@@ -5086,6 +5119,8 @@ function checkMappingDocument(document) {
|
|
|
5086
5119
|
extraKeys(listed, ["path", "fields"], `kinds.${name}.${list2}`, at);
|
|
5087
5120
|
if (typeof listed["path"] !== "string") at(`kinds.${name}.${list2}.path`, "a list's path is required");
|
|
5088
5121
|
else pathProblem(listed["path"], "required", `kinds.${name}.${list2}.path`, at);
|
|
5122
|
+
const listSteps = typeof listed["path"] === "string" ? parsePath(listed["path"], "required") : "not a path";
|
|
5123
|
+
const listKeys = typeof listSteps === "string" ? null : keysOf(listSteps);
|
|
5089
5124
|
const listFields = listed["fields"];
|
|
5090
5125
|
if (!isObject(listFields) || Object.keys(listFields).length === 0 || Object.keys(listFields).length > MAX_LIST_FIELDS) {
|
|
5091
5126
|
at(`kinds.${name}.${list2}.fields`, `a list maps 1 to ${MAX_LIST_FIELDS} targets`);
|
|
@@ -5093,7 +5128,7 @@ function checkMappingDocument(document) {
|
|
|
5093
5128
|
}
|
|
5094
5129
|
for (const [target, field] of Object.entries(listFields)) {
|
|
5095
5130
|
if (!allowed.includes(target)) at(`kinds.${name}.${list2}.fields.${target}`, `${list2} has no target ${target.slice(0, 64)}; targets: ${allowed.join(", ")}`);
|
|
5096
|
-
checkField(field, `kinds.${name}.${list2}.fields.${target}`, at);
|
|
5131
|
+
checkField(field, `kinds.${name}.${list2}.fields.${target}`, at, listKeys);
|
|
5097
5132
|
}
|
|
5098
5133
|
}
|
|
5099
5134
|
}
|
|
@@ -5111,7 +5146,19 @@ function pathProblem(text, star, where, at) {
|
|
|
5111
5146
|
const parsed = parsePath(text, star);
|
|
5112
5147
|
if (typeof parsed === "string") at(where, parsed);
|
|
5113
5148
|
}
|
|
5114
|
-
function
|
|
5149
|
+
function keysOf(steps) {
|
|
5150
|
+
return steps.flatMap((step3) => step3.kind === "key" ? [step3.key] : []);
|
|
5151
|
+
}
|
|
5152
|
+
function sourcePathProblem(text, star, prefix, where, at) {
|
|
5153
|
+
const parsed = parsePath(text, star);
|
|
5154
|
+
if (typeof parsed === "string") {
|
|
5155
|
+
at(where, parsed);
|
|
5156
|
+
return;
|
|
5157
|
+
}
|
|
5158
|
+
const problem = ownerPathProblem([...prefix, ...keysOf(parsed)]);
|
|
5159
|
+
if (problem !== null) at(where, problem);
|
|
5160
|
+
}
|
|
5161
|
+
function checkField(field, where, at, prefix = []) {
|
|
5115
5162
|
if (!isObject(field)) {
|
|
5116
5163
|
at(where, "a field is an object: {path} or {paths}, with optional transforms");
|
|
5117
5164
|
return;
|
|
@@ -5132,7 +5179,8 @@ function checkField(field, where, at) {
|
|
|
5132
5179
|
if (path === void 0 && paths === void 0 && !constant) at(where, "a field needs a path, paths or a leading constant transform");
|
|
5133
5180
|
if (path !== void 0) {
|
|
5134
5181
|
if (typeof path !== "string") at(`${where}.path`, "a path is a string");
|
|
5135
|
-
else pathProblem(path, "forbidden", `${where}.path`, at);
|
|
5182
|
+
else if (prefix === null) pathProblem(path, "forbidden", `${where}.path`, at);
|
|
5183
|
+
else sourcePathProblem(path, "forbidden", prefix, `${where}.path`, at);
|
|
5136
5184
|
}
|
|
5137
5185
|
if (paths !== void 0) {
|
|
5138
5186
|
if (!Array.isArray(paths) || paths.length === 0 || paths.length > MAX_FIELD_PATHS) {
|
|
@@ -5140,7 +5188,8 @@ function checkField(field, where, at) {
|
|
|
5140
5188
|
} else {
|
|
5141
5189
|
paths.forEach((text, index) => {
|
|
5142
5190
|
if (typeof text !== "string") at(`${where}.paths[${index}]`, "a path is a string");
|
|
5143
|
-
else pathProblem(text, "forbidden", `${where}.paths[${index}]`, at);
|
|
5191
|
+
else if (prefix === null) pathProblem(text, "forbidden", `${where}.paths[${index}]`, at);
|
|
5192
|
+
else sourcePathProblem(text, "forbidden", prefix, `${where}.paths[${index}]`, at);
|
|
5144
5193
|
});
|
|
5145
5194
|
}
|
|
5146
5195
|
}
|
|
@@ -5327,7 +5376,7 @@ var CLAIM_RULES = Object.freeze([
|
|
|
5327
5376
|
{ target: "amount_claimed_cents", scope: "claim", names: ["amountclaimed", "claimedamount", "claimamount", "requestedamount", "amountrequested", "claimed", "requested"], shape: "money", unscoped: true },
|
|
5328
5377
|
{ target: "billed_cents", scope: "claim", names: ["billedamount", "billed", "total", "totalamount", "invoicetotal", "invoiceamount", "amount", "totalbilled", "cost", "charges"], shape: "money", unscoped: true },
|
|
5329
5378
|
{ target: "clinic_name", scope: "clinic", names: ["name", "clinicname", "clinic", "vetname", "hospitalname", "practicename", "providername", "vet", "hospital", "practice", "provider"], shape: "text" },
|
|
5330
|
-
{ target: "packet_complete", scope: "claim", names: ["packetcomplete", "complete", "iscomplete", "final", "isfinal", "finalized", "finalised", "ready", "documentscomplete", "docscomplete"], shape: "bool", unscoped: true },
|
|
5379
|
+
{ target: "packet_complete", scope: "claim", names: ["packetcomplete", "complete", "iscomplete", "final", "isfinal", "finalized", "finalised", "ready", "documentscomplete", "docscomplete", "alldocumentsreceived", "alldocsreceived", "documentsreceived", "docsreceived", "allreceived", "allfilesreceived", "filescomplete", "packetready", "readyforreview", "submissioncomplete"], shape: "bool", unscoped: true },
|
|
5331
5380
|
{ target: "pet.pet_ref", scope: "pet", names: ["petid", "petref", "petnumber", "animalid", "patientid", ...ID_NAMES], shape: "ref" },
|
|
5332
5381
|
{ target: "pet.name", scope: "pet", names: ["name", "petname", "animalname", "patientname", "callname"], shape: "text" },
|
|
5333
5382
|
{ target: "pet.species", scope: "pet", names: ["species", "speciescode", "kind", "type", "animaltype", "pettype", "animalkind"], shape: "species" },
|
|
@@ -5364,7 +5413,7 @@ function rulesFor(kind) {
|
|
|
5364
5413
|
return Object.entries(PROFILE_FROM_CLAIM).map(([target, from]) => ({ ...byTarget.get(from), target }));
|
|
5365
5414
|
}
|
|
5366
5415
|
var DOCUMENT_RULES = Object.freeze([
|
|
5367
|
-
{ target: "base64", scope: null, names: ["base64", "content", "contents", "data", "body", "bytes", "file", "filedata", "blob", "payload", "encoded", "filecontent"], shape: "base64", unscoped: true },
|
|
5416
|
+
{ target: "base64", scope: null, names: ["base64", "contentbase64", "base64content", "filebase64", "base64data", "database64", "documentbase64", "base64file", "content", "contents", "data", "body", "bytes", "file", "filedata", "blob", "payload", "encoded", "filecontent"], shape: "base64", unscoped: true },
|
|
5368
5417
|
{ target: "url", scope: null, names: ["url", "link", "href", "uri", "downloadurl", "fileurl", "location", "signedurl", "presignedurl", "download"], shape: "url", unscoped: true },
|
|
5369
5418
|
{ target: "file_name", scope: null, names: ["filename", "name", "title", "documentname", "originalname", "originalfilename", "label"], shape: "file_name", unscoped: true },
|
|
5370
5419
|
{ target: "kind", scope: null, names: ["kind", "category", "type", "documenttype", "doctype", "documentkind", "doccategory", "class"], shape: "doc_kind", unscoped: true },
|
|
@@ -5385,6 +5434,8 @@ var SPECIES_SYNONYMS = Object.freeze({
|
|
|
5385
5434
|
d: "dog",
|
|
5386
5435
|
puppy: "dog",
|
|
5387
5436
|
canin: "dog",
|
|
5437
|
+
can: "dog",
|
|
5438
|
+
cn: "dog",
|
|
5388
5439
|
cat: "cat",
|
|
5389
5440
|
cats: "cat",
|
|
5390
5441
|
feline: "cat",
|
|
@@ -5466,7 +5517,7 @@ function shapeFits(shape, leaf) {
|
|
|
5466
5517
|
case "content_type":
|
|
5467
5518
|
return only("ref", "text", "int", "bool");
|
|
5468
5519
|
case "base64":
|
|
5469
|
-
return only("base64");
|
|
5520
|
+
return only("base64") || foldKey(leaf.keys[leaf.keys.length - 1] ?? "").includes("base64") && only("base64", "ref", "text") && present(leaf.values).every((value) => BASE64.test(String(value).replace(/\s+/g, "")));
|
|
5470
5521
|
case "url":
|
|
5471
5522
|
return only("url");
|
|
5472
5523
|
}
|
|
@@ -5731,11 +5782,12 @@ function transformsFor(shape, leaf, order, target, orderDecided = false) {
|
|
|
5731
5782
|
}
|
|
5732
5783
|
return { transforms, why, confidence, reviewNote, untrustedCodes };
|
|
5733
5784
|
}
|
|
5734
|
-
function pick(rule, leaves, used, parentKeys, documentElement = false) {
|
|
5785
|
+
function pick(rule, leaves, used, parentKeys, documentElement = false, ownerRule = true) {
|
|
5735
5786
|
let best = null;
|
|
5736
5787
|
let bestScore = 0;
|
|
5737
5788
|
for (const leaf of leaves) {
|
|
5738
5789
|
if (used.has(leaf.path)) continue;
|
|
5790
|
+
if (ownerRule && ownerPathProblem([...parentKeys, ...leaf.keys]) !== null) continue;
|
|
5739
5791
|
if (rule.target !== "member_ref" && personalData(leaf, parentKeys, documentElement) !== null) continue;
|
|
5740
5792
|
if (rule.target === "member_ref" && (isPiiKey(leaf.keys[leaf.keys.length - 1] ?? "") || leaf.shapes.has("email") || leaf.shapes.has("phone"))) continue;
|
|
5741
5793
|
if (!shapeFits(rule.shape, leaf)) continue;
|
|
@@ -5942,8 +5994,26 @@ function proposeMapping(input) {
|
|
|
5942
5994
|
const pinnedPath = pinned[rule.target];
|
|
5943
5995
|
const leaf = pinnedPath !== void 0 ? flat.leaves.get(pinnedPath) ?? { path: pinnedPath, keys: pinnedPath.split("."), values: [], shapes: /* @__PURE__ */ new Set(["text"]) } : pick(rule, flat.leaves.values(), used, []);
|
|
5944
5996
|
const required = REQUIRED_TARGETS[kind].includes(rule.target);
|
|
5997
|
+
const refused = leaf === null && pinnedPath === void 0 ? pick(rule, flat.leaves.values(), used, [], false, false) : null;
|
|
5998
|
+
if (refused !== null) {
|
|
5999
|
+
const where = echoCode(refused.path, "[a path not shown]");
|
|
6000
|
+
addGap({
|
|
6001
|
+
kind,
|
|
6002
|
+
target: rule.target,
|
|
6003
|
+
required,
|
|
6004
|
+
code: "unfilled",
|
|
6005
|
+
why: `${rule.target} reads like ${where}, but that key sits under an owner object (owner, holder, member, customer, ...) and is not named like an id or ref. The door's scrub drops it before mapping, and the API refuses a mapping that reads it (mapping_invalid).`,
|
|
6006
|
+
fix: "Have the claims system also send the value under a key named like an id or ref inside that object (memberId, member_id, memberRef, id), or outside the owner object; then pin it with hints.field_paths."
|
|
6007
|
+
});
|
|
6008
|
+
continue;
|
|
6009
|
+
}
|
|
6010
|
+
if (pinnedPath !== void 0 && ownerPathProblem(pinnedPath.split(".").map((part) => part.replace(/\[.*$/, ""))) !== null) {
|
|
6011
|
+
addGap({ kind, target: rule.target, required, code: "unfilled", why: "the pinned path passes through an owner object and its last key is not named like an id or ref; the scrub drops it and the API refuses the mapping (mapping_invalid)", fix: "Pin a key named like an id or ref (memberId, member_id, id), or one outside the owner object." });
|
|
6012
|
+
continue;
|
|
6013
|
+
}
|
|
5945
6014
|
if (leaf === null) {
|
|
5946
6015
|
if (required) addGap({ kind, target: rule.target, required, code: "unfilled", why: `no field in the ${kind} samples reads like ${rule.target}`, fix: `Pass hints.field_paths.${kind}["${rule.target}"] with the path that holds it, or make the insurer system send it.` });
|
|
6016
|
+
else if (rule.target === "packet_complete") addGap({ kind, target: rule.target, required: false, code: "needs_review", why: 'no field reads like "all documents are in". packet_complete is false when unmapped, and only an event with packet_complete true sends the claim to review, so with none mapped no claim ever leaves intake.', fix: `Map packet_complete to the claims system's own "documents complete" flag (hints.field_paths.${kind}["packet_complete"], a bool), or to a constant true when every ${kind} event carries the whole packet.` });
|
|
5947
6017
|
continue;
|
|
5948
6018
|
}
|
|
5949
6019
|
if (pinnedPath !== void 0 && personalData(leaf) !== null && rule.target !== "member_ref") {
|
|
@@ -6430,7 +6500,7 @@ function inboundFailure(failure, action, notFound) {
|
|
|
6430
6500
|
}
|
|
6431
6501
|
return sandboxFailure(failure, action);
|
|
6432
6502
|
}
|
|
6433
|
-
var CREATE_ONCE = `The sandbox key can create the sandbox inbound endpoint
|
|
6503
|
+
var CREATE_ONCE = `The sandbox key can create the sandbox inbound endpoint (one per tenant) with ${SETUP3} (create_endpoint: true, signing, secret_env_file and confirm: true from a person): its inbound URL (with the token) and first secret are shown once, in that answer, and are written to secret_env_file as ${INBOUND_URL_ENV} and ${INBOUND_SECRET_ENV}. Live inbound endpoints are set up by Everfur.`;
|
|
6434
6504
|
var URL_SHOWN_ONCE = `The inbound URL was shown once, when the endpoint was created: set ${INBOUND_URL_ENV} from where it was saved (the env file the create wrote, or the claims system's config). No route shows it again: rotate_secret gives a new secret, and rotate_token a new URL (the old one stops at once).`;
|
|
6435
6505
|
var ENDPOINT_404 = `The sandbox claims-inbound routes answered 404: the inbound webhook is not switched on for this deployment or this sandbox tenant, the tenant has no claims portal, or no inbound endpoint exists for it yet. The first two are settings Everfur holds. ${CREATE_ONCE}`;
|
|
6436
6506
|
var CREATE_404 = "The create answered 404: the sandbox claims-inbound routes are not switched on for this deployment or this sandbox tenant, or the tenant has no claims portal. Both are settings Everfur holds. Nothing was created.";
|
|
@@ -6481,21 +6551,28 @@ function mappingSummary(view) {
|
|
|
6481
6551
|
}
|
|
6482
6552
|
function validationErrors(body) {
|
|
6483
6553
|
if (typeof body !== "object" || body === null) return [];
|
|
6484
|
-
const
|
|
6554
|
+
const record = body;
|
|
6555
|
+
const detail = record["detail"];
|
|
6556
|
+
const errors = !Array.isArray(record["errors"]) && typeof detail === "object" && detail !== null ? detail["errors"] : record["errors"];
|
|
6485
6557
|
if (!Array.isArray(errors)) return [];
|
|
6486
6558
|
return errors.slice(0, 20).flatMap((item) => {
|
|
6487
6559
|
if (typeof item !== "object" || item === null) return [];
|
|
6488
|
-
const
|
|
6489
|
-
const loc = Array.isArray(
|
|
6490
|
-
const msg = typeof
|
|
6560
|
+
const record2 = item;
|
|
6561
|
+
const loc = Array.isArray(record2["loc"]) ? record2["loc"].map(String).join(".") : String(record2["loc"] ?? "");
|
|
6562
|
+
const msg = typeof record2["msg"] === "string" ? record2["msg"] : "";
|
|
6491
6563
|
return [{ loc: loc.slice(0, 200), msg: msg.slice(0, 300) }];
|
|
6492
6564
|
});
|
|
6493
6565
|
}
|
|
6494
6566
|
function bodyCode(body) {
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6567
|
+
return errorCodeOf(body).code;
|
|
6568
|
+
}
|
|
6569
|
+
function unexpectedRefusal(answer, action, nothing) {
|
|
6570
|
+
const code = bodyCode(answer.value);
|
|
6571
|
+
return refusal(
|
|
6572
|
+
"CLAIMS_SANDBOX_CALL_FAILED",
|
|
6573
|
+
`The API answered ${answer.status} ${code === null ? "(no code)" : relayedReason(code)}, which this action does not expect. ${nothing}` + (code === null ? "" : " everfur_explain_claims_error explains the code."),
|
|
6574
|
+
{ action, status: answer.status, code: code === null ? null : relayedReason(code), request_id: answer.requestId }
|
|
6575
|
+
);
|
|
6499
6576
|
}
|
|
6500
6577
|
var SAMPLE_EVENT = z.record(z.string(), z.unknown());
|
|
6501
6578
|
function loadSamples(samples, files, scope) {
|
|
@@ -6580,7 +6657,16 @@ var PREVIEW_RESULT = z.object({
|
|
|
6580
6657
|
});
|
|
6581
6658
|
async function preview(sandbox, mapping, events, action) {
|
|
6582
6659
|
const body = { ...mapping === void 0 ? {} : { mapping }, events };
|
|
6583
|
-
const answer = await sandbox.client.request({ method: "POST", path: `${INBOUND_SANDBOX_ROUTE}/mapping/preview`, credentials: sandbox.credentials, body });
|
|
6660
|
+
const answer = await sandbox.client.request({ method: "POST", path: `${INBOUND_SANDBOX_ROUTE}/mapping/preview`, credentials: sandbox.credentials, body, acceptStatuses: [422] });
|
|
6661
|
+
if (answer.ok && answer.status === 422) {
|
|
6662
|
+
const code = bodyCode(answer.value);
|
|
6663
|
+
const problems = bodyInvalidErrors(answer.value);
|
|
6664
|
+
return refusal(
|
|
6665
|
+
code === "mapping_invalid" ? "CLAIMS_MAPPING_INVALID" : "CLAIMS_ARGUMENTS_INVALID",
|
|
6666
|
+
`The preview answered 422 ${code === null ? "(no code)" : relayedReason(code)}: ${problems.length > 0 ? problems.join("; ") : "the API named no field"}. Nothing was stored.`,
|
|
6667
|
+
{ action, status: 422, code: code === null ? null : relayedReason(code), problems, request_id: answer.requestId }
|
|
6668
|
+
);
|
|
6669
|
+
}
|
|
6584
6670
|
if (!answer.ok) {
|
|
6585
6671
|
return inboundFailure(answer, action, mapping === void 0 ? `The preview answered 404: no mapping was passed and there is no draft to preview (an activated draft is no longer a draft). ${MAPPING_ROUTES_404}` : MAPPING_ROUTES_404);
|
|
6586
6672
|
}
|
|
@@ -6657,7 +6743,9 @@ async function proposeClaimsMappingTool(args, context, ports = {}, options = {})
|
|
|
6657
6743
|
} else {
|
|
6658
6744
|
const results = await preview(sandbox, proposal.mapping, loaded.samples, "preview");
|
|
6659
6745
|
if (!Array.isArray(results)) {
|
|
6660
|
-
|
|
6746
|
+
const error = results.document["error"];
|
|
6747
|
+
const problems = Array.isArray(error?.details?.problems) ? error.details.problems : results.document["problems"] ?? void 0;
|
|
6748
|
+
document["server_preview"] = { skipped: true, why: results.document["message"] ?? "the preview failed", code: error?.code ?? null, ...problems === void 0 ? {} : { problems } };
|
|
6661
6749
|
} else {
|
|
6662
6750
|
const relayed = results.map((item, index) => relayPreview(item, index));
|
|
6663
6751
|
document["server_preview"] = { passed: relayed.every((item) => item["gaps"].length === 0), results: relayed };
|
|
@@ -6732,6 +6820,7 @@ async function saveClaimsMappingTool(args, context, ports = {}) {
|
|
|
6732
6820
|
});
|
|
6733
6821
|
if (!answer2.ok) return inboundFailure(answer2, action, MAPPING_ROUTES_404);
|
|
6734
6822
|
if (answer2.status === 422) {
|
|
6823
|
+
if (bodyCode(answer2.value) !== "mapping_invalid") return unexpectedRefusal(answer2, action, "Nothing was saved.");
|
|
6735
6824
|
return refusal("CLAIMS_MAPPING_INVALID", "The API refused the mapping (mapping_invalid); nothing was saved.", {
|
|
6736
6825
|
action,
|
|
6737
6826
|
problems: validationErrors(answer2.value).map((item) => `${item.loc}: ${item.msg}`),
|
|
@@ -6803,11 +6892,12 @@ async function saveClaimsMappingTool(args, context, ports = {}) {
|
|
|
6803
6892
|
);
|
|
6804
6893
|
}
|
|
6805
6894
|
if (answer.status === 409 || answer.status === 422) {
|
|
6806
|
-
const code = bodyCode(answer.value)
|
|
6895
|
+
const code = bodyCode(answer.value);
|
|
6896
|
+
if (code !== "event_time_mapping_required" && code !== "mapping_invalid") return unexpectedRefusal(answer, action, "Nothing was activated.");
|
|
6807
6897
|
return refusal(
|
|
6808
6898
|
"CLAIMS_MAPPING_INVALID",
|
|
6809
6899
|
code === "event_time_mapping_required" ? "The endpoint's signing signs no time (a body-only signature or a secret header), so the mapping must name event_time before it can be activated. Nothing was activated." : "The API refused to activate the draft (mapping_invalid). Nothing was activated.",
|
|
6810
|
-
{ action, code
|
|
6900
|
+
{ action, code, problems: validationErrors(answer.value).map((item) => `${item.loc}: ${item.msg}`), request_id: answer.requestId }
|
|
6811
6901
|
);
|
|
6812
6902
|
}
|
|
6813
6903
|
const view = MAPPING_VIEW.safeParse(answer.value);
|
|
@@ -6821,7 +6911,9 @@ function describeSigning(signing) {
|
|
|
6821
6911
|
var CLAIMS_INBOUND_SIGNING_SETUP_INPUT_SHAPE = {
|
|
6822
6912
|
create_endpoint: z.boolean().optional().describe(`Create the sandbox inbound endpoint, once, with signing, and write its inbound URL and first secret to secret_env_file as ${INBOUND_URL_ENV} and ${INBOUND_SECRET_ENV}. Needs confirm: true. The API shows the URL and secret only in that answer; neither is returned. Default false.`),
|
|
6823
6913
|
signing: SIGNING_CONFIG.optional().describe("create_endpoint: the signing config the claims system will use. Use hmac with signed_payload timestamp_body: it is the only signing a live endpoint accepts. hmac over the body alone and secret_header are sandbox only (a live endpoint refuses them with 422 signing_mode_sandbox_only)."),
|
|
6824
|
-
confirm: z.boolean().optional().describe("create_endpoint: true only when a human has read the signing config and asked for the endpoint to be created
|
|
6914
|
+
confirm: z.boolean().optional().describe("create_endpoint: true only when a human has read the signing config and asked for the endpoint to be created, changed (set_signing) or deleted (delete_endpoint). Never set it on your own."),
|
|
6915
|
+
set_signing: z.boolean().optional().describe("Change the sandbox endpoint's signing config to signing (the header names, the prefix, the encoding, the mode). The URL and secret stay the same. Needs signing and confirm: true. Default false."),
|
|
6916
|
+
delete_endpoint: z.boolean().optional().describe("Delete the sandbox inbound endpoint: its URL answers 404 at once, and the event log and mappings stay, so create_endpoint can make a new one (a new URL and secret). Needs confirm: true. Live endpoints are kept by Everfur. Default false."),
|
|
6825
6917
|
rotate_secret: z.boolean().optional().describe("Rotate the sandbox endpoint's shared secret and write the new one to secret_env_file. Default false: only read."),
|
|
6826
6918
|
rotate_token: z.boolean().optional().describe(`Rotate the sandbox endpoint's URL token, after the inbound URL leaked, and write the new inbound URL to secret_env_file as ${INBOUND_URL_ENV}. The old URL answers 404 at once, with no overlap; the secret and the signing are unchanged. The new URL is never returned. Default false: only read.`),
|
|
6827
6919
|
secret_env_file: z.string().min(1).max(1024).optional().describe(`create_endpoint, rotate_secret and rotate_token: absolute path of a local env file the secret is written to as ${INBOUND_SECRET_ENV}=... (on create also, and on rotate_token only, the inbound URL as ${INBOUND_URL_ENV}=...), replacing a line that already sets it, created with mode 600 when missing. Neither value is ever returned. It must be named .env or .env.<name>, inside the project this server runs in or ~/.config/everfur, ignored by git, and not a symlink.`),
|
|
@@ -6875,8 +6967,7 @@ function stripUndefined(env) {
|
|
|
6875
6967
|
return out;
|
|
6876
6968
|
}
|
|
6877
6969
|
function bodyInvalidErrors(body) {
|
|
6878
|
-
|
|
6879
|
-
return validationErrors(detail).map((item) => `${item.loc}: ${item.msg}`);
|
|
6970
|
+
return validationErrors(body).map((item) => `${item.loc}: ${item.msg}`);
|
|
6880
6971
|
}
|
|
6881
6972
|
function doorTokenOf(urlPath) {
|
|
6882
6973
|
if (typeof urlPath !== "string") return null;
|
|
@@ -6897,7 +6988,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6897
6988
|
if (args.confirm !== true) {
|
|
6898
6989
|
return refusal(
|
|
6899
6990
|
"CLAIMS_INBOUND_CREATE_CONFIRMATION_REQUIRED",
|
|
6900
|
-
"create_endpoint needs confirm: true, set only when a person has read the signing config and asked for the sandbox endpoint to be created.
|
|
6991
|
+
"create_endpoint needs confirm: true, set only when a person has read the signing config and asked for the sandbox endpoint to be created. The URL and secret are shown once, and a tenant has one endpoint (delete_endpoint removes it). Nothing was created.",
|
|
6901
6992
|
{ action, arguments: ["confirm"] }
|
|
6902
6993
|
);
|
|
6903
6994
|
}
|
|
@@ -6913,7 +7004,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6913
7004
|
const gate = await humanGate(context, ports, {
|
|
6914
7005
|
action: "create_endpoint",
|
|
6915
7006
|
subject: JSON.stringify([signing, file]),
|
|
6916
|
-
summary: `Create the sandbox inbound claims endpoint
|
|
7007
|
+
summary: `Create the sandbox inbound claims endpoint with ${describeSigning(signing)}, and write its inbound URL and first secret to ${file}.`,
|
|
6917
7008
|
code: args.confirmation_code
|
|
6918
7009
|
}, "Nothing was created.");
|
|
6919
7010
|
if (gate !== null) return gate;
|
|
@@ -6941,28 +7032,31 @@ async function createEndpoint(args, context, ports) {
|
|
|
6941
7032
|
}
|
|
6942
7033
|
return inboundFailure(answer, action, CREATE_404);
|
|
6943
7034
|
}
|
|
6944
|
-
|
|
7035
|
+
const refusedCode = answer.status >= 400 ? bodyCode(answer.value) : null;
|
|
7036
|
+
if (refusedCode === "event_time_mapping_required") {
|
|
6945
7037
|
return refusal(
|
|
6946
7038
|
"CLAIMS_MAPPING_INVALID",
|
|
6947
7039
|
"The signing config signs no time (a body-only signature or a secret header), and the active mapping names no event_time, so the API refused it (event_time_mapping_required). Nothing was created. Sign over a timestamp (hmac with signed_payload timestamp_body), or add event_time to the mapping and activate it first.",
|
|
6948
7040
|
{ action, status: 409, code: "event_time_mapping_required", request_id: answer.requestId }
|
|
6949
7041
|
);
|
|
6950
7042
|
}
|
|
6951
|
-
if (
|
|
7043
|
+
if (refusedCode === "endpoint_exists") {
|
|
6952
7044
|
return refusal(
|
|
6953
7045
|
"CLAIMS_INBOUND_ENDPOINT_EXISTS",
|
|
6954
|
-
`This sandbox tenant already has an inbound endpoint (endpoint_exists), and it has one at most. Nothing was created. Its inbound URL was shown once, when it was created: set ${INBOUND_URL_ENV} from where it was saved. For a new secret, call ${SETUP3} with rotate_secret: true and secret_env_file
|
|
6955
|
-
{ action, status: 409, code:
|
|
7046
|
+
`This sandbox tenant already has an inbound endpoint (endpoint_exists), and it has one at most. Nothing was created. Its inbound URL was shown once, when it was created: set ${INBOUND_URL_ENV} from where it was saved. For a new secret, call ${SETUP3} with rotate_secret: true and secret_env_file; to start over, delete_endpoint: true (a person confirms) and create again.`,
|
|
7047
|
+
{ action, status: 409, code: "endpoint_exists", request_id: answer.requestId }
|
|
6956
7048
|
);
|
|
6957
7049
|
}
|
|
6958
|
-
if (
|
|
6959
|
-
return refusal("CLAIMS_ARGUMENTS_INVALID", "The API refused the signing config (body_invalid). Nothing was created.", {
|
|
7050
|
+
if (refusedCode === "body_invalid" || refusedCode === "signing_mode_sandbox_only") {
|
|
7051
|
+
return refusal("CLAIMS_ARGUMENTS_INVALID", refusedCode === "body_invalid" ? "The API refused the signing config (body_invalid). Nothing was created." : "The API refused the signing config (signing_mode_sandbox_only): this tenant is not a sandbox tenant, so it signs only with hmac and signed_payload timestamp_body. Nothing was created.", {
|
|
6960
7052
|
action,
|
|
6961
7053
|
arguments: ["signing"],
|
|
7054
|
+
code: refusedCode,
|
|
6962
7055
|
problems: bodyInvalidErrors(answer.value),
|
|
6963
7056
|
request_id: answer.requestId
|
|
6964
7057
|
});
|
|
6965
7058
|
}
|
|
7059
|
+
if (answer.status === 409 || answer.status === 422) return unexpectedRefusal(answer, action, "Nothing was created.");
|
|
6966
7060
|
const created = typeof answer.value === "object" && answer.value !== null ? answer.value : {};
|
|
6967
7061
|
const token = doorTokenOf(created["url_path"]);
|
|
6968
7062
|
const secret = typeof created["secret"] === "string" && SECRET_SHAPE.test(created["secret"]) ? created["secret"] : null;
|
|
@@ -6976,7 +7070,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6976
7070
|
const why = token === null || secret === null ? "came back in an unexpected shape and" : `could not be written to secret_env_file (${failure?.why ?? "unknown"}), and`;
|
|
6977
7071
|
return refusal(
|
|
6978
7072
|
"CLAIMS_INBOUND_CREDENTIALS_NOT_WRITTEN",
|
|
6979
|
-
`The sandbox inbound endpoint now exists, but ${lost} ${why} the API shows them only once. ` + (secretWritten ? "" : "The secret is lost: rotate_secret: true with a writable secret_env_file recovers a new one. ") + (urlWritten ? "" : "The inbound URL is lost and no route shows it again: rotate_token: true with a writable secret_env_file gives a new one. ") + "
|
|
7073
|
+
`The sandbox inbound endpoint now exists, but ${lost} ${why} the API shows them only once. ` + (secretWritten ? "" : "The secret is lost: rotate_secret: true with a writable secret_env_file recovers a new one. ") + (urlWritten ? "" : "The inbound URL is lost and no route shows it again: rotate_token: true with a writable secret_env_file gives a new one. ") + "Creating again answers 409 while this endpoint exists; delete_endpoint removes it first.",
|
|
6980
7074
|
{ action, written_to: file, url_written: urlWritten, secret_written: secretWritten, ...failure === void 0 ? {} : { why: failure.why }, request_id: answer.requestId }
|
|
6981
7075
|
);
|
|
6982
7076
|
}
|
|
@@ -6997,7 +7091,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6997
7091
|
steps: [
|
|
6998
7092
|
...signingSteps(finalSigning),
|
|
6999
7093
|
`The inbound URL and secret were written to ${file}; set the same two in the claims system's config. Neither is shown again.`,
|
|
7000
|
-
|
|
7094
|
+
`To change the signing config (the header names, the prefix, the encoding), call ${SETUP3} with set_signing: true and the new signing; on a live endpoint Everfur changes it.`
|
|
7001
7095
|
],
|
|
7002
7096
|
needs_event_time: needsEventTime(finalSigning),
|
|
7003
7097
|
local: localState(context, file, scope),
|
|
@@ -7012,15 +7106,16 @@ async function createEndpoint(args, context, ports) {
|
|
|
7012
7106
|
}
|
|
7013
7107
|
async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
7014
7108
|
if (isHosted(context)) return notHosted(SETUP3, "it reads the sandbox endpoint with the sandbox tenant's secret key from a local shell only.");
|
|
7015
|
-
const actions = ["create_endpoint", "rotate_secret", "rotate_token"].filter((name) => args[name] === true);
|
|
7109
|
+
const actions = ["create_endpoint", "rotate_secret", "rotate_token", "set_signing", "delete_endpoint"].filter((name) => args[name] === true);
|
|
7016
7110
|
if (actions.length > 1) {
|
|
7017
7111
|
return refusal(
|
|
7018
7112
|
"CLAIMS_ARGUMENTS_INVALID",
|
|
7019
|
-
`Pass one of create_endpoint, rotate_secret and
|
|
7113
|
+
`Pass one of create_endpoint, rotate_secret, rotate_token, set_signing and delete_endpoint, not ${actions.join(" and ")}: each is its own confirmed action. Nothing was done.`,
|
|
7020
7114
|
{ arguments: [...actions] }
|
|
7021
7115
|
);
|
|
7022
7116
|
}
|
|
7023
7117
|
if (args.create_endpoint === true) return createEndpoint(args, context, ports);
|
|
7118
|
+
if (args.set_signing === true || args.delete_endpoint === true) return changeEndpoint(args, context, ports);
|
|
7024
7119
|
const scope = localScope(context.env, context.cwd);
|
|
7025
7120
|
const rotation = args.rotate_secret === true ? { name: "rotate_secret", envVar: INBOUND_SECRET_ENV, what: "the new secret", value: "secret" } : args.rotate_token === true ? { name: "rotate_token", envVar: INBOUND_URL_ENV, what: "the new inbound URL", value: "URL" } : null;
|
|
7026
7121
|
if (rotation !== null) {
|
|
@@ -7049,7 +7144,7 @@ async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
|
7049
7144
|
steps: [
|
|
7050
7145
|
...signingSteps(signing),
|
|
7051
7146
|
`${URL_SHOWN_ONCE} Keep it in the claims system's config too.`,
|
|
7052
|
-
|
|
7147
|
+
`To change the signing config (the header names, the prefix, the encoding), call ${SETUP3} with set_signing: true and the new signing; on a live endpoint Everfur changes it.`
|
|
7053
7148
|
],
|
|
7054
7149
|
needs_event_time: needsEventTime(signing),
|
|
7055
7150
|
local: localState(context, args.secret_env_file, scope)
|
|
@@ -7100,6 +7195,95 @@ async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
|
7100
7195
|
}
|
|
7101
7196
|
};
|
|
7102
7197
|
}
|
|
7198
|
+
async function changeEndpoint(args, context, ports) {
|
|
7199
|
+
const action = args.set_signing === true ? "set_signing" : "delete_endpoint";
|
|
7200
|
+
const nothing = action === "set_signing" ? "Nothing was changed." : "Nothing was deleted.";
|
|
7201
|
+
const missing = [action === "set_signing" && args.signing === void 0 ? "signing" : null, args.confirm !== true ? "confirm" : null].filter((name) => name !== null);
|
|
7202
|
+
if (missing.length > 0) {
|
|
7203
|
+
return refusal(
|
|
7204
|
+
"CLAIMS_ARGUMENTS_INVALID",
|
|
7205
|
+
`${action} needs ${missing.join(" and ")}: confirm: true is set only when a person has asked for it. ${nothing}`,
|
|
7206
|
+
{ action, arguments: missing }
|
|
7207
|
+
);
|
|
7208
|
+
}
|
|
7209
|
+
const sandbox = sandboxClient(context, ports);
|
|
7210
|
+
if (!isSandbox(sandbox)) return sandbox;
|
|
7211
|
+
const read = await readEndpoint(sandbox, action);
|
|
7212
|
+
if ("isError" in read) return read;
|
|
7213
|
+
const signing = args.signing;
|
|
7214
|
+
const gate = await humanGate(context, ports, action === "set_signing" ? {
|
|
7215
|
+
action,
|
|
7216
|
+
subject: JSON.stringify([read.endpoint.endpoint_id, signing]),
|
|
7217
|
+
summary: `Change the sandbox inbound endpoint's signing to ${describeSigning(signing)}. Events signed the old way are refused (401) from then on; the URL and secret stay the same.`,
|
|
7218
|
+
code: args.confirmation_code
|
|
7219
|
+
} : {
|
|
7220
|
+
action,
|
|
7221
|
+
subject: JSON.stringify([read.endpoint.endpoint_id]),
|
|
7222
|
+
summary: "Delete the sandbox inbound endpoint. Its URL answers 404 at once; the event log and mappings stay, and create_endpoint makes a new URL and secret.",
|
|
7223
|
+
code: args.confirmation_code
|
|
7224
|
+
}, nothing);
|
|
7225
|
+
if (gate !== null) return gate;
|
|
7226
|
+
const scope = localScope(context.env, context.cwd);
|
|
7227
|
+
if (action === "delete_endpoint") {
|
|
7228
|
+
const answer2 = await sandbox.client.request({ method: "DELETE", path: `${INBOUND_SANDBOX_ROUTE}/endpoint`, credentials: sandbox.credentials });
|
|
7229
|
+
if (!answer2.ok) return inboundFailure(answer2, action, ENDPOINT_404);
|
|
7230
|
+
return {
|
|
7231
|
+
isError: false,
|
|
7232
|
+
document: {
|
|
7233
|
+
ok: true,
|
|
7234
|
+
endpoint: { endpoint_id: read.endpoint.endpoint_id, deleted: true },
|
|
7235
|
+
steps: [
|
|
7236
|
+
`The sandbox inbound endpoint was deleted; its URL answers 404 now. ${INBOUND_URL_ENV} and ${INBOUND_SECRET_ENV} in local env files no longer work.`,
|
|
7237
|
+
`The event log and the mappings stay. Create a new endpoint with ${SETUP3} (create_endpoint: true, signing, secret_env_file, confirm: true from a person).`
|
|
7238
|
+
],
|
|
7239
|
+
local: localState(context, args.secret_env_file, scope)
|
|
7240
|
+
}
|
|
7241
|
+
};
|
|
7242
|
+
}
|
|
7243
|
+
const answer = await sandbox.client.request({
|
|
7244
|
+
method: "PUT",
|
|
7245
|
+
path: `${INBOUND_SANDBOX_ROUTE}/endpoint/signing`,
|
|
7246
|
+
credentials: sandbox.credentials,
|
|
7247
|
+
body: signing,
|
|
7248
|
+
acceptStatuses: [409, 422]
|
|
7249
|
+
});
|
|
7250
|
+
if (!answer.ok) return inboundFailure(answer, action, ENDPOINT_404);
|
|
7251
|
+
const refusedCode = answer.status >= 400 ? bodyCode(answer.value) : null;
|
|
7252
|
+
if (refusedCode === "event_time_mapping_required") {
|
|
7253
|
+
return refusal(
|
|
7254
|
+
"CLAIMS_MAPPING_INVALID",
|
|
7255
|
+
"The new signing signs no time (a body-only signature or a secret header), and the active mapping names no event_time, so the API refused it (event_time_mapping_required). Nothing was changed. Keep signed_payload timestamp_body, or add event_time to the mapping and activate it first.",
|
|
7256
|
+
{ action, status: answer.status, code: refusedCode, request_id: answer.requestId }
|
|
7257
|
+
);
|
|
7258
|
+
}
|
|
7259
|
+
if (refusedCode === "body_invalid" || refusedCode === "signing_mode_sandbox_only") {
|
|
7260
|
+
return refusal(
|
|
7261
|
+
"CLAIMS_ARGUMENTS_INVALID",
|
|
7262
|
+
`The API refused the signing config (${refusedCode}). Nothing was changed.`,
|
|
7263
|
+
{ action, arguments: ["signing"], code: refusedCode, problems: bodyInvalidErrors(answer.value), request_id: answer.requestId }
|
|
7264
|
+
);
|
|
7265
|
+
}
|
|
7266
|
+
if (answer.status >= 400) return unexpectedRefusal(answer, action, nothing);
|
|
7267
|
+
const view = ENDPOINT_VIEW.safeParse(answer.value);
|
|
7268
|
+
const stored = view.success ? SIGNING_CONFIG.safeParse(view.data.signing) : null;
|
|
7269
|
+
const finalSigning = stored !== null && stored.success ? stored.data : signing;
|
|
7270
|
+
return {
|
|
7271
|
+
isError: false,
|
|
7272
|
+
document: {
|
|
7273
|
+
ok: true,
|
|
7274
|
+
endpoint: {
|
|
7275
|
+
endpoint_id: read.endpoint.endpoint_id,
|
|
7276
|
+
previous_secret_expires_at: view.success ? view.data.previous_secret_expires_at ?? null : null,
|
|
7277
|
+
created_at: view.success ? view.data.created_at ?? null : null,
|
|
7278
|
+
rotated_at: view.success ? view.data.rotated_at ?? null : null
|
|
7279
|
+
},
|
|
7280
|
+
signing: finalSigning,
|
|
7281
|
+
steps: [...signingSteps(finalSigning), "The signing changed now: set the claims system to sign this way before it sends again. The URL and secret are unchanged."],
|
|
7282
|
+
needs_event_time: needsEventTime(finalSigning),
|
|
7283
|
+
local: localState(context, args.secret_env_file, scope)
|
|
7284
|
+
}
|
|
7285
|
+
};
|
|
7286
|
+
}
|
|
7103
7287
|
async function rotateToken(args, context, ports, sandbox, endpointId, document, scope) {
|
|
7104
7288
|
const file = args.secret_env_file;
|
|
7105
7289
|
const gate = await humanGate(context, ports, {
|
|
@@ -7981,7 +8165,7 @@ function sandboxFailure(failure, action, capability) {
|
|
|
7981
8165
|
if (failure.status === 404 && (failure.code === null || failure.code === "ResourceNotFoundException")) {
|
|
7982
8166
|
return refusal(
|
|
7983
8167
|
"CLAIMS_SANDBOX_NOT_ENABLED",
|
|
7984
|
-
"The sandbox webhook routes answered 404:
|
|
8168
|
+
"The sandbox webhook routes answered 404: outbound webhooks are not switched on for this deployment or for this tenant (its plan's webhooks feature), or the endpoint_id names no endpoint of this tenant. Switching them on is a setting Everfur holds. A receiver still in development on this machine is checked with everfur_verify_claims_receiver (allow_localhost: true) instead; test events go only to a public https URL.",
|
|
7985
8169
|
details
|
|
7986
8170
|
);
|
|
7987
8171
|
}
|
|
@@ -10083,14 +10267,15 @@ a field mapping turns them into claims, documents and pet profiles. everfur_prop
|
|
|
10083
10267
|
mapping from sample native events, offline, with the gaps and the personal data paths to scrub;
|
|
10084
10268
|
everfur_save_claims_mapping saves it as the sandbox draft, and activates the draft only with confirm: true and the
|
|
10085
10269
|
confirmation phrase typed back by a person who has read it, never on the agent's own initiative. Activating, creating
|
|
10086
|
-
the inbound endpoint, rotating its secret or its URL token and creating an outbound test endpoint each also need the person's own
|
|
10270
|
+
the inbound endpoint, rotating its secret or its URL token, changing its signing, deleting it and creating an outbound test endpoint each also need the person's own
|
|
10087
10271
|
answer: the client asks them when it can; otherwise the tool writes a one-time code to a local file and answers with
|
|
10088
10272
|
its path, and the person types the code back as confirmation_code. Never open that file yourself.
|
|
10089
10273
|
everfur_claims_inbound_signing_setup explains the endpoint's signing as steps for the claims system and can rotate the
|
|
10090
|
-
sandbox secret, or the URL token after the URL leaks, into a local env file. The sandbox key can create the sandbox inbound endpoint
|
|
10091
|
-
everfur_claims_inbound_signing_setup with create_endpoint, signing, secret_env_file and confirm: true, set only when
|
|
10274
|
+
sandbox secret, or the URL token after the URL leaks, into a local env file. The sandbox key can create the sandbox inbound endpoint
|
|
10275
|
+
(one per tenant): everfur_claims_inbound_signing_setup with create_endpoint, signing, secret_env_file and confirm: true, set only when
|
|
10092
10276
|
a person asks for it; its URL and first secret are shown once and are written to that file as
|
|
10093
|
-
EVERFUR_CLAIMS_INBOUND_URL and EVERFUR_CLAIMS_INBOUND_SECRET, never returned.
|
|
10277
|
+
EVERFUR_CLAIMS_INBOUND_URL and EVERFUR_CLAIMS_INBOUND_SECRET, never returned. With confirm: true from a person, set_signing
|
|
10278
|
+
changes the sandbox endpoint's signing config and delete_endpoint deletes it (the event log and mappings stay). Live inbound endpoints are set up by
|
|
10094
10279
|
Everfur, with their signing and the live mapping. everfur_send_claims_inbound_samples signs synthetic samples, posts them to the
|
|
10095
10280
|
sandbox inbound URL and reports each event's status, reason code and fix; with read_event_log it sends nothing and
|
|
10096
10281
|
reads the sandbox event log, for events the claims system itself sent. The tools that read the sandbox tenant's
|
|
@@ -10345,7 +10530,7 @@ function buildServer(context, ports = {}, options = {}) {
|
|
|
10345
10530
|
"everfur_claims_inbound_signing_setup",
|
|
10346
10531
|
{
|
|
10347
10532
|
title: TOOL_ANNOTATIONS.everfur_claims_inbound_signing_setup.title,
|
|
10348
|
-
description: "Read the sandbox inbound claims endpoint's signing config and explain, as plain steps, how the insurer's claims system must sign each event (HMAC-SHA256 over the timestamp and body or the body alone, hex or base64, the header names and prefix; or the secret in a header), plus whether the shared secret and inbound URL are set locally. With rotate_secret: true it rotates the sandbox secret and writes the new one to secret_env_file (mode 600); the secret is never returned. With rotate_token: true, after the inbound URL leaked, it rotates the URL token and writes the new URL to secret_env_file as EVERFUR_CLAIMS_INBOUND_URL (the old URL answers 404 at once); the URL is never returned. With create_endpoint: true, signing and confirm: true (set only when a person asks;
|
|
10533
|
+
description: "Read the sandbox inbound claims endpoint's signing config and explain, as plain steps, how the insurer's claims system must sign each event (HMAC-SHA256 over the timestamp and body or the body alone, hex or base64, the header names and prefix; or the secret in a header), plus whether the shared secret and inbound URL are set locally. With rotate_secret: true it rotates the sandbox secret and writes the new one to secret_env_file (mode 600); the secret is never returned. With rotate_token: true, after the inbound URL leaked, it rotates the URL token and writes the new URL to secret_env_file as EVERFUR_CLAIMS_INBOUND_URL (the old URL answers 404 at once); the URL is never returned. With create_endpoint: true, signing and confirm: true (set only when a person asks; one endpoint per tenant) it creates the sandbox inbound endpoint and writes its URL and first secret, shown once, to secret_env_file as EVERFUR_CLAIMS_INBOUND_URL and EVERFUR_CLAIMS_INBOUND_SECRET (mode 600); neither is returned. With set_signing: true, signing and confirm: true it changes the sandbox endpoint's signing config (URL and secret unchanged); with delete_endpoint: true and confirm: true it deletes the sandbox endpoint (its URL answers 404 at once; the event log and mappings stay). Live inbound endpoints are set up by Everfur. Create, set_signing, delete and each rotation also need the person's own confirmation (the client asks them, or they type back a one-time code from a local file as confirmation_code). Sandbox key from a local shell only.",
|
|
10349
10534
|
inputSchema: CLAIMS_INBOUND_SIGNING_SETUP_INPUT_SHAPE,
|
|
10350
10535
|
outputSchema: CLAIMS_INBOUND_SIGNING_SETUP_OUTPUT_SHAPE,
|
|
10351
10536
|
annotations: { ...TOOL_ANNOTATIONS.everfur_claims_inbound_signing_setup }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { buildServer } from './chunk-
|
|
3
|
+
import { buildServer } from './chunk-G7CJK7Z5.js';
|
|
4
4
|
import { createServer } from 'http';
|
|
5
5
|
import { timingSafeEqual } from 'crypto';
|
|
6
6
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
@@ -5476,7 +5476,7 @@ function booleanAttribute(outcome, key) {
|
|
|
5476
5476
|
}
|
|
5477
5477
|
|
|
5478
5478
|
// src/version.ts
|
|
5479
|
-
var CLI_VERSION = "0.9.
|
|
5479
|
+
var CLI_VERSION = "0.9.2";
|
|
5480
5480
|
var CLI_PUBLISHED_VERSION = "0.9.0";
|
|
5481
5481
|
|
|
5482
5482
|
// src/commands/diagnose/reasons.ts
|
|
@@ -13973,8 +13973,8 @@ function planIntegration(input) {
|
|
|
13973
13973
|
// src/registry/sdk/client/contract/contract.generated.ts
|
|
13974
13974
|
var CONTRACT_SOURCE = Object.freeze({
|
|
13975
13975
|
digestAlgorithm: "sha256",
|
|
13976
|
-
digest: "
|
|
13977
|
-
generatedAt: "2026-
|
|
13976
|
+
digest: "af9a9a3f89b48449238033ef3227df17ccfcc3b81308764a212d25b61a4994cf",
|
|
13977
|
+
generatedAt: "2026-11-02T13:18:35Z",
|
|
13978
13978
|
capabilitySchemaVersion: 1,
|
|
13979
13979
|
errorSchemaVersion: 1
|
|
13980
13980
|
});
|
|
@@ -14499,7 +14499,7 @@ var MANIFEST_default = {
|
|
|
14499
14499
|
files: [
|
|
14500
14500
|
{
|
|
14501
14501
|
path: "client/contract/contract.generated.ts",
|
|
14502
|
-
sha256: "
|
|
14502
|
+
sha256: "453c2dc536c4e1198a747a184e0f8ac60409e53ed0ed1940ebb2304f51bb75d2"
|
|
14503
14503
|
},
|
|
14504
14504
|
{
|
|
14505
14505
|
path: "client/errors/EverfurError.ts",
|
|
@@ -17233,7 +17233,7 @@ var MEANINGS = Object.freeze({
|
|
|
17233
17233
|
},
|
|
17234
17234
|
CLAIMS_SANDBOX_NOT_ENABLED: {
|
|
17235
17235
|
tools: [CLAIMS_SANDBOX, ...CLAIMS_INBOUND],
|
|
17236
|
-
meaning: "The sandbox route answered 404 with no code of its own: the sandbox webhook or claims-inbound routes are not switched on for this tenant or deployment, the endpoint_id names no endpoint of this tenant, or (inbound) the tenant has no claims portal or no inbound endpoint exists yet. The sandbox key can create the sandbox inbound endpoint
|
|
17236
|
+
meaning: "The sandbox route answered 404 with no code of its own: the sandbox webhook or claims-inbound routes are not switched on for this tenant or deployment, the endpoint_id names no endpoint of this tenant, or (inbound) the tenant has no claims portal or no inbound endpoint exists yet. The sandbox key can create the sandbox inbound endpoint (one per tenant) (everfur_claims_inbound_signing_setup, create_endpoint with confirm: true from a person); its inbound URL and first secret are shown once, at creation. Live inbound endpoints are set up by Everfur.",
|
|
17237
17237
|
nextAction: "Check the endpoint_id with list_endpoints; when list_endpoints itself answers this, switching the routes on is a step Everfur holds. When an inbound route answers it and the routes are on, the sandbox endpoint may not exist yet: offer create_endpoint, and create it only when a person confirms."
|
|
17238
17238
|
},
|
|
17239
17239
|
CLAIMS_SANDBOX_CALL_FAILED: {
|
|
@@ -17293,13 +17293,13 @@ var MEANINGS = Object.freeze({
|
|
|
17293
17293
|
},
|
|
17294
17294
|
CLAIMS_INBOUND_CREATE_CONFIRMATION_REQUIRED: {
|
|
17295
17295
|
tools: [CLAIMS_SETUP],
|
|
17296
|
-
meaning: "create_endpoint was called without confirm: true. Creating the sandbox inbound endpoint
|
|
17296
|
+
meaning: "create_endpoint was called without confirm: true. Creating the sandbox inbound endpoint shows its URL and secret once, and a tenant has one endpoint (delete_endpoint removes it), so a person decides it. Nothing was created.",
|
|
17297
17297
|
nextAction: "Show the developer the signing config; call create_endpoint with confirm: true only when a person asks for it. Never confirm on your own."
|
|
17298
17298
|
},
|
|
17299
17299
|
CLAIMS_INBOUND_ENDPOINT_EXISTS: {
|
|
17300
17300
|
tools: [CLAIMS_SETUP],
|
|
17301
17301
|
meaning: "The create answered 409 endpoint_exists: this sandbox tenant already has its inbound endpoint, whose URL was shown once, at creation. Nothing was created.",
|
|
17302
|
-
nextAction: "Tell the developer to set EVERFUR_CLAIMS_INBOUND_URL from where they saved it, and offer rotate_secret for a new secret or rotate_token for a new URL."
|
|
17302
|
+
nextAction: "Tell the developer to set EVERFUR_CLAIMS_INBOUND_URL from where they saved it, and offer rotate_secret for a new secret or rotate_token for a new URL; to start over, delete_endpoint (a person confirms) then create again."
|
|
17303
17303
|
},
|
|
17304
17304
|
CLAIMS_INBOUND_CREDENTIALS_NOT_WRITTEN: {
|
|
17305
17305
|
tools: [CLAIMS_SETUP],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { VERIFY_IDENTITY_MODES, SURFACES, ENVIRONMENTS, BASE_URL_ENV_VAR, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, ALL_CAPABILITIES, expandCapabilities, errorOutcome, describeFailure, failureDetails, countsAsNotOn, diagnoseVerdict, isJsonObject, succeed, CAPABILITY_QUESTION, CAPABILITIES_TREE, WEB_EMBEDDING_QUESTION, PLATFORM_TREE, loadDecisionSpace, fetchContract, contractUnavailableOutcome, loadDecisionSpaceFromContract, parseEnvironment, checkTenantMode, detectProject, planIntegration, fail, ExitCode, DOCS_KEY, resolveContractPath, validateContractFile, buildSupportBundle, renderSupportBundle, chooseWidgetAuth, DIAGNOSTICS_PATH, diagnoseFailure, parseDiagnostics, buildDiagnosisDocument, PARTNER_KEY, SESSION_TOKEN, resolveCredential, ADMIN_TOKEN, withPrefix, parseOrigin, parseLoaderUrl, parseSurfaces, parseIdentityMode, runVerification, PARTNER_SECRET_KEY, resolveOffline, resolveWithoutRegistry, knownCodes, loadErrorRegistryFromContract, loadErrorRegistry, resolveAfterRegistryMiss, registryAlsoIn, buildExplanationDocument, renderExplanation, alsoInLines, resolveEndpoint, isCorrelatableRequestId, EMPTY_REGISTRY, createApiClient, offlineDocument, renderOffline, IDENTITY_QUESTION, IDENTITY_TREE, BACKEND_LANGUAGE_QUESTION, SESSION_MINT_TREE, CREDENTIAL_SPECS } from './chunk-
|
|
3
|
+
import { VERIFY_IDENTITY_MODES, SURFACES, ENVIRONMENTS, BASE_URL_ENV_VAR, MIN_TIMEOUT_MS, MAX_TIMEOUT_MS, DEFAULT_TIMEOUT_MS, ALL_CAPABILITIES, expandCapabilities, errorOutcome, describeFailure, failureDetails, countsAsNotOn, diagnoseVerdict, isJsonObject, succeed, CAPABILITY_QUESTION, CAPABILITIES_TREE, WEB_EMBEDDING_QUESTION, PLATFORM_TREE, loadDecisionSpace, fetchContract, contractUnavailableOutcome, loadDecisionSpaceFromContract, parseEnvironment, checkTenantMode, detectProject, planIntegration, fail, ExitCode, DOCS_KEY, resolveContractPath, validateContractFile, buildSupportBundle, renderSupportBundle, chooseWidgetAuth, DIAGNOSTICS_PATH, diagnoseFailure, parseDiagnostics, buildDiagnosisDocument, PARTNER_KEY, SESSION_TOKEN, resolveCredential, ADMIN_TOKEN, withPrefix, parseOrigin, parseLoaderUrl, parseSurfaces, parseIdentityMode, runVerification, PARTNER_SECRET_KEY, resolveOffline, resolveWithoutRegistry, knownCodes, loadErrorRegistryFromContract, loadErrorRegistry, resolveAfterRegistryMiss, registryAlsoIn, buildExplanationDocument, renderExplanation, alsoInLines, resolveEndpoint, isCorrelatableRequestId, EMPTY_REGISTRY, createApiClient, offlineDocument, renderOffline, IDENTITY_QUESTION, IDENTITY_TREE, BACKEND_LANGUAGE_QUESTION, SESSION_MINT_TREE, CREDENTIAL_SPECS } from './chunk-VSZ4RPKA.js';
|
|
4
4
|
import { isAbsolute, resolve } from 'path';
|
|
5
5
|
|
|
6
6
|
// src/cli/format.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { loadHostedMcpConfig, startHostedMcpServer } from './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
6
|
-
import { CLI_VERSION } from './chunk-
|
|
3
|
+
import { loadHostedMcpConfig, startHostedMcpServer } from './chunk-5GXXNW3F.js';
|
|
4
|
+
import './chunk-LH4AWYCB.js';
|
|
5
|
+
import './chunk-G7CJK7Z5.js';
|
|
6
|
+
import { CLI_VERSION } from './chunk-VSZ4RPKA.js';
|
|
7
7
|
|
|
8
8
|
// src/bin/everfur-mcp-hosted.ts
|
|
9
9
|
async function main() {
|
package/dist/everfur-mcp-http.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { startRemoteMcpServer, loadRemoteMcpConfig } from './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import { CLI_VERSION } from './chunk-
|
|
3
|
+
import { startRemoteMcpServer, loadRemoteMcpConfig } from './chunk-LH4AWYCB.js';
|
|
4
|
+
import './chunk-G7CJK7Z5.js';
|
|
5
|
+
import { CLI_VERSION } from './chunk-VSZ4RPKA.js';
|
|
6
6
|
|
|
7
7
|
// src/bin/everfur-mcp-http.ts
|
|
8
8
|
async function main() {
|
package/dist/everfur-mcp.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { runStdioServer } from './chunk-
|
|
4
|
-
import { CLI_VERSION } from './chunk-
|
|
3
|
+
import { runStdioServer } from './chunk-G7CJK7Z5.js';
|
|
4
|
+
import { CLI_VERSION } from './chunk-VSZ4RPKA.js';
|
|
5
5
|
|
|
6
6
|
// src/bin/everfur-mcp.ts
|
|
7
7
|
if (process.argv.slice(2).includes("--version")) {
|
package/dist/everfur.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
import { runCli } from './chunk-
|
|
4
|
-
import { ExitCode, systemClock, fetchTransport, CLI_VERSION, nodeFileSystem, nodeContractCache } from './chunk-
|
|
3
|
+
import { runCli } from './chunk-WL42DEHE.js';
|
|
4
|
+
import { ExitCode, systemClock, fetchTransport, CLI_VERSION, nodeFileSystem, nodeContractCache } from './chunk-VSZ4RPKA.js';
|
|
5
5
|
|
|
6
6
|
// src/bin/everfur.ts
|
|
7
7
|
async function main() {
|
package/dist/index.d.ts
CHANGED
|
@@ -3651,6 +3651,6 @@ declare function parseSuppliedFacts(capabilitiesRaw: string | null, identityRaw:
|
|
|
3651
3651
|
* install, and a bundled artifact. `tests/unit/version.test.ts` asserts this constant equals
|
|
3652
3652
|
* the package.json version, so the two cannot drift.
|
|
3653
3653
|
*/
|
|
3654
|
-
declare const CLI_VERSION = "0.9.
|
|
3654
|
+
declare const CLI_VERSION = "0.9.2";
|
|
3655
3655
|
|
|
3656
3656
|
export { ADMIN_TOKEN, API_PREFIX, type ApiClient, type ApiFailure, type ApiResult, type ApiSuccess, BASE_URL_ENV_VAR, type BlockedCapability, type BlockedOutcome, CLI_VERSION, COMMANDS, CREDENTIAL_SPECS, type Capability, type CapabilityDiagnosis, type ClockPort, type Command, type CommandContext, type CommandOutcome, type ContractValidationOutcome, type Credential, type CredentialSpec, DEFAULT_TIMEOUT_MS, type DecisionSpace, type DecisionSpaceProvenance, type DecisionTree, type DetectedDependency, type DetectedTheme, type Diagnosis, EMPTY_REGISTRY, ERRORS_DOCUMENT_KEY, type ErrorRegistry, type ErrorRegistryEntry, ExitCode, type FileSystemPort, type FormatOptions, type FormattedOutput, type HttpMethod, type HttpRequest, type HttpResponse, IDEMPOTENT_METHODS, type IdentityMode, MISSING_FACT_NAMES, type MissingFact, type MissingFactName, type Outcome, PARTNER_KEY, PARTNER_SECRET_KEY, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, type PackageManager, type PlanDocument, type PlanInput, type PlanPrinciple, type PlanStep, type PlanWarning, type PositionalSpec, type ProjectDetection, type ProjectType, REASON_CODES, REDACTED, type ReasonCode, type RegistryLoad, type RequestSpec, type ResolvedCredential, type ResolvedEndpoint, type RunOptions, SCHEMAS, SESSION_TOKEN, type SandboxCreateStatus, type SandboxCreation, type SchemaValidation, type SchemaViolation, type SessionMintLanguage, type StepResult, THEME_TOKEN_ORDER, type TerminalOutcome, type ThemeConfidence, type ThemeDetection, type ThemeEvidence, type ThemeSource, type ThemeToken, TransportError, type TransportPort, type TreeOption, type TreeQuestion, type Verification, type VerifyStep, type WalkResult, apiUrl, buildDecisionSpace, buildDiagnosisDocument, buildExplanationDocument, buildSandboxDocument, buildVerificationDocument, clampTimeout, createApiClient, createMemoryFileSystem, createRecordingClock, describeFailure, detectProject, detectTheme, detectThemeFromText, digestOfProjection, digestsEqual, editDistance, entryFromRow, ephemeralCredential, errorCodeOf, failureDetails, failureOutcome, fetchTransport, formatOutcome, isCorrelatableRequestId, isIdempotent, isKnownReasonCode, loadDecisionSpace, loadErrorRegistry, matchCommand, missingFactsFor, nextActionFor as nextActionForErrorCode, nextActionFor$1 as nextActionForReason, nextActionsFor, nodeFileSystem, parseCapabilities, parseDiagnostics, parseIdentityMode, parseSessionMintLanguage, parseSuppliedFacts, planIntegration, projectSandboxCreate, renderDiagnosis, renderExplanation, renderPlan, renderSandboxCreate, renderVerification, resolveContractPath, resolveCredential, resolveEndpoint, runCli, runVerification, suggestCodes, systemClock, validateContractFile, validateContractPublicEnvelope, validateDiagnosisDocument, validateErrorExplanationDocument, validatePlanDocument, validateSandboxCreateDocument, validateVerificationDocument, verifyDigest, walkSingle, walkTree, withPrefix };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*! @everfur/cli. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
3
|
-
export { COMMANDS, buildSandboxDocument, buildVerificationDocument, failureOutcome, formatOutcome, matchCommand, nextActionsFor, parseCapabilities, parseIdentityMode, parseSessionMintLanguage, parseSuppliedFacts, projectSandboxCreate, renderDiagnosis, renderPlan, renderSandboxCreate, renderVerification, runCli } from './chunk-
|
|
4
|
-
export { ADMIN_TOKEN, API_PREFIX, BASE_URL_ENV_VAR, CLI_VERSION, CREDENTIAL_SPECS, DEFAULT_TIMEOUT_MS, EMPTY_REGISTRY, ERRORS_DOCUMENT_KEY, ExitCode, IDEMPOTENT_METHODS, MISSING_FACT_NAMES, PARTNER_KEY, PARTNER_SECRET_KEY, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, REASON_CODES, REDACTED, SCHEMAS, SESSION_TOKEN, THEME_TOKEN_ORDER, TransportError, apiUrl, buildDecisionSpace, buildDiagnosisDocument, buildExplanationDocument, clampTimeout, createApiClient, createMemoryFileSystem, createRecordingClock, describeFailure, detectProject, detectTheme, detectThemeFromText, digestOfProjection, digestsEqual, editDistance, entryFromRow, ephemeralCredential, errorCodeOf, failureDetails, fetchTransport, isCorrelatableRequestId, isIdempotent, isKnownReasonCode, loadDecisionSpace, loadErrorRegistry, missingFactsFor, nextActionFor2 as nextActionForErrorCode, nextActionFor as nextActionForReason, nodeFileSystem, parseDiagnostics, planIntegration, renderExplanation, resolveContractPath, resolveCredential, resolveEndpoint, runVerification, suggestCodes, systemClock, validateContractFile, validateContractPublicEnvelope, validateDiagnosisDocument, validateErrorExplanationDocument, validatePlanDocument, validateSandboxCreateDocument, validateVerificationDocument, verifyDigest, walkSingle, walkTree, withPrefix } from './chunk-
|
|
3
|
+
export { COMMANDS, buildSandboxDocument, buildVerificationDocument, failureOutcome, formatOutcome, matchCommand, nextActionsFor, parseCapabilities, parseIdentityMode, parseSessionMintLanguage, parseSuppliedFacts, projectSandboxCreate, renderDiagnosis, renderPlan, renderSandboxCreate, renderVerification, runCli } from './chunk-WL42DEHE.js';
|
|
4
|
+
export { ADMIN_TOKEN, API_PREFIX, BASE_URL_ENV_VAR, CLI_VERSION, CREDENTIAL_SPECS, DEFAULT_TIMEOUT_MS, EMPTY_REGISTRY, ERRORS_DOCUMENT_KEY, ExitCode, IDEMPOTENT_METHODS, MISSING_FACT_NAMES, PARTNER_KEY, PARTNER_SECRET_KEY, PLAN_DOCUMENT_KIND, PLAN_SCHEMA_VERSION, REASON_CODES, REDACTED, SCHEMAS, SESSION_TOKEN, THEME_TOKEN_ORDER, TransportError, apiUrl, buildDecisionSpace, buildDiagnosisDocument, buildExplanationDocument, clampTimeout, createApiClient, createMemoryFileSystem, createRecordingClock, describeFailure, detectProject, detectTheme, detectThemeFromText, digestOfProjection, digestsEqual, editDistance, entryFromRow, ephemeralCredential, errorCodeOf, failureDetails, fetchTransport, isCorrelatableRequestId, isIdempotent, isKnownReasonCode, loadDecisionSpace, loadErrorRegistry, missingFactsFor, nextActionFor2 as nextActionForErrorCode, nextActionFor as nextActionForReason, nodeFileSystem, parseDiagnostics, planIntegration, renderExplanation, resolveContractPath, resolveCredential, resolveEndpoint, runVerification, suggestCodes, systemClock, validateContractFile, validateContractPublicEnvelope, validateDiagnosisDocument, validateErrorExplanationDocument, validatePlanDocument, validateSandboxCreateDocument, validateVerificationDocument, verifyDigest, walkSingle, walkTree, withPrefix } from './chunk-VSZ4RPKA.js';
|
package/package.json
CHANGED