Skip to content

Commit 5b77c67

Browse files
committed
Making it through the full workflow run!
As in, incl a data transfer _and_ a transfer to the user. Yay!
1 parent 2694ba9 commit 5b77c67

File tree

31 files changed

+127
-92
lines changed

31 files changed

+127
-92
lines changed

Dockerfile.let

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ARG USERID=1000
1919
ARG GROUPID=1000
2020

2121
# Setup a user mirroring the main one
22-
RUN if [[ -z "$(cat /etc/group | grep ':20:')" ]]; then addgroup --gid $GROUPID brane && export GROUP=brane else export GROUP=$(getent group $GROUPID | cut -d: -f1); fi
22+
RUN if [[ ! "$(getent group $GROUPID)" ]]; then addgroup --gid $GROUPID brane && export GROUP=brane else export GROUP=$(getent group $GROUPID | cut -d: -f1); fi
2323
RUN adduser --uid $USERID --gid $GROUPID --gecos "Brane" --disabled-password brane
2424

2525
# Install build dependencies

brane-chk/src/apis/deliberation.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 28 Oct 2024, 20:44:52
66
// Last edited:
7-
// 29 Apr 2025, 23:33:44
7+
// 02 May 2025, 15:01:31
88
// Auto updated?
99
// Yes
1010
//
@@ -379,12 +379,21 @@ where
379379
};
380380

381381
// Decide the input
382-
let task_id: String = pc_to_id(&req.workflow, req.task);
383-
let input: Input = Input {
384-
store: this.store.clone(),
385-
usecase: req.usecase,
386-
workflow: req.workflow,
387-
input: QuestionInput::TransferInput { task: task_id, input: req.input },
382+
let input: Input = if let Some(task) = req.task {
383+
let task_id: String = pc_to_id(&req.workflow, task);
384+
Input {
385+
store: this.store.clone(),
386+
usecase: req.usecase,
387+
workflow: req.workflow,
388+
input: QuestionInput::TransferInput { task: task_id, input: req.input },
389+
}
390+
} else {
391+
Input {
392+
store: this.store.clone(),
393+
usecase: req.usecase,
394+
workflow: req.workflow,
395+
input: QuestionInput::TransferResult { result: req.input },
396+
}
388397
};
389398

390399
// Continue with the agnostic function for maintainability

brane-chk/src/question.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 17 Oct 2024, 16:10:59
66
// Last edited:
7-
// 29 Apr 2025, 15:37:12
7+
// 02 May 2025, 14:59:38
88
// Auto updated?
99
// Yes
1010
//
@@ -15,7 +15,7 @@
1515
use std::fmt::{Formatter, Result as FResult};
1616

1717
use policy_reasoner::reasoners::eflint_haskell::spec::EFlintable;
18-
use policy_reasoner::workflow::Workflow;
18+
use policy_reasoner::workflow::{Entity, Workflow};
1919
use serde::{Deserialize, Serialize};
2020

2121
use crate::workflow;
@@ -46,6 +46,13 @@ pub enum Question {
4646
/// The input to that task that we want to validate.
4747
input: String,
4848
},
49+
/// Checks if a domain agrees with providing the given result to the end user of the workflow.
50+
TransferResult {
51+
/// The workflow that we want to validate.
52+
workflow: Workflow,
53+
/// The input to that task that we want to validate.
54+
result: String,
55+
},
4956
}
5057
impl EFlintable for Question {
5158
#[inline]
@@ -66,6 +73,16 @@ impl EFlintable for Question {
6673
writeln!(f, "?dataset-to-transfer(node-input(node(workflow({:?}), {:?}), asset({:?})))", workflow.id, task, input)?;
6774
Ok(())
6875
},
76+
Self::TransferResult { workflow, result } => {
77+
workflow::eflint_fmt(workflow, f)?;
78+
let user: &Entity = workflow.user.as_ref().unwrap_or_else(|| panic!("Cannot ask for a transfer result without a user in workflow"));
79+
writeln!(
80+
f,
81+
"?result-to-transfer(workflow-result-recipient(workflow-result(workflow({:?}), asset({:?})), user({:?})))",
82+
workflow.id, result, user.id
83+
)?;
84+
Ok(())
85+
},
6986
}
7087
}
7188
}

brane-chk/src/stateresolver.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 17 Oct 2024, 16:09:36
66
// Last edited:
7-
// 01 May 2025, 17:14:40
7+
// 02 May 2025, 14:59:31
88
// Auto updated?
99
// Yes
1010
//
@@ -725,6 +725,7 @@ pub enum QuestionInput {
725725
ValidateWorkflow,
726726
ExecuteTask { task: String },
727727
TransferInput { task: String, input: String },
728+
TransferResult { result: String },
728729
}
729730

