@everfur/cli 0.9.0 → 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-UZZJUV5A.js → chunk-5GXXNW3F.js} +3 -3
- package/dist/{chunk-J7SL4FA7.js → chunk-G7CJK7Z5.js} +288 -59
- package/dist/{chunk-JI6USLIZ.js → chunk-LH4AWYCB.js} +1 -1
- package/dist/{chunk-OHA3JVME.js → chunk-VSZ4RPKA.js} +10 -10
- package/dist/{chunk-UROEKBHB.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));
|
|
@@ -1956,8 +1989,16 @@ var INBOUND_CODES = Object.freeze([
|
|
|
1956
1989
|
"inbound_sandbox",
|
|
1957
1990
|
409,
|
|
1958
1991
|
"fix_mapping",
|
|
1959
|
-
"The endpoint's signing has no signed time (a body-only signature or a secret header), and the mapping names no event_time, so
|
|
1960
|
-
"Add event_time to the mapping, save it and activate again."
|
|
1992
|
+
"The endpoint's signing has no signed time (a body-only signature or a secret header), and the mapping names no event_time, so the mapping cannot be activated, or an endpoint with that signing cannot be created.",
|
|
1993
|
+
"Add event_time to the mapping, save it and activate it, then create the endpoint or activate again. Or sign over a timestamp (hmac with signed_payload timestamp_body)."
|
|
1994
|
+
),
|
|
1995
|
+
inbound(
|
|
1996
|
+
"endpoint_exists",
|
|
1997
|
+
"inbound_sandbox",
|
|
1998
|
+
409,
|
|
1999
|
+
"stop",
|
|
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.",
|
|
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.`
|
|
1961
2002
|
),
|
|
1962
2003
|
inbound(
|
|
1963
2004
|
"events_invalid",
|
|
@@ -2044,8 +2085,13 @@ var CLAIMS_EVENT_TYPES = Object.freeze([
|
|
|
2044
2085
|
"claim.failed",
|
|
2045
2086
|
"claim.duplicate",
|
|
2046
2087
|
"claim.decided",
|
|
2088
|
+
"insured_pet.profile.ready",
|
|
2089
|
+
"insured_pet.profile.updated",
|
|
2047
2090
|
"webhook_endpoint.test"
|
|
2048
2091
|
]);
|
|
2092
|
+
var CLAIMS_TESTABLE_EVENT_TYPES = Object.freeze(
|
|
2093
|
+
CLAIMS_EVENT_TYPES.filter((type) => !type.startsWith("insured_pet."))
|
|
2094
|
+
);
|
|
2049
2095
|
var CLAIMS_DELIVERY_TIMEOUT_SECONDS = 10;
|
|
2050
2096
|
var CLAIMS_RECEIVER_SLOW_SECONDS = 5;
|
|
2051
2097
|
var CLAIMS_ROUTES = Object.freeze({
|
|
@@ -2947,6 +2993,12 @@ export async function processEverfurEvent(
|
|
|
2947
2993
|
if (claimId === null) return;
|
|
2948
2994
|
await store.saveClaimEvent(claimId, event.type, data);
|
|
2949
2995
|
return;
|
|
2996
|
+
case 'insured_pet.profile.ready':
|
|
2997
|
+
case 'insured_pet.profile.updated':
|
|
2998
|
+
// REPLACE: an insured pet's profile, keyed by insured_pet_id (pet_ref can be null). ready comes once, updated once
|
|
2999
|
+
// per later version; keep the highest version. Each field is null when not known; read the full profile from
|
|
3000
|
+
// profile_path. Neither event names a claim or carries a record.
|
|
3001
|
+
return;
|
|
2950
3002
|
default:
|
|
2951
3003
|
// A type this file does not know yet: it was acknowledged, and is logged rather than refused.
|
|
2952
3004
|
console.warn('everfur webhooks: unhandled event type', event.type);
|
|
@@ -3933,6 +3985,11 @@ def process_event(
|
|
|
3933
3985
|
return
|
|
3934
3986
|
kept.save_claim_event(claim_id, event_type, data)
|
|
3935
3987
|
return
|
|
3988
|
+
if event_type in ("insured_pet.profile.ready", "insured_pet.profile.updated"):
|
|
3989
|
+
# REPLACE: an insured pet's profile, keyed by insured_pet_id (pet_ref can be None). ready comes once, updated once
|
|
3990
|
+
# per later version; keep the highest version. Each field is None when not known; read the full profile from
|
|
3991
|
+
# profile_path. Neither event names a claim or carries a record.
|
|
3992
|
+
return
|
|
3936
3993
|
# A type this file does not know yet: it was acknowledged, and is logged rather than refused.
|
|
3937
3994
|
log.warning("everfur webhooks: unhandled event type %s", event_type)
|
|
3938
3995
|
|
|
@@ -4550,7 +4607,7 @@ function rotateDetail() {
|
|
|
4550
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.`;
|
|
4551
4608
|
}
|
|
4552
4609
|
function goLiveDetail() {
|
|
4553
|
-
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.`;
|
|
4554
4611
|
}
|
|
4555
4612
|
function portalDetail() {
|
|
4556
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).`;
|
|
@@ -4997,7 +5054,7 @@ function checkMappingDocument(document) {
|
|
|
4997
5054
|
extraKeys(kind, ["path", "values"], "kind", at);
|
|
4998
5055
|
const path = kind["path"];
|
|
4999
5056
|
if (typeof path !== "string") at("kind.path", "kind.path is required");
|
|
5000
|
-
else
|
|
5057
|
+
else sourcePathProblem(path, "forbidden", [], "kind.path", at);
|
|
5001
5058
|
const values = kind["values"];
|
|
5002
5059
|
if (!isObject(values) || Object.keys(values).length === 0 || Object.keys(values).length > MAX_KIND_VALUES) {
|
|
5003
5060
|
at("kind.values", `kind.values maps 1 to ${MAX_KIND_VALUES} native values to a kind`);
|
|
@@ -5062,6 +5119,8 @@ function checkMappingDocument(document) {
|
|
|
5062
5119
|
extraKeys(listed, ["path", "fields"], `kinds.${name}.${list2}`, at);
|
|
5063
5120
|
if (typeof listed["path"] !== "string") at(`kinds.${name}.${list2}.path`, "a list's path is required");
|
|
5064
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);
|
|
5065
5124
|
const listFields = listed["fields"];
|
|
5066
5125
|
if (!isObject(listFields) || Object.keys(listFields).length === 0 || Object.keys(listFields).length > MAX_LIST_FIELDS) {
|
|
5067
5126
|
at(`kinds.${name}.${list2}.fields`, `a list maps 1 to ${MAX_LIST_FIELDS} targets`);
|
|
@@ -5069,7 +5128,7 @@ function checkMappingDocument(document) {
|
|
|
5069
5128
|
}
|
|
5070
5129
|
for (const [target, field] of Object.entries(listFields)) {
|
|
5071
5130
|
if (!allowed.includes(target)) at(`kinds.${name}.${list2}.fields.${target}`, `${list2} has no target ${target.slice(0, 64)}; targets: ${allowed.join(", ")}`);
|
|
5072
|
-
checkField(field, `kinds.${name}.${list2}.fields.${target}`, at);
|
|
5131
|
+
checkField(field, `kinds.${name}.${list2}.fields.${target}`, at, listKeys);
|
|
5073
5132
|
}
|
|
5074
5133
|
}
|
|
5075
5134
|
}
|
|
@@ -5087,7 +5146,19 @@ function pathProblem(text, star, where, at) {
|
|
|
5087
5146
|
const parsed = parsePath(text, star);
|
|
5088
5147
|
if (typeof parsed === "string") at(where, parsed);
|
|
5089
5148
|
}
|
|
5090
|
-
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 = []) {
|
|
5091
5162
|
if (!isObject(field)) {
|
|
5092
5163
|
at(where, "a field is an object: {path} or {paths}, with optional transforms");
|
|
5093
5164
|
return;
|
|
@@ -5108,7 +5179,8 @@ function checkField(field, where, at) {
|
|
|
5108
5179
|
if (path === void 0 && paths === void 0 && !constant) at(where, "a field needs a path, paths or a leading constant transform");
|
|
5109
5180
|
if (path !== void 0) {
|
|
5110
5181
|
if (typeof path !== "string") at(`${where}.path`, "a path is a string");
|
|
5111
|
-
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);
|
|
5112
5184
|
}
|
|
5113
5185
|
if (paths !== void 0) {
|
|
5114
5186
|
if (!Array.isArray(paths) || paths.length === 0 || paths.length > MAX_FIELD_PATHS) {
|
|
@@ -5116,7 +5188,8 @@ function checkField(field, where, at) {
|
|
|
5116
5188
|
} else {
|
|
5117
5189
|
paths.forEach((text, index) => {
|
|
5118
5190
|
if (typeof text !== "string") at(`${where}.paths[${index}]`, "a path is a string");
|
|
5119
|
-
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);
|
|
5120
5193
|
});
|
|
5121
5194
|
}
|
|
5122
5195
|
}
|
|
@@ -5303,7 +5376,7 @@ var CLAIM_RULES = Object.freeze([
|
|
|
5303
5376
|
{ target: "amount_claimed_cents", scope: "claim", names: ["amountclaimed", "claimedamount", "claimamount", "requestedamount", "amountrequested", "claimed", "requested"], shape: "money", unscoped: true },
|
|
5304
5377
|
{ target: "billed_cents", scope: "claim", names: ["billedamount", "billed", "total", "totalamount", "invoicetotal", "invoiceamount", "amount", "totalbilled", "cost", "charges"], shape: "money", unscoped: true },
|
|
5305
5378
|
{ target: "clinic_name", scope: "clinic", names: ["name", "clinicname", "clinic", "vetname", "hospitalname", "practicename", "providername", "vet", "hospital", "practice", "provider"], shape: "text" },
|
|
5306
|
-
{ 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 },
|
|
5307
5380
|
{ target: "pet.pet_ref", scope: "pet", names: ["petid", "petref", "petnumber", "animalid", "patientid", ...ID_NAMES], shape: "ref" },
|
|
5308
5381
|
{ target: "pet.name", scope: "pet", names: ["name", "petname", "animalname", "patientname", "callname"], shape: "text" },
|
|
5309
5382
|
{ target: "pet.species", scope: "pet", names: ["species", "speciescode", "kind", "type", "animaltype", "pettype", "animalkind"], shape: "species" },
|
|
@@ -5340,7 +5413,7 @@ function rulesFor(kind) {
|
|
|
5340
5413
|
return Object.entries(PROFILE_FROM_CLAIM).map(([target, from]) => ({ ...byTarget.get(from), target }));
|
|
5341
5414
|
}
|
|
5342
5415
|
var DOCUMENT_RULES = Object.freeze([
|
|
5343
|
-
{ 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 },
|
|
5344
5417
|
{ target: "url", scope: null, names: ["url", "link", "href", "uri", "downloadurl", "fileurl", "location", "signedurl", "presignedurl", "download"], shape: "url", unscoped: true },
|
|
5345
5418
|
{ target: "file_name", scope: null, names: ["filename", "name", "title", "documentname", "originalname", "originalfilename", "label"], shape: "file_name", unscoped: true },
|
|
5346
5419
|
{ target: "kind", scope: null, names: ["kind", "category", "type", "documenttype", "doctype", "documentkind", "doccategory", "class"], shape: "doc_kind", unscoped: true },
|
|
@@ -5361,6 +5434,8 @@ var SPECIES_SYNONYMS = Object.freeze({
|
|
|
5361
5434
|
d: "dog",
|
|
5362
5435
|
puppy: "dog",
|
|
5363
5436
|
canin: "dog",
|
|
5437
|
+
can: "dog",
|
|
5438
|
+
cn: "dog",
|
|
5364
5439
|
cat: "cat",
|
|
5365
5440
|
cats: "cat",
|
|
5366
5441
|
feline: "cat",
|
|
@@ -5442,7 +5517,7 @@ function shapeFits(shape, leaf) {
|
|
|
5442
5517
|
case "content_type":
|
|
5443
5518
|
return only("ref", "text", "int", "bool");
|
|
5444
5519
|
case "base64":
|
|
5445
|
-
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, "")));
|
|
5446
5521
|
case "url":
|
|
5447
5522
|
return only("url");
|
|
5448
5523
|
}
|
|
@@ -5707,11 +5782,12 @@ function transformsFor(shape, leaf, order, target, orderDecided = false) {
|
|
|
5707
5782
|
}
|
|
5708
5783
|
return { transforms, why, confidence, reviewNote, untrustedCodes };
|
|
5709
5784
|
}
|
|
5710
|
-
function pick(rule, leaves, used, parentKeys, documentElement = false) {
|
|
5785
|
+
function pick(rule, leaves, used, parentKeys, documentElement = false, ownerRule = true) {
|
|
5711
5786
|
let best = null;
|
|
5712
5787
|
let bestScore = 0;
|
|
5713
5788
|
for (const leaf of leaves) {
|
|
5714
5789
|
if (used.has(leaf.path)) continue;
|
|
5790
|
+
if (ownerRule && ownerPathProblem([...parentKeys, ...leaf.keys]) !== null) continue;
|
|
5715
5791
|
if (rule.target !== "member_ref" && personalData(leaf, parentKeys, documentElement) !== null) continue;
|
|
5716
5792
|
if (rule.target === "member_ref" && (isPiiKey(leaf.keys[leaf.keys.length - 1] ?? "") || leaf.shapes.has("email") || leaf.shapes.has("phone"))) continue;
|
|
5717
5793
|
if (!shapeFits(rule.shape, leaf)) continue;
|
|
@@ -5918,8 +5994,26 @@ function proposeMapping(input) {
|
|
|
5918
5994
|
const pinnedPath = pinned[rule.target];
|
|
5919
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, []);
|
|
5920
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
|
+
}
|
|
5921
6014
|
if (leaf === null) {
|
|
5922
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.` });
|
|
5923
6017
|
continue;
|
|
5924
6018
|
}
|
|
5925
6019
|
if (pinnedPath !== void 0 && personalData(leaf) !== null && rule.target !== "member_ref") {
|
|
@@ -6406,7 +6500,7 @@ function inboundFailure(failure, action, notFound) {
|
|
|
6406
6500
|
}
|
|
6407
6501
|
return sandboxFailure(failure, action);
|
|
6408
6502
|
}
|
|
6409
|
-
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.`;
|
|
6410
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).`;
|
|
6411
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}`;
|
|
6412
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.";
|
|
@@ -6457,21 +6551,28 @@ function mappingSummary(view) {
|
|
|
6457
6551
|
}
|
|
6458
6552
|
function validationErrors(body) {
|
|
6459
6553
|
if (typeof body !== "object" || body === null) return [];
|
|
6460
|
-
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"];
|
|
6461
6557
|
if (!Array.isArray(errors)) return [];
|
|
6462
6558
|
return errors.slice(0, 20).flatMap((item) => {
|
|
6463
6559
|
if (typeof item !== "object" || item === null) return [];
|
|
6464
|
-
const
|
|
6465
|
-
const loc = Array.isArray(
|
|
6466
|
-
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"] : "";
|
|
6467
6563
|
return [{ loc: loc.slice(0, 200), msg: msg.slice(0, 300) }];
|
|
6468
6564
|
});
|
|
6469
6565
|
}
|
|
6470
6566
|
function bodyCode(body) {
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
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
|
+
);
|
|
6475
6576
|
}
|
|
6476
6577
|
var SAMPLE_EVENT = z.record(z.string(), z.unknown());
|
|
6477
6578
|
function loadSamples(samples, files, scope) {
|
|
@@ -6556,7 +6657,16 @@ var PREVIEW_RESULT = z.object({
|
|
|
6556
6657
|
});
|
|
6557
6658
|
async function preview(sandbox, mapping, events, action) {
|
|
6558
6659
|
const body = { ...mapping === void 0 ? {} : { mapping }, events };
|
|
6559
|
-
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
|
+
}
|
|
6560
6670
|
if (!answer.ok) {
|
|
6561
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);
|
|
6562
6672
|
}
|
|
@@ -6633,7 +6743,9 @@ async function proposeClaimsMappingTool(args, context, ports = {}, options = {})
|
|
|
6633
6743
|
} else {
|
|
6634
6744
|
const results = await preview(sandbox, proposal.mapping, loaded.samples, "preview");
|
|
6635
6745
|
if (!Array.isArray(results)) {
|
|
6636
|
-
|
|
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 } };
|
|
6637
6749
|
} else {
|
|
6638
6750
|
const relayed = results.map((item, index) => relayPreview(item, index));
|
|
6639
6751
|
document["server_preview"] = { passed: relayed.every((item) => item["gaps"].length === 0), results: relayed };
|
|
@@ -6708,6 +6820,7 @@ async function saveClaimsMappingTool(args, context, ports = {}) {
|
|
|
6708
6820
|
});
|
|
6709
6821
|
if (!answer2.ok) return inboundFailure(answer2, action, MAPPING_ROUTES_404);
|
|
6710
6822
|
if (answer2.status === 422) {
|
|
6823
|
+
if (bodyCode(answer2.value) !== "mapping_invalid") return unexpectedRefusal(answer2, action, "Nothing was saved.");
|
|
6711
6824
|
return refusal("CLAIMS_MAPPING_INVALID", "The API refused the mapping (mapping_invalid); nothing was saved.", {
|
|
6712
6825
|
action,
|
|
6713
6826
|
problems: validationErrors(answer2.value).map((item) => `${item.loc}: ${item.msg}`),
|
|
@@ -6779,11 +6892,12 @@ async function saveClaimsMappingTool(args, context, ports = {}) {
|
|
|
6779
6892
|
);
|
|
6780
6893
|
}
|
|
6781
6894
|
if (answer.status === 409 || answer.status === 422) {
|
|
6782
|
-
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.");
|
|
6783
6897
|
return refusal(
|
|
6784
6898
|
"CLAIMS_MAPPING_INVALID",
|
|
6785
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.",
|
|
6786
|
-
{ action, code
|
|
6900
|
+
{ action, code, problems: validationErrors(answer.value).map((item) => `${item.loc}: ${item.msg}`), request_id: answer.requestId }
|
|
6787
6901
|
);
|
|
6788
6902
|
}
|
|
6789
6903
|
const view = MAPPING_VIEW.safeParse(answer.value);
|
|
@@ -6797,7 +6911,9 @@ function describeSigning(signing) {
|
|
|
6797
6911
|
var CLAIMS_INBOUND_SIGNING_SETUP_INPUT_SHAPE = {
|
|
6798
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.`),
|
|
6799
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)."),
|
|
6800
|
-
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."),
|
|
6801
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."),
|
|
6802
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.`),
|
|
6803
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.`),
|
|
@@ -6851,8 +6967,7 @@ function stripUndefined(env) {
|
|
|
6851
6967
|
return out;
|
|
6852
6968
|
}
|
|
6853
6969
|
function bodyInvalidErrors(body) {
|
|
6854
|
-
|
|
6855
|
-
return validationErrors(detail).map((item) => `${item.loc}: ${item.msg}`);
|
|
6970
|
+
return validationErrors(body).map((item) => `${item.loc}: ${item.msg}`);
|
|
6856
6971
|
}
|
|
6857
6972
|
function doorTokenOf(urlPath) {
|
|
6858
6973
|
if (typeof urlPath !== "string") return null;
|
|
@@ -6873,7 +6988,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6873
6988
|
if (args.confirm !== true) {
|
|
6874
6989
|
return refusal(
|
|
6875
6990
|
"CLAIMS_INBOUND_CREATE_CONFIRMATION_REQUIRED",
|
|
6876
|
-
"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.",
|
|
6877
6992
|
{ action, arguments: ["confirm"] }
|
|
6878
6993
|
);
|
|
6879
6994
|
}
|
|
@@ -6889,7 +7004,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6889
7004
|
const gate = await humanGate(context, ports, {
|
|
6890
7005
|
action: "create_endpoint",
|
|
6891
7006
|
subject: JSON.stringify([signing, file]),
|
|
6892
|
-
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}.`,
|
|
6893
7008
|
code: args.confirmation_code
|
|
6894
7009
|
}, "Nothing was created.");
|
|
6895
7010
|
if (gate !== null) return gate;
|
|
@@ -6917,21 +7032,31 @@ async function createEndpoint(args, context, ports) {
|
|
|
6917
7032
|
}
|
|
6918
7033
|
return inboundFailure(answer, action, CREATE_404);
|
|
6919
7034
|
}
|
|
6920
|
-
|
|
7035
|
+
const refusedCode = answer.status >= 400 ? bodyCode(answer.value) : null;
|
|
7036
|
+
if (refusedCode === "event_time_mapping_required") {
|
|
7037
|
+
return refusal(
|
|
7038
|
+
"CLAIMS_MAPPING_INVALID",
|
|
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.",
|
|
7040
|
+
{ action, status: 409, code: "event_time_mapping_required", request_id: answer.requestId }
|
|
7041
|
+
);
|
|
7042
|
+
}
|
|
7043
|
+
if (refusedCode === "endpoint_exists") {
|
|
6921
7044
|
return refusal(
|
|
6922
7045
|
"CLAIMS_INBOUND_ENDPOINT_EXISTS",
|
|
6923
|
-
`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
|
|
6924
|
-
{ 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 }
|
|
6925
7048
|
);
|
|
6926
7049
|
}
|
|
6927
|
-
if (
|
|
6928
|
-
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.", {
|
|
6929
7052
|
action,
|
|
6930
7053
|
arguments: ["signing"],
|
|
7054
|
+
code: refusedCode,
|
|
6931
7055
|
problems: bodyInvalidErrors(answer.value),
|
|
6932
7056
|
request_id: answer.requestId
|
|
6933
7057
|
});
|
|
6934
7058
|
}
|
|
7059
|
+
if (answer.status === 409 || answer.status === 422) return unexpectedRefusal(answer, action, "Nothing was created.");
|
|
6935
7060
|
const created = typeof answer.value === "object" && answer.value !== null ? answer.value : {};
|
|
6936
7061
|
const token = doorTokenOf(created["url_path"]);
|
|
6937
7062
|
const secret = typeof created["secret"] === "string" && SECRET_SHAPE.test(created["secret"]) ? created["secret"] : null;
|
|
@@ -6945,7 +7070,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6945
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`;
|
|
6946
7071
|
return refusal(
|
|
6947
7072
|
"CLAIMS_INBOUND_CREDENTIALS_NOT_WRITTEN",
|
|
6948
|
-
`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.",
|
|
6949
7074
|
{ action, written_to: file, url_written: urlWritten, secret_written: secretWritten, ...failure === void 0 ? {} : { why: failure.why }, request_id: answer.requestId }
|
|
6950
7075
|
);
|
|
6951
7076
|
}
|
|
@@ -6966,7 +7091,7 @@ async function createEndpoint(args, context, ports) {
|
|
|
6966
7091
|
steps: [
|
|
6967
7092
|
...signingSteps(finalSigning),
|
|
6968
7093
|
`The inbound URL and secret were written to ${file}; set the same two in the claims system's config. Neither is shown again.`,
|
|
6969
|
-
|
|
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.`
|
|
6970
7095
|
],
|
|
6971
7096
|
needs_event_time: needsEventTime(finalSigning),
|
|
6972
7097
|
local: localState(context, file, scope),
|
|
@@ -6981,15 +7106,16 @@ async function createEndpoint(args, context, ports) {
|
|
|
6981
7106
|
}
|
|
6982
7107
|
async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
6983
7108
|
if (isHosted(context)) return notHosted(SETUP3, "it reads the sandbox endpoint with the sandbox tenant's secret key from a local shell only.");
|
|
6984
|
-
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);
|
|
6985
7110
|
if (actions.length > 1) {
|
|
6986
7111
|
return refusal(
|
|
6987
7112
|
"CLAIMS_ARGUMENTS_INVALID",
|
|
6988
|
-
`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.`,
|
|
6989
7114
|
{ arguments: [...actions] }
|
|
6990
7115
|
);
|
|
6991
7116
|
}
|
|
6992
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);
|
|
6993
7119
|
const scope = localScope(context.env, context.cwd);
|
|
6994
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;
|
|
6995
7121
|
if (rotation !== null) {
|
|
@@ -7018,7 +7144,7 @@ async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
|
7018
7144
|
steps: [
|
|
7019
7145
|
...signingSteps(signing),
|
|
7020
7146
|
`${URL_SHOWN_ONCE} Keep it in the claims system's config too.`,
|
|
7021
|
-
|
|
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.`
|
|
7022
7148
|
],
|
|
7023
7149
|
needs_event_time: needsEventTime(signing),
|
|
7024
7150
|
local: localState(context, args.secret_env_file, scope)
|
|
@@ -7069,6 +7195,95 @@ async function claimsInboundSigningSetupTool(args, context, ports = {}) {
|
|
|
7069
7195
|
}
|
|
7070
7196
|
};
|
|
7071
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
|
+
}
|
|
7072
7287
|
async function rotateToken(args, context, ports, sandbox, endpointId, document, scope) {
|
|
7073
7288
|
const file = args.secret_env_file;
|
|
7074
7289
|
const gate = await humanGate(context, ports, {
|
|
@@ -7834,7 +8049,7 @@ var SEND_CLAIMS_TEST_EVENTS_INPUT_SHAPE = {
|
|
|
7834
8049
|
description: z.string().min(1).max(200).optional().describe("create_endpoint: a label for the endpoint."),
|
|
7835
8050
|
enabled_events: z.array(ENABLED_EVENT).min(1).max(CLAIMS_EVENT_TYPES.length + 1).optional().describe('create_endpoint: the event types the endpoint receives, or ["*"] for all. Default ["*"].'),
|
|
7836
8051
|
endpoint_id: z.string().min(1).max(128).optional().describe("delete_endpoint and send_test_event: the endpoint, as list_endpoints names it."),
|
|
7837
|
-
event_type: z.enum(
|
|
8052
|
+
event_type: z.enum(CLAIMS_TESTABLE_EVENT_TYPES).optional().describe('send_test_event: the synthetic event to send. Its data carries "synthetic": true and a SYN-TEST- claim id.'),
|
|
7838
8053
|
secret_env_file: z.string().min(1).max(1024).optional().describe("create_endpoint: absolute path of a local env file the endpoint's signing secret is appended to as EVERFUR_WEBHOOK_SECRET=..., created with mode 600 when missing. The API shows the secret once; this tool writes it there and never returns it. The file must not already set EVERFUR_WEBHOOK_SECRET. 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."),
|
|
7839
8054
|
confirmation_code: z.string().min(1).max(32).optional().describe("create_endpoint: the one-time code the PERSON typed back, when the first call asked for one (the code is in a local file they open; never read it yourself). Not needed when this client asks the person directly.")
|
|
7840
8055
|
};
|
|
@@ -7931,7 +8146,13 @@ function sandboxServerKey(context) {
|
|
|
7931
8146
|
)
|
|
7932
8147
|
};
|
|
7933
8148
|
}
|
|
7934
|
-
|
|
8149
|
+
var WEBHOOK_CAPABILITY = {
|
|
8150
|
+
list_endpoints: "partner_events.event.read",
|
|
8151
|
+
create_endpoint: "partner_events.endpoint.update",
|
|
8152
|
+
delete_endpoint: "partner_events.endpoint.update",
|
|
8153
|
+
send_test_event: "partner_events.endpoint.update"
|
|
8154
|
+
};
|
|
8155
|
+
function sandboxFailure(failure, action, capability) {
|
|
7935
8156
|
if (failure.kind === "http") {
|
|
7936
8157
|
const retryAfter = failure.retrySignals?.retryAfter ?? null;
|
|
7937
8158
|
const details = {
|
|
@@ -7944,7 +8165,7 @@ function sandboxFailure(failure, action) {
|
|
|
7944
8165
|
if (failure.status === 404 && (failure.code === null || failure.code === "ResourceNotFoundException")) {
|
|
7945
8166
|
return refusal(
|
|
7946
8167
|
"CLAIMS_SANDBOX_NOT_ENABLED",
|
|
7947
|
-
"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.",
|
|
7948
8169
|
details
|
|
7949
8170
|
);
|
|
7950
8171
|
}
|
|
@@ -7955,6 +8176,13 @@ function sandboxFailure(failure, action) {
|
|
|
7955
8176
|
details
|
|
7956
8177
|
);
|
|
7957
8178
|
}
|
|
8179
|
+
if (failure.status === 403 && capability !== void 0) {
|
|
8180
|
+
return refusal(
|
|
8181
|
+
"CLAIMS_SANDBOX_CALL_FAILED",
|
|
8182
|
+
`The sandbox call answered 403 ${failure.code ?? "(no code)"}: a restricted key needs the ${capability} capability for this action. Use a key with it, or have it granted to this restricted key.`,
|
|
8183
|
+
{ ...details, capability }
|
|
8184
|
+
);
|
|
8185
|
+
}
|
|
7958
8186
|
return refusal(
|
|
7959
8187
|
"CLAIMS_SANDBOX_CALL_FAILED",
|
|
7960
8188
|
`The sandbox call answered ${failure.status} ${failure.code ?? "(no code)"}.` + (failure.code === null ? "" : " everfur_explain_claims_error explains the code."),
|
|
@@ -7983,7 +8211,7 @@ async function sendClaimsTestEventsTool(args, context, ports = {}) {
|
|
|
7983
8211
|
return argumentsInvalid(action, ["endpoint_id"], `${action} needs endpoint_id, as list_endpoints names it.`);
|
|
7984
8212
|
}
|
|
7985
8213
|
if (action === "send_test_event" && args.event_type === void 0) {
|
|
7986
|
-
return argumentsInvalid(action, ["event_type"], `send_test_event needs event_type, one of ${
|
|
8214
|
+
return argumentsInvalid(action, ["event_type"], `send_test_event needs event_type, one of ${CLAIMS_TESTABLE_EVENT_TYPES.join(", ")}.`);
|
|
7987
8215
|
}
|
|
7988
8216
|
const scope = localScope(context.env, context.cwd);
|
|
7989
8217
|
if (action === "create_endpoint") {
|
|
@@ -8014,7 +8242,7 @@ async function sendClaimsTestEventsTool(args, context, ports = {}) {
|
|
|
8014
8242
|
const credentials = { [CLAIMS_SECRET_KEY_HEADER]: key.credential };
|
|
8015
8243
|
if (action === "list_endpoints") {
|
|
8016
8244
|
const answer2 = await client.request({ method: "GET", path: SANDBOX_ROUTE, credentials });
|
|
8017
|
-
if (!answer2.ok) return sandboxFailure(answer2, action);
|
|
8245
|
+
if (!answer2.ok) return sandboxFailure(answer2, action, WEBHOOK_CAPABILITY[action]);
|
|
8018
8246
|
const parsed2 = z.object({ data: z.array(WEBHOOK_ENDPOINT) }).safeParse(answer2.value);
|
|
8019
8247
|
if (!parsed2.success) return refusal("CLAIMS_SANDBOX_CALL_FAILED", "The endpoint list came back in an unexpected shape.", { action, request_id: answer2.requestId });
|
|
8020
8248
|
return { isError: false, document: { ok: true, action, endpoints: parsed2.data.data.map(relayEndpoint) } };
|
|
@@ -8026,7 +8254,7 @@ async function sendClaimsTestEventsTool(args, context, ports = {}) {
|
|
|
8026
8254
|
enabled_events: [...args.enabled_events ?? ["*"]]
|
|
8027
8255
|
};
|
|
8028
8256
|
const answer2 = await client.request({ method: "POST", path: SANDBOX_ROUTE, credentials, body });
|
|
8029
|
-
if (!answer2.ok) return sandboxFailure(answer2, action);
|
|
8257
|
+
if (!answer2.ok) return sandboxFailure(answer2, action, WEBHOOK_CAPABILITY[action]);
|
|
8030
8258
|
const parsed2 = WEBHOOK_ENDPOINT.extend({ signing_secret: z.string().startsWith("whsec_") }).safeParse(answer2.value);
|
|
8031
8259
|
if (!parsed2.success) {
|
|
8032
8260
|
return refusal("CLAIMS_SANDBOX_CALL_FAILED", "The created endpoint came back in an unexpected shape; its secret was not written.", { action, request_id: answer2.requestId });
|
|
@@ -8055,7 +8283,7 @@ async function sendClaimsTestEventsTool(args, context, ports = {}) {
|
|
|
8055
8283
|
const endpointPath = `${SANDBOX_ROUTE}/${encodeURIComponent(args.endpoint_id)}`;
|
|
8056
8284
|
if (action === "delete_endpoint") {
|
|
8057
8285
|
const answer2 = await client.request({ method: "DELETE", path: endpointPath, credentials });
|
|
8058
|
-
if (!answer2.ok) return sandboxFailure(answer2, action);
|
|
8286
|
+
if (!answer2.ok) return sandboxFailure(answer2, action, WEBHOOK_CAPABILITY[action]);
|
|
8059
8287
|
return { isError: false, document: { ok: true, action, endpoint_id: args.endpoint_id, deleted: true } };
|
|
8060
8288
|
}
|
|
8061
8289
|
const answer = await client.request({
|
|
@@ -8064,7 +8292,7 @@ async function sendClaimsTestEventsTool(args, context, ports = {}) {
|
|
|
8064
8292
|
credentials,
|
|
8065
8293
|
body: { event_type: args.event_type }
|
|
8066
8294
|
});
|
|
8067
|
-
if (!answer.ok) return sandboxFailure(answer, action);
|
|
8295
|
+
if (!answer.ok) return sandboxFailure(answer, action, WEBHOOK_CAPABILITY[action]);
|
|
8068
8296
|
const parsed = z.object({ event_id: z.string(), delivery_id: z.string() }).safeParse(answer.value);
|
|
8069
8297
|
if (!parsed.success) return refusal("CLAIMS_SANDBOX_CALL_FAILED", "The test event answer came back in an unexpected shape.", { action, request_id: answer.requestId });
|
|
8070
8298
|
return {
|
|
@@ -10039,14 +10267,15 @@ a field mapping turns them into claims, documents and pet profiles. everfur_prop
|
|
|
10039
10267
|
mapping from sample native events, offline, with the gaps and the personal data paths to scrub;
|
|
10040
10268
|
everfur_save_claims_mapping saves it as the sandbox draft, and activates the draft only with confirm: true and the
|
|
10041
10269
|
confirmation phrase typed back by a person who has read it, never on the agent's own initiative. Activating, creating
|
|
10042
|
-
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
|
|
10043
10271
|
answer: the client asks them when it can; otherwise the tool writes a one-time code to a local file and answers with
|
|
10044
10272
|
its path, and the person types the code back as confirmation_code. Never open that file yourself.
|
|
10045
10273
|
everfur_claims_inbound_signing_setup explains the endpoint's signing as steps for the claims system and can rotate the
|
|
10046
|
-
sandbox secret, or the URL token after the URL leaks, into a local env file. The sandbox key can create the sandbox inbound endpoint
|
|
10047
|
-
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
|
|
10048
10276
|
a person asks for it; its URL and first secret are shown once and are written to that file as
|
|
10049
|
-
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
|
|
10050
10279
|
Everfur, with their signing and the live mapping. everfur_send_claims_inbound_samples signs synthetic samples, posts them to the
|
|
10051
10280
|
sandbox inbound URL and reports each event's status, reason code and fix; with read_event_log it sends nothing and
|
|
10052
10281
|
reads the sandbox event log, for events the claims system itself sent. The tools that read the sandbox tenant's
|
|
@@ -10301,7 +10530,7 @@ function buildServer(context, ports = {}, options = {}) {
|
|
|
10301
10530
|
"everfur_claims_inbound_signing_setup",
|
|
10302
10531
|
{
|
|
10303
10532
|
title: TOOL_ANNOTATIONS.everfur_claims_inbound_signing_setup.title,
|
|
10304
|
-
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.",
|
|
10305
10534
|
inputSchema: CLAIMS_INBOUND_SIGNING_SETUP_INPUT_SHAPE,
|
|
10306
10535
|
outputSchema: CLAIMS_INBOUND_SIGNING_SETUP_OUTPUT_SHAPE,
|
|
10307
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,8 +5476,8 @@ function booleanAttribute(outcome, key) {
|
|
|
5476
5476
|
}
|
|
5477
5477
|
|
|
5478
5478
|
// src/version.ts
|
|
5479
|
-
var CLI_VERSION = "0.9.
|
|
5480
|
-
var CLI_PUBLISHED_VERSION = "0.
|
|
5479
|
+
var CLI_VERSION = "0.9.2";
|
|
5480
|
+
var CLI_PUBLISHED_VERSION = "0.9.0";
|
|
5481
5481
|
|
|
5482
5482
|
// src/commands/diagnose/reasons.ts
|
|
5483
5483
|
var REASON_CODES = Object.freeze([
|
|
@@ -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: {
|
|
@@ -17267,8 +17267,8 @@ var MEANINGS = Object.freeze({
|
|
|
17267
17267
|
nextAction: "Tell the developer to run the tool from the local MCP server or the CLI."
|
|
17268
17268
|
},
|
|
17269
17269
|
CLAIMS_MAPPING_INVALID: {
|
|
17270
|
-
tools: [CLAIMS_SAVE],
|
|
17271
|
-
meaning: "The mapping does not pass the mapping checks (error.details.problems: a path, a transform, a limit, or pii_paths hiding a field the mapping reads), or the API refused to save or activate it. Nothing was saved or
|
|
17270
|
+
tools: [CLAIMS_SAVE, CLAIMS_SETUP],
|
|
17271
|
+
meaning: "The mapping does not pass the mapping checks (error.details.problems: a path, a transform, a limit, or pii_paths hiding a field the mapping reads), or the API refused to save or activate it, or refused a signing config that signs no time while the mapping names no event_time (error.details.code event_time_mapping_required). Nothing was saved, activated or created.",
|
|
17272
17272
|
nextAction: "Fix each problem in the mapping (everfur_propose_claims_mapping can propose one again), then save again."
|
|
17273
17273
|
},
|
|
17274
17274
|
CLAIMS_MAPPING_CONFIRMATION_REQUIRED: {
|
|
@@ -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