@farmslot/recipe-runner 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +21 -0
  3. package/README.md +274 -0
  4. package/bin/farmslot-visual-review.mjs +152 -0
  5. package/dist/adapters/app-lifecycle.d.ts +41 -0
  6. package/dist/adapters/app-lifecycle.d.ts.map +1 -0
  7. package/dist/adapters/app-lifecycle.js +224 -0
  8. package/dist/adapters/app-lifecycle.js.map +1 -0
  9. package/dist/adapters/core.d.ts +5 -0
  10. package/dist/adapters/core.d.ts.map +1 -0
  11. package/dist/adapters/core.js +433 -0
  12. package/dist/adapters/core.js.map +1 -0
  13. package/dist/adapters/gesture.d.ts +12 -0
  14. package/dist/adapters/gesture.d.ts.map +1 -0
  15. package/dist/adapters/gesture.js +76 -0
  16. package/dist/adapters/gesture.js.map +1 -0
  17. package/dist/adapters/ui.d.ts +33 -0
  18. package/dist/adapters/ui.d.ts.map +1 -0
  19. package/dist/adapters/ui.js +130 -0
  20. package/dist/adapters/ui.js.map +1 -0
  21. package/dist/cli/error-output.d.ts +6 -0
  22. package/dist/cli/error-output.d.ts.map +1 -0
  23. package/dist/cli/error-output.js +19 -0
  24. package/dist/cli/error-output.js.map +1 -0
  25. package/dist/cli/index.d.ts +12 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +29 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/cli/run-command.d.ts +8 -0
  30. package/dist/cli/run-command.d.ts.map +1 -0
  31. package/dist/cli/run-command.js +253 -0
  32. package/dist/cli/run-command.js.map +1 -0
  33. package/dist/cli/support.d.ts +31 -0
  34. package/dist/cli/support.d.ts.map +1 -0
  35. package/dist/cli/support.js +297 -0
  36. package/dist/cli/support.js.map +1 -0
  37. package/dist/cli/validate-command.d.ts +4 -0
  38. package/dist/cli/validate-command.d.ts.map +1 -0
  39. package/dist/cli/validate-command.js +52 -0
  40. package/dist/cli/validate-command.js.map +1 -0
  41. package/dist/core/compose.d.ts +23 -0
  42. package/dist/core/compose.d.ts.map +1 -0
  43. package/dist/core/compose.js +104 -0
  44. package/dist/core/compose.js.map +1 -0
  45. package/dist/core/execution.d.ts +44 -0
  46. package/dist/core/execution.d.ts.map +1 -0
  47. package/dist/core/execution.js +304 -0
  48. package/dist/core/execution.js.map +1 -0
  49. package/dist/core/failure.d.ts +23 -0
  50. package/dist/core/failure.d.ts.map +1 -0
  51. package/dist/core/failure.js +43 -0
  52. package/dist/core/failure.js.map +1 -0
  53. package/dist/core/graph.d.ts +12 -0
  54. package/dist/core/graph.d.ts.map +1 -0
  55. package/dist/core/graph.js +65 -0
  56. package/dist/core/graph.js.map +1 -0
  57. package/dist/core/hud.d.ts +11 -0
  58. package/dist/core/hud.d.ts.map +1 -0
  59. package/dist/core/hud.js +120 -0
  60. package/dist/core/hud.js.map +1 -0
  61. package/dist/core/invocation.d.ts +13 -0
  62. package/dist/core/invocation.d.ts.map +1 -0
  63. package/dist/core/invocation.js +68 -0
  64. package/dist/core/invocation.js.map +1 -0
  65. package/dist/core/json.d.ts +9 -0
  66. package/dist/core/json.d.ts.map +1 -0
  67. package/dist/core/json.js +74 -0
  68. package/dist/core/json.js.map +1 -0
  69. package/dist/core/library-manifest.d.ts +53 -0
  70. package/dist/core/library-manifest.d.ts.map +1 -0
  71. package/dist/core/library-manifest.js +263 -0
  72. package/dist/core/library-manifest.js.map +1 -0
  73. package/dist/core/library.d.ts +80 -0
  74. package/dist/core/library.d.ts.map +1 -0
  75. package/dist/core/library.js +321 -0
  76. package/dist/core/library.js.map +1 -0
  77. package/dist/core/parameters.d.ts +5 -0
  78. package/dist/core/parameters.d.ts.map +1 -0
  79. package/dist/core/parameters.js +57 -0
  80. package/dist/core/parameters.js.map +1 -0
  81. package/dist/core/passive-observations.d.ts +25 -0
  82. package/dist/core/passive-observations.d.ts.map +1 -0
  83. package/dist/core/passive-observations.js +62 -0
  84. package/dist/core/passive-observations.js.map +1 -0
  85. package/dist/core/path.d.ts +7 -0
  86. package/dist/core/path.d.ts.map +1 -0
  87. package/dist/core/path.js +147 -0
  88. package/dist/core/path.js.map +1 -0
  89. package/dist/core/recording-cleanup.d.ts +10 -0
  90. package/dist/core/recording-cleanup.d.ts.map +1 -0
  91. package/dist/core/recording-cleanup.js +32 -0
  92. package/dist/core/recording-cleanup.js.map +1 -0
  93. package/dist/core/resolution-error.d.ts +7 -0
  94. package/dist/core/resolution-error.d.ts.map +1 -0
  95. package/dist/core/resolution-error.js +9 -0
  96. package/dist/core/resolution-error.js.map +1 -0
  97. package/dist/core/runner.d.ts +4 -0
  98. package/dist/core/runner.d.ts.map +1 -0
  99. package/dist/core/runner.js +738 -0
  100. package/dist/core/runner.js.map +1 -0
  101. package/dist/core/scroll-to.d.ts +111 -0
  102. package/dist/core/scroll-to.d.ts.map +1 -0
  103. package/dist/core/scroll-to.js +353 -0
  104. package/dist/core/scroll-to.js.map +1 -0
  105. package/dist/core/suite.d.ts +25 -0
  106. package/dist/core/suite.d.ts.map +1 -0
  107. package/dist/core/suite.js +76 -0
  108. package/dist/core/suite.js.map +1 -0
  109. package/dist/core/trace.d.ts +5 -0
  110. package/dist/core/trace.d.ts.map +1 -0
  111. package/dist/core/trace.js +25 -0
  112. package/dist/core/trace.js.map +1 -0
  113. package/dist/core/trust-error.d.ts +9 -0
  114. package/dist/core/trust-error.d.ts.map +1 -0
  115. package/dist/core/trust-error.js +18 -0
  116. package/dist/core/trust-error.js.map +1 -0
  117. package/dist/core/trust-input.d.ts +20 -0
  118. package/dist/core/trust-input.d.ts.map +1 -0
  119. package/dist/core/trust-input.js +68 -0
  120. package/dist/core/trust-input.js.map +1 -0
  121. package/dist/core/trust.d.ts +28 -0
  122. package/dist/core/trust.d.ts.map +1 -0
  123. package/dist/core/trust.js +284 -0
  124. package/dist/core/trust.js.map +1 -0
  125. package/dist/core/types.d.ts +319 -0
  126. package/dist/core/types.d.ts.map +1 -0
  127. package/dist/core/types.js +2 -0
  128. package/dist/core/types.js.map +1 -0
  129. package/dist/core/validation.d.ts +4 -0
  130. package/dist/core/validation.d.ts.map +1 -0
  131. package/dist/core/validation.js +18 -0
  132. package/dist/core/validation.js.map +1 -0
  133. package/dist/index.d.ts +32 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +25 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/node/writers.d.ts +27 -0
  138. package/dist/node/writers.d.ts.map +1 -0
  139. package/dist/node/writers.js +99 -0
  140. package/dist/node/writers.js.map +1 -0
  141. package/dist/recording/android-mirror.d.ts +10 -0
  142. package/dist/recording/android-mirror.d.ts.map +1 -0
  143. package/dist/recording/android-mirror.js +180 -0
  144. package/dist/recording/android-mirror.js.map +1 -0
  145. package/dist/recording/capture-helper-timing.d.ts +4 -0
  146. package/dist/recording/capture-helper-timing.d.ts.map +1 -0
  147. package/dist/recording/capture-helper-timing.js +47 -0
  148. package/dist/recording/capture-helper-timing.js.map +1 -0
  149. package/dist/recording/capture-helper.d.ts +10 -0
  150. package/dist/recording/capture-helper.d.ts.map +1 -0
  151. package/dist/recording/capture-helper.js +335 -0
  152. package/dist/recording/capture-helper.js.map +1 -0
  153. package/dist/recording/cdp-video-recorder.d.ts +9 -0
  154. package/dist/recording/cdp-video-recorder.d.ts.map +1 -0
  155. package/dist/recording/cdp-video-recorder.js +319 -0
  156. package/dist/recording/cdp-video-recorder.js.map +1 -0
  157. package/dist/recording/frame-sampler.d.ts +19 -0
  158. package/dist/recording/frame-sampler.d.ts.map +1 -0
  159. package/dist/recording/frame-sampler.js +29 -0
  160. package/dist/recording/frame-sampler.js.map +1 -0
  161. package/dist/recording/timeline.d.ts +15 -0
  162. package/dist/recording/timeline.d.ts.map +1 -0
  163. package/dist/recording/timeline.js +88 -0
  164. package/dist/recording/timeline.js.map +1 -0
  165. package/dist/runtime/browser-extension.d.ts +17 -0
  166. package/dist/runtime/browser-extension.d.ts.map +1 -0
  167. package/dist/runtime/browser-extension.js +42 -0
  168. package/dist/runtime/browser-extension.js.map +1 -0
  169. package/dist/runtime/cdp.d.ts +138 -0
  170. package/dist/runtime/cdp.d.ts.map +1 -0
  171. package/dist/runtime/cdp.js +1429 -0
  172. package/dist/runtime/cdp.js.map +1 -0
  173. package/dist/runtime/decision-types.d.ts +23 -0
  174. package/dist/runtime/decision-types.d.ts.map +1 -0
  175. package/dist/runtime/decision-types.js +2 -0
  176. package/dist/runtime/decision-types.js.map +1 -0
  177. package/dist/runtime/deps-readiness.d.ts +21 -0
  178. package/dist/runtime/deps-readiness.d.ts.map +1 -0
  179. package/dist/runtime/deps-readiness.js +141 -0
  180. package/dist/runtime/deps-readiness.js.map +1 -0
  181. package/dist/runtime/log-analysis.d.ts +48 -0
  182. package/dist/runtime/log-analysis.d.ts.map +1 -0
  183. package/dist/runtime/log-analysis.js +128 -0
  184. package/dist/runtime/log-analysis.js.map +1 -0
  185. package/dist/runtime/metro-probe.d.ts +5 -0
  186. package/dist/runtime/metro-probe.d.ts.map +1 -0
  187. package/dist/runtime/metro-probe.js +24 -0
  188. package/dist/runtime/metro-probe.js.map +1 -0
  189. package/dist/runtime/operation.d.ts +32 -0
  190. package/dist/runtime/operation.d.ts.map +1 -0
  191. package/dist/runtime/operation.js +184 -0
  192. package/dist/runtime/operation.js.map +1 -0
  193. package/dist/runtime/orchestrate-up.d.ts +22 -0
  194. package/dist/runtime/orchestrate-up.d.ts.map +1 -0
  195. package/dist/runtime/orchestrate-up.js +35 -0
  196. package/dist/runtime/orchestrate-up.js.map +1 -0
  197. package/dist/runtime/react-native-bridge.d.ts +17 -0
  198. package/dist/runtime/react-native-bridge.d.ts.map +1 -0
  199. package/dist/runtime/react-native-bridge.js +57 -0
  200. package/dist/runtime/react-native-bridge.js.map +1 -0
  201. package/dist/version.d.ts +2 -0
  202. package/dist/version.d.ts.map +1 -0
  203. package/dist/version.js +8 -0
  204. package/dist/version.js.map +1 -0
  205. package/package.json +163 -0
  206. package/test/fixtures/scroll-to-visible/README.md +39 -0
  207. package/visual-review/feedback-draft.mjs +82 -0
  208. package/visual-review/index.d.mts +41 -0
  209. package/visual-review/index.mjs +4 -0
  210. package/visual-review/recipe-board.mjs +142 -0
  211. package/visual-review/review-board.mjs +981 -0
  212. package/visual-review/server.mjs +69 -0
