@apilift/cli 1.5.5 → 1.5.6-dev.1792431466.96ed48a06d2c8cb1e147eada2a56b2e5f4f8cb92
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/apilift.js
CHANGED
|
@@ -30696,6 +30696,10 @@ var init_drafts = __esm({
|
|
|
30696
30696
|
const row = this.state.db.prepare("SELECT state,response_path,response_digest FROM discovery_request_attempt WHERE draft_id=? AND fingerprint=?").get(draftId, fingerprint2);
|
|
30697
30697
|
return row ? { state: row.state, responsePath: row.response_path, responseDigest: row.response_digest } : null;
|
|
30698
30698
|
}
|
|
30699
|
+
hasDispatchedRequestAttempt(draftId) {
|
|
30700
|
+
this.requestAttempts();
|
|
30701
|
+
return Boolean(this.state.db.prepare("SELECT 1 FROM discovery_request_attempt WHERE draft_id=? AND state!='client-rejected' LIMIT 1").get(draftId));
|
|
30702
|
+
}
|
|
30699
30703
|
saveRequestAttempt(draftId, fingerprint2, state, responsePath, responseDigest) {
|
|
30700
30704
|
this.requestAttempts();
|
|
30701
30705
|
this.state.db.prepare("INSERT INTO discovery_request_attempt (draft_id,fingerprint,state,response_path,response_digest) VALUES (?,?,?,?,?) ON CONFLICT(draft_id,fingerprint) DO UPDATE SET state=excluded.state,response_path=CASE WHEN excluded.state='possibly-dispatched' AND excluded.response_path IS NULL THEN NULL ELSE COALESCE(excluded.response_path,discovery_request_attempt.response_path) END,response_digest=CASE WHEN excluded.state='possibly-dispatched' AND excluded.response_path IS NULL THEN NULL ELSE COALESCE(excluded.response_digest,discovery_request_attempt.response_digest) END").run(draftId, fingerprint2, state, responsePath ?? null, responseDigest ?? null);
|
|
@@ -34699,6 +34703,15 @@ Abandon removal: ${command4(invocation, "discover discard")}
|
|
|
34699
34703
|
release();
|
|
34700
34704
|
}
|
|
34701
34705
|
}
|
|
34706
|
+
function primaryInputSchema(schema) {
|
|
34707
|
+
if (typeof schema === "boolean" || !schema.properties) return schema;
|
|
34708
|
+
return { ...schema, properties: Object.fromEntries(Object.entries(schema.properties).map(([name, property]) => {
|
|
34709
|
+
if (typeof property !== "object" || property === null) return [name, property];
|
|
34710
|
+
const input2 = { ...property };
|
|
34711
|
+
delete input2["x-source"];
|
|
34712
|
+
return [name, input2];
|
|
34713
|
+
})) };
|
|
34714
|
+
}
|
|
34702
34715
|
async function verificationIdentity(api, checked) {
|
|
34703
34716
|
const kind = backendKind(checked.draft.kind), definition2 = checked.definition;
|
|
34704
34717
|
const executable = await executableHash(kind, checked.draft.name, definition2);
|
|
@@ -34717,8 +34730,9 @@ async function verificationIdentity(api, checked) {
|
|
|
34717
34730
|
}
|
|
34718
34731
|
const closure = await closureHash(executable, deps);
|
|
34719
34732
|
const fingerprint3 = await hashJson({ executable, closure, inputs: checked.envelope?.verification?.inputs ?? {} });
|
|
34720
|
-
const
|
|
34721
|
-
|
|
34733
|
+
const primaryIdentity = { appId: checked.draft.appId, name: checked.draft.name, effect: "effect" in action ? action.effect : null, request: "request" in action ? action.request : null, inputs: "inputs" in action ? action.inputs ? semanticSchema(action.inputs) : null : null, generated: "generated" in action ? action.generated ?? null : null, samples: checked.envelope?.verification?.inputs ?? {}, deps };
|
|
34734
|
+
const primary = await hashJson({ ...primaryIdentity, inputs: primaryIdentity.inputs === null ? null : primaryInputSchema(primaryIdentity.inputs) });
|
|
34735
|
+
return { executable, closure, fingerprint: fingerprint3, primary, legacyPrimary: await hashJson(primaryIdentity) };
|
|
34722
34736
|
}
|
|
34723
34737
|
const fingerprint2 = await hashJson({ executable, inputs: checked.envelope?.verification?.inputs ?? {} });
|
|
34724
34738
|
return { executable, fingerprint: fingerprint2 };
|
|
@@ -34912,15 +34926,16 @@ async function verifyDraft(invocation, api, state, store, session, fetcher, root
|
|
|
34912
34926
|
const write = Boolean(action && "effect" in action && action.effect !== "read");
|
|
34913
34927
|
const proofOnly = invocation.flags.includes("proof-only");
|
|
34914
34928
|
if (proofOnly && !write) return fail5("--proof-only requires a mutation draft with a saved successful primary response. No app request was sent.\n");
|
|
34915
|
-
const
|
|
34916
|
-
const
|
|
34929
|
+
const primaryContext = { browserTab: transport.mode === "browser" ? envelope.capture?.tab || state.browserTab(session.id, draft.appId) || null : null, credential: state.useSession(session.id, draft.appId)?.credentials[action && "transport" in action ? action.transport : draft.name] ?? null };
|
|
34930
|
+
const primaryFingerprint = await hashJson({ primary: "primary" in identity2 ? identity2.primary : identity2.fingerprint, ...primaryContext });
|
|
34931
|
+
const previous = store.requestAttempt(draft.id, primaryFingerprint) ?? ("legacyPrimary" in identity2 ? store.requestAttempt(draft.id, await hashJson({ primary: identity2.legacyPrimary, ...primaryContext })) : null);
|
|
34917
34932
|
const legacy = store.attempt(draft.id);
|
|
34918
34933
|
const proofCommand = command4(invocation, "discover run --proof-only");
|
|
34919
34934
|
const evidence = store.evidence(draft.id);
|
|
34920
34935
|
if (write && !proofOnly && evidence?.fingerprint === identity2.fingerprint && (previous?.state === "success" || legacy?.fingerprint === identity2.fingerprint && legacy.state === "success")) return ok4(`This configured mutation was already tested successfully. Saved output: ${evidence.resultPath}
|
|
34921
34936
|
Review it and publish; no app request was sent.
|
|
34922
34937
|
`);
|
|
34923
|
-
if (write && !proofOnly && (
|
|
34938
|
+
if (write && !proofOnly && (store.hasDispatchedRequestAttempt(draft.id) || legacy && legacy.state !== "client-rejected")) return fail5(`This mutation was already sent or may have reached the app. Do not repeat it. ${previous?.responsePath ? `Inspect the saved response: ${previous.responsePath}. After repairing response/proof, check without repeating the write: ${proofCommand}` : "No saved response matches the current contract. Restore the original test definition for proof-only recovery, or inspect the app through an authorized read."}
|
|
34924
34939
|
`, 12);
|
|
34925
34940
|
let primaryEvidence;
|
|
34926
34941
|
if (proofOnly) {
|
|
@@ -34962,7 +34977,7 @@ ${responsePath ? `Saved primary response and test inputs: ${responsePath}
|
|
|
34962
34977
|
` : ""}`, executed.exitCode, executed.dispatched);
|
|
34963
34978
|
}
|
|
34964
34979
|
withBaselines(root, (baselines) => baselines.finishPreparation(session.id, draft.appSlug, draft.appId, transport.mode));
|
|
34965
|
-
if (write) store.saveRequestAttempt(draft.id, primaryFingerprint, "success");
|
|
34980
|
+
if (write) store.saveRequestAttempt(draft.id, primaryFingerprint, "success", proofOnly ? previous?.responsePath ?? void 0 : void 0, proofOnly ? previous?.responseDigest ?? void 0 : void 0);
|
|
34966
34981
|
const resultPath = store.artifactPath(draft.id, "verification.json");
|
|
34967
34982
|
writeFileSync8(resultPath, `${JSON.stringify(executed.output, null, 2)}
|
|
34968
34983
|
`, { flag: "wx", mode: 384 });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apilift/cli",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6-dev.1792431466.96ed48a06d2c8cb1e147eada2a56b2e5f4f8cb92",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=24.16.0 <27"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "96ed48a06d2c8cb1e147eada2a56b2e5f4f8cb92",
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
42
|
"url": "git+https://github.com/egor-sergeev/apilift.git",
|