Files
alkhttp/tasks/adapters/review-002-fwd16-missing-capability.md
T

3.2 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
review-002-fwd16-missing-capability Loud error on missing capability instead of silent unauthenticated request (FWD-16) completed
narrow low component implementation
adapters
review-002
security
from-openapi

Description

Review 002 FWD-16 [major]. The FWD-08 remediation made every malformed credential fail loudly, but the missing-capability arm stays silent: forward.rs:200-238

if let Some(scheme) = auth_scheme {
    if let Some(secret) = context.capabilities.get(namespace) {
        // ... four loud arms for malformed names/values
    }
    // capability == None → falls through: the request is sent
    // with NO credential and NO diagnostic
}

Capabilities::get keys on api_key:/http_token: prefixes (alkcall core/types.rs:97-107), so an assembly layer that registered the secret under a wrong key form (or forgot) produces corrupted upstream 401s at call time with zero local diagnostics. This is the most probable misconfiguration shape and the one inconsistent arm in an otherwise-loud match — every other arm was made loud by review-001's FWD-08 fix (tested at forward.rs:1646-1736).

Acceptance Criteria

  • When auth_scheme.is_some() and the capability is absent, the request is NOT sent; the caller gets an INTERNAL-family error naming the missing capability key (e.g. "capability http_token:{namespace} is absent; refusing to send the request unauthenticated") — message contains no secret material
  • When auth_scheme.is_none() the behavior is unchanged (unauthenticated ops stay unauthenticated)
  • Wire test: authed op, empty capabilities → error envelope (and the test asserts via the existing spawn_responder-style seam that the upstream received zero requests)
  • Existing FWD-08 loud-arm tests unchanged and passing
  • Doc note in the module doc: the loud-missing matrix now covers malformed name/value AND absent capability
  • cargo test, cargo clippy --all-targets -- -D warnings, cargo fmt --check pass

References

  • docs/reviews/002-post-remediation-review.md (Part D', FWD-16)
  • src/adapters/forward.rs:200-238 (the silent arm), :1646-1736 (the FWD-08 test family to mirror)
  • docs/architecture/decisions/014-secret-material-flow-and-capability-injection.md
  • tasks/adapters/review-001-forward-url-safety.md (FWD-08's loud-error work this completes)

Notes

Error class choice: INTERNAL (misconfiguration, not caller fault) — matches the FWD-08 precedent. Non-retryable, since re-sending cannot succeed without the assembly layer changing. If a deployment legitimately runs authed-ops with optionally-present credentials (none known today), that would be a new config flag — do not preemptively add one; the invariant (ADR-014: credentials flow only via Capabilities) argues loud-and-closed.

Summary

Silent missing-capability arm now fails with INTERNAL naming both key forms (api_key:/http_token:) and refusing the unauthenticated send; module doc loud-missing-matrix paragraph; 3 tests incl. a zero-upstream-requests wire test. Two pre-existing no-env-vars tests updated (they pinned the silent arm).