witnora 0.18.0 → 0.18.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/onboard.js +10 -2
- package/dist/private-discovery.js +25 -0
- package/dist/real-path-activation.js +26 -2
- package/dist/runtime-sandbox-fixture.js +14 -8
- package/dist/runtime-sandbox-kit.js +2 -2
- package/dist/vendor/onegent-runtime/production-evaluator-kit.d.ts +2 -1
- package/dist/vendor/onegent-runtime/production-evaluator-kit.d.ts.map +1 -1
- package/dist/vendor/onegent-runtime/production-evaluator-kit.js +1 -0
- package/dist/vendor/onegent-runtime/provider-integration-packs.d.ts +1 -1
- package/dist/vendor/onegent-runtime/provider-integration-packs.d.ts.map +1 -1
- package/dist/vendor/onegent-runtime/provider-integration-packs.js +7 -1
- package/package.json +1 -1
package/dist/onboard.js
CHANGED
|
@@ -61,7 +61,7 @@ export async function runOnboard(options) {
|
|
|
61
61
|
const references = localRuntime.references;
|
|
62
62
|
const modules = references?.sandboxOrigin && references.adapterDigestSha256 && references.probeDigestSha256 && references.fixtureContractDigestSha256
|
|
63
63
|
? { sandboxOrigin: references.sandboxOrigin, adapterDigestSha256: references.adapterDigestSha256, probeDigestSha256: references.probeDigestSha256, fixtureContractDigestSha256: references.fixtureContractDigestSha256 }
|
|
64
|
-
: await planRuntimeSandboxModules();
|
|
64
|
+
: await planRuntimeSandboxModules({ excludedPorts: configuredGatewayPorts(options.env ?? process.env) });
|
|
65
65
|
const bootstrap = await bootstrapLocalRuntime({
|
|
66
66
|
projectId: token.projectId,
|
|
67
67
|
planId: setupPlan.id,
|
|
@@ -273,6 +273,13 @@ export async function runOnboard(options) {
|
|
|
273
273
|
throw new Error(`Witnora Setup Autopilot rolled back this install attempt: ${diagnosis}`);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
+
function configuredGatewayPorts(environment) {
|
|
277
|
+
const value = environment.WITNORA_GATEWAY_PORT?.trim();
|
|
278
|
+
if (!value)
|
|
279
|
+
return new Set();
|
|
280
|
+
const port = Number(value);
|
|
281
|
+
return Number.isInteger(port) && port > 0 && port <= 65_535 ? new Set([port]) : new Set();
|
|
282
|
+
}
|
|
276
283
|
async function inspectGatewayBinding(directory, projectId, server) {
|
|
277
284
|
let value;
|
|
278
285
|
try {
|
|
@@ -383,7 +390,8 @@ export async function inspectRepository(repositoryPath, explicitTemplate) {
|
|
|
383
390
|
...Object.keys(record(packageJson.devDependencies)),
|
|
384
391
|
...Object.keys(record(packageJson.peerDependencies)),
|
|
385
392
|
] : [];
|
|
386
|
-
const
|
|
393
|
+
const manifest = await optionalJson(join(repositoryPath, "witnora.discovery.json"));
|
|
394
|
+
const capabilities = inferPrivateCapabilities({ dependencyNames, topLevelNames: names, manifest });
|
|
387
395
|
return { kind, name, slug, template, fingerprintSha256, capabilities };
|
|
388
396
|
}
|
|
389
397
|
async function generateRepositoryConfig(repositoryPath, template, subject) {
|
|
@@ -83,8 +83,33 @@ export function inferPrivateCapabilities(input) {
|
|
|
83
83
|
add("data:structured", "Structured data access", "data");
|
|
84
84
|
if (/slack|discord|twilio|resend|sendgrid|postmark|nodemailer|email/.test(searchable))
|
|
85
85
|
add("messaging:external", "External messaging", "messaging");
|
|
86
|
+
for (const capability of repositoryManifestCapabilities(input.manifest))
|
|
87
|
+
add(capability.key, capability.observedName, capability.transport);
|
|
86
88
|
return [...detected.values()].sort((left, right) => left.key.localeCompare(right.key));
|
|
87
89
|
}
|
|
90
|
+
function repositoryManifestCapabilities(value) {
|
|
91
|
+
if (value === undefined)
|
|
92
|
+
return [];
|
|
93
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
94
|
+
throw new Error("Repository discovery manifest is invalid.");
|
|
95
|
+
const manifest = value;
|
|
96
|
+
if (Object.keys(manifest).some((key) => key !== "schemaVersion" && key !== "capabilities") || manifest.schemaVersion !== "witnora.repository_discovery.v0.1" || !Array.isArray(manifest.capabilities) || manifest.capabilities.length > 100) {
|
|
97
|
+
throw new Error("Repository discovery manifest failed its bounded contract.");
|
|
98
|
+
}
|
|
99
|
+
const transports = new Set(["tool", "mcp", "http", "browser", "coding", "workflow", "data", "messaging"]);
|
|
100
|
+
return manifest.capabilities.map((item, index) => {
|
|
101
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
102
|
+
throw new Error(`Repository discovery manifest capability ${index} is invalid.`);
|
|
103
|
+
const capability = item;
|
|
104
|
+
if (Object.keys(capability).some((key) => key !== "key" && key !== "observedName" && key !== "transport")
|
|
105
|
+
|| typeof capability.key !== "string" || !/^[A-Za-z0-9._:-]{1,120}$/.test(capability.key)
|
|
106
|
+
|| typeof capability.observedName !== "string" || !/^[A-Za-z0-9._:-]{1,120}$/.test(capability.observedName)
|
|
107
|
+
|| !transports.has(capability.transport)) {
|
|
108
|
+
throw new Error(`Repository discovery manifest capability ${index} failed its bounded contract.`);
|
|
109
|
+
}
|
|
110
|
+
return { key: capability.key, observedName: capability.observedName, transport: capability.transport };
|
|
111
|
+
});
|
|
112
|
+
}
|
|
88
113
|
function discoveryIdentityPath(projectId, configHome) {
|
|
89
114
|
const root = configHome ?? process.env.WITNORA_CONFIG_HOME ?? process.env.AGENTCERT_CONFIG_HOME
|
|
90
115
|
?? join(process.env.USERPROFILE ?? process.env.HOME ?? ".", ".witnora");
|
|
@@ -12,7 +12,7 @@ export async function activateRealPathIntegrations(options) {
|
|
|
12
12
|
throw new Error(`Could not load approved real-path integrations (${response.status}).`);
|
|
13
13
|
const body = await boundedJson(response);
|
|
14
14
|
const approved = Array.isArray(body.integrations) ? body.integrations.map(parsePlan).filter((plan) => plan.status === "READY_TO_ACTIVATE") : [];
|
|
15
|
-
const plans = approved.filter((plan) => ["STRIPE_REFUND", "ZENDESK_TICKET", "SALESFORCE_RECORD", "HUBSPOT_CRM_RECORD", "POSTGRES_RECORD"].includes(plan.generated.providerPackId) && plan.environment === "sandbox" && plan.customerSummary.evaluationMode === "SHADOW");
|
|
15
|
+
const plans = approved.filter((plan) => ["STRIPE_REFUND", "SHOPIFY_DISPUTE", "ZENDESK_TICKET", "SALESFORCE_RECORD", "HUBSPOT_CRM_RECORD", "POSTGRES_RECORD"].includes(plan.generated.providerPackId) && plan.environment === "sandbox" && plan.customerSummary.evaluationMode === "SHADOW");
|
|
16
16
|
if (!plans.length)
|
|
17
17
|
return { state: "NOT_CONFIGURED", created: false, activations: [], generatedFiles: [] };
|
|
18
18
|
const environment = options.env ?? process.env;
|
|
@@ -71,6 +71,8 @@ async function providerPreflight(request, env, plan, now, postgresClientFactory)
|
|
|
71
71
|
throw new Error("Stripe test-mode activation requires STRIPE_SECRET_KEY to reference an sk_test_ credential in the customer environment.");
|
|
72
72
|
return stripePreflight(request, secret, plan, now);
|
|
73
73
|
}
|
|
74
|
+
if (plan.generated.providerPackId === "SHOPIFY_DISPUTE")
|
|
75
|
+
return shopifyDisputePreflight(request, env, plan, now);
|
|
74
76
|
if (plan.generated.providerPackId === "ZENDESK_TICKET")
|
|
75
77
|
return zendeskPreflight(request, env, plan, now);
|
|
76
78
|
if (plan.generated.providerPackId === "SALESFORCE_RECORD")
|
|
@@ -81,6 +83,26 @@ async function providerPreflight(request, env, plan, now, postgresClientFactory)
|
|
|
81
83
|
return postgresPreflight(env, plan, now, postgresClientFactory);
|
|
82
84
|
throw new Error(`${plan.generated.providerPackId} activation is not implemented by this CLI version.`);
|
|
83
85
|
}
|
|
86
|
+
async function shopifyDisputePreflight(request, env, plan, now) {
|
|
87
|
+
const token = env.SHOPIFY_READ_ACCESS_TOKEN;
|
|
88
|
+
if (!token || token.length < 8)
|
|
89
|
+
throw new Error("Shopify activation requires the read-only SHOPIFY_READ_ACCESS_TOKEN in the customer environment.");
|
|
90
|
+
const origin = providerOrigin(plan, "Shopify", ".myshopify.com");
|
|
91
|
+
if (!/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/.test(new URL(origin).hostname))
|
|
92
|
+
throw new Error("Shopify integration requires the exact myshopify.com shop origin.");
|
|
93
|
+
const response = await request(`${origin}/admin/api/2025-07/shopify_payments/disputes.json?limit=1`, { method: "GET", headers: { accept: "application/json", "x-shopify-access-token": token }, redirect: "error", signal: AbortSignal.timeout(5_000) });
|
|
94
|
+
if (!response.ok)
|
|
95
|
+
throw new Error(`Shopify read-only dispute preflight failed (${response.status}).`);
|
|
96
|
+
const body = await boundedJson(response);
|
|
97
|
+
const disputes = Array.isArray(body.disputes) ? body.disputes : [];
|
|
98
|
+
const first = record(disputes[0], "Shopify dispute");
|
|
99
|
+
const id = first.id;
|
|
100
|
+
if (typeof id !== "string" && !Number.isInteger(id))
|
|
101
|
+
throw new Error("Shopify preflight requires one existing sandbox dispute.");
|
|
102
|
+
const observation = pick(first, ["status", "type", "amount", "currency", "evidence_due_by"]);
|
|
103
|
+
assertCriterion(plan, observation);
|
|
104
|
+
return preflightResult(plan, now, "shopify", id, observation);
|
|
105
|
+
}
|
|
84
106
|
async function stripePreflight(request, secret, plan, now) {
|
|
85
107
|
const response = await request("https://api.stripe.com/v1/refunds?limit=1", { headers: { authorization: `Bearer ${secret}` }, redirect: "error", signal: AbortSignal.timeout(5_000) });
|
|
86
108
|
if (!response.ok)
|
|
@@ -199,7 +221,7 @@ import {join} from "node:path";
|
|
|
199
221
|
const contracts=${JSON.stringify(contracts)};
|
|
200
222
|
const sha=(value)=>createHash("sha256").update(typeof value==="string"?value:JSON.stringify(value)).digest("hex");
|
|
201
223
|
const request=async(url,key)=>{const response=await fetch(url,{method:"GET",headers:{accept:"application/json",authorization:"Bearer "+key},redirect:"error",signal:AbortSignal.timeout(5000)});if(!response.ok)throw new Error("Provider read-only observation failed ("+response.status+").");return response.json();};
|
|
202
|
-
const observe=async(contract,resourceId,repository)=>{const key=(await readFile(join(repository,contract.credentialHandle),"utf8")).trim();if(!key)throw new Error("The local read-only Provider credential is unavailable.");if(contract.providerPackId==="STRIPE_REFUND"){if(!key.startsWith("sk_test_"))throw new Error("Stripe test-mode credential is unavailable.");return request("https://api.stripe.com/v1/refunds/"+encodeURIComponent(resourceId),key);}if(contract.providerPackId==="ZENDESK_TICKET")return (await request(contract.providerConfiguration.origin+"/api/v2/tickets/"+encodeURIComponent(resourceId)+".json",key)).ticket;if(contract.providerPackId==="SALESFORCE_RECORD")return request(contract.providerConfiguration.origin+"/services/data/v61.0/sobjects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId),key);if(contract.providerPackId==="HUBSPOT_CRM_RECORD")return (await request("https://api.hubapi.com/crm/v3/objects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId)+"?properties="+encodeURIComponent(contract.criterion.field),key)).properties;if(contract.providerPackId==="POSTGRES_RECORD"){for(const name of [contract.providerConfiguration.viewName,contract.providerConfiguration.idColumn,contract.criterion.field])if(!/^[A-Za-z][A-Za-z0-9_]{0,99}$/.test(name))throw new Error("PostgreSQL identifier is invalid.");const {Client}=await import("pg");const client=new Client({connectionString:key,application_name:"witnora-read-only-probe"});await client.connect();try{await client.query("BEGIN READ ONLY");const result=await client.query({name:"witnora-provider-observe",text:'SELECT "'+contract.criterion.field+'" FROM "'+contract.providerConfiguration.viewName+'" WHERE "'+contract.providerConfiguration.idColumn+'" = $1 LIMIT 1',values:[resourceId]});await client.query("ROLLBACK");return result.rows[0]??{};}catch(error){await client.query("ROLLBACK").catch(()=>{});throw error;}finally{await client.end();}}throw new Error("Provider Harness contract is unsupported.");};
|
|
224
|
+
const observe=async(contract,resourceId,repository)=>{const key=(await readFile(join(repository,contract.credentialHandle),"utf8")).trim();if(!key)throw new Error("The local read-only Provider credential is unavailable.");if(contract.providerPackId==="STRIPE_REFUND"){if(!key.startsWith("sk_test_"))throw new Error("Stripe test-mode credential is unavailable.");return request("https://api.stripe.com/v1/refunds/"+encodeURIComponent(resourceId),key);}if(contract.providerPackId==="SHOPIFY_DISPUTE"){const response=await fetch(contract.providerConfiguration.origin+"/admin/api/2025-07/shopify_payments/disputes/"+encodeURIComponent(resourceId)+".json",{method:"GET",headers:{accept:"application/json","x-shopify-access-token":key},redirect:"error",signal:AbortSignal.timeout(5000)});if(!response.ok)throw new Error("Provider read-only observation failed ("+response.status+").");return (await response.json()).dispute;}if(contract.providerPackId==="ZENDESK_TICKET")return (await request(contract.providerConfiguration.origin+"/api/v2/tickets/"+encodeURIComponent(resourceId)+".json",key)).ticket;if(contract.providerPackId==="SALESFORCE_RECORD")return request(contract.providerConfiguration.origin+"/services/data/v61.0/sobjects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId),key);if(contract.providerPackId==="HUBSPOT_CRM_RECORD")return (await request("https://api.hubapi.com/crm/v3/objects/"+encodeURIComponent(contract.providerConfiguration.resourceType)+"/"+encodeURIComponent(resourceId)+"?properties="+encodeURIComponent(contract.criterion.field),key)).properties;if(contract.providerPackId==="POSTGRES_RECORD"){for(const name of [contract.providerConfiguration.viewName,contract.providerConfiguration.idColumn,contract.criterion.field])if(!/^[A-Za-z][A-Za-z0-9_]{0,99}$/.test(name))throw new Error("PostgreSQL identifier is invalid.");const {Client}=await import("pg");const client=new Client({connectionString:key,application_name:"witnora-read-only-probe"});await client.connect();try{await client.query("BEGIN READ ONLY");const result=await client.query({name:"witnora-provider-observe",text:'SELECT "'+contract.criterion.field+'" FROM "'+contract.providerConfiguration.viewName+'" WHERE "'+contract.providerConfiguration.idColumn+'" = $1 LIMIT 1',values:[resourceId]});await client.query("ROLLBACK");return result.rows[0]??{};}catch(error){await client.query("ROLLBACK").catch(()=>{});throw error;}finally{await client.end();}}throw new Error("Provider Harness contract is unsupported.");};
|
|
203
225
|
export function createWitnoraBusinessTaskEvaluatorOptions(context){return {
|
|
204
226
|
loadShadowObservations:async(task)=>{const contract=contracts.find((item)=>item.taskContractId===task.id);if(!contract)throw new Error("No exact real-path contract.");const path=join(context.repository,".witnora","scenarios",task.id+".json");const value=JSON.parse(await readFile(path,"utf8"));if(!Array.isArray(value)||value.length>100)throw new Error("Local scenario file is invalid.");return value;},
|
|
205
227
|
evaluateShadowCandidate:async(candidate,task)=>{const contract=contracts.find((item)=>item.taskContractId===task.id);if(!contract)throw new Error("No exact real-path contract.");const resourceId=String(candidate.input?.resourceId??"");if(!/^[A-Za-z0-9._:-]{1,200}$/.test(resourceId))throw new Error("Provider resourceId is invalid.");for(const pathId of contract.actionPathIds)candidate.propose({pathId,parametersDigestSha256:sha(resourceId)});const raw=await observe(contract,resourceId,context.repository);const actual=raw?.[contract.criterion.field];const observed=actual===undefined?{}:{[contract.criterion.field]:actual};return {resultDigestSha256:sha(observed),criteria:[{id:contract.criterion.id,passed:actual===contract.criterion.expected}]};}
|
|
@@ -224,6 +246,8 @@ async function persistProviderCredential(repository, plan, environment) {
|
|
|
224
246
|
function providerCredentialEnvironmentName(packId) {
|
|
225
247
|
if (packId === "STRIPE_REFUND")
|
|
226
248
|
return "STRIPE_SECRET_KEY";
|
|
249
|
+
if (packId === "SHOPIFY_DISPUTE")
|
|
250
|
+
return "SHOPIFY_READ_ACCESS_TOKEN";
|
|
227
251
|
if (packId === "ZENDESK_TICKET")
|
|
228
252
|
return "ZENDESK_API_TOKEN";
|
|
229
253
|
if (packId === "SALESFORCE_RECORD")
|
|
@@ -10,14 +10,20 @@ const MAX_AUDIT_BYTES = 10 * 1024 * 1024;
|
|
|
10
10
|
const MAX_RESOURCES = 1_000;
|
|
11
11
|
const RESOURCE = /^\/mock-state\/([A-Za-z0-9._:-]{1,128})$/;
|
|
12
12
|
const AUDIT = /^\/audit\/actions\/([A-Za-z0-9._:-]{1,256})\/sessions\/([A-Za-z0-9._:-]{1,256})$/;
|
|
13
|
-
export async function findAvailableRuntimeSandboxOrigin() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
export async function findAvailableRuntimeSandboxOrigin(excludedPorts = new Set()) {
|
|
14
|
+
for (let attempt = 0; attempt < 20; attempt += 1) {
|
|
15
|
+
const server = createServer();
|
|
16
|
+
await listen(server, 0);
|
|
17
|
+
const address = server.address();
|
|
18
|
+
if (!address || typeof address === "string") {
|
|
19
|
+
await close(server);
|
|
20
|
+
throw new Error("Could not allocate a localhost sandbox port.");
|
|
21
|
+
}
|
|
22
|
+
await close(server);
|
|
23
|
+
if (!excludedPorts.has(address.port))
|
|
24
|
+
return `http://127.0.0.1:${address.port}`;
|
|
25
|
+
}
|
|
26
|
+
throw new Error("Could not allocate a localhost sandbox port distinct from the customer Gateway.");
|
|
21
27
|
}
|
|
22
28
|
export async function startRuntimeSandboxFixture(input) {
|
|
23
29
|
const origin = exactOrigin(input.origin);
|
|
@@ -90,8 +90,8 @@ export async function saveRuntimeReferenceManifest(path, projectId, server, refe
|
|
|
90
90
|
await rename(temporary, path);
|
|
91
91
|
await chmod(path, 0o600).catch(() => undefined);
|
|
92
92
|
}
|
|
93
|
-
export async function planRuntimeSandboxModules() {
|
|
94
|
-
const sandboxOrigin = await findAvailableRuntimeSandboxOrigin();
|
|
93
|
+
export async function planRuntimeSandboxModules(options = {}) {
|
|
94
|
+
const sandboxOrigin = await findAvailableRuntimeSandboxOrigin(options.excludedPorts);
|
|
95
95
|
const generated = generateRuntimeSandboxKit(sandboxOrigin);
|
|
96
96
|
return {
|
|
97
97
|
sandboxOrigin,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PRODUCTION_EVALUATOR_OBSERVATION_VERSION: "witnora.production_evaluator_observation.v0.1";
|
|
2
|
-
export type ProductionEvaluatorTemplate = "CRM_RECORD_STATE" | "TICKET_STATUS" | "EMAIL_DELIVERY" | "DATABASE_READ_ONLY" | "WEBHOOK_DELIVERY" | "QUEUE_JOB_COMPLETION" | "PAYMENT_REFUND_RESULT" | "BROWSER_WORKFLOW_OUTCOME";
|
|
2
|
+
export type ProductionEvaluatorTemplate = "CRM_RECORD_STATE" | "TICKET_STATUS" | "EMAIL_DELIVERY" | "DATABASE_READ_ONLY" | "WEBHOOK_DELIVERY" | "QUEUE_JOB_COMPLETION" | "PAYMENT_REFUND_RESULT" | "DISPUTE_STATUS" | "BROWSER_WORKFLOW_OUTCOME";
|
|
3
3
|
type SafeScalar = string | number | boolean | null;
|
|
4
4
|
type SafeFields = Record<string, SafeScalar>;
|
|
5
5
|
export interface ProductionEvaluatorRequest {
|
|
@@ -79,6 +79,7 @@ export declare const createEmailDeliveryEvaluator: (options: HttpProductionEvalu
|
|
|
79
79
|
export declare const createWebhookDeliveryEvaluator: (options: HttpProductionEvaluatorOptions) => ProductionOutcomeEvaluator;
|
|
80
80
|
export declare const createQueueJobCompletionEvaluator: (options: HttpProductionEvaluatorOptions) => ProductionOutcomeEvaluator;
|
|
81
81
|
export declare const createPaymentRefundResultEvaluator: (options: HttpProductionEvaluatorOptions) => ProductionOutcomeEvaluator;
|
|
82
|
+
export declare const createDisputeStatusEvaluator: (options: HttpProductionEvaluatorOptions) => ProductionOutcomeEvaluator;
|
|
82
83
|
export declare function createDatabaseReadOnlyEvaluator(options: DatabaseReadOnlyEvaluatorOptions): ProductionOutcomeEvaluator;
|
|
83
84
|
export declare function createBrowserWorkflowOutcomeEvaluator(options: BrowserWorkflowOutcomeEvaluatorOptions): ProductionOutcomeEvaluator;
|
|
84
85
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"production-evaluator-kit.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/production-evaluator-kit.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wCAAwC,EAAG,+CAAwD,CAAC;AACjH,MAAM,MAAM,2BAA2B,GAAG,kBAAkB,GAAG,eAAe,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,sBAAsB,GAAG,uBAAuB,GAAG,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"production-evaluator-kit.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/production-evaluator-kit.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ export const createEmailDeliveryEvaluator = (options) => createHttpEvaluator("EM
|
|
|
8
8
|
export const createWebhookDeliveryEvaluator = (options) => createHttpEvaluator("WEBHOOK_DELIVERY", options);
|
|
9
9
|
export const createQueueJobCompletionEvaluator = (options) => createHttpEvaluator("QUEUE_JOB_COMPLETION", options);
|
|
10
10
|
export const createPaymentRefundResultEvaluator = (options) => createHttpEvaluator("PAYMENT_REFUND_RESULT", options);
|
|
11
|
+
export const createDisputeStatusEvaluator = (options) => createHttpEvaluator("DISPUTE_STATUS", options);
|
|
11
12
|
export function createDatabaseReadOnlyEvaluator(options) {
|
|
12
13
|
validateCommon(options);
|
|
13
14
|
identifier(options.statementId, "statementId");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type BrowserWorkflowOutcomeEvaluatorOptions, type DatabaseReadOnlyEvaluatorOptions, type HttpProductionEvaluatorOptions, type ProductionOutcomeEvaluator, type ProductionEvaluatorTemplate } from "./production-evaluator-kit.js";
|
|
2
2
|
export declare const PROVIDER_INTEGRATION_PACK_SCHEMA_VERSION: "witnora.provider_integration_pack.v0.1";
|
|
3
|
-
export type ProviderIntegrationPackId = "STRIPE_REFUND" | "SALESFORCE_RECORD" | "HUBSPOT_CRM_RECORD" | "ZENDESK_TICKET" | "INTERCOM_TICKET" | "POSTGRES_RECORD" | "MYSQL_RECORD" | "WEBHOOK_DELIVERY" | "QUEUE_JOB" | "EMAIL_DELIVERY" | "BROWSER_WORKFLOW";
|
|
3
|
+
export type ProviderIntegrationPackId = "STRIPE_REFUND" | "SHOPIFY_DISPUTE" | "SALESFORCE_RECORD" | "HUBSPOT_CRM_RECORD" | "ZENDESK_TICKET" | "INTERCOM_TICKET" | "POSTGRES_RECORD" | "MYSQL_RECORD" | "WEBHOOK_DELIVERY" | "QUEUE_JOB" | "EMAIL_DELIVERY" | "BROWSER_WORKFLOW";
|
|
4
4
|
export interface ProviderIntegrationPack {
|
|
5
5
|
schemaVersion: typeof PROVIDER_INTEGRATION_PACK_SCHEMA_VERSION;
|
|
6
6
|
id: ProviderIntegrationPackId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-integration-packs.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/provider-integration-packs.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"provider-integration-packs.d.ts","sourceRoot":"","sources":["../../../../onegent-runtime/src/provider-integration-packs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { createBrowserWorkflowOutcomeEvaluator, createCrmRecordStateEvaluator, createDatabaseReadOnlyEvaluator, createEmailDeliveryEvaluator, createPaymentRefundResultEvaluator, createQueueJobCompletionEvaluator, createTicketStatusEvaluator, createWebhookDeliveryEvaluator, } from "./production-evaluator-kit.js";
|
|
2
|
+
import { createBrowserWorkflowOutcomeEvaluator, createCrmRecordStateEvaluator, createDatabaseReadOnlyEvaluator, createDisputeStatusEvaluator, createEmailDeliveryEvaluator, createPaymentRefundResultEvaluator, createQueueJobCompletionEvaluator, createTicketStatusEvaluator, createWebhookDeliveryEvaluator, } from "./production-evaluator-kit.js";
|
|
3
3
|
import { canonicalJson } from "./trust-crypto.js";
|
|
4
4
|
export const PROVIDER_INTEGRATION_PACK_SCHEMA_VERSION = "witnora.provider_integration_pack.v0.1";
|
|
5
5
|
const BASE = [
|
|
6
6
|
pack("STRIPE_REFUND", "stripe", "Stripe refund result", "PAYMENT_REFUND_RESULT", ["sandbox", "production"], ["refunds:read"], "env://STRIPE_SECRET_KEY", ["status", "amount", "currency", "failure_reason"], "/v1/refunds/{resourceId}", "https://api.stripe.com", [criterion("refund-complete", "Which Stripe status means the refund completed?", "status", ["succeeded"])]),
|
|
7
|
+
pack("SHOPIFY_DISPUTE", "shopify", "Shopify Payments dispute status", "DISPUTE_STATUS", ["sandbox", "production"], ["shopify_payments_disputes:read"], "env://SHOPIFY_READ_ACCESS_TOKEN", ["status", "type", "amount", "currency", "evidence_due_by"], "/admin/api/2025-07/shopify_payments/disputes/{resourceId}.json", undefined, [criterion("dispute-decided", "Which Shopify dispute state establishes the final business result?", "status", ["won", "lost"])]),
|
|
7
8
|
pack("SALESFORCE_RECORD", "salesforce", "Salesforce record state", "CRM_RECORD_STATE", ["sandbox", "production"], ["API enabled with object and field read-only permission set"], "env://SALESFORCE_ACCESS_TOKEN", ["Status__c", "Refund_Status__c", "IsClosed", "StageName"], "/services/data/v61.0/sobjects/{object}/{resourceId}", undefined, [criterion("crm-state", "Which Salesforce field and value establish success?", "Status__c", ["Completed", "Approved"])]),
|
|
8
9
|
pack("HUBSPOT_CRM_RECORD", "hubspot", "HubSpot CRM record", "CRM_RECORD_STATE", ["sandbox", "production"], ["crm.objects.read"], "env://HUBSPOT_ACCESS_TOKEN", ["hs_pipeline_stage", "hs_status", "closedate", "amount"], "/crm/v3/objects/{object}/{resourceId}", "https://api.hubapi.com", [criterion("crm-state", "Which HubSpot property means the business task completed?", "hs_status", ["closed", "completed"])]),
|
|
9
10
|
pack("ZENDESK_TICKET", "zendesk", "Zendesk ticket status", "TICKET_STATUS", ["sandbox", "production"], ["tickets:read"], "env://ZENDESK_API_TOKEN", ["status", "priority", "type", "via.channel"], "/api/v2/tickets/{resourceId}.json", undefined, [criterion("ticket-complete", "Which Zendesk status means the ticket is complete?", "status", ["solved", "closed"])]),
|
|
@@ -47,6 +48,7 @@ export function createProviderPackEvaluator(options) {
|
|
|
47
48
|
case "WEBHOOK_DELIVERY": return createWebhookDeliveryEvaluator(input);
|
|
48
49
|
case "QUEUE_JOB_COMPLETION": return createQueueJobCompletionEvaluator(input);
|
|
49
50
|
case "PAYMENT_REFUND_RESULT": return createPaymentRefundResultEvaluator(input);
|
|
51
|
+
case "DISPUTE_STATUS": return createDisputeStatusEvaluator(input);
|
|
50
52
|
default: throw new Error("Provider pack evaluator template is unsupported.");
|
|
51
53
|
}
|
|
52
54
|
}
|
|
@@ -80,6 +82,8 @@ function resourcePathBuilder(packId, pattern, resourceType, fields) {
|
|
|
80
82
|
};
|
|
81
83
|
}
|
|
82
84
|
function providerPayload(packId, value) {
|
|
85
|
+
if (packId === "SHOPIFY_DISPUTE")
|
|
86
|
+
return nestedRecord(value, "dispute", "Shopify dispute response");
|
|
83
87
|
if (packId === "ZENDESK_TICKET")
|
|
84
88
|
return nestedRecord(value, "ticket", "Zendesk ticket response");
|
|
85
89
|
if (packId === "HUBSPOT_CRM_RECORD")
|
|
@@ -88,6 +92,8 @@ function providerPayload(packId, value) {
|
|
|
88
92
|
}
|
|
89
93
|
function validateProviderOrigin(packId, value) {
|
|
90
94
|
const url = new URL(value);
|
|
95
|
+
if (packId === "SHOPIFY_DISPUTE" && (url.protocol !== "https:" || !/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/.test(url.hostname)))
|
|
96
|
+
throw new Error("Shopify origin must be the exact HTTPS myshopify.com shop domain.");
|
|
91
97
|
if (packId === "ZENDESK_TICKET" && (url.protocol !== "https:" || !url.hostname.endsWith(".zendesk.com")))
|
|
92
98
|
throw new Error("Zendesk origin must be an HTTPS customer subdomain of zendesk.com.");
|
|
93
99
|
if (packId === "SALESFORCE_RECORD" && (url.protocol !== "https:" || !url.hostname.endsWith(".my.salesforce.com")))
|