feat(broker): wire session attribution into commit attestation
Merged
KH
3mo ago+548+548+012345678901234567890123456789-5-5-0123456789
Summary
- Adds
session_ref: Option<String>toCommitAttestation(wire key:sessionRef) so git commits stamped by spawned agents carry aSession-Id:trailer linking the commit to the session that produced it - Updates
with_commit_attestation_env()to injectRELAY_ATTEST_SESSION_IDwhensession_refis present and valid; strips any stale inherited value before re-injecting so child agents cannot inherit an ancestor's session - Updates the embedded
prepare-commit-msghook to stampSession-Id: $RELAY_ATTEST_SESSION_IDinside the existing attestation block - Fixes
broker_payload_from_action(bridge.rs): usesfind_mapacross four key aliases in priority order —session_ref→sessionRef→session_id→sessionId— matching the canonical fleet on-wire format used byrelaycast_spawn_session_ref; blank/whitespace values are skipped so they cannot suppress a valid later alias
Why
relayauth#79 covers the ledger half of the attribution chain. This closes the spawner half:
commit → attestation ledger → OIDC-bound human → session → reasoning
↑
Session-Id trailer (this PR)
Without this, sessionRef stays null in the ledger even after relayauth#79 merges, because relay's spawner never injects the session into the commit environment.
What's out of scope
- relayauth: ledger side already handled by relayauth#79
- factory:
POST /v1/attestations/grantsneeds to forwardsessionReffrom the spawn spec to relayauth — separate, smaller change, noted for Chief routing
Test plan
-
broker_hook_appends_session_id_trailer_when_session_ref_present— end-to-end: realgit committhrough a spawned agent carriesSession-Id:trailer -
session_ref_in_attestation_is_injected_as_relay_attest_session_id -
absent_session_ref_does_not_inject_session_id_env_var— backward-compatible: existing attestations without session_ref are unaffected -
invalid_session_ref_is_silently_skipped— control chars / empty strings skipped -
stale_session_id_is_stripped_when_attestation_has_no_session_ref— child cannot inherit ancestor session -
valid_session_ref_overwrites_stale_session_id— re-injection replaces stale value -
bridges_top_level_session_ref_canonical_key— fleet canonicalsession_refkey bridges correctly -
bridges_top_level_session_ref_camel_case_alias— fleetsessionRefcamelCase alias bridges correctly -
blank_session_ref_falls_through_to_valid_session_ref_alias— blank value does not suppress valid alias -
blank_session_id_falls_through_to_valid_session_id_alias— whitespace-only value does not suppress valid alias -
bridges_top_level_session_id_into_attestation_session_ref— legacysession_idkey still works -
bridges_top_level_session_id_camel_case_alias— legacysessionIdcamelCase alias still works -
session_id_without_attestation_is_silently_ignored— un-attested spawns unaffected -
explicit_attestation_session_ref_wins_over_top_level_session_id— no overwrite if already set - Full broker suite: 897 passed, 0 failed (CI green on
e4fe62483)
Known pre-existing issue (not caused by this PR)
runtime::tests::delivery_retry_transient_blip_emits_failed_event_for_present_worker occasionally fails under heavy local parallel test load. It does not fail in CI (passes on both main and this branch), passes cleanly when run in isolation, and runtime/tests.rs was last touched three commits before this branch diverged. Not a blocker.
🤖 Generated with Claude Code