[pitboss] sweep after phase 03: 3 deferred items resolved

This commit is contained in:
pitboss 2026-05-14 03:45:51 -05:00
parent 364d09d6a8
commit 3b660ba1d3
11 changed files with 131 additions and 33 deletions

View file

@ -20,7 +20,7 @@
//! Payload slot support:
//! - `PayloadSlot::Param(0)` — pass payload as `string` first argument.
//! - `PayloadSlot::EnvVar(name)` — set env var before calling entry.
//! - Other slots produce `UnsupportedReason::EntryKindUnsupported`.
//! - Other slots produce `UnsupportedReason::PayloadSlotUnsupported`.
//!
//! Build container: `nyx-build-go:{toolchain_id}` (deferred; §19.1).
@ -57,7 +57,7 @@ impl LangEmitter for GoEmitter {
pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
match &spec.payload_slot {
PayloadSlot::Param(0) | PayloadSlot::EnvVar(_) => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let main_go = generate_main_go(spec);
@ -218,14 +218,14 @@ mod tests {
fn emit_param_gt_0_is_unsupported() {
let spec = make_spec(PayloadSlot::Param(1));
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]
fn emit_stdin_is_unsupported() {
let spec = make_spec(PayloadSlot::Stdin);
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]

View file

@ -22,7 +22,7 @@
//! Payload slot support:
//! - `PayloadSlot::Param(0)` — pass payload as `String` first argument.
//! - `PayloadSlot::EnvVar(name)` — set system property before calling entry.
//! - Other slots produce `UnsupportedReason::EntryKindUnsupported`.
//! - Other slots produce `UnsupportedReason::PayloadSlotUnsupported`.
//!
//! Build container: `nyx-build-java:{toolchain_id}` (deferred; §19.1).
@ -59,7 +59,7 @@ impl LangEmitter for JavaEmitter {
pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
match &spec.payload_slot {
PayloadSlot::Param(0) | PayloadSlot::EnvVar(_) => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let source = generate_harness_java(spec);
@ -197,14 +197,14 @@ mod tests {
fn emit_param_gt_0_is_unsupported() {
let spec = make_spec(PayloadSlot::Param(1));
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]
fn emit_stdin_is_unsupported() {
let spec = make_spec(PayloadSlot::Stdin);
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]

View file

@ -14,7 +14,7 @@
//! - `PayloadSlot::Param(n)` — n-th positional argument.
//! - `PayloadSlot::EnvVar(name)` — set env var before calling.
//! - `PayloadSlot::Stdin` — pipe payload to process.stdin.
//! - Other slots produce `UnsupportedReason::EntryKindUnsupported`.
//! - Other slots produce `UnsupportedReason::PayloadSlotUnsupported`.
//!
//! Build: no compilation step. Command is `node harness.js`.
//! Build container: `nyx-build-node:{toolchain_id}` (deferred; §19.1).
@ -53,7 +53,7 @@ impl LangEmitter for JavaScriptEmitter {
pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
match &spec.payload_slot {
PayloadSlot::Param(_) | PayloadSlot::EnvVar(_) | PayloadSlot::Stdin => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let source = generate_source(spec);
@ -246,7 +246,7 @@ mod tests {
fn emit_http_body_is_unsupported() {
let spec = make_spec(PayloadSlot::HttpBody);
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]

View file

@ -13,7 +13,7 @@
//! - `PayloadSlot::Param(n)` — n-th positional argument.
//! - `PayloadSlot::EnvVar(name)` — set `$_ENV`/`putenv()` before calling.
//! - `PayloadSlot::Stdin` — wrap `STDIN` with the payload.
//! - Other slots produce `UnsupportedReason::EntryKindUnsupported`.
//! - Other slots produce `UnsupportedReason::PayloadSlotUnsupported`.
//!
//! Build: no compilation step. Command is `php harness.php`.
//! Build container: `nyx-build-php:{toolchain_id}` (deferred; §19.1).
@ -51,7 +51,7 @@ impl LangEmitter for PhpEmitter {
pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
match &spec.payload_slot {
PayloadSlot::Param(_) | PayloadSlot::EnvVar(_) | PayloadSlot::Stdin => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let source = generate_source(spec);
@ -208,7 +208,7 @@ mod tests {
fn emit_http_body_is_unsupported() {
let spec = make_spec(PayloadSlot::HttpBody);
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]

View file

@ -11,7 +11,7 @@
//! Payload slot support:
//! - `PayloadSlot::Param(n)` — n-th positional argument.
//! - `PayloadSlot::EnvVar(name)` — set env var before calling.
//! - Other slots produce `UnsupportedReason::EntryKindUnsupported`.
//! - Other slots produce `UnsupportedReason::PayloadSlotUnsupported`.
use crate::dynamic::lang::{HarnessSource, LangEmitter};
use crate::dynamic::spec::{EntryKind, HarnessSpec, PayloadSlot};
@ -47,7 +47,7 @@ pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
// Validate payload slot.
match &spec.payload_slot {
PayloadSlot::Param(_) | PayloadSlot::EnvVar(_) | PayloadSlot::Stdin => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let source = generate_source(spec);

View file

@ -16,7 +16,7 @@
//! - `PayloadSlot::Param(0)` — pass payload as `&str` first argument.
//! - `PayloadSlot::EnvVar(name)` — set env var before calling entry.
//! - All other slots (`Stdin`, `Param(n>0)`, `QueryParam`, `HttpBody`, `Argv`)
//! produce `UnsupportedReason::EntryKindUnsupported`. Stdin piping into the
//! produce `UnsupportedReason::PayloadSlotUnsupported`. Stdin piping into the
//! generated harness is not yet wired (deferred).
//!
//! HTML_ESCAPE is n/a for Rust (§15.4).
@ -55,7 +55,7 @@ impl LangEmitter for RustEmitter {
pub fn emit(spec: &HarnessSpec) -> Result<HarnessSource, UnsupportedReason> {
match &spec.payload_slot {
PayloadSlot::Param(0) | PayloadSlot::EnvVar(_) => {}
_ => return Err(UnsupportedReason::EntryKindUnsupported),
_ => return Err(UnsupportedReason::PayloadSlotUnsupported),
}
let cargo_toml = generate_cargo_toml(spec.expected_cap);
@ -262,7 +262,7 @@ mod tests {
fn emit_param_gt_0_is_unsupported() {
let spec = make_spec(PayloadSlot::Param(1));
let err = emit(&spec).unwrap_err();
assert_eq!(err, UnsupportedReason::EntryKindUnsupported);
assert_eq!(err, UnsupportedReason::PayloadSlotUnsupported);
}
#[test]

View file

@ -567,24 +567,28 @@ fn build_verdict(
toolchain_match: None,
},
Err(RunError::Harness(e)) => {
// EntryKindUnsupported coming back from the lang emitter is
// promoted to a structured `Inconclusive(EntryKindUnsupported)`
// verdict so the operator sees the supported list + hint, not a
// bare `Unsupported`. The pre-flight gate in `verify_finding`
// catches the common case (entry_kind decided by spec
// derivation); this arm covers the residual where an emitter
// rejects a payload-slot / shape combination internally.
// Defence-in-depth residual for `EntryKindUnsupported` from the
// lang dispatcher. Promote to `Inconclusive(EntryKindUnsupported)`
// so the operator sees the supported list + hint, but only when
// the spec's entry kind is genuinely outside the supported list —
// otherwise the pre-flight gate already handled it (or a stray
// emitter mis-tagged a payload-slot rejection, which now uses
// `PayloadSlotUnsupported` and falls through to the generic
// `Unsupported(reason)` arm below).
if let crate::dynamic::harness::HarnessError::Unsupported(
UnsupportedReason::EntryKindUnsupported,
) = &e
{
return entry_kind_unsupported_verdict(
finding_id.to_owned(),
None,
&spec.entry_file,
spec.lang,
spec.entry_kind,
);
let supported = crate::dynamic::lang::entry_kinds_supported(spec.lang);
if !supported.contains(&spec.entry_kind) {
return entry_kind_unsupported_verdict(
finding_id.to_owned(),
None,
&spec.entry_file,
spec.lang,
spec.entry_kind,
);
}
}
// Typed `Unsupported(reason)` carries its semantics in `reason`; the
// free-form `detail` is reserved for `Inconclusive`/unexpected paths

View file

@ -172,6 +172,11 @@ pub enum UnsupportedReason {
/// The entry kind (e.g. `HttpRoute`, `CliSubcommand`) is not yet supported;
/// only `EntryKind::Function` is driven in current milestones.
EntryKindUnsupported,
/// The lang emitter does not yet support the spec's [`crate::dynamic::spec::PayloadSlot`]
/// shape (e.g. `PayloadSlot::Param(n>0)` on Rust, `PayloadSlot::HttpBody`
/// on JavaScript). Distinct from [`UnsupportedReason::EntryKindUnsupported`]:
/// the entry kind is driveable, only the payload-injection slot is not.
PayloadSlotUnsupported,
/// Finding confidence is below `Medium`; dynamic verification is not
/// attempted for low-confidence findings to avoid noise.
ConfidenceTooLow,

View file

@ -502,6 +502,7 @@ fn format_unsupported_reason(r: &crate::evidence::UnsupportedReason) -> String {
match r {
UnsupportedReason::BackendUnavailable => "backend unavailable".to_string(),
UnsupportedReason::EntryKindUnsupported => "entry kind not supported".to_string(),
UnsupportedReason::PayloadSlotUnsupported => "payload slot not supported".to_string(),
UnsupportedReason::ConfidenceTooLow => "confidence too low".to_string(),
UnsupportedReason::NoFlowSteps => "no flow steps".to_string(),
UnsupportedReason::NoPayloadsForCap => "no payloads for cap".to_string(),