Skip to content

Commit 39d79c0

Browse files
hyperpolymathclaude
andcommitted
fix: unblock Evidence Envelope critical chain — 7 schema violations fixed
Constraint-first (v3 methodology): identified the critical chain bottleneck as "nobody writes valid Evidence Envelopes" and resolved it. - Wire HCT --envelope flag (was parsed but discarded as `_`) - Fix service-autopsy: tool value, artifact types, path field, UUID format - Add "hardware-crash-team" to schema tool enum - Both HCT and service-autopsy now emit schema-conformant envelopes Coverage audit: 29/29 components audited, 12 skipped MUSTs found in unvisited components (session-sentinel P0, 3 license violations P1). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d1b0274 commit 39d79c0

5 files changed

Lines changed: 53 additions & 12 deletions

File tree

‎Cargo.lock‎

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎contracts/schemas/evidence-envelope.schema.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"properties": {
2929
"tool": {
3030
"type": "string",
31-
"enum": ["big-up", "ambient", "a-and-e", "sysobs", "psa"],
31+
"enum": ["big-up", "ambient", "a-and-e", "sysobs", "psa", "hardware-crash-team"],
3232
"description": "Which tool produced this envelope"
3333
},
3434
"tool_version": {

‎hardware-crash-team/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
3131
reqwest = { version = "0.12", features = ["json"], optional = true }
3232
tokio = { version = "1", features = ["full"], optional = true }
3333

34+
gethostname = "0.4"
3435
ambientops-contracts = { path = "../contracts-rust" }
3536

3637
# TUI

‎hardware-crash-team/src/main.rs‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,26 @@ fn main() -> Result<()> {
142142
let cli = Cli::parse();
143143

144144
match cli.command {
145-
Commands::Scan { format, envelope: _, output } => {
145+
Commands::Scan { format, envelope, output } => {
146146
let report = scanner::scan_system(cli.verbose)?;
147-
let rendered = match format.as_str() {
148-
"json" => serde_json::to_string_pretty(&report)?,
149-
"sarif" => sarif::format_sarif(&report)?,
150-
_ => scanner::format_report(&report, "text")?,
147+
148+
let rendered = if envelope {
149+
// Wrap scan output in a contract-conformant EvidenceEnvelope.
150+
let report_json = serde_json::to_value(&report)?;
151+
let hostname = gethostname::gethostname()
152+
.to_string_lossy()
153+
.to_string();
154+
let env = ambientops_contracts::conversions::system_report_to_envelope(
155+
&report_json,
156+
&hostname,
157+
);
158+
serde_json::to_string_pretty(&env)?
159+
} else {
160+
match format.as_str() {
161+
"json" => serde_json::to_string_pretty(&report)?,
162+
"sarif" => sarif::format_sarif(&report)?,
163+
_ => scanner::format_report(&report, "text")?,
164+
}
151165
};
152166

153167
if let Some(path) = output {

‎records/service-autopsy/lib/service_autopsy/collector.ex‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ defmodule ServiceAutopsy.Collector do
2222

2323
require Logger
2424

25-
@source "service-autopsy"
25+
@source "psa"
2626
@journal_lines 50
2727
@envelope_version "1.0.0"
2828

@@ -200,7 +200,8 @@ defmodule ServiceAutopsy.Collector do
200200
if results[:journal] != [] do
201201
[%{
202202
"artifact_id" => generate_artifact_id(),
203-
"type" => "journal_excerpt",
203+
"type" => "log",
204+
"path" => "journal/#{unit_name}.log",
204205
"label" => "Journal entries for #{unit_name}",
205206
"line_count" => length(results[:journal] || [])
206207
} | artifacts]
@@ -212,7 +213,8 @@ defmodule ServiceAutopsy.Collector do
212213
if results[:coredump] != [] do
213214
[%{
214215
"artifact_id" => generate_artifact_id(),
215-
"type" => "coredump_listing",
216+
"type" => "report",
217+
"path" => "coredumps/#{unit_name}.report",
216218
"label" => "Coredumps for #{unit_name}",
217219
"entry_count" => length(results[:coredump] || [])
218220
} | artifacts]
@@ -224,7 +226,8 @@ defmodule ServiceAutopsy.Collector do
224226
if results[:unit_file] != nil do
225227
[%{
226228
"artifact_id" => generate_artifact_id(),
227-
"type" => "unit_file",
229+
"type" => "config",
230+
"path" => "units/#{unit_name}",
228231
"label" => "Unit file for #{unit_name}"
229232
} | artifacts]
230233
else
@@ -321,10 +324,22 @@ defmodule ServiceAutopsy.Collector do
321324
end
322325

323326
defp generate_envelope_id do
324-
"autopsy-" <> (:crypto.strong_rand_bytes(8) |> Base.url_encode64(padding: false))
327+
generate_uuid()
325328
end
326329

327330
defp generate_artifact_id do
328-
"art-" <> (:crypto.strong_rand_bytes(6) |> Base.url_encode64(padding: false))
331+
generate_uuid()
332+
end
333+
334+
# Generate a RFC 4122 v4 UUID from random bytes.
335+
defp generate_uuid do
336+
<<a::48, _::4, b::12, _::2, c::62>> = :crypto.strong_rand_bytes(16)
337+
<<a::48, 4::4, b::12, 2::2, c::62>>
338+
|> Base.encode16(case: :lower)
339+
|> format_uuid_hex()
340+
end
341+
342+
defp format_uuid_hex(<<a::binary-8, b::binary-4, c::binary-4, d::binary-4, e::binary-12>>) do
343+
"#{a}-#{b}-#{c}-#{d}-#{e}"
329344
end
330345
end

0 commit comments

Comments
 (0)