From 5d14b2ed0b2614c549c388cd17cf685b343158a3 Mon Sep 17 00:00:00 2001 From: Fabro Date: Wed, 27 May 2026 05:06:28 +0000 Subject: [PATCH] Make run provenance total --- .../app/components/run-summary-panel.test.tsx | 10 +++--- .../app/components/run-summary-panel.tsx | 2 +- .../components/runs-list/run-table-row.tsx | 12 +++---- apps/fabro-web/app/data/runs.test.ts | 3 +- apps/fabro-web/app/data/runs.ts | 2 +- apps/fabro-web/app/lib/run-actions.test.ts | 3 +- apps/fabro-web/app/lib/test-principal.ts | 10 ++++++ apps/fabro-web/app/routes/run-detail.test.ts | 3 +- .../app/routes/run-files.render.test.tsx | 3 +- .../app/routes/runs.preferences.test.tsx | 3 +- apps/fabro-web/app/routes/runs.test.tsx | 3 +- docs/public/api-reference/fabro-api.yaml | 15 ++++---- lib/crates/fabro-api/Cargo.toml | 3 ++ .../fabro-api/tests/principal_round_trip.rs | 4 +-- .../fabro-api/tests/run_event_round_trip.rs | 6 ++-- .../tests/run_projection_round_trip.rs | 4 +-- .../fabro-api/tests/run_summary_round_trip.rs | 16 +++++++-- lib/crates/fabro-cli/Cargo.toml | 1 + .../fabro-cli/src/commands/run/attach.rs | 3 +- lib/crates/fabro-cli/tests/it/cmd/inspect.rs | 16 ++++++++- lib/crates/fabro-cli/tests/it/cmd/support.rs | 9 +++++ lib/crates/fabro-cli/tests/it/support/mod.rs | 4 +-- lib/crates/fabro-dump/src/lib.rs | 4 +-- lib/crates/fabro-server/src/demo/mod.rs | 17 ++++++--- lib/crates/fabro-server/src/run_files.rs | 4 +-- lib/crates/fabro-server/src/run_manifest.rs | 7 ++-- .../fabro-server/src/server/handler/events.rs | 4 +-- .../src/server/handler/lifecycle.rs | 2 +- .../fabro-server/src/server/handler/pair.rs | 4 +-- .../fabro-server/src/server/handler/runs.rs | 5 +-- .../src/server/handler/sandbox.rs | 3 +- .../src/server/handler/sessions.rs | 3 +- lib/crates/fabro-server/src/server/tests.rs | 25 ++++++------- .../fabro-server/tests/it/api/run_files.rs | 4 +-- lib/crates/fabro-store/Cargo.toml | 1 + lib/crates/fabro-store/src/run_state.rs | 33 ++++++++--------- lib/crates/fabro-store/src/slate/mod.rs | 7 ++-- lib/crates/fabro-store/src/slate/run_store.rs | 3 +- .../tests/serializable_projection.rs | 4 +-- lib/crates/fabro-tool/Cargo.toml | 1 + lib/crates/fabro-tool/src/common.rs | 6 ++-- lib/crates/fabro-tool/src/create.rs | 4 +-- lib/crates/fabro-tool/src/interact.rs | 4 +-- lib/crates/fabro-tool/src/search.rs | 6 ++-- lib/crates/fabro-types/src/lib.rs | 2 ++ lib/crates/fabro-types/src/run.rs | 8 ++--- lib/crates/fabro-types/src/run_event/mod.rs | 6 ++-- lib/crates/fabro-types/src/run_event/run.rs | 3 +- lib/crates/fabro-types/src/run_projection.rs | 8 ++--- lib/crates/fabro-types/src/run_summary.rs | 3 +- lib/crates/fabro-types/src/test_support.rs | 21 +++++++++++ .../fabro-types/tests/run_event_serde.rs | 22 ++++++++---- .../fabro-types/tests/run_spec_methods.rs | 12 ++++++- .../fabro-types/tests/run_spec_serde.rs | 12 ++++++- .../fabro-workflow/src/billing_rollup.rs | 4 +-- .../fabro-workflow/src/event/convert.rs | 36 +++++++++---------- lib/crates/fabro-workflow/src/event/events.rs | 3 +- lib/crates/fabro-workflow/src/event/sink.rs | 4 +-- .../fabro-workflow/src/event/stored_fields.rs | 2 +- lib/crates/fabro-workflow/src/git.rs | 4 +-- .../fabro-workflow/src/handler/agent.rs | 4 +-- .../fabro-workflow/src/handler/command.rs | 6 ++-- .../fabro-workflow/src/handler/llm/api.rs | 3 +- .../fabro-workflow/src/handler/parallel.rs | 4 +-- .../fabro-workflow/src/handler/prompt.rs | 4 +-- .../fabro-workflow/src/lifecycle/git.rs | 4 +-- .../fabro-workflow/src/operations/archive.rs | 6 ++-- .../fabro-workflow/src/operations/create.rs | 28 +++++++-------- .../fabro-workflow/src/operations/fork.rs | 4 +-- .../fabro-workflow/src/operations/retry.rs | 21 ++++------- .../fabro-workflow/src/operations/start.rs | 8 +++-- .../fabro-workflow/src/operations/timeline.rs | 3 +- .../src/pipeline/execute/tests.rs | 8 +++-- .../fabro-workflow/src/pipeline/finalize.rs | 6 ++-- .../fabro-workflow/src/pipeline/initialize.rs | 4 +-- .../fabro-workflow/src/pipeline/persist.rs | 4 +-- .../src/pipeline/pull_request.rs | 18 +++++----- lib/crates/fabro-workflow/src/run_lookup.rs | 4 +-- lib/crates/fabro-workflow/src/run_metadata.rs | 6 ++-- .../fabro-workflow/src/runtime_store.rs | 6 ++-- lib/crates/fabro-workflow/src/test_support.rs | 8 ++++- .../src/models/run-provenance.ts | 2 +- .../fabro-api-client/src/models/run-spec.ts | 2 +- .../fabro-api-client/src/models/run.ts | 2 +- 84 files changed, 365 insertions(+), 236 deletions(-) create mode 100644 apps/fabro-web/app/lib/test-principal.ts create mode 100644 lib/crates/fabro-types/src/test_support.rs diff --git a/apps/fabro-web/app/components/run-summary-panel.test.tsx b/apps/fabro-web/app/components/run-summary-panel.test.tsx index ed56824ed..0a3ff3bbd 100644 --- a/apps/fabro-web/app/components/run-summary-panel.test.tsx +++ b/apps/fabro-web/app/components/run-summary-panel.test.tsx @@ -6,6 +6,7 @@ import { RunSummaryPanelView, type RunSummaryPanelViewProps, } from "./run-summary-panel"; +import { testPrincipal } from "../lib/test-principal"; function instanceText(instance: TestRenderer.ReactTestInstance): string { const parts: string[] = []; @@ -53,7 +54,7 @@ function cellAfterLabel( function makeRun(overrides: Record = {}) { return { id: "run_1", - created_by: null, + created_by: testPrincipal(), diff: null, billing: null, ...overrides, @@ -71,9 +72,8 @@ describe("RunSummaryPanelView", () => { } }); - test("shows unavailable copy for missing run fields after load", () => { + test("shows unavailable copy for missing optional run fields after load", () => { const tree = render({ run: makeRun() }); - expect(instanceText(cellAfterLabel(tree, "Created by"))).toBe(EMPTY_VALUE); expect(instanceText(cellAfterLabel(tree, "Changes"))).toBe(EMPTY_VALUE); expect(instanceText(cellAfterLabel(tree, "Cost"))).toBe(EMPTY_VALUE); }); @@ -174,7 +174,7 @@ describe("RunSummaryPanelView", () => { kind: "user", identity: { issuer: "github", subject: "1" }, login: "brynary", - auth_method: "oauth", + auth_method: "github", }, }), }); @@ -188,7 +188,7 @@ describe("RunSummaryPanelView", () => { kind: "user", identity: { issuer: "github", subject: "1" }, login: "brynary", - auth_method: "oauth", + auth_method: "github", avatar_url: "https://example.com/brynary.png", }, }), diff --git a/apps/fabro-web/app/components/run-summary-panel.tsx b/apps/fabro-web/app/components/run-summary-panel.tsx index 5d9c78ce4..8e3f6db65 100644 --- a/apps/fabro-web/app/components/run-summary-panel.tsx +++ b/apps/fabro-web/app/components/run-summary-panel.tsx @@ -92,7 +92,7 @@ export function RunSummaryPanelView({ artifactsCount, artifactsLoading, }: RunSummaryPanelViewProps) { - const created = run?.created_by ? principalDisplay(run.created_by) : null; + const created = run ? principalDisplay(run.created_by) : null; const diff = run?.diff ?? null; const cost = formatUsdMicros(run?.billing?.total_usd_micros); diff --git a/apps/fabro-web/app/components/runs-list/run-table-row.tsx b/apps/fabro-web/app/components/runs-list/run-table-row.tsx index ca521fb92..6f38e2425 100644 --- a/apps/fabro-web/app/components/runs-list/run-table-row.tsx +++ b/apps/fabro-web/app/components/runs-list/run-table-row.tsx @@ -35,6 +35,7 @@ export function RunTableRow({ }) { const lifecycleLabel = listLifecycleStatusLabel(run); const statusDisplay = columnStatusDisplay[run.status]; + const createdBy = principalDisplay(run.createdBy); const show = (col: ToggleableColumn) => !hiddenColumns.has(col); return ( @@ -54,14 +55,9 @@ export function RunTableRow({ {show("created_by") && ( - {run.createdBy && (() => { - const display = principalDisplay(run.createdBy); - return ( - - {display.glyph} - - ); - })()} + + {createdBy.glyph} + )} {show("repo") && ( diff --git a/apps/fabro-web/app/data/runs.test.ts b/apps/fabro-web/app/data/runs.test.ts index 98586b2c4..1894ffe27 100644 --- a/apps/fabro-web/app/data/runs.test.ts +++ b/apps/fabro-web/app/data/runs.test.ts @@ -8,6 +8,7 @@ import { mapRunToRunItem, runStatusDisplay, } from "./runs"; +import { testPrincipal } from "../lib/test-principal"; function makeRun(overrides: Partial = {}): Run { return { @@ -17,7 +18,7 @@ function makeRun(overrides: Partial = {}): Run { workflow: { slug: "fix_build", name: "Fix Build", graph_name: "FixBuild", node_count: 0, edge_count: 0 }, automation: null, repository: { name: "myrepo", origin_url: null, provider: "unknown" }, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/apps/fabro-web/app/data/runs.ts b/apps/fabro-web/app/data/runs.ts index f820b24c1..e5595cf81 100644 --- a/apps/fabro-web/app/data/runs.ts +++ b/apps/fabro-web/app/data/runs.ts @@ -40,7 +40,7 @@ export interface RunItem { sandboxWorkingDirectory?: string; sourceDirectory?: string; createdAt?: string; - createdBy?: Principal | null; + createdBy: Principal; lastEventAt?: string; size?: RunSize; } diff --git a/apps/fabro-web/app/lib/run-actions.test.ts b/apps/fabro-web/app/lib/run-actions.test.ts index 8acde997f..2780ee2ed 100644 --- a/apps/fabro-web/app/lib/run-actions.test.ts +++ b/apps/fabro-web/app/lib/run-actions.test.ts @@ -24,6 +24,7 @@ import { unarchiveRuns, } from "./run-actions"; import { generatedAxios } from "./api-client"; +import { testPrincipal } from "./test-principal"; type StubResponseInit = { status: number; @@ -47,7 +48,7 @@ function makeRun(status: RunStatus, archived = false): Run { workflow: { slug: "fix_build", name: "Fix Build", graph_name: null, node_count: 0, edge_count: 0 }, automation: null, repository: null, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/apps/fabro-web/app/lib/test-principal.ts b/apps/fabro-web/app/lib/test-principal.ts new file mode 100644 index 000000000..7ecf7ad9e --- /dev/null +++ b/apps/fabro-web/app/lib/test-principal.ts @@ -0,0 +1,10 @@ +import type { Principal } from "@qltysh/fabro-api-client"; + +export function testPrincipal(login = "test"): Principal { + return { + kind: "user", + identity: { issuer: "fabro:test", subject: `${login}-user` }, + login, + auth_method: "dev_token", + }; +} diff --git a/apps/fabro-web/app/routes/run-detail.test.ts b/apps/fabro-web/app/routes/run-detail.test.ts index e30d38da8..08ecf0411 100644 --- a/apps/fabro-web/app/routes/run-detail.test.ts +++ b/apps/fabro-web/app/routes/run-detail.test.ts @@ -178,6 +178,7 @@ import { } from "./run-detail/lifecycle-toasts"; const { default: RunDetail } = await import("./run-detail"); +const { testPrincipal } = await import("../lib/test-principal"); mock.restore(); type LifecycleToastState = import("./run-detail/lifecycle-toasts").LifecycleToastState; type RunDetailActionResult = import("./run-detail/lifecycle-toasts").RunDetailActionResult; @@ -209,7 +210,7 @@ function makeRunSummary( workflow: { slug: "default", name: "Default", graph_name: null, node_count: 0, edge_count: 0 }, automation: null, repository: { name: "fabro", origin_url: null, provider: "unknown" }, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/apps/fabro-web/app/routes/run-files.render.test.tsx b/apps/fabro-web/app/routes/run-files.render.test.tsx index 5c9a24722..6a4678d60 100644 --- a/apps/fabro-web/app/routes/run-files.render.test.tsx +++ b/apps/fabro-web/app/routes/run-files.render.test.tsx @@ -4,6 +4,7 @@ import TestRenderer, { act } from "react-test-renderer"; import { MemoryRouter, Route, Routes } from "react-router"; import { ToastProvider } from "../components/toast"; +import { testPrincipal } from "../lib/test-principal"; let currentFilesPayload: any = null; let currentCommitsPayload: any = null; @@ -50,7 +51,7 @@ mock.module("../lib/queries", () => ({ workflow: { slug: "default", name: "Default", graph_name: null, node_count: 0, edge_count: 0 }, automation: null, repository: { name: "fabro", origin_url: null, provider: "unknown" }, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/apps/fabro-web/app/routes/runs.preferences.test.tsx b/apps/fabro-web/app/routes/runs.preferences.test.tsx index 648d8e35a..137a62a78 100644 --- a/apps/fabro-web/app/routes/runs.preferences.test.tsx +++ b/apps/fabro-web/app/routes/runs.preferences.test.tsx @@ -4,6 +4,7 @@ import { createMemoryRouter, RouterProvider } from "react-router"; import type { PaginatedRunList, Run } from "@qltysh/fabro-api-client"; import { ToastProvider } from "../components/toast"; +import { testPrincipal } from "../lib/test-principal"; import { setupReactTestEnv } from "../lib/test-utils"; class MemoryStorage { @@ -34,7 +35,7 @@ function run(id: string, repo = "qlty/fabro", workflow = "release"): Run { workflow: { slug: workflow, name: workflow, graph_name: null, node_count: 0, edge_count: 0 }, automation: null, repository: { name: repo, origin_url: null, provider: "github" }, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/apps/fabro-web/app/routes/runs.test.tsx b/apps/fabro-web/app/routes/runs.test.tsx index 51483cff2..2e5f65bde 100644 --- a/apps/fabro-web/app/routes/runs.test.tsx +++ b/apps/fabro-web/app/routes/runs.test.tsx @@ -11,6 +11,7 @@ import { shouldRefreshBoardForEvent, } from "./runs"; import { summarizeBatchLifecycleAction } from "../components/runs-list/batch-lifecycle"; +import { testPrincipal } from "../lib/test-principal"; function boardRun(id: string, column: BoardColumn, questionText?: string): Run { const status = @@ -34,7 +35,7 @@ function boardRun(id: string, column: BoardColumn, questionText?: string): Run { workflow: { slug: "test", name: "Test", graph_name: null, node_count: 0, edge_count: 0 }, automation: null, repository: { name: "repo", origin_url: null, provider: "unknown" }, - created_by: null, + created_by: testPrincipal(), origin: { kind: "api" }, labels: {}, lifecycle: { diff --git a/docs/public/api-reference/fabro-api.yaml b/docs/public/api-reference/fabro-api.yaml index 6fb81063b..8a49fb17a 100644 --- a/docs/public/api-reference/fabro-api.yaml +++ b/docs/public/api-reference/fabro-api.yaml @@ -7863,6 +7863,8 @@ components: RunProvenance: type: object + required: + - subject properties: server: oneOf: @@ -7873,9 +7875,7 @@ components: - $ref: "#/components/schemas/RunClientProvenance" - type: "null" subject: - oneOf: - - $ref: "#/components/schemas/Principal" - - type: "null" + $ref: "#/components/schemas/Principal" Principal: oneOf: @@ -9110,6 +9110,7 @@ components: - run_id - settings - graph + - provenance properties: run_id: type: string @@ -9129,9 +9130,7 @@ components: additionalProperties: type: string provenance: - oneOf: - - $ref: "#/components/schemas/RunProvenance" - - type: "null" + $ref: "#/components/schemas/RunProvenance" manifest_blob: type: ["string", "null"] definition_blob: @@ -9443,9 +9442,7 @@ components: - $ref: "#/components/schemas/RepositoryRef" - type: "null" created_by: - oneOf: - - $ref: "#/components/schemas/Principal" - - type: "null" + $ref: "#/components/schemas/Principal" origin: $ref: "#/components/schemas/RunOrigin" labels: diff --git a/lib/crates/fabro-api/Cargo.toml b/lib/crates/fabro-api/Cargo.toml index 8b347f032..459e6bfda 100644 --- a/lib/crates/fabro-api/Cargo.toml +++ b/lib/crates/fabro-api/Cargo.toml @@ -32,3 +32,6 @@ serde_json = "1" serde_yaml = "0.9" prettyplease = "0.2" syn = "2" + +[dev-dependencies] +fabro-types = { path = "../fabro-types", features = ["test-support"] } diff --git a/lib/crates/fabro-api/tests/principal_round_trip.rs b/lib/crates/fabro-api/tests/principal_round_trip.rs index 601e6372c..ac2b2c258 100644 --- a/lib/crates/fabro-api/tests/principal_round_trip.rs +++ b/lib/crates/fabro-api/tests/principal_round_trip.rs @@ -139,9 +139,9 @@ fn run_provenance_subject_round_trips_as_principal() { name: Some("fabro-cli".to_string()), version: Some("0.1.0".to_string()), }), - subject: Some(Principal::Worker { + subject: Principal::Worker { run_id: fixtures::RUN_1, - }), + }, }; let json = serde_json::to_value(&provenance).unwrap(); diff --git a/lib/crates/fabro-api/tests/run_event_round_trip.rs b/lib/crates/fabro-api/tests/run_event_round_trip.rs index e39f3d8f4..8e1cf5d36 100644 --- a/lib/crates/fabro-api/tests/run_event_round_trip.rs +++ b/lib/crates/fabro-api/tests/run_event_round_trip.rs @@ -1,7 +1,7 @@ use std::any::{TypeId, type_name}; use fabro_api::types::RunEvent as ApiRunEvent; -use fabro_types::{Graph, RunEvent, WorkflowSettings, fixtures}; +use fabro_types::{Graph, RunEvent, WorkflowSettings, fixtures, test_support}; use serde_json::{Value, json}; #[test] @@ -20,7 +20,8 @@ fn run_event_round_trips_run_created() { "settings": WorkflowSettings::default(), "graph": Graph::new("test"), "run_dir": "/tmp/fabro/run-1", - "source_directory": "/tmp/fabro/run-1" + "source_directory": "/tmp/fabro/run-1", + "provenance": test_support::test_run_provenance() } }); @@ -39,6 +40,7 @@ fn run_event_round_trips_run_created_with_web_url() { "graph": Graph::new("test"), "run_dir": "/tmp/fabro/run-1", "source_directory": "/tmp/fabro/run-1", + "provenance": test_support::test_run_provenance(), "web_url": format!("http://localhost:3000/runs/{}", fixtures::RUN_1) } }); diff --git a/lib/crates/fabro-api/tests/run_projection_round_trip.rs b/lib/crates/fabro-api/tests/run_projection_round_trip.rs index 64a00df91..30295d76a 100644 --- a/lib/crates/fabro-api/tests/run_projection_round_trip.rs +++ b/lib/crates/fabro-api/tests/run_projection_round_trip.rs @@ -1,7 +1,7 @@ use std::any::{TypeId, type_name}; use fabro_api::types::RunProjection as ApiRunProjection; -use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings}; +use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings, test_support}; use serde_json::json; #[test] @@ -130,7 +130,7 @@ fn run_spec_json() -> serde_json::Value { workflow_slug: None, source_directory: None, labels: std::collections::HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-api/tests/run_summary_round_trip.rs b/lib/crates/fabro-api/tests/run_summary_round_trip.rs index 21d237434..1e94c7b1b 100644 --- a/lib/crates/fabro-api/tests/run_summary_round_trip.rs +++ b/lib/crates/fabro-api/tests/run_summary_round_trip.rs @@ -12,7 +12,7 @@ use fabro_types::{ AskFabro, AskFabroUnavailableReason, DiffSummary, PullRequestLink, RepositoryProvider, RepositoryRef, Run, RunApproval, RunApprovalState, RunBillingSummary, RunId, RunLifecycle, RunLinks, RunOrigin, RunRunnableSource, RunSize, RunTimestamps, RunTiming, WorkflowRef, - fixtures, + fixtures, test_support, }; use serde_json::json; @@ -83,7 +83,7 @@ fn run_summary_json_matches_openapi_shape() { origin_url: None, provider: RepositoryProvider::Unknown, }), - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::from([("team".to_string(), "core".to_string())]), lifecycle: RunLifecycle { @@ -152,7 +152,15 @@ fn run_summary_json_matches_openapi_shape() { "origin_url": null, "provider": "unknown" }, - "created_by": null, + "created_by": { + "kind": "user", + "identity": { + "issuer": "fabro:test", + "subject": "test-user" + }, + "login": "test", + "auth_method": "dev_token" + }, "origin": { "kind": "api" }, @@ -244,6 +252,7 @@ fn run_summary_deserializes_when_optional_fields_are_absent() { "origin_url": null, "provider": "unknown" }, + "created_by": test_support::test_principal(), "models": [], "timestamps": { "created_at": "2026-04-20T12:00:00Z", @@ -276,6 +285,7 @@ fn run_summary_deserializes_when_optional_fields_are_absent() { provider: RepositoryProvider::Unknown, }) ); + assert_eq!(summary.created_by, test_support::test_principal()); assert_eq!(summary.timestamps.started_at, None); assert_eq!(summary.timestamps.created_at, created_at); assert_eq!(summary.timestamps.last_event_at, None); diff --git a/lib/crates/fabro-cli/Cargo.toml b/lib/crates/fabro-cli/Cargo.toml index 4bff98f8d..9568ac22a 100644 --- a/lib/crates/fabro-cli/Cargo.toml +++ b/lib/crates/fabro-cli/Cargo.toml @@ -129,3 +129,4 @@ fabro-test = { workspace = true } fabro-macros = { path = "../fabro-macros" } hkdf.workspace = true reqwest = { workspace = true, features = ["cookies"] } +fabro-types = { path = "../fabro-types", features = ["clap", "test-support"] } diff --git a/lib/crates/fabro-cli/src/commands/run/attach.rs b/lib/crates/fabro-cli/src/commands/run/attach.rs index c8ad2fff2..8dbb31b35 100644 --- a/lib/crates/fabro-cli/src/commands/run/attach.rs +++ b/lib/crates/fabro-cli/src/commands/run/attach.rs @@ -822,6 +822,7 @@ mod tests { )] use fabro_interview::{Answer, AnswerValue}; + use fabro_types::test_support; use fabro_util::terminal::Styles; use httpmock::MockServer; @@ -840,7 +841,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: std::collections::HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-cli/tests/it/cmd/inspect.rs b/lib/crates/fabro-cli/tests/it/cmd/inspect.rs index ebcf1a2a0..f426c167b 100644 --- a/lib/crates/fabro-cli/tests/it/cmd/inspect.rs +++ b/lib/crates/fabro-cli/tests/it/cmd/inspect.rs @@ -221,7 +221,21 @@ fn inspect_resolves_selector_via_server_endpoint() { "attrs": {} }, "workflow_slug": "remote-workflow", - "source_directory": "/srv/repo" + "source_directory": "/srv/repo", + "provenance": { + "server": { + "version": "test" + }, + "subject": { + "kind": "user", + "identity": { + "issuer": "fabro:test", + "subject": "test-user" + }, + "login": "test", + "auth_method": "dev_token" + } + } }, "start_record": null, "conclusion": null, diff --git a/lib/crates/fabro-cli/tests/it/cmd/support.rs b/lib/crates/fabro-cli/tests/it/cmd/support.rs index 9ac2e7673..d8572ac19 100644 --- a/lib/crates/fabro-cli/tests/it/cmd/support.rs +++ b/lib/crates/fabro-cli/tests/it/cmd/support.rs @@ -177,6 +177,15 @@ pub(crate) fn remote_run_summary_json( "origin_url": null, "provider": "unknown" }, + "created_by": { + "kind": "user", + "identity": { + "issuer": "fabro:test", + "subject": "test-user" + }, + "login": "test", + "auth_method": "dev_token" + }, "origin": { "kind": "api" }, diff --git a/lib/crates/fabro-cli/tests/it/support/mod.rs b/lib/crates/fabro-cli/tests/it/support/mod.rs index 7c7c59a22..41150f3f2 100644 --- a/lib/crates/fabro-cli/tests/it/support/mod.rs +++ b/lib/crates/fabro-cli/tests/it/support/mod.rs @@ -9,7 +9,7 @@ pub(crate) use auth_harness::{ pub(crate) use auth_tokens::{TEST_SESSION_SECRET, issue_test_github_jwt, issue_test_worker_jwt}; use fabro_store::EventEnvelope; use fabro_test::{EnvVars, TestContext, preserve_coverage_env}; -use fabro_types::{Graph, RunId, RunSpec, WorkflowSettings}; +use fabro_types::{Graph, RunId, RunSpec, WorkflowSettings, test_support}; pub(crate) fn run_output_filters(context: &TestContext) -> Vec<(String, String)> { let mut filters = context.filters(); @@ -48,7 +48,7 @@ pub(crate) fn run_projection_json(run_id: &str, status: &serde_json::Value) -> s workflow_slug: Some("remote-workflow".to_string()), source_directory: Some("/srv/repo".to_string()), labels: std::collections::HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-dump/src/lib.rs b/lib/crates/fabro-dump/src/lib.rs index d44e01215..ae3598666 100644 --- a/lib/crates/fabro-dump/src/lib.rs +++ b/lib/crates/fabro-dump/src/lib.rs @@ -475,7 +475,7 @@ mod tests { use fabro_types::{ Checkpoint, CheckpointRecord, Conclusion, RunDiff, RunSandbox, RunStatus, SandboxProviderKind, StageCompletion, StageModelUsage, StageOutcome, StartRecord, - SuccessReason, WorkflowSettings, first_event_seq, fixtures, + SuccessReason, WorkflowSettings, first_event_seq, fixtures, test_support, }; use futures::executor; @@ -497,7 +497,7 @@ mod tests { push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::from([("team".to_string(), "platform".to_string())]), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, diff --git a/lib/crates/fabro-server/src/demo/mod.rs b/lib/crates/fabro-server/src/demo/mod.rs index 42e19a97c..b731cfd2e 100644 --- a/lib/crates/fabro-server/src/demo/mod.rs +++ b/lib/crates/fabro-server/src/demo/mod.rs @@ -1080,7 +1080,7 @@ fn ts(s: &str) -> DateTime { mod runs { use std::collections::HashMap; - use std::sync::OnceLock; + use std::sync::{LazyLock, OnceLock}; use std::time::Duration; use fabro_api::types::*; @@ -1091,13 +1091,22 @@ mod runs { }; use fabro_types::settings::{InterpString, ProjectNamespace, WorkflowNamespace}; use fabro_types::{ - PendingReason, RepositoryRef, RunBillingSummary, RunId, RunLifecycle, RunLinks, RunOrigin, - RunSize, RunTimestamps, StageId, WorkflowRef, WorkflowSettings, + AuthMethod, IdpIdentity, PendingReason, Principal, RepositoryRef, RunBillingSummary, RunId, + RunLifecycle, RunLinks, RunOrigin, RunSize, RunTimestamps, StageId, WorkflowRef, + WorkflowSettings, }; use super::ts; use crate::server::run_stage_from_stage_id; + static DEMO_PRINCIPAL: LazyLock = LazyLock::new(|| { + Principal::user( + IdpIdentity::new("fabro:demo", "demo").expect("demo identity should be valid"), + "demo".to_string(), + AuthMethod::DevToken, + ) + }); + fn labels(entries: &[(&str, &str)]) -> HashMap { entries .iter() @@ -1170,7 +1179,7 @@ mod runs { repo_origin_url, source_directory.as_deref(), )), - created_by: None, + created_by: DEMO_PRINCIPAL.clone(), origin: RunOrigin::default(), labels: labels(entries), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-server/src/run_files.rs b/lib/crates/fabro-server/src/run_files.rs index 53657282a..082f13025 100644 --- a/lib/crates/fabro-server/src/run_files.rs +++ b/lib/crates/fabro-server/src/run_files.rs @@ -1715,7 +1715,7 @@ fn count_flags(data: &[FileDiff]) -> (u64, u64, u64, u64) { mod tests { use std::sync::atomic::{AtomicUsize, Ordering}; - use fabro_types::{CommandTermination, RunId}; + use fabro_types::{CommandTermination, RunId, test_support}; use tokio::time::{Duration, sleep}; use super::*; @@ -2386,7 +2386,7 @@ index 1111111..2222222 160000 workflow_slug: None, source_directory: None, labels: HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-server/src/run_manifest.rs b/lib/crates/fabro-server/src/run_manifest.rs index a004872cb..1760d76cf 100644 --- a/lib/crates/fabro-server/src/run_manifest.rs +++ b/lib/crates/fabro-server/src/run_manifest.rs @@ -26,7 +26,9 @@ use fabro_static::EnvVars; use fabro_types::settings::cli::OutputVerbosity; use fabro_types::settings::interp::InterpString; use fabro_types::settings::run::{EnvironmentProvider, RunGoal, RunNamespace}; -use fabro_types::{ManifestPath, RunId, SandboxProviderKind, ServerSettings, WorkflowSettings}; +use fabro_types::{ + ManifestPath, RunId, RunProvenance, SandboxProviderKind, ServerSettings, WorkflowSettings, +}; use fabro_util::check_report::{CheckDetail, CheckReport, CheckResult, CheckSection, CheckStatus}; use fabro_validate::Severity; use fabro_workflow::Error as WorkflowError; @@ -201,6 +203,7 @@ pub(crate) fn validate_prepared_manifest( pub(crate) fn create_run_input( prepared: PreparedManifest, configured_providers: Vec, + provenance: RunProvenance, web_url: Option, ) -> CreateRunInput { CreateRunInput { @@ -216,7 +219,7 @@ pub(crate) fn create_run_input( git: prepared.git, fork_source_ref: None, parent_id: prepared.parent_id, - provenance: None, + provenance, configured_providers, web_url, } diff --git a/lib/crates/fabro-server/src/server/handler/events.rs b/lib/crates/fabro-server/src/server/handler/events.rs index 8e7806522..562e3d5fc 100644 --- a/lib/crates/fabro-server/src/server/handler/events.rs +++ b/lib/crates/fabro-server/src/server/handler/events.rs @@ -535,7 +535,7 @@ mod stage_events_tests { use axum::body::{Body, to_bytes}; use axum::http::{Request, StatusCode, header}; use fabro_store::EventPayload; - use fabro_types::{Graph, RunId, WorkflowSettings}; + use fabro_types::{Graph, RunId, WorkflowSettings, test_support}; use fabro_workflow::event as workflow_event; use http_body_util::BodyExt; use serde_json::json; @@ -569,7 +569,7 @@ mod stage_events_tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-server/src/server/handler/lifecycle.rs b/lib/crates/fabro-server/src/server/handler/lifecycle.rs index 0c2697133..2d55e9b33 100644 --- a/lib/crates/fabro-server/src/server/handler/lifecycle.rs +++ b/lib/crates/fabro-server/src/server/handler/lifecycle.rs @@ -864,7 +864,7 @@ async fn retry_run( let input = operations::RetryRunInput { source_run_id: id, new_run_id, - provenance: Some(run_provenance(&headers, &actor)), + provenance: run_provenance(&headers, &actor), web_url: state.run_web_url(&new_run_id), }; match Box::pin(operations::retry_run(&state.store, &input)).await { diff --git a/lib/crates/fabro-server/src/server/handler/pair.rs b/lib/crates/fabro-server/src/server/handler/pair.rs index e43f4e6f8..ea64e05ab 100644 --- a/lib/crates/fabro-server/src/server/handler/pair.rs +++ b/lib/crates/fabro-server/src/server/handler/pair.rs @@ -850,7 +850,7 @@ mod tests { use fabro_types::run_event::AgentMessageProps; use fabro_types::{ BilledTokenCounts, EventEnvelope, Graph, PairMessageId, RunEvent, StageId, - WorkflowSettings, fixtures, + WorkflowSettings, fixtures, test_support, }; use fabro_workflow::event as workflow_event; use tower::ServiceExt; @@ -1023,7 +1023,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-server/src/server/handler/runs.rs b/lib/crates/fabro-server/src/server/handler/runs.rs index 090d1ba5d..e581c8048 100644 --- a/lib/crates/fabro-server/src/server/handler/runs.rs +++ b/lib/crates/fabro-server/src/server/handler/runs.rs @@ -641,13 +641,14 @@ async fn create_run( .as_ref() .map(LlmClientResult::provider_ids) .unwrap_or_default(); + let provenance = run_provenance(&headers, &actor); let mut create_input = run_manifest::create_run_input( prepared.clone(), ready_provider_ids.clone(), + provenance, web_url.clone(), ); create_input.run_id = Some(run_id); - create_input.provenance = Some(run_provenance(&headers, &actor)); create_input.submitted_manifest_bytes = Some(body.to_vec()); let storage_root = match resolve_interp_string(&state.server_settings().server.storage.root) { @@ -817,7 +818,7 @@ pub(super) fn run_provenance(headers: &HeaderMap, subject: &Principal) -> RunPro version: FABRO_VERSION.to_string(), }), client: run_client_provenance(headers), - subject: Some(subject.clone()), + subject: subject.clone(), } } diff --git a/lib/crates/fabro-server/src/server/handler/sandbox.rs b/lib/crates/fabro-server/src/server/handler/sandbox.rs index bfba9c242..be7d22023 100644 --- a/lib/crates/fabro-server/src/server/handler/sandbox.rs +++ b/lib/crates/fabro-server/src/server/handler/sandbox.rs @@ -1307,7 +1307,7 @@ FABRO_PROC_NET_TCP /proc/net/tcp6 mod retrieve_sandbox_tests { use axum::body::{Body, to_bytes}; use axum::http::{Request, StatusCode}; - use fabro_types::{Graph, RunId, WorkflowSettings}; + use fabro_types::{Graph, RunId, WorkflowSettings, test_support}; use serde_json::{Value, json}; use tower::ServiceExt; @@ -1347,6 +1347,7 @@ mod retrieve_sandbox_tests { "settings": WorkflowSettings::default(), "graph": Graph::new("test"), "run_dir": "/tmp/test", + "provenance": test_support::test_run_provenance(), }, }), run_id, diff --git a/lib/crates/fabro-server/src/server/handler/sessions.rs b/lib/crates/fabro-server/src/server/handler/sessions.rs index 1791ee57b..5aa30cfed 100644 --- a/lib/crates/fabro-server/src/server/handler/sessions.rs +++ b/lib/crates/fabro-server/src/server/handler/sessions.rs @@ -1508,6 +1508,7 @@ mod tests { use fabro_agent::config::ToolAccess; use fabro_agent::tool_registry::{RegisteredTool, ToolContext, ToolRegistry, ToolSource}; use fabro_llm::types::{ToolCall, ToolDefinition}; + use fabro_types::test_support; use super::*; @@ -1701,7 +1702,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-server/src/server/tests.rs b/lib/crates/fabro-server/src/server/tests.rs index ba4520d87..62d4331c1 100644 --- a/lib/crates/fabro-server/src/server/tests.rs +++ b/lib/crates/fabro-server/src/server/tests.rs @@ -24,7 +24,7 @@ use fabro_types::{ SandboxProviderKind, StageContextWindowBreakdownItem, StageContextWindowCategory, StageContextWindowCountMethod, StageContextWindowProjection, StageContextWindowStaleness, StageContextWindowWarning, StageModelUsage, StageTiming, SuccessReason, SystemActorKind, - WorkflowSettings, fixtures, + WorkflowSettings, fixtures, test_support, }; use fabro_util::check_report::CheckStatus; use fabro_workflow::records::CheckpointExt; @@ -3367,7 +3367,7 @@ async fn append_default_run_created(run_store: &fabro_store::RunDatabase, run_id source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -3412,7 +3412,7 @@ async fn create_slack_notification_run( source_directory: None, workflow_slug: workflow_slug.map(str::to_string), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -4418,7 +4418,7 @@ async fn list_run_stages_distinguishes_visits() { source_directory: None, workflow_slug: Some("test".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -5470,7 +5470,7 @@ async fn create_completed_run_ready_for_pull_request( source_directory: Some("/tmp/project".to_string()), git: git.clone(), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -9272,15 +9272,10 @@ async fn run_tool_worker_token_can_use_client_backend_routes_across_runs() { .unwrap() .expect("created run should be cached"); assert_eq!( - cached - .projection - .spec - .provenance - .as_ref() - .and_then(|provenance| provenance.subject.as_ref()), - Some(&Principal::Worker { + cached.projection.spec.provenance.subject, + Principal::Worker { run_id: parent_run_id, - }), + }, ); let response = app @@ -11604,7 +11599,7 @@ async fn create_preserved_local_sandbox_run(state: &Arc, run_id: RunId source_directory: Some("/tmp/fabro-run".to_string()), workflow_slug: Some("test".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -12353,7 +12348,7 @@ async fn delete_run_retry_after_missing_provider_resource_removes_metadata() { source_directory: Some("/tmp/fabro-run".to_string()), workflow_slug: Some("test".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-server/tests/it/api/run_files.rs b/lib/crates/fabro-server/tests/it/api/run_files.rs index e820b00f9..5af21eb92 100644 --- a/lib/crates/fabro-server/tests/it/api/run_files.rs +++ b/lib/crates/fabro-server/tests/it/api/run_files.rs @@ -14,7 +14,7 @@ use axum::body::Body; use axum::http::{Request, StatusCode}; use fabro_server::test_support::test_app_state_with_store; use fabro_store::{ArtifactStore, Database}; -use fabro_types::{Graph, RunId, WorkflowSettings}; +use fabro_types::{Graph, RunId, WorkflowSettings, test_support}; use fabro_workflow::event as workflow_event; use fabro_workflow::run_status::SuccessReason; use object_store::memory::InMemory as MemoryObjectStore; @@ -68,7 +68,7 @@ async fn append_completed_run_with_final_patch( source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-store/Cargo.toml b/lib/crates/fabro-store/Cargo.toml index 016b55d3d..860ffbf7c 100644 --- a/lib/crates/fabro-store/Cargo.toml +++ b/lib/crates/fabro-store/Cargo.toml @@ -36,3 +36,4 @@ tokio = { workspace = true, features = ["test-util", "macros"] } tempfile = "3" ulid.workspace = true insta = { workspace = true } +fabro-types = { path = "../fabro-types", features = ["test-support"] } diff --git a/lib/crates/fabro-store/src/run_state.rs b/lib/crates/fabro-store/src/run_state.rs index 552891d2e..619e12fb4 100644 --- a/lib/crates/fabro-store/src/run_state.rs +++ b/lib/crates/fabro-store/src/run_state.rs @@ -902,11 +902,7 @@ pub(crate) fn build_summary(state: &RunProjection, run_id: &RunId) -> Run { }) .map(|(_, record)| record.question.clone()); let models = run_models(state); - let created_by = state - .spec - .provenance - .as_ref() - .and_then(|provenance| provenance.subject.clone()); + let created_by = state.spec.provenance.subject.clone(); let source_directory = state.spec.source_directory.clone(); let repo_origin_url = state.spec.git.as_ref().map(|git| git.origin_url.clone()); let start_time = state.start.as_ref().map(|start| start.start_time); @@ -1255,7 +1251,7 @@ mod tests { StageContextWindowBreakdownItem, StageContextWindowCategory, StageContextWindowCountMethod, StageContextWindowProjection, StageContextWindowStaleness, StageContextWindowWarning, StageModelUsage, StageOutcome, StageState, SubAgentStatus, SuccessReason, WorkflowSettings, - first_event_seq, fixtures, + first_event_seq, fixtures, test_support, }; use serde_json::json; @@ -1336,7 +1332,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, @@ -1372,7 +1368,7 @@ mod tests { } #[test] - fn legacy_run_created_projects_retried_from_none() { + fn run_created_projects_retried_from_none() { let event = test_raw_event( 1, "run.created", @@ -1380,7 +1376,8 @@ mod tests { "settings": WorkflowSettings::default(), "graph": Graph::new("test"), "labels": {}, - "run_dir": "/tmp/run" + "run_dir": "/tmp/run", + "provenance": test_support::test_run_provenance() }), None, ); @@ -1577,7 +1574,7 @@ mod tests { "repo_origin_url": null, "base_branch": null, "labels": {}, - "provenance": null, + "provenance": test_support::test_run_provenance(), "manifest_blob": null, "definition_blob": null, "git": null, @@ -2605,7 +2602,7 @@ mod tests { source_directory: Some("/tmp/repo".to_string()), git: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -2630,7 +2627,7 @@ mod tests { source_directory: Some("/tmp/repo".to_string()), git: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -2669,7 +2666,8 @@ mod tests { "attrs": { "goal": { "String": "Goal title" } } }, "labels": {}, - "run_dir": "/tmp/run" + "run_dir": "/tmp/run", + "provenance": test_support::test_run_provenance() }), None, ); @@ -2683,7 +2681,7 @@ mod tests { } #[test] - fn legacy_run_created_without_title_infers_projection_title() { + fn run_created_without_title_infers_projection_title() { let event = test_raw_event( 1, "run.created", @@ -2696,7 +2694,8 @@ mod tests { "attrs": { "goal": { "String": "## Plan: Legacy title\n\nDetails" } } }, "labels": {}, - "run_dir": "/tmp/run" + "run_dir": "/tmp/run", + "provenance": test_support::test_run_provenance() }), None, ); @@ -2725,7 +2724,8 @@ mod tests { "attrs": { "goal": { "String": "Goal title" } } }, "labels": {}, - "run_dir": "/tmp/run" + "run_dir": "/tmp/run", + "provenance": test_support::test_run_provenance() }), None, ), @@ -2769,6 +2769,7 @@ mod tests { "labels": {}, "run_dir": "/tmp/run", "source_directory": "/tmp/run", + "provenance": test_support::test_run_provenance(), "manifest_blob": manifest_blob } })) diff --git a/lib/crates/fabro-store/src/slate/mod.rs b/lib/crates/fabro-store/src/slate/mod.rs index 784868ace..4f1432319 100644 --- a/lib/crates/fabro-store/src/slate/mod.rs +++ b/lib/crates/fabro-store/src/slate/mod.rs @@ -472,7 +472,7 @@ mod tests { use chrono::{DateTime, Utc}; use fabro_types::{ AttrValue, FailureReason, Graph, RunControlAction, RunSpec, RunStatus, StageId, - SuccessReason, WorkflowSettings, + SuccessReason, WorkflowSettings, test_support, }; use futures::TryStreamExt; use object_store::memory::InMemory; @@ -541,7 +541,7 @@ mod tests { workflow_slug: Some("night-sky".to_string()), source_directory: Some(format!("/tmp/{label}")), labels: std::collections::HashMap::from([("team".to_string(), "infra".to_string())]), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: Some(fabro_types::GitContext { @@ -600,6 +600,7 @@ mod tests { "run_dir": format!("/tmp/{label}"), "git": run_spec.git, "labels": run_spec.labels, + "provenance": run_spec.provenance, }), )) .await @@ -625,6 +626,7 @@ mod tests { "run_dir": format!("/tmp/{label}"), "git": run_spec.git, "labels": run_spec.labels, + "provenance": run_spec.provenance, "parent_id": parent_id, }), )) @@ -1299,6 +1301,7 @@ mod tests { "run_dir": "/tmp/run-2", "git": run_spec["git"], "labels": run_spec["labels"], + "provenance": run_spec["provenance"], }, })) .unwrap(), diff --git a/lib/crates/fabro-store/src/slate/run_store.rs b/lib/crates/fabro-store/src/slate/run_store.rs index 1718cb662..94116fa94 100644 --- a/lib/crates/fabro-store/src/slate/run_store.rs +++ b/lib/crates/fabro-store/src/slate/run_store.rs @@ -667,7 +667,7 @@ mod tests { use std::sync::Arc; use std::time::Duration; - use fabro_types::{Graph, RunId, SessionId, StageId, WorkflowSettings}; + use fabro_types::{Graph, RunId, SessionId, StageId, WorkflowSettings, test_support}; use object_store::memory::InMemory; use serde_json::json; @@ -723,6 +723,7 @@ mod tests { "settings": WorkflowSettings::default(), "graph": Graph::new("test"), "run_dir": "/tmp/test", + "provenance": test_support::test_run_provenance(), }, }), run_id, diff --git a/lib/crates/fabro-store/tests/serializable_projection.rs b/lib/crates/fabro-store/tests/serializable_projection.rs index f6aa256fd..12ee8c932 100644 --- a/lib/crates/fabro-store/tests/serializable_projection.rs +++ b/lib/crates/fabro-store/tests/serializable_projection.rs @@ -8,7 +8,7 @@ use fabro_types::{ BilledModelUsage, BilledTokenCounts, Checkpoint, CheckpointRecord, InterviewQuestionRecord, QuestionType, RunDiff, RunSandbox, RunSandboxRuntime, RunStatus, SandboxProviderKind, StageCompletion, StageModelUsage, StageOutcome, StartRecord, WorkflowSettings, first_event_seq, - fixtures, + fixtures, test_support, }; use serde_json::json; @@ -21,7 +21,7 @@ fn sample_run_spec() -> RunSpec { workflow_slug: Some("demo".to_string()), source_directory: Some("/tmp/project".to_string()), labels: HashMap::from([("team".to_string(), "platform".to_string())]), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: Some(fabro_types::GitContext { diff --git a/lib/crates/fabro-tool/Cargo.toml b/lib/crates/fabro-tool/Cargo.toml index 08b6df7cf..c50ea6a38 100644 --- a/lib/crates/fabro-tool/Cargo.toml +++ b/lib/crates/fabro-tool/Cargo.toml @@ -29,4 +29,5 @@ tokio.workspace = true toml.workspace = true [dev-dependencies] +fabro-types = { path = "../fabro-types", features = ["test-support"] } tempfile = "3" diff --git a/lib/crates/fabro-tool/src/common.rs b/lib/crates/fabro-tool/src/common.rs index 9dd64599a..159ec426d 100644 --- a/lib/crates/fabro-tool/src/common.rs +++ b/lib/crates/fabro-tool/src/common.rs @@ -307,7 +307,9 @@ fn format_tool_error(err: &anyhow::Error) -> String { #[cfg(test)] mod tests { use chrono::{TimeZone, Utc}; - use fabro_types::{RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef}; + use fabro_types::{ + RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef, test_support, + }; use super::*; @@ -413,7 +415,7 @@ mod tests { }, automation: None, repository: None, - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::new(), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-tool/src/create.rs b/lib/crates/fabro-tool/src/create.rs index 8488f8f0b..57e41acd5 100644 --- a/lib/crates/fabro-tool/src/create.rs +++ b/lib/crates/fabro-tool/src/create.rs @@ -508,7 +508,7 @@ mod tests { use fabro_api::types; use fabro_types::{ EventEnvelope, Run, RunLifecycle, RunLinks, RunOrigin, RunProjection, RunStatus, - RunTimestamps, WorkflowRef, + RunTimestamps, WorkflowRef, test_support, }; use schemars::SchemaGenerator; use serde_json::json; @@ -902,7 +902,7 @@ mod tests { }, automation: None, repository: None, - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::new(), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-tool/src/interact.rs b/lib/crates/fabro-tool/src/interact.rs index 34023120d..503147ece 100644 --- a/lib/crates/fabro-tool/src/interact.rs +++ b/lib/crates/fabro-tool/src/interact.rs @@ -453,7 +453,7 @@ mod tests { use chrono::{TimeZone, Utc}; use fabro_types::{ EventEnvelope, FailureReason, Run, RunId, RunLifecycle, RunLinks, RunOrigin, RunProjection, - RunStatus, RunTimestamps, WorkflowRef, + RunStatus, RunTimestamps, WorkflowRef, test_support, }; use serde_json::json; @@ -690,7 +690,7 @@ mod tests { }, automation: None, repository: None, - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::new(), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-tool/src/search.rs b/lib/crates/fabro-tool/src/search.rs index 0df7e391a..e3d0162c6 100644 --- a/lib/crates/fabro-tool/src/search.rs +++ b/lib/crates/fabro-tool/src/search.rs @@ -293,7 +293,9 @@ mod tests { use std::collections::HashMap; use chrono::{TimeZone, Utc}; - use fabro_types::{RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef}; + use fabro_types::{ + RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef, test_support, + }; use super::*; @@ -444,7 +446,7 @@ mod tests { }, automation: None, repository: None, - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::from([("group".to_string(), group.to_string())]), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-types/src/lib.rs b/lib/crates/fabro-types/src/lib.rs index 318f982ad..339d1a0dc 100644 --- a/lib/crates/fabro-types/src/lib.rs +++ b/lib/crates/fabro-types/src/lib.rs @@ -44,6 +44,8 @@ pub mod start; pub mod status; pub mod steering; pub mod system_integrations; +#[cfg(any(test, feature = "test-support"))] +pub mod test_support; pub mod timing; pub mod todo; pub mod transcript; diff --git a/lib/crates/fabro-types/src/run.rs b/lib/crates/fabro-types/src/run.rs index 269db43ee..afb2a1f24 100644 --- a/lib/crates/fabro-types/src/run.rs +++ b/lib/crates/fabro-types/src/run.rs @@ -23,14 +23,13 @@ pub struct RunClientProvenance { pub version: Option, } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct RunProvenance { #[serde(default, skip_serializing_if = "Option::is_none")] pub server: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub client: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub subject: Option, + pub subject: Principal, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] @@ -90,8 +89,7 @@ pub struct RunSpec { pub source_directory: Option, #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub labels: HashMap, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub provenance: Option, + pub provenance: RunProvenance, #[serde(default, skip_serializing_if = "Option::is_none")] pub manifest_blob: Option, #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/lib/crates/fabro-types/src/run_event/mod.rs b/lib/crates/fabro-types/src/run_event/mod.rs index 01ed04f4d..e57b5ed0a 100644 --- a/lib/crates/fabro-types/src/run_event/mod.rs +++ b/lib/crates/fabro-types/src/run_event/mod.rs @@ -961,7 +961,7 @@ mod tests { use super::*; use crate::{ AuthMethod, Edge, Graph, IdpIdentity, Node, PendingReason, RunBlobId, WorkflowSettings, - fixtures, + fixtures, test_support, }; fn user_principal(login: &str) -> Principal { @@ -1045,7 +1045,8 @@ mod tests { "graph": graph, "labels": {}, "run_dir": "/tmp/run", - "source_directory": "/tmp/run" + "source_directory": "/tmp/run", + "provenance": test_support::test_run_provenance() } }); @@ -1066,6 +1067,7 @@ mod tests { "labels": {}, "run_dir": "/tmp/run", "source_directory": "/tmp/run", + "provenance": test_support::test_run_provenance(), "manifest_blob": RunBlobId::new(br#"{"version":1}"#).to_string() } }); diff --git a/lib/crates/fabro-types/src/run_event/run.rs b/lib/crates/fabro-types/src/run_event/run.rs index fa189171f..be16946e2 100644 --- a/lib/crates/fabro-types/src/run_event/run.rs +++ b/lib/crates/fabro-types/src/run_event/run.rs @@ -28,8 +28,7 @@ pub struct RunCreatedProps { pub workflow_slug: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub db_prefix: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - pub provenance: Option, + pub provenance: RunProvenance, #[serde(default, skip_serializing_if = "Option::is_none")] pub manifest_blob: Option, #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/lib/crates/fabro-types/src/run_projection.rs b/lib/crates/fabro-types/src/run_projection.rs index 3bba6d43e..b667f4fc8 100644 --- a/lib/crates/fabro-types/src/run_projection.rs +++ b/lib/crates/fabro-types/src/run_projection.rs @@ -680,7 +680,7 @@ mod title_tests { use chrono::Utc; - use crate::{AttrValue, Graph, RunId, RunProjection, RunSpec, WorkflowSettings}; + use crate::{AttrValue, Graph, RunId, RunProjection, RunSpec, WorkflowSettings, test_support}; fn projection_with_goal(goal: Option<&str>) -> RunProjection { let mut graph = Graph::new("test"); @@ -698,7 +698,7 @@ mod title_tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, @@ -750,7 +750,7 @@ mod iter_stages_tests { use serde_json::json; use super::RunProjection; - use crate::{Graph, RunId, RunSpec, StageProjection, WorkflowSettings}; + use crate::{Graph, RunId, RunSpec, StageProjection, WorkflowSettings, test_support}; fn seq(n: u32) -> NonZeroU32 { NonZeroU32::new(n).unwrap() @@ -767,7 +767,7 @@ mod iter_stages_tests { workflow_slug: None, source_directory: None, labels: HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-types/src/run_summary.rs b/lib/crates/fabro-types/src/run_summary.rs index 1cde31614..509303d3c 100644 --- a/lib/crates/fabro-types/src/run_summary.rs +++ b/lib/crates/fabro-types/src/run_summary.rs @@ -52,8 +52,7 @@ pub struct Run { pub automation: Option, #[serde(default)] pub repository: Option, - #[serde(default)] - pub created_by: Option, + pub created_by: Principal, pub origin: RunOrigin, pub labels: HashMap, pub lifecycle: RunLifecycle, diff --git a/lib/crates/fabro-types/src/test_support.rs b/lib/crates/fabro-types/src/test_support.rs new file mode 100644 index 000000000..9db7eff91 --- /dev/null +++ b/lib/crates/fabro-types/src/test_support.rs @@ -0,0 +1,21 @@ +use crate::{AuthMethod, IdpIdentity, Principal, RunProvenance, RunServerProvenance}; + +#[must_use] +pub fn test_principal() -> Principal { + Principal::user( + IdpIdentity::new("fabro:test", "test-user").expect("test identity should be valid"), + "test".to_string(), + AuthMethod::DevToken, + ) +} + +#[must_use] +pub fn test_run_provenance() -> RunProvenance { + RunProvenance { + server: Some(RunServerProvenance { + version: "test".to_string(), + }), + client: None, + subject: test_principal(), + } +} diff --git a/lib/crates/fabro-types/tests/run_event_serde.rs b/lib/crates/fabro-types/tests/run_event_serde.rs index 8f2df1972..533d21f15 100644 --- a/lib/crates/fabro-types/tests/run_event_serde.rs +++ b/lib/crates/fabro-types/tests/run_event_serde.rs @@ -8,6 +8,16 @@ use fabro_types::settings::InterpString; use fabro_types::settings::run::RunGoal; use fabro_types::{EventBody, TurnId, WorkflowSettings, fixtures}; +fn test_run_provenance() -> fabro_types::RunProvenance { + fabro_types::RunProvenance { + server: None, + client: None, + subject: fabro_types::Principal::System { + system_kind: fabro_types::SystemActorKind::Engine, + }, + } +} + fn templated_settings() -> WorkflowSettings { let mut settings = WorkflowSettings::default(); settings.run.goal = Some(RunGoal::Inline(InterpString::parse("Ship {{ env.TASK }}"))); @@ -27,7 +37,7 @@ fn run_created_props_round_trip_templated_settings() { source_directory: Some("/Users/client/project".to_string()), workflow_slug: Some("demo".to_string()), db_prefix: Some("run_".to_string()), - provenance: None, + provenance: test_run_provenance(), manifest_blob: None, git: Some(GitContext { origin_url: "https://github.com/fabro-sh/fabro.git".to_string(), @@ -89,7 +99,7 @@ fn run_created_props_omits_web_url_when_absent() { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -120,17 +130,17 @@ fn run_created_props_omits_web_url_when_absent() { } #[test] -fn run_created_props_defaults_retried_from_for_legacy_events() { +fn run_created_props_defaults_retried_from_when_absent() { let json = serde_json::json!({ "title": null, "settings": WorkflowSettings::default(), "graph": Graph::new("ship"), "labels": {}, - "run_dir": "/tmp/run" + "run_dir": "/tmp/run", + "provenance": test_run_provenance() }); - let props: RunCreatedProps = - serde_json::from_value(json).expect("legacy props should deserialize"); + let props: RunCreatedProps = serde_json::from_value(json).expect("props should deserialize"); assert_eq!(props.retried_from, None); } diff --git a/lib/crates/fabro-types/tests/run_spec_methods.rs b/lib/crates/fabro-types/tests/run_spec_methods.rs index f5e8cf25f..ef29ce763 100644 --- a/lib/crates/fabro-types/tests/run_spec_methods.rs +++ b/lib/crates/fabro-types/tests/run_spec_methods.rs @@ -5,6 +5,16 @@ use fabro_types::run::{DirtyStatus, GitContext, PreRunPushOutcome, RunSpec}; use fabro_types::settings::{ProjectNamespace, WorkflowNamespace}; use fabro_types::{WorkflowSettings, fixtures}; +fn test_run_provenance() -> fabro_types::RunProvenance { + fabro_types::RunProvenance { + server: None, + client: None, + subject: fabro_types::Principal::System { + system_kind: fabro_types::SystemActorKind::Engine, + }, + } +} + fn sample_run_spec() -> RunSpec { let settings = WorkflowSettings { project: ProjectNamespace { @@ -26,7 +36,7 @@ fn sample_run_spec() -> RunSpec { workflow_slug: Some("demo".to_string()), source_directory: Some("/Users/client/project".to_string()), labels: HashMap::from([("team".to_string(), "platform".to_string())]), - provenance: None, + provenance: test_run_provenance(), manifest_blob: None, definition_blob: None, git: Some(GitContext { diff --git a/lib/crates/fabro-types/tests/run_spec_serde.rs b/lib/crates/fabro-types/tests/run_spec_serde.rs index f6278ff34..d45c56ac8 100644 --- a/lib/crates/fabro-types/tests/run_spec_serde.rs +++ b/lib/crates/fabro-types/tests/run_spec_serde.rs @@ -6,6 +6,16 @@ use fabro_types::settings::InterpString; use fabro_types::settings::run::RunGoal; use fabro_types::{WorkflowSettings, fixtures}; +fn test_run_provenance() -> fabro_types::RunProvenance { + fabro_types::RunProvenance { + server: None, + client: None, + subject: fabro_types::Principal::System { + system_kind: fabro_types::SystemActorKind::Engine, + }, + } +} + fn templated_settings() -> WorkflowSettings { let mut settings = WorkflowSettings::default(); settings.run.goal = Some(RunGoal::Inline(InterpString::parse("Ship {{ env.TASK }}"))); @@ -22,7 +32,7 @@ fn run_spec_round_trips_templated_settings() { workflow_slug: Some("demo".to_string()), source_directory: Some("/Users/client/project".to_string()), labels: HashMap::from([("team".to_string(), "platform".to_string())]), - provenance: None, + provenance: test_run_provenance(), manifest_blob: None, definition_blob: None, git: Some(GitContext { diff --git a/lib/crates/fabro-workflow/src/billing_rollup.rs b/lib/crates/fabro-workflow/src/billing_rollup.rs index feceb0e12..e6fb39136 100644 --- a/lib/crates/fabro-workflow/src/billing_rollup.rs +++ b/lib/crates/fabro-workflow/src/billing_rollup.rs @@ -165,7 +165,7 @@ mod tests { use fabro_model::{Catalog, ModelRef, ProviderId}; use fabro_types::{ AttrValue, BilledTokenCounts, Graph, Node, RunProjection, RunSpec, StageCompletion, - StageOutcome, WorkflowSettings, first_event_seq, fixtures, + StageOutcome, WorkflowSettings, first_event_seq, fixtures, test_support, }; use super::billing_rollup_from_projection; @@ -352,7 +352,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-workflow/src/event/convert.rs b/lib/crates/fabro-workflow/src/event/convert.rs index 684af5164..17eb5d157 100644 --- a/lib/crates/fabro-workflow/src/event/convert.rs +++ b/lib/crates/fabro-workflow/src/event/convert.rs @@ -2403,28 +2403,28 @@ mod tests { let provenance = RunProvenance { server: None, client: None, - subject: Some(user_principal("alice")), + subject: user_principal("alice"), }; let stored = to_run_event(&fixtures::RUN_1, &Event::RunCreated { - run_id: fixtures::RUN_1, - title: None, - settings: serde_json::to_value(WorkflowSettings::default()).unwrap(), - graph: serde_json::to_value(Graph::new("test")).unwrap(), - workflow_source: None, - workflow_config: None, - labels: BTreeMap::default(), - run_dir: "/tmp/run".to_string(), + run_id: fixtures::RUN_1, + title: None, + settings: serde_json::to_value(WorkflowSettings::default()).unwrap(), + graph: serde_json::to_value(Graph::new("test")).unwrap(), + workflow_source: None, + workflow_config: None, + labels: BTreeMap::default(), + run_dir: "/tmp/run".to_string(), source_directory: Some("/tmp/run".to_string()), - workflow_slug: None, - db_prefix: None, - provenance: Some(provenance), - manifest_blob: None, - git: None, - fork_source_ref: None, - retried_from: None, - parent_id: None, - web_url: None, + workflow_slug: None, + db_prefix: None, + provenance, + manifest_blob: None, + git: None, + fork_source_ref: None, + retried_from: None, + parent_id: None, + web_url: None, }); let actor = stored.actor.as_ref().expect("actor set"); assert_eq!(actor, &user_principal("alice")); diff --git a/lib/crates/fabro-workflow/src/event/events.rs b/lib/crates/fabro-workflow/src/event/events.rs index cf458c121..5a70af52c 100644 --- a/lib/crates/fabro-workflow/src/event/events.rs +++ b/lib/crates/fabro-workflow/src/event/events.rs @@ -39,8 +39,7 @@ pub enum Event { workflow_slug: Option, #[serde(default, skip_serializing_if = "Option::is_none")] db_prefix: Option, - #[serde(default, skip_serializing_if = "Option::is_none")] - provenance: Option, + provenance: RunProvenance, #[serde(default, skip_serializing_if = "Option::is_none")] manifest_blob: Option, #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/lib/crates/fabro-workflow/src/event/sink.rs b/lib/crates/fabro-workflow/src/event/sink.rs index 967f0570a..2c49372e4 100644 --- a/lib/crates/fabro-workflow/src/event/sink.rs +++ b/lib/crates/fabro-workflow/src/event/sink.rs @@ -212,7 +212,7 @@ impl StoreProgressLogger { mod tests { use std::sync::Arc; - use ::fabro_types::{Graph, RunNoticeLevel, WorkflowSettings, fixtures}; + use ::fabro_types::{Graph, RunNoticeLevel, WorkflowSettings, fixtures, test_support}; use tokio::sync::Mutex as AsyncMutex; use super::*; @@ -243,7 +243,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/event/stored_fields.rs b/lib/crates/fabro-workflow/src/event/stored_fields.rs index 94fba25ad..4ada17b67 100644 --- a/lib/crates/fabro-workflow/src/event/stored_fields.rs +++ b/lib/crates/fabro-workflow/src/event/stored_fields.rs @@ -57,7 +57,7 @@ pub(super) fn stored_event_fields(event: &Event, scope: Option<&StageScope>) -> fn stored_event_fields_for_variant(event: &Event) -> StoredEventFields { match event { Event::RunCreated { provenance, .. } => StoredEventFields { - actor: provenance.as_ref().and_then(|p| p.subject.clone()), + actor: Some(provenance.subject.clone()), ..StoredEventFields::default() }, Event::RunCancelRequested { actor } diff --git a/lib/crates/fabro-workflow/src/git.rs b/lib/crates/fabro-workflow/src/git.rs index f48683dd0..177f09079 100644 --- a/lib/crates/fabro-workflow/src/git.rs +++ b/lib/crates/fabro-workflow/src/git.rs @@ -343,7 +343,7 @@ mod tests { use fabro_dump::RunDump; use fabro_store::Database; - use fabro_types::{CommandTermination, StageModelUsage, fixtures}; + use fabro_types::{CommandTermination, StageModelUsage, fixtures, test_support}; use object_store::memory::InMemory; use super::*; @@ -468,7 +468,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/handler/agent.rs b/lib/crates/fabro-workflow/src/handler/agent.rs index 648f00c4b..0f46cdfed 100644 --- a/lib/crates/fabro-workflow/src/handler/agent.rs +++ b/lib/crates/fabro-workflow/src/handler/agent.rs @@ -429,7 +429,7 @@ mod tests { use fabro_graphviz::graph::AttrValue; use fabro_model::{ReasoningEffort, Speed}; use fabro_store::{Database, RunDatabase, StageId}; - use fabro_types::fixtures; + use fabro_types::{fixtures, test_support}; use object_store::memory::InMemory; use tempfile::TempDir; @@ -483,7 +483,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/handler/command.rs b/lib/crates/fabro-workflow/src/handler/command.rs index dde68dd5d..10ad51ce0 100644 --- a/lib/crates/fabro-workflow/src/handler/command.rs +++ b/lib/crates/fabro-workflow/src/handler/command.rs @@ -228,7 +228,7 @@ mod tests { use bytes::Bytes; use fabro_graphviz::graph::AttrValue; use fabro_store::{Database, RunDatabase, StageId}; - use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings, fixtures}; + use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings, fixtures, test_support}; use object_store::memory::InMemory; use tokio::sync::Mutex; @@ -255,7 +255,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: std::collections::HashMap::default(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, @@ -355,7 +355,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/handler/llm/api.rs b/lib/crates/fabro-workflow/src/handler/llm/api.rs index 91753f4c9..499cdd784 100644 --- a/lib/crates/fabro-workflow/src/handler/llm/api.rs +++ b/lib/crates/fabro-workflow/src/handler/llm/api.rs @@ -1600,6 +1600,7 @@ mod tests { use fabro_types::{ EventEnvelope, FailureReason, Run, RunId, RunLifecycle, RunLinks, RunOrigin, RunPairStatusResponse, RunProjection, RunStatus, RunTimestamps, SuccessReason, WorkflowRef, + test_support, }; use fabro_vault::{SecretType, Vault}; use futures::stream; @@ -2133,7 +2134,7 @@ reasoning = false }, automation: None, repository: None, - created_by: None, + created_by: test_support::test_principal(), origin: RunOrigin::default(), labels: HashMap::new(), lifecycle: RunLifecycle { diff --git a/lib/crates/fabro-workflow/src/handler/parallel.rs b/lib/crates/fabro-workflow/src/handler/parallel.rs index 7c85042cc..e9b4d4fe3 100644 --- a/lib/crates/fabro-workflow/src/handler/parallel.rs +++ b/lib/crates/fabro-workflow/src/handler/parallel.rs @@ -692,7 +692,7 @@ mod tests { use fabro_graphviz::graph::{AttrValue, Edge}; use fabro_store::{Database, StageId}; - use fabro_types::fixtures; + use fabro_types::{fixtures, test_support}; use object_store::memory::InMemory; use super::*; @@ -727,7 +727,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/handler/prompt.rs b/lib/crates/fabro-workflow/src/handler/prompt.rs index 8d5b2fdf6..5c3ab7c11 100644 --- a/lib/crates/fabro-workflow/src/handler/prompt.rs +++ b/lib/crates/fabro-workflow/src/handler/prompt.rs @@ -225,7 +225,7 @@ mod tests { use fabro_graphviz::graph::AttrValue; use fabro_model::{ReasoningEffort, Speed}; use fabro_store::{Database, RunDatabase, StageId}; - use fabro_types::fixtures; + use fabro_types::{fixtures, test_support}; use object_store::memory::InMemory; use tempfile::TempDir; @@ -282,7 +282,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/lifecycle/git.rs b/lib/crates/fabro-workflow/src/lifecycle/git.rs index fefaafa8c..e3cfeff89 100644 --- a/lib/crates/fabro-workflow/src/lifecycle/git.rs +++ b/lib/crates/fabro-workflow/src/lifecycle/git.rs @@ -598,7 +598,7 @@ mod tests { use fabro_model::Catalog; use fabro_store::{Database, EventEnvelope, RunDatabase, RunProjection}; use fabro_types::run_event::{MetadataSnapshotFailureKind, MetadataSnapshotPhase}; - use fabro_types::{EventBody, RunBlobId, RunEvent, WorkflowSettings, fixtures}; + use fabro_types::{EventBody, RunBlobId, RunEvent, WorkflowSettings, fixtures, test_support}; use object_store::memory::InMemory; use super::*; @@ -735,7 +735,7 @@ mod tests { source_directory: Some("/tmp/project".to_string()), workflow_slug: Some("metadata".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/operations/archive.rs b/lib/crates/fabro-workflow/src/operations/archive.rs index bb3693398..4393af607 100644 --- a/lib/crates/fabro-workflow/src/operations/archive.rs +++ b/lib/crates/fabro-workflow/src/operations/archive.rs @@ -136,7 +136,9 @@ mod tests { use std::time::Duration; use fabro_store::Database; - use fabro_types::{FailureReason, RunId, SuccessReason, TerminalStatus, fixtures}; + use fabro_types::{ + FailureReason, RunId, SuccessReason, TerminalStatus, fixtures, test_support, + }; use object_store::memory::InMemory; use super::*; @@ -225,7 +227,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/operations/create.rs b/lib/crates/fabro-workflow/src/operations/create.rs index 0460a1874..6b7233484 100644 --- a/lib/crates/fabro-workflow/src/operations/create.rs +++ b/lib/crates/fabro-workflow/src/operations/create.rs @@ -44,7 +44,7 @@ pub struct CreateRunInput { pub git: Option, pub fork_source_ref: Option, pub parent_id: Option, - pub provenance: Option, + pub provenance: RunProvenance, pub configured_providers: Vec, /// Public URL where this run can be viewed in the web UI, when the server /// has the web UI enabled. Recorded on the `run.created` event so attach @@ -70,7 +70,7 @@ struct PersistCreateOptions { source_directory: Option, git: Option, fork_source_ref: Option, - provenance: Option, + provenance: RunProvenance, configured_providers: Vec, catalog: Arc, } @@ -415,7 +415,7 @@ mod tests { use fabro_store::Database; use fabro_types::settings::InterpString; use fabro_types::settings::run::RunMode; - use fabro_types::{WorkflowSettings, fixtures}; + use fabro_types::{WorkflowSettings, fixtures, test_support}; use fabro_util::error::collect_chain; use fabro_validate::Severity; use object_store::local::LocalFileSystem; @@ -1099,7 +1099,7 @@ mod tests { git: None, fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1166,7 +1166,7 @@ mod tests { }), fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1277,7 +1277,7 @@ mod tests { git: None, fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1322,7 +1322,7 @@ mod tests { }), fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1389,7 +1389,7 @@ mod tests { git: None, fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1435,7 +1435,7 @@ mod tests { git: None, fork_source_ref: None, parent_id: None, - provenance: Some(fabro_types::RunProvenance { + provenance: fabro_types::RunProvenance { server: Some(fabro_types::RunServerProvenance { version: "0.9.0".to_string(), }), @@ -1444,12 +1444,12 @@ mod tests { name: Some("fabro-cli".to_string()), version: Some("0.9.0".to_string()), }), - subject: Some(fabro_types::Principal::user( + subject: fabro_types::Principal::user( fabro_types::IdpIdentity::new("https://github.com", "12345").unwrap(), "octocat".to_string(), fabro_types::AuthMethod::Github, - )), - }), + ), + }, configured_providers: Vec::new(), web_url: None, }, @@ -1462,7 +1462,7 @@ mod tests { let run_store = store.open_run_reader(&created.run_id).await.unwrap(); let state = run_store.state().await.unwrap(); let run = state.spec; - let provenance = run.provenance.expect("provenance should be projected"); + let provenance = run.provenance; assert_eq!(provenance.server.unwrap().version, "0.9.0"); assert_eq!( @@ -1470,7 +1470,7 @@ mod tests { Some("fabro-cli") ); assert_eq!( - provenance.subject.unwrap(), + provenance.subject, fabro_types::Principal::user( fabro_types::IdpIdentity::new("https://github.com", "12345").unwrap(), "octocat".to_string(), diff --git a/lib/crates/fabro-workflow/src/operations/fork.rs b/lib/crates/fabro-workflow/src/operations/fork.rs index 513975d71..eb3a6720e 100644 --- a/lib/crates/fabro-workflow/src/operations/fork.rs +++ b/lib/crates/fabro-workflow/src/operations/fork.rs @@ -283,7 +283,7 @@ mod tests { use fabro_graphviz::graph::Graph; use fabro_store::{Database, RunProjectionReducer}; - use fabro_types::{StageId, WorkflowSettings, fixtures}; + use fabro_types::{StageId, WorkflowSettings, fixtures, test_support}; use object_store::memory::InMemory; use super::*; @@ -381,7 +381,7 @@ mod tests { source_directory: Some("/client/source".to_string()), workflow_slug: Some("fork-source".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: Some(fabro_types::GitContext { origin_url: "https://github.com/example/repo.git".to_string(), diff --git a/lib/crates/fabro-workflow/src/operations/retry.rs b/lib/crates/fabro-workflow/src/operations/retry.rs index 6551687c5..f71b90626 100644 --- a/lib/crates/fabro-workflow/src/operations/retry.rs +++ b/lib/crates/fabro-workflow/src/operations/retry.rs @@ -12,7 +12,7 @@ use crate::event::{self, Event}; pub struct RetryRunInput { pub source_run_id: RunId, pub new_run_id: RunId, - pub provenance: Option, + pub provenance: RunProvenance, pub web_url: Option, } @@ -149,7 +149,7 @@ mod tests { version: "test".to_string(), }), client: None, - subject: Some(actor(login)), + subject: actor(login), } } @@ -187,7 +187,7 @@ mod tests { source_directory: Some("/workspace/source".to_string()), workflow_slug: Some("retry-source".to_string()), db_prefix: None, - provenance: Some(provenance("source-user")), + provenance: provenance("source-user"), manifest_blob, git: Some(git_context()), fork_source_ref, @@ -345,7 +345,7 @@ mod tests { let outcome = retry_run(&store, &RetryRunInput { source_run_id, new_run_id: RunId::new(), - provenance: Some(provenance("retry-user")), + provenance: provenance("retry-user"), web_url: Some("http://localhost:3000/runs/retry".to_string()), }) .await @@ -379,14 +379,7 @@ mod tests { assert_eq!(retry_state.spec.manifest_blob, manifest_blob); assert_eq!(retry_state.spec.definition_blob, definition_blob); assert_eq!(retry_state.spec.fork_source_ref, Some(fork_source_ref)); - assert_eq!( - retry_state - .spec - .provenance - .as_ref() - .and_then(|provenance| provenance.subject.as_ref()), - Some(&actor("retry-user")) - ); + assert_eq!(&retry_state.spec.provenance.subject, &actor("retry-user")); assert_eq!( retry_state.web_url.as_deref(), Some("http://localhost:3000/runs/retry") @@ -469,7 +462,7 @@ mod tests { let err = retry_run(&store, &RetryRunInput { source_run_id: run_id, new_run_id: RunId::new(), - provenance: None, + provenance: provenance("retry-user"), web_url: None, }) .await @@ -487,7 +480,7 @@ mod tests { let err = retry_run(&store, &RetryRunInput { source_run_id: fixtures::RUN_1, new_run_id: RunId::new(), - provenance: None, + provenance: provenance("retry-user"), web_url: None, }) .await diff --git a/lib/crates/fabro-workflow/src/operations/start.rs b/lib/crates/fabro-workflow/src/operations/start.rs index a962cd0e5..adf2741d7 100644 --- a/lib/crates/fabro-workflow/src/operations/start.rs +++ b/lib/crates/fabro-workflow/src/operations/start.rs @@ -1112,7 +1112,9 @@ mod tests { use fabro_store::Database; use fabro_types::settings::run::RunMode; use fabro_types::settings::{InterpString, ModelRef}; - use fabro_types::{BilledModelUsage, ManifestPath, StageTiming, WorkflowSettings, fixtures}; + use fabro_types::{ + BilledModelUsage, ManifestPath, StageTiming, WorkflowSettings, fixtures, test_support, + }; use object_store::memory::InMemory; use super::*; @@ -1416,7 +1418,7 @@ reasoning = false git: None, fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, @@ -1837,7 +1839,7 @@ reasoning = false git: None, fork_source_ref: None, parent_id: None, - provenance: None, + provenance: test_support::test_run_provenance(), configured_providers: Vec::new(), web_url: None, }, diff --git a/lib/crates/fabro-workflow/src/operations/timeline.rs b/lib/crates/fabro-workflow/src/operations/timeline.rs index 2170dc28a..fdfdea119 100644 --- a/lib/crates/fabro-workflow/src/operations/timeline.rs +++ b/lib/crates/fabro-workflow/src/operations/timeline.rs @@ -204,6 +204,7 @@ mod tests { use chrono::Utc; use fabro_types::{ Checkpoint, CheckpointRecord, Graph, RunDiff, RunSpec, WorkflowSettings, fixtures, + test_support, }; use super::*; @@ -247,7 +248,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-workflow/src/pipeline/execute/tests.rs b/lib/crates/fabro-workflow/src/pipeline/execute/tests.rs index cef35cc39..39392007b 100644 --- a/lib/crates/fabro-workflow/src/pipeline/execute/tests.rs +++ b/lib/crates/fabro-workflow/src/pipeline/execute/tests.rs @@ -18,7 +18,9 @@ use fabro_interview::AutoApproveInterviewer; use fabro_sandbox::SandboxSpec; use fabro_store::Database; use fabro_types::settings::run::RunModelControls; -use fabro_types::{Principal, RunId, SystemActorKind, WorkflowSettings, fixtures, format_blob_ref}; +use fabro_types::{ + Principal, RunId, SystemActorKind, WorkflowSettings, fixtures, format_blob_ref, test_support, +}; use object_store::memory::InMemory; use super::*; @@ -164,7 +166,7 @@ fn persisted_workflow(graph: Graph, source: String, run_dir: &Path, run_id: RunI push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -207,7 +209,7 @@ async fn seed_created_and_starting( source_directory: Some(std::env::current_dir().unwrap().display().to_string()), workflow_slug: run_options.workflow_slug.clone(), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: run_options.pre_run_git.clone(), fork_source_ref: run_options.fork_source_ref.clone(), diff --git a/lib/crates/fabro-workflow/src/pipeline/finalize.rs b/lib/crates/fabro-workflow/src/pipeline/finalize.rs index 05d6db1d0..36b3b7452 100644 --- a/lib/crates/fabro-workflow/src/pipeline/finalize.rs +++ b/lib/crates/fabro-workflow/src/pipeline/finalize.rs @@ -651,7 +651,7 @@ mod tests { use fabro_types::run_event::{MetadataSnapshotFailureKind, MetadataSnapshotPhase}; use fabro_types::{ BilledTokenCounts, EventBody, RunBlobId, RunEvent, RunId, RunSpec, StageCompletion, - WorkflowSettings, first_event_seq, fixtures, + WorkflowSettings, first_event_seq, fixtures, test_support, }; use object_store::memory::InMemory; @@ -738,7 +738,7 @@ mod tests { source_directory: Some("/tmp/project".to_string()), workflow_slug: Some("metadata".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, @@ -854,7 +854,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, diff --git a/lib/crates/fabro-workflow/src/pipeline/initialize.rs b/lib/crates/fabro-workflow/src/pipeline/initialize.rs index 761a58e42..b8b8e5147 100644 --- a/lib/crates/fabro-workflow/src/pipeline/initialize.rs +++ b/lib/crates/fabro-workflow/src/pipeline/initialize.rs @@ -764,7 +764,7 @@ mod tests { use fabro_sandbox::SandboxSpec; use fabro_store::Database; use fabro_types::settings::run::RunModelControls; - use fabro_types::{EventBody, RunEvent, RunId, WorkflowSettings, fixtures}; + use fabro_types::{EventBody, RunEvent, RunId, WorkflowSettings, fixtures, test_support}; use fabro_vault::{SecretType, Vault}; use object_store::memory::InMemory; use tokio::fs::{create_dir_all, write}; @@ -888,7 +888,7 @@ mod tests { push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/pipeline/persist.rs b/lib/crates/fabro-workflow/src/pipeline/persist.rs index ee6150696..93da4da2c 100644 --- a/lib/crates/fabro-workflow/src/pipeline/persist.rs +++ b/lib/crates/fabro-workflow/src/pipeline/persist.rs @@ -59,7 +59,7 @@ mod tests { use fabro_graphviz::graph::{AttrValue, Edge, Graph, Node}; use fabro_store::{Database, RunDatabase}; - use fabro_types::fixtures; + use fabro_types::{fixtures, test_support}; use object_store::memory::InMemory; use super::*; @@ -147,7 +147,7 @@ mod tests { ("env".to_string(), "test".to_string()), ("team".to_string(), "workflow".to_string()), ]), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/pipeline/pull_request.rs b/lib/crates/fabro-workflow/src/pipeline/pull_request.rs index 92f4a0bc3..41e1f3434 100644 --- a/lib/crates/fabro-workflow/src/pipeline/pull_request.rs +++ b/lib/crates/fabro-workflow/src/pipeline/pull_request.rs @@ -680,7 +680,7 @@ mod tests { use fabro_store::Database; use fabro_types::{ BilledTokenCounts, RunProjection, RunSpec, SuccessReason, WorkflowSettings, - first_event_seq, fixtures, + first_event_seq, fixtures, test_support, }; use fabro_vault::{SecretType, Vault}; use futures::stream; @@ -822,7 +822,7 @@ mod tests { workflow_slug: None, source_directory: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, git: None, @@ -1146,7 +1146,7 @@ mod tests { push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -1215,7 +1215,7 @@ mod tests { push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -1569,7 +1569,7 @@ mod tests { source_directory: Some(tmp.path().display().to_string()), git: None, labels: std::collections::HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -1696,7 +1696,7 @@ mod tests { source_directory: Some("/tmp/project".to_string()), git: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -1713,7 +1713,7 @@ mod tests { source_directory: run_spec.source_directory.clone(), workflow_slug: run_spec.workflow_slug.clone(), db_prefix: None, - provenance: None, + provenance: run_spec.provenance.clone(), manifest_blob: None, git: None, fork_source_ref: None, @@ -1865,7 +1865,7 @@ mod tests { source_directory: None, git: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -1882,7 +1882,7 @@ mod tests { source_directory: None, workflow_slug: None, db_prefix: None, - provenance: None, + provenance: run_spec.provenance.clone(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/run_lookup.rs b/lib/crates/fabro-workflow/src/run_lookup.rs index 5d8cdeb3b..750d2d5ea 100644 --- a/lib/crates/fabro-workflow/src/run_lookup.rs +++ b/lib/crates/fabro-workflow/src/run_lookup.rs @@ -457,7 +457,7 @@ mod tests { use fabro_graphviz::graph::Graph; use fabro_store::Database; - use fabro_types::{RunStatus, WorkflowSettings, fixtures}; + use fabro_types::{RunStatus, WorkflowSettings, fixtures, test_support}; use object_store::memory::InMemory; use super::scan_runs_combined; @@ -490,7 +490,7 @@ mod tests { push_outcome: fabro_types::PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/run_metadata.rs b/lib/crates/fabro-workflow/src/run_metadata.rs index 9d679d0b4..f8606a307 100644 --- a/lib/crates/fabro-workflow/src/run_metadata.rs +++ b/lib/crates/fabro-workflow/src/run_metadata.rs @@ -537,7 +537,9 @@ mod tests { use std::sync::Arc; use fabro_store::RunProjection; - use fabro_types::{DirtyStatus, GitContext, PreRunPushOutcome, RunSpec, WorkflowSettings}; + use fabro_types::{ + DirtyStatus, GitContext, PreRunPushOutcome, RunSpec, WorkflowSettings, test_support, + }; use git2::{ErrorClass, ErrorCode}; use super::*; @@ -638,7 +640,7 @@ mod tests { push_outcome: PreRunPushOutcome::NotAttempted, }), labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/runtime_store.rs b/lib/crates/fabro-workflow/src/runtime_store.rs index 0f590c70f..e3b464abb 100644 --- a/lib/crates/fabro-workflow/src/runtime_store.rs +++ b/lib/crates/fabro-workflow/src/runtime_store.rs @@ -120,7 +120,7 @@ mod tests { use fabro_graphviz::graph::Graph; use fabro_store::Database; use fabro_types::run_event::RunSubmittedProps; - use fabro_types::{EventBody, RunEvent, WorkflowSettings, fixtures}; + use fabro_types::{EventBody, RunEvent, WorkflowSettings, fixtures, test_support}; use object_store::memory::InMemory; use super::RunStoreHandle; @@ -147,7 +147,7 @@ mod tests { source_directory: Some("/tmp/test".to_string()), git: None, labels: HashMap::new(), - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, definition_blob: None, fork_source_ref: None, @@ -168,7 +168,7 @@ mod tests { source_directory: Some("/tmp/test".to_string()), workflow_slug: Some("test".to_string()), db_prefix: None, - provenance: None, + provenance: test_support::test_run_provenance(), manifest_blob: None, git: None, fork_source_ref: None, diff --git a/lib/crates/fabro-workflow/src/test_support.rs b/lib/crates/fabro-workflow/src/test_support.rs index c587e49fa..c54affbdc 100644 --- a/lib/crates/fabro-workflow/src/test_support.rs +++ b/lib/crates/fabro-workflow/src/test_support.rs @@ -174,7 +174,13 @@ async fn initialized( source_directory: Some(sandbox.working_directory().to_string()), workflow_slug: run_options.workflow_slug.clone(), db_prefix: None, - provenance: None, + provenance: fabro_types::RunProvenance { + server: None, + client: None, + subject: fabro_types::Principal::System { + system_kind: fabro_types::SystemActorKind::Engine, + }, + }, manifest_blob: None, git: run_options.pre_run_git.clone(), fork_source_ref: run_options.fork_source_ref.clone(), diff --git a/lib/packages/fabro-api-client/src/models/run-provenance.ts b/lib/packages/fabro-api-client/src/models/run-provenance.ts index 7276857f8..59fa7a063 100644 --- a/lib/packages/fabro-api-client/src/models/run-provenance.ts +++ b/lib/packages/fabro-api-client/src/models/run-provenance.ts @@ -26,5 +26,5 @@ import type { RunServerProvenance } from './run-server-provenance'; export interface RunProvenance { 'server'?: RunServerProvenance | null; 'client'?: RunClientProvenance | null; - 'subject'?: Principal | null; + 'subject': Principal; } diff --git a/lib/packages/fabro-api-client/src/models/run-spec.ts b/lib/packages/fabro-api-client/src/models/run-spec.ts index 2be7312b7..f86098a2d 100644 --- a/lib/packages/fabro-api-client/src/models/run-spec.ts +++ b/lib/packages/fabro-api-client/src/models/run-spec.ts @@ -37,7 +37,7 @@ export interface RunSpec { 'workflow_slug'?: string | null; 'source_directory'?: string | null; 'labels'?: { [key: string]: string; }; - 'provenance'?: RunProvenance | null; + 'provenance': RunProvenance; 'manifest_blob'?: string | null; 'definition_blob'?: string | null; 'git'?: GitContext | null; diff --git a/lib/packages/fabro-api-client/src/models/run.ts b/lib/packages/fabro-api-client/src/models/run.ts index 1ed6c6c26..a4ade38a3 100644 --- a/lib/packages/fabro-api-client/src/models/run.ts +++ b/lib/packages/fabro-api-client/src/models/run.ts @@ -83,7 +83,7 @@ export interface Run { 'workflow': WorkflowRef; 'automation': AutomationRef | null; 'repository': RepositoryRef | null; - 'created_by': Principal | null; + 'created_by': Principal; 'origin': RunOrigin; 'labels': { [key: string]: string; }; 'lifecycle': RunLifecycle;