730731

@@ -813,6 +814,7 @@ impl StateResolver for BraneStateResolver {
813814
}
814815
Ok((policy, Question::TransferInput { workflow: wf, task, input }))
815816
},
817+
QuestionInput::TransferResult { result } => Ok((policy, Question::TransferResult { workflow: wf, result })),
816818
}
817819
}
818820
}

brane-chk/src/workflow/compiler.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 21 Oct 2024, 10:47:42
66
// Last edited:
7-
// 29 Apr 2025, 23:37:33
7+
// 02 May 2025, 11:50:06
88
// Auto updated?
99
// Yes
1010
//
@@ -134,9 +134,9 @@ struct Arguments {
134134
#[clap(
135135
short = '2',
136136
long,
137-
default_value = "eflint-json",
138-
help = "The output language to compile to. Options are 'wf'/'workflow' for the policy reasoner's workflow representation, 'eflint-json' for \
139-
eFLINT JSON Specification, or 'eflint'/'eflint-dsl' for the eFLINT DSL."
137+
default_value = "eflint",
138+
help = "The output language to compile to. Options are 'wf'/'workflow' for the policy reasoner's workflow representation, or \
139+
'eflint'/'eflint-dsl' for the eFLINT DSL."
140140
)]
141141
output_lang: OutputLanguage,
142142
}

