///|
fn metadata_hash_file(path : String, check : () -> Unit raise) -> String raise {
let digest = @crypto.SHA256::new()
@platform.file_chunks(path, 536870912, fn(bytes) raise {
check()
digest.update(bytes)
})
check()
@crypto.bytes_to_hex_string(digest.finalize())
}
///|
/// Inspect the fixed host helper bundle for an explicit grant document. This
/// reads only named runtime files; it never executes a service or creates trust.
pub fn metadata_helper_bundle_sha256(helper : String) -> String raise {
metadata_bundle_hash(helper, fn() { () })
}
///|
fn metadata_bundle_hash(
helper : String,
check : () -> Unit raise,
) -> String raise {
if !helper.has_suffix("/metadata.mjs") {
raise @config.Invalid("metadata.restore_unqualified_helper")
}
let directory = helper[:helper.length() - "metadata.mjs".length()].to_owned()
let entries = [
"WindowsJob.cs", "metadata.mjs", "supervision.mjs", "windows-job.mjs", "windows-job.ps1",
].map(fn(name) raise {
check()
let bytes = metadata_read_file(directory + name, 1048576, check)
if bytes.length() > 1048576 {
raise @config.Invalid("metadata.restore_helper_limit")
}
Json::array([Json::string(name), Json::string(@identity.sha256(bytes))])
})
@identity.sha256(@utf8.encode(Json::array(entries).stringify()))
}
///|
fn[T] metadata_observe(
observer : @observe.Observer,
operation : String,
project : String,
stage : @observe.Stage,
code : String,
run : () -> T raise,
audit~ : MetadataAuditContext? = None,
) -> T raise {
let scoped = {
..observer,
try_record: fn(record) raise {
(observer.try_record)({
..record,
correlation: Some({
target: "local-library-mvp",
lease_id: operation,
call_id: project,
attempt_id: code,
}),
details: Some({
entry: project,
code: code +
(match record.signal {
Started => ".started"
Succeeded => ".succeeded"
Failed => ".failed"
Cancelled => ".cancelled"
Notice => ".notice"
}),
}),
})
},
}
let work = fn() raise {
scoped
.scope()
.observe(stage, fn(_) raise { run() }, is_cancelled=fn(error) {
error_message(error).contains("Cancelled")
})
}
match audit {
None => work()
Some(context) => {
let phase : MetadataAuditPhase = match code {
"metadata.acquire" => Acquire
"metadata.probe" => Probe
"metadata.restore" => Restore
"metadata.decode" => Decode
"metadata.context" => Context
_ => Cleanup
}
context.observe(phase, work)
}
}
}
///|
fn metadata_read_file(
path : String,
limit : Int32,
check : () -> Unit raise,
) -> Bytes raise {
let chunks : Array[Bytes] = []
@platform.file_chunks(path, limit, fn(bytes) raise {
check()
chunks.push(bytes)
})
Bytes::from_iter(chunks.iter().flat_map(bytes => bytes.iter()))
}