@@ -0,0 +1,76 @@
1
+ import { mkdir, readFile } from 'node:fs/promises';
2
+ import { digestRecipeDocument, digestRecipeSuiteScope, RECIPE_SUITE_RESULT_SCHEMA_URL, validateRecipeSuitePackage, validateRecipeSuiteScopeDocument, } from '@farmslot/protocol';
3
+ import { writeFileWithinRoot } from './path.js';
4
+ export function freezeRecipeSuiteScope(scope) {
5
+ const validation = validateRecipeSuiteScopeDocument(scope);
6
+ if (validation.status === 'invalid') {
7
+ throw new Error(formatSuiteValidationFailure('Recipe suite scope is invalid', validation.findings));
8
+ }
9
+ const retained = structuredClone(scope);
10
+ deepFreeze(retained);
11
+ return Object.freeze({ scope: retained, digest: digestRecipeSuiteScope(retained) });
12
+ }
13
+ export async function finalizeRecipeSuite(request) {
14
+ if (digestRecipeSuiteScope(request.scope.scope) !== request.scope.digest) {
15
+ throw new Error('Recipe suite scope changed after it was frozen.');
16
+ }
17
+ const summaries = {};
18
+ const summaryFiles = [];
19
+ const resolutions = [];
20
+ let summaryIndex = 0;
21
+ for (const input of request.resolutions) {
22
+ if (input.kind === 'not_executed') {
23
+ resolutions.push(structuredClone(input));
24
+ continue;
25
+ }
26
+ const summary = JSON.parse(await readFile(input.result.summaryPath, 'utf8'));
27
+ const summaryPath = `summaries/${String(++summaryIndex).padStart(4, '0')}.json`;
28
+ summaries[summaryPath] = summary;
29
+ summaryFiles.push({ path: summaryPath, content: `${JSON.stringify(summary, null, 2)}\n` });
30
+ resolutions.push({
31
+ id: input.id,
32
+ kind: 'verdict',
33
+ status: input.result.status,
34
+ summary_path: summaryPath,
35
+ summary_digest: digestRecipeDocument(summary),
36
+ });
37
+ }
38
+ const result = {
39
+ $schema: RECIPE_SUITE_RESULT_SCHEMA_URL,
40
+ suite_id: request.scope.scope.suite_id,
41
+ scope_digest: request.scope.digest,
42
+ totals: {
43
+ declared: request.scope.scope.cases.length,
44
+ executed: resolutions.filter((entry) => entry.kind === 'verdict').length,
45
+ not_executed: resolutions.filter((entry) => entry.kind === 'not_executed').length,
46
+ },
47
+ resolutions,
48
+ };
49
+ const validation = validateRecipeSuitePackage({
50
+ scope: request.scope.scope,
51
+ result,
52
+ summaries,
53
+ });
54
+ if (validation.status === 'invalid') {
55
+ throw new Error(formatSuiteValidationFailure('Recipe suite result is invalid', validation.findings));
56
+ }
57
+ await mkdir(request.outputDir, { recursive: true, mode: 0o700 });
58
+ for (const file of summaryFiles) {
59
+ await writeFileWithinRoot(request.outputDir, file.path, file.content);
60
+ }
61
+ const scopePath = await writeFileWithinRoot(request.outputDir, 'suite-scope.json', `${JSON.stringify(request.scope.scope, null, 2)}\n`);
62
+ const resultPath = await writeFileWithinRoot(request.outputDir, 'suite-result.json', `${JSON.stringify(result, null, 2)}\n`);
63
+ return { scopePath, resultPath, result };
64
+ }
65
+ function deepFreeze(value) {
66
+ if (value && typeof value === 'object') {
67
+ Object.freeze(value);
68
+ for (const child of Object.values(value))
69
+ deepFreeze(child);
70
+ }
71
+ return value;
72
+ }
73
+ function formatSuiteValidationFailure(prefix, findings) {
74
+ return `${prefix}: ${findings.map((finding) => `${finding.code} ${finding.path}`).join(', ')}.`;
75
+ }
76
+ //# sourceMappingURL=suite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suite.js","sourceRoot":"","sources":["../../src/core/suite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { RecipeFailureCause } from '@farmslot/protocol';
2
+ import type { ActionResult, TraceEntry, TraceWriter } from './types.js';
3
+ export declare function recordSyntheticFailure(traceWriter: TraceWriter, nodeId: string, error: Error, action: string | undefined, causeClass: RecipeFailureCause): void;
4
+ export declare function traceNodeMetadata(node: Record<string, unknown>, result?: ActionResult): Pick<TraceEntry, 'intent' | 'proves' | 'artifacts'>;
5
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExE,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,kBAAkB,GAC7B,IAAI,CAYN;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,CAAC,EAAE,YAAY,GACpB,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC,CAUrD"}
@@ -0,0 +1,25 @@
1
+ export function recordSyntheticFailure(traceWriter, nodeId, error, action, causeClass) {
2
+ const now = new Date().toISOString();
3
+ traceWriter.record({
4
+ nodeId,
5
+ action: action ?? 'unknown',
6
+ startedAt: now,
7
+ endedAt: now,
8
+ durationMs: 0,
9
+ ok: false,
10
+ cause_class: causeClass,
11
+ error: error.message,
12
+ });
13
+ }
14
+ export function traceNodeMetadata(node, result) {
15
+ const metadata = {};
16
+ if (typeof node.intent === 'string' && node.intent.trim())
17
+ metadata.intent = node.intent;
18
+ if (Array.isArray(node.proves)) {
19
+ metadata.proves = node.proves.filter((proofTarget) => typeof proofTarget === 'string');
20
+ }
21
+ if (result?.artifacts?.length)
22
+ metadata.artifacts = result.artifacts;
23
+ return metadata;
24
+ }
25
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/core/trace.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,sBAAsB,CACpC,WAAwB,EACxB,MAAc,EACd,KAAY,EACZ,MAA0B,EAC1B,UAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,WAAW,CAAC,MAAM,CAAC;QACjB,MAAM;QACN,MAAM,EAAE,MAAM,IAAI,SAAS;QAC3B,SAAS,EAAE,GAAG;QACd,OAAO,EAAE,GAAG;QACZ,UAAU,EAAE,CAAC;QACb,EAAE,EAAE,KAAK;QACT,WAAW,EAAE,UAAU;QACvB,KAAK,EAAE,KAAK,CAAC,OAAO;KACrB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAA6B,EAC7B,MAAqB;IAErB,MAAM,QAAQ,GAAwD,EAAE,CAAC;IACzE,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzF,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAClC,CAAC,WAAW,EAAyB,EAAE,CAAC,OAAO,WAAW,KAAK,QAAQ,CACxE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,EAAE,SAAS,EAAE,MAAM;QAAE,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACrE,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { RecipeTrustFailure } from '@farmslot/protocol';
2
+ export declare class RecipeTrustError extends Error {
3
+ readonly code: RecipeTrustFailure['code'];
4
+ readonly userAction: string;
5
+ readonly failure: RecipeTrustFailure;
6
+ constructor(failure: RecipeTrustFailure);
7
+ }
8
+ export declare function invalidRecipeSource(message: string, userAction: string): RecipeTrustError;
9
+ //# sourceMappingURL=trust-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-error.d.ts","sourceRoot":"","sources":["../../src/core/trust-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBAEzB,OAAO,EAAE,kBAAkB;CAOxC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAOzF"}
@@ -0,0 +1,18 @@
1
+ export class RecipeTrustError extends Error {
2
+ constructor(failure) {
3
+ super(failure.message);
4
+ this.name = 'RecipeTrustError';
5
+ this.code = failure.code;
6
+ this.userAction = failure.userAction;
7
+ this.failure = failure;
8
+ }
9
+ }
10
+ export function invalidRecipeSource(message, userAction) {
11
+ return new RecipeTrustError({
12
+ code: 'RECIPE_SOURCE_INVALID',
13
+ message,
14
+ userAction,
15
+ reason: 'invalid-source',
16
+ });
17
+ }
18
+ //# sourceMappingURL=trust-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-error.js","sourceRoot":"","sources":["../../src/core/trust-error.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAKzC,YAAY,OAA2B;QACrC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,UAAkB;IACrE,OAAO,IAAI,gBAAgB,CAAC;QAC1B,IAAI,EAAE,uBAAuB;QAC7B,OAAO;QACP,UAAU;QACV,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type RecipeExecutionApproval, type RecipeSourceProvenance } from '@farmslot/protocol';
2
+ export declare const RECIPE_TRUST_ENV: {
3
+ readonly sourceTrust: "FARMSLOT_RECIPE_SOURCE_TRUST";
4
+ readonly sourceKind: "FARMSLOT_RECIPE_SOURCE_KIND";
5
+ readonly sourceName: "FARMSLOT_RECIPE_SOURCE_NAME";
6
+ readonly sourceDigest: "FARMSLOT_RECIPE_SOURCE_DIGEST";
7
+ readonly approvalDigest: "FARMSLOT_RECIPE_APPROVE_PLAN";
8
+ };
9
+ export interface RecipeTrustInput {
10
+ source?: RecipeSourceProvenance;
11
+ approval?: RecipeExecutionApproval;
12
+ }
13
+ export declare function resolveRecipeTrustInput(options?: {
14
+ sourceTrust?: string;
15
+ sourceKind?: string;
16
+ sourceName?: string;
17
+ sourceDigest?: string;
18
+ approvalDigest?: string;
19
+ }, env?: Record<string, string | undefined>): RecipeTrustInput;
20
+ //# sourceMappingURL=trust-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-input.d.ts","sourceRoot":"","sources":["../../src/core/trust-input.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAE5B,KAAK,sBAAsB,EAC5B,MAAM,oBAAoB,CAAC;AAI5B,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAYX,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACpC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACpB,EACN,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,gBAAgB,CAsBlB"}
@@ -0,0 +1,68 @@
1
+ import { invalidRecipeSource } from './trust-error.js';
2
+ export const RECIPE_TRUST_ENV = {
3
+ sourceTrust: 'FARMSLOT_RECIPE_SOURCE_TRUST',
4
+ sourceKind: 'FARMSLOT_RECIPE_SOURCE_KIND',
5
+ sourceName: 'FARMSLOT_RECIPE_SOURCE_NAME',
6
+ sourceDigest: 'FARMSLOT_RECIPE_SOURCE_DIGEST',
7
+ approvalDigest: 'FARMSLOT_RECIPE_APPROVE_PLAN',
8
+ };
9
+ const sourceTrustValues = new Set(['trusted', 'untrusted', 'unknown']);
10
+ const sourceKindValues = new Set([
11
+ 'bundled',
12
+ 'operator',
13
+ 'task',
14
+ 'recipe-file',
15
+ 'library',
16
+ 'custom-adapter',
17
+ ]);
18
+ export function resolveRecipeTrustInput(options = {}, env = process.env) {
19
+ const optionSource = parseSource(options, 'option');
20
+ const environmentSource = parseSource({
21
+ sourceTrust: env[RECIPE_TRUST_ENV.sourceTrust],
22
+ sourceKind: env[RECIPE_TRUST_ENV.sourceKind],
23
+ sourceName: env[RECIPE_TRUST_ENV.sourceName],
24
+ sourceDigest: env[RECIPE_TRUST_ENV.sourceDigest],
25
+ }, 'environment');
26
+ const source = restrictSource(environmentSource, optionSource);
27
+ const environmentApproval = env[RECIPE_TRUST_ENV.approvalDigest];
28
+ const approvalDigest = environmentSource && environmentSource.trust !== 'trusted'
29
+ ? environmentApproval
30
+ : (options.approvalDigest ?? environmentApproval);
31
+ return {
32
+ ...(source ? { source } : {}),
33
+ ...(approvalDigest ? { approval: { planDigest: approvalDigest } } : {}),
34
+ };
35
+ }
36
+ function parseSource(values, input) {
37
+ const { sourceTrust, sourceKind, sourceName, sourceDigest } = values;
38
+ if ((sourceTrust == null) !== (sourceKind == null)) {
39
+ throw invalidRecipeSource(`Recipe source trust and kind must be supplied together in the ${input}.`, `set both ${RECIPE_TRUST_ENV.sourceTrust} and ${RECIPE_TRUST_ENV.sourceKind}`);
40
+ }
41
+ if ((sourceName != null || sourceDigest != null) && (sourceTrust == null || sourceKind == null)) {
42
+ throw invalidRecipeSource(`Recipe source name or digest requires source trust and kind in the ${input}.`, `set both ${RECIPE_TRUST_ENV.sourceTrust} and ${RECIPE_TRUST_ENV.sourceKind}`);
43
+ }
44
+ if (sourceTrust && !sourceTrustValues.has(sourceTrust)) {
45
+ throw invalidRecipeSource(`Unknown recipe source trust ${JSON.stringify(sourceTrust)}.`, 'use trusted, untrusted, or unknown');
46
+ }
47
+ if (sourceKind && !sourceKindValues.has(sourceKind)) {
48
+ throw invalidRecipeSource(`Unknown recipe source kind ${JSON.stringify(sourceKind)}.`, 'use a Recipe Protocol source kind reported by the runner');
49
+ }
50
+ if (!sourceTrust || !sourceKind)
51
+ return undefined;
52
+ return {
53
+ trust: sourceTrust,
54
+ kind: sourceKind,
55
+ ...(sourceName ? { name: sourceName } : {}),
56
+ ...(sourceDigest ? { digest: sourceDigest } : {}),
57
+ };
58
+ }
59
+ function restrictSource(environmentSource, optionSource) {
60
+ if (!environmentSource)
61
+ return optionSource;
62
+ if (!optionSource)
63
+ return environmentSource;
64
+ if (environmentSource.trust !== 'trusted')
65
+ return environmentSource;
66
+ return optionSource;
67
+ }
68
+ //# sourceMappingURL=trust-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-input.js","sourceRoot":"","sources":["../../src/core/trust-input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type RecipeActionManifestDocument, type RecipeExecutionCapability, type RecipeExecutionPlan, type RecipeSourceProvenance } from '@farmslot/protocol';
2
+ import type { ResolvedLibraryRecipe } from './library.js';
3
+ import type { DefaultObserverRefs } from './passive-observations.js';
4
+ import type { ActionAdapter, RecipeHudOptions, RecipeRunRequest } from './types.js';
5
+ export declare function recipeSourceForRequest(request: RecipeRunRequest, recipe: unknown, sourceRecipePath?: string, defaultSource?: RecipeSourceProvenance): RecipeSourceProvenance;
6
+ export declare function buildRecipeExecutionPlan({ recipe, params, source, recipes, adapters, actionManifest, defaultObserverRefs, projectRoot, artifactsDir, env, hud, recordVideo, }: {
7
+ recipe: Record<string, unknown>;
8
+ params: Record<string, unknown>;
9
+ source: RecipeSourceProvenance;
10
+ recipes: ReadonlyMap<string, ResolvedLibraryRecipe>;
11
+ adapters: ReadonlyMap<string, ActionAdapter>;
12
+ actionManifest: RecipeActionManifestDocument;
13
+ defaultObserverRefs: DefaultObserverRefs;
14
+ projectRoot: string;
15
+ artifactsDir: string;
16
+ env: Record<string, string | undefined>;
17
+ hud?: RecipeHudOptions | false;
18
+ recordVideo?: RecipeRunRequest['recordVideo'];
19
+ }): RecipeExecutionPlan;
20
+ export declare function enforceRecipeExecutionPlan(plan: RecipeExecutionPlan, request: Pick<RecipeRunRequest, 'approval'>, blockedCapabilities?: readonly RecipeExecutionCapability[]): void;
21
+ export declare function verifyExecutableSource(executable: Pick<ActionAdapter, 'source' | 'resolveSourceDigest'>, label: string): Promise<void>;
22
+ /**
23
+ * The environment an approval binds to. Only the volatile package-manager values above are
24
+ * dropped, plus the per-invocation shim folder Yarn puts first on PATH, so repeated runs through
25
+ * the same invocation path (for example `yarn farmslot recipe run`) approve the same digest.
26
+ */
27
+ export declare function planEnvironment(env: Readonly<Record<string, string | undefined>>): Record<string, string | undefined>;
28
+ //# sourceMappingURL=trust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/core/trust.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EAExB,KAAK,sBAAsB,EAC5B,MAAM,oBAAoB,CAAC;AAI5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGrE,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASpF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,OAAO,EACf,gBAAgB,CAAC,EAAE,MAAM,EACzB,aAAa,CAAC,EAAE,sBAAsB,GACrC,sBAAsB,CAoBxB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,MAAM,EACN,MAAM,EACN,MAAM,EACN,OAAO,EACP,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,GAAG,EACH,GAAG,EACH,WAAW,GACZ,EAAE;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACpD,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,cAAc,EAAE,4BAA4B,CAAC;IAC7C,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,GAAG,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAC;IAC/B,WAAW,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAC;CAC/C,GAAG,mBAAmB,CA2GtB;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,EAC3C,mBAAmB,GAAE,SAAS,yBAAyB,EAAkD,GACxG,IAAI,CA6DN;AAED,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,GAAG,qBAAqB,CAAC,EACjE,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAef;AA8GD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAYpC"}
@@ -0,0 +1,284 @@
1
+ import path from 'node:path';
2
+ import { DEFAULT_UNTRUSTED_RECIPE_BLOCKED_CAPABILITIES, digestRecipeDocument, normalizeRecipeRef, OFFICIAL_RECIPE_ACTIONS, officialRecipeActionCapabilities, } from '@farmslot/protocol';
3
+ import { extractWorkflowGraph } from './graph.js';
4
+ import { isRecord } from './json.js';
5
+ import { resolveRecipeParams, resolveRecipeValue } from './parameters.js';
6
+ import { RecipeResolutionError } from './resolution-error.js';
7
+ import { invalidRecipeSource, RecipeTrustError } from './trust-error.js';
8
+ const officialActions = new Set(OFFICIAL_RECIPE_ACTIONS);
9
+ const bundledSource = {
10
+ kind: 'bundled',
11
+ trust: 'trusted',
12
+ name: '@farmslot/recipe-runner',
13
+ };
14
+ export function recipeSourceForRequest(request, recipe, sourceRecipePath, defaultSource) {
15
+ const digest = digestValue(recipe);
16
+ const claimedDigest = request.source?.digest ?? defaultSource?.digest;
17
+ if (claimedDigest && claimedDigest !== digest) {
18
+ throw invalidRecipeSource(`Recipe source digest ${claimedDigest} does not match the loaded document.`, `use the loaded recipe digest ${digest} or omit the caller digest`);
19
+ }
20
+ const fallback = {
21
+ kind: request.recipeDocument == null ? 'recipe-file' : 'operator',
22
+ trust: 'unknown',
23
+ };
24
+ return {
25
+ ...fallback,
26
+ ...defaultSource,
27
+ ...request.source,
28
+ ...(sourceRecipePath ? { path: sourceRecipePath } : {}),
29
+ digest,
30
+ };
31
+ }
32
+ export function buildRecipeExecutionPlan({ recipe, params, source, recipes, adapters, actionManifest, defaultObserverRefs, projectRoot, artifactsDir, env, hud, recordVideo, }) {
33
+ const nodes = [];
34
+ const digestNodes = [];
35
+ const addNode = (nodeId, node, origin, invocationOrigin) => {
36
+ if (typeof node.action !== 'string' || !node.action.trim())
37
+ return;
38
+ const adapter = adapters.get(node.action);
39
+ const adapterOrigin = adapterSource(node.action, adapter);
40
+ const observerRefs = [...(defaultObserverRefs.get(node.action) ?? [])];
41
+ const capabilities = actionCapabilities(node.action, adapter, adapterOrigin, declaredActionCapabilities(actionManifest, node.action), observerRefs.length > 0);
42
+ const planNode = {
43
+ nodeId,
44
+ action: node.action,
45
+ capabilities,
46
+ origin,
47
+ ...(observerRefs.length > 0 ? { observerRefs } : {}),
48
+ ...(containsRecipeOutputTemplate(node) ? { runtimeOutputDependent: true } : {}),
49
+ ...(invocationOrigin ? { invocationOrigin } : {}),
50
+ ...(adapterOrigin ? { adapterOrigin } : {}),
51
+ };
52
+ nodes.push(planNode);
53
+ digestNodes.push({ plan: planNode, node });
54
+ };
55
+ const visitRecipe = (activeRecipe, activeParams, origin, invocationOrigin, prefix) => {
56
+ const activeGraph = extractWorkflowGraph(activeRecipe);
57
+ for (const [nodeId, rawNode] of Object.entries(activeGraph.nodes)) {
58
+ const resolvedNode = resolveRecipeValue(rawNode, activeParams);
59
+ if (!isRecord(resolvedNode)) {
60
+ throw new RecipeResolutionError('RECIPE_PARAMS_INVALID', `Recipe node ${prefix}${nodeId} did not resolve to an object.`, `inspect parameter templates used by ${prefix}${nodeId}`);
61
+ }
62
+ const planNodeId = `${prefix}${nodeId}`;
63
+ addNode(planNodeId, resolvedNode, origin, invocationOrigin);
64
+ if (resolvedNode.action !== 'call' || typeof resolvedNode.ref !== 'string')
65
+ continue;
66
+ const ref = normalizeRecipeRef(resolvedNode.ref);
67
+ const dependency = recipes.get(ref);
68
+ if (!dependency) {
69
+ throw new RecipeResolutionError('RECIPE_REFERENCE_NOT_FOUND', `Recipe ${ref} is not available from configured libraries.`, `add ${ref} to a configured recipe library or correct call.ref`);
70
+ }
71
+ const childInput = isRecord(resolvedNode.params) ? resolvedNode.params : {};
72
+ const childParams = resolveRecipeParams(ref, dependency.document, childInput, {
73
+ allowTemplates: true,
74
+ });
75
+ visitRecipe(dependency.document, childParams, dependency.provenance, effectiveInvocationOrigin(origin, invocationOrigin), `${planNodeId}/`);
76
+ }
77
+ };
78
+ visitRecipe(recipe, params, source, undefined, '');
79
+ if (hud !== false && hud?.enabled !== false && adapters.has('app.hud')) {
80
+ addNode('run:hud', { action: 'app.hud', automatic: true, options: hud ?? {} }, source);
81
+ }
82
+ if (recordVideo && recordVideo !== 'off') {
83
+ const planNode = {
84
+ nodeId: 'run:recording',
85
+ action: 'recording',
86
+ capabilities: ['host-read-export'],
87
+ origin: source,
88
+ adapterOrigin: bundledSource,
89
+ };
90
+ nodes.push(planNode);
91
+ digestNodes.push({ plan: planNode, node: { recordVideo } });
92
+ }
93
+ const executionContextDigest = digestValue({
94
+ projectRoot,
95
+ artifactsDir,
96
+ env: planEnvironment(env),
97
+ params,
98
+ });
99
+ const planBody = { schemaVersion: 1, executionContextDigest, source, nodes };
100
+ return {
101
+ ...planBody,
102
+ digest: digestValue({ recipe, source, executionContextDigest, nodes: digestNodes }),
103
+ };
104
+ }
105
+ export function enforceRecipeExecutionPlan(plan, request, blockedCapabilities = DEFAULT_UNTRUSTED_RECIPE_BLOCKED_CAPABILITIES) {
106
+ for (const node of plan.nodes) {
107
+ if (node.capabilities.includes('arbitrary-code') &&
108
+ node.adapterOrigin?.trust !== 'trusted' &&
109
+ !node.adapterOrigin?.digest) {
110
+ throw invalidRecipeSource(`Custom implementation ${node.action} has no content digest.`, 'register a trusted adapter or supply provenance with a digest before approval');
111
+ }
112
+ }
113
+ const blockedSet = new Set(blockedCapabilities);
114
+ const blocked = plan.nodes.filter((node) => {
115
+ const untrustedRecipe = node.origin.trust !== 'trusted';
116
+ const untrustedInvocation = node.invocationOrigin != null && node.invocationOrigin.trust !== 'trusted';
117
+ const untrustedAdapter = node.adapterOrigin?.trust !== 'trusted';
118
+ return node.capabilities.some((capability) => blockedSet.has(capability) && (untrustedRecipe || untrustedInvocation || untrustedAdapter));
119
+ });
120
+ if (blocked.length === 0)
121
+ return;
122
+ const runtimeDependent = blocked.filter((node) => node.runtimeOutputDependent);
123
+ if (runtimeDependent.length > 0) {
124
+ throw new RecipeTrustError({
125
+ code: 'RECIPE_TRUST_REQUIRED',
126
+ message: 'Untrusted restricted recipe nodes cannot derive executable values from runtime outputs.',
127
+ userAction: 'replace {{outputs.*}} executable values with reviewed recipe parameters, or move the behavior into a trusted recipe',
128
+ reason: 'blocked-capability',
129
+ recipeDigest: plan.digest,
130
+ trust: plan.source.trust,
131
+ blocked: runtimeDependent.map(redactPlanNodeProvenance),
132
+ });
133
+ }
134
+ if (request.approval?.planDigest === plan.digest)
135
+ return;
136
+ const publicBlocked = blocked.map(redactPlanNodeProvenance);
137
+ if (request.approval) {
138
+ throw new RecipeTrustError({
139
+ code: 'RECIPE_APPROVAL_MISMATCH',
140
+ message: 'Recipe approval does not match the resolved execution plan.',
141
+ userAction: approvalUserAction(plan.digest),
142
+ reason: 'approval-mismatch',
143
+ recipeDigest: plan.digest,
144
+ trust: plan.source.trust,
145
+ blocked: publicBlocked,
146
+ });
147
+ }
148
+ throw new RecipeTrustError({
149
+ code: 'RECIPE_TRUST_REQUIRED',
150
+ message: 'Untrusted recipe sources cannot execute restricted capabilities.',
151
+ userAction: approvalUserAction(plan.digest),
152
+ reason: 'blocked-capability',
153
+ recipeDigest: plan.digest,
154
+ trust: plan.source.trust,
155
+ blocked: publicBlocked,
156
+ });
157
+ }
158
+ export async function verifyExecutableSource(executable, label) {
159
+ if (!executable.resolveSourceDigest)
160
+ return;
161
+ if (!executable.source?.digest) {
162
+ throw invalidRecipeSource(`${label} has an integrity verifier but no approved source digest.`, 'resolve the implementation again and review its content digest before execution');
163
+ }
164
+ const actualDigest = await executable.resolveSourceDigest();
165
+ if (actualDigest !== executable.source.digest) {
166
+ throw invalidRecipeSource(`${label} changed after the execution plan was resolved.`, 'resolve and review a new execution plan for the current implementation bytes');
167
+ }
168
+ }
169
+ function approvalUserAction(planDigest) {
170
+ return (`review the resolved plan, then approve ${planDigest} through the trusted caller ` +
171
+ `(direct CLI: --approve-plan ${planDigest}; managed run: ` +
172
+ `FARMSLOT_RECIPE_APPROVE_PLAN=${planDigest})`);
173
+ }
174
+ function effectiveInvocationOrigin(definitionOrigin, invocationOrigin) {
175
+ if (invocationOrigin && invocationOrigin.trust !== 'trusted')
176
+ return invocationOrigin;
177
+ if (definitionOrigin.trust !== 'trusted')
178
+ return definitionOrigin;
179
+ return invocationOrigin ?? definitionOrigin;
180
+ }
181
+ function redactPlanNodeProvenance(node) {
182
+ return {
183
+ ...node,
184
+ origin: redactSourceDetails(node.origin),
185
+ ...(node.invocationOrigin
186
+ ? { invocationOrigin: redactSourceDetails(node.invocationOrigin) }
187
+ : {}),
188
+ ...(node.adapterOrigin ? { adapterOrigin: redactSourceDetails(node.adapterOrigin) } : {}),
189
+ };
190
+ }
191
+ function redactSourceDetails(source) {
192
+ const { name: _name, path: _path, ...publicSource } = source;
193
+ return publicSource;
194
+ }
195
+ function actionCapabilities(action, adapter, adapterOrigin, manifestCapabilities, observes) {
196
+ const declared = adapter?.capabilities;
197
+ const official = officialActions.has(action)
198
+ ? officialRecipeActionCapabilities(action)
199
+ : [];
200
+ const observerCapabilities = observes ? ['host-read-export'] : [];
201
+ const base = officialActions.has(action)
202
+ ? [
203
+ ...new Set([
204
+ ...official,
205
+ ...manifestCapabilities,
206
+ ...(declared ?? []),
207
+ ...observerCapabilities,
208
+ ]),
209
+ ]
210
+ : declared
211
+ ? [...new Set([...manifestCapabilities, ...declared, ...observerCapabilities])]
212
+ : action === 'call'
213
+ ? observerCapabilities
214
+ : [
215
+ ...new Set([
216
+ 'arbitrary-code',
217
+ ...manifestCapabilities,
218
+ ...observerCapabilities,
219
+ ]),
220
+ ];
221
+ if (adapterOrigin?.trust === 'trusted' || base.includes('arbitrary-code'))
222
+ return [...base];
223
+ return [...base, 'arbitrary-code'];
224
+ }
225
+ function declaredActionCapabilities(manifest, action) {
226
+ return manifest.actions[action]?.execution_capabilities ?? [];
227
+ }
228
+ function adapterSource(action, adapter) {
229
+ if (action === 'call' || action === 'end')
230
+ return bundledSource;
231
+ if (adapter?.source)
232
+ return adapter.source;
233
+ return {
234
+ kind: 'custom-adapter',
235
+ trust: 'unknown',
236
+ name: action,
237
+ };
238
+ }
239
+ /**
240
+ * Values Yarn (via Corepack) sets on every `yarn <script>` that say nothing about what the run does:
241
+ * the per-invocation shim paths, and package metadata. Everything else, including user-set
242
+ * `npm_config_*` and `COREPACK_*` settings such as a registry, stays bound to the approval.
243
+ */
244
+ const VOLATILE_PACKAGE_MANAGER_ENV = new Set([
245
+ 'BERRY_BIN_FOLDER',
246
+ 'npm_execpath',
247
+ 'npm_node_execpath',
248
+ 'npm_config_user_agent',
249
+ 'INIT_CWD',
250
+ 'PROJECT_CWD',
251
+ 'COREPACK_ROOT',
252
+ 'COREPACK_ENABLE_DOWNLOAD_PROMPT',
253
+ ]);
254
+ const PACKAGE_METADATA_ENV = /^npm_package_/u;
255
+ /**
256
+ * The environment an approval binds to. Only the volatile package-manager values above are
257
+ * dropped, plus the per-invocation shim folder Yarn puts first on PATH, so repeated runs through
258
+ * the same invocation path (for example `yarn farmslot recipe run`) approve the same digest.
259
+ */
260
+ export function planEnvironment(env) {
261
+ const shims = env.BERRY_BIN_FOLDER;
262
+ return Object.fromEntries(Object.entries(env)
263
+ .filter(([key]) => !VOLATILE_PACKAGE_MANAGER_ENV.has(key) && !PACKAGE_METADATA_ENV.test(key))
264
+ .map(([key, value]) => {
265
+ if (key !== 'PATH' || !shims || !value)
266
+ return [key, value];
267
+ const [first, ...rest] = value.split(path.delimiter);
268
+ // Only Yarn's own shim entry at the front of PATH is volatile.
269
+ return [key, first === shims ? rest.join(path.delimiter) : value];
270
+ }));
271
+ }
272
+ function digestValue(value) {
273
+ return digestRecipeDocument(value);
274
+ }
275
+ function containsRecipeOutputTemplate(value) {
276
+ if (typeof value === 'string')
277
+ return value.includes('{{outputs.');
278
+ if (Array.isArray(value))
279
+ return value.some(containsRecipeOutputTemplate);
280
+ if (!isRecord(value))
281
+ return false;
282
+ return Object.values(value).some(containsRecipeOutputTemplate);
283
+ }
284
+ //# sourceMappingURL=trust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust.js","sourceRoot":"","sources":["../../src/core/trust.ts"],"names":[],"mappings":"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"}