brane-cli-c/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 14 Jun 2023, 17:38:09
66
// Last edited:
7-
// 14 Nov 2024, 17:59:09
7+
// 02 May 2025, 15:05:31
88
// Auto updated?
99
// Yes
1010
//
@@ -1174,8 +1174,8 @@ pub unsafe extern "C" fn fvalue_serialize(fvalue: *const FullValue, data_dir: *c
11741174

11751175
// Serialize the result only if there is anything to serialize
11761176
let mut sfvalue: String = String::new();
1177-
if fvalue != &FullValue::Void {
1178-
writeln!(&mut sfvalue, "\nWorkflow returned value {}", style(format!("'{fvalue}'")).bold().cyan()).unwrap();
1177+
if !matches!(fvalue, FullValue::Void) {
1178+
writeln!(&mut sfvalue, "\nWorkflow returned value {}", style(format!("'{}'", fvalue)).bold().cyan()).unwrap();
11791179

11801180
// Treat some values special
11811181
match fvalue {
@@ -1342,7 +1342,7 @@ pub unsafe extern "C" fn vm_free(vm: *mut VirtualMachine) {
13421342
/// - `vm`: The [`VirtualMachine`] that we execute with. This determines which backend to use.
13431343
/// - `workflow`: The compiled workflow to execute.
13441344
/// - `prints`: A newly allocated string which represents any stdout- or stderr prints done during workflow execution. Will be [`NULL`] if there is an error (see below).
1345-
/// - `result`: A [`FullValue`] which represents the return value of the workflow. Will be [`NULL`] if there is an error (see below).
1345+
/// - `result`: A [`FullValue`] which represents the return value of the workflow, and a [`ProgramCounter`] that denotes which instruction produced it (or [`None`] if the workflow was empty). Will be [`NULL`] if there is an error (see below).
13461346
///
13471347
/// # Returns
13481348
/// An [`Error`]-struct that contains the error occurred, or [`NULL`] otherwise.

brane-cli/src/data.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 12 Sep 2022, 17:39:06
66
// Last edited:
7-
// 29 Apr 2025, 14:00:18
7+
// 02 May 2025, 15:03:01
88
// Auto updated?
99
// Yes
1010
//
@@ -56,6 +56,7 @@ use crate::utils::{ensure_dataset_dir, ensure_datasets_dir, get_dataset_dir};
5656
/// - `certs_dir`: The directory where certificates are stored. Expected to contain nested directories that store the certs by domain ID.
5757
/// - `data_dir`: The directory to download the dataset to.
5858
/// - `name`: The name of the dataset to download.
59+
/// - `workflow`: A workflow for which we're downloading a result.
5960
/// - `access`: The locations where it is available.
6061
///
6162
/// # Returns

brane-cli/src/errors.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 17 Feb 2022, 10:27:28
66
// Last edited:
7-
// 29 Apr 2025, 13:40:48
7+
// 02 May 2025, 14:16:13
88
// Auto updated?
99
// Yes
1010
//
@@ -15,6 +15,7 @@
1515
use std::error::Error;
1616
use std::path::PathBuf;
1717

18+
use brane_exe::value::DataId;
1819
use brane_shr::formatters::{BlockFormatter, PrettyListFormatter};
1920
use reqwest::StatusCode;
2021
use specifications::address::Address;
@@ -867,6 +868,9 @@ pub enum RunError {
867868
/// Failed to download remote dataset.
868869
#[error("Failed to download remote dataset")]
869870
DataDownloadError { source: DataError },
871+
/// Workflow returned result without PC.
872+
#[error("Workflow returned data \"{data}\" without providing information where in the workflow it's downloaded from.")]
873+
DataDownloadWithoutPc { data: DataId },
870874

871875
/// Failed to read the source from stdin
872876
#[error("Failed to read source from stdin")]

brane-cli/src/repl.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 12 Sep 2022, 16:42:47
66
// Last edited:
7-
// 29 Apr 2025, 11:58:06
7+
// 02 May 2025, 14:38:28
88
// Auto updated?
99
// Yes
1010
//
@@ -24,6 +24,7 @@ use brane_dsl::Language;
2424
use brane_exe::FullValue;
2525
use brane_tsk::docker::DockerOptions;
2626
use brane_tsk::spec::AppId;
27+
use error_trace::ErrorTrace as _;
2728
use log::warn;
2829
use rustyline::completion::{Completer, FilenameCompleter, Pair};
2930
use rustyline::error::ReadlineError;
@@ -425,7 +426,7 @@ async fn remote_repl(
425426

426427
// Then, we collect and process the result
427428
if let Err(source) = process_instance_result(&api_address, &proxy_addr, use_case.clone(), snippet.workflow, res).await {
428-
error!("{}", Error::ProcessError { what: "remote instance VM", source });
429+
error!("{}", Error::ProcessError { what: "remote instance VM", source }.trace());
429430
continue;
430431
}
431432

@@ -513,7 +514,7 @@ async fn local_repl(
513514

514515
// Then, we collect and process the result
515516
if let Err(source) = process_offline_result(res) {
516-
error!("{}", Error::ProcessError { what: "offline VM", source });
517+
error!("{}", Error::ProcessError { what: "offline VM", source }.trace());
517518
continue;
518519
}
519520

brane-cli/src/run.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created:
55
// 12 Sep 2022, 16:42:57
66
// Last edited:
7-
// 29 Apr 2025, 14:00:29
7+
// 05 May 2025, 11:15:39
88
// Auto updated?
99
// Yes
1010
//
@@ -128,7 +128,7 @@ pub async fn initialize_instance<O: Write, E: Write>(
128128
/// - `profile`: If given, prints the profile timings to stdout if reported by the remote.
129129
///
130130
/// # Returns
131-
/// A [`FullValue`] carrying the result of the snippet (or [`FullValue::Void`]).
131+
/// A [`FullValue`] carrying the result of the snippet (or [`FullValue::Void`]), and a [`ProgramCounter`] in case a [`FullValue::Data`] is returned telling us which edge downloaded it.
132132
///
133133
/// # Errors
134134
/// This function may error if anything in the whole shebang crashed. This can be things client-side, but also remote-side.
@@ -219,7 +219,7 @@ pub async fn run_instance<O: Write, E: Write>(
219219
/// - `proxy_addr`: If given, proxies all data transfers through the proxy at the given location.
220220
/// - `certs_dir`: The directory where certificates are stored. Expected to contain nested directories that store the certs by domain ID.
221221
/// - `datasets_dir`: The directory where we will download the data to. It will be added under a new folder with its own name.
222-
/// - `result`: The value to process.
222+
/// - `result`: The value to process, together with a program counter if it was the result of a toplevel return.
223223
///
224224
/// # Returns
225225
/// Nothing, but does print any result to stdout. It may also download a remote dataset if one is given.
@@ -240,8 +240,8 @@ pub async fn process_instance(
240240
let datasets_dir: &Path = datasets_dir.as_ref();
241241

242242
// We only print
243-
if result != FullValue::Void {
244-
println!("\nWorkflow returned value {}", style(format!("'{result}'")).bold().cyan());
243+
if !matches!(result, FullValue::Void) {
244+
println!("\nWorkflow returned value {}", style(format!("'{}'", result)).bold().cyan());
245245

246246
// FIXME: Clean up this blob
247247
// Treat some values special

0 commit comments

Comments
 (0)