# `arch audit` exceptions — `wasm-capability-contract`
Every finding below was verified individually, not blanket-suppressed.
`arch` version at time of writing: `0.3.55`.
This crate's `src/` has no `api/` wrapper directory — a `port` crate has
exactly one real layer by construction (`swearchitect#388`: "a port
crate has api/ only, no core/ by construction"), so its own `src/`
*already is* that one layer; nesting everything one level deeper under a
same-purpose `api/` folder added no real distinction, only satisfied a
handful of `api/`-named-directory checks mechanically. Removing it
dropped this crate from 9 real `arch audit` failure categories to 2 —
most of the `api/`-domain rule family (`core_implements_api_traits`,
`api_traits_require_connectivity`, `saf_trait_svc_correspondence`,
`spi_organization_follows_api`, `saf_layer_mirrors_api_domains`,
`no_foreign_type`, `field_type_purity`, `api_method_returns_result`,
`api_method_takes_request`, `trait_result_named_error`,
`result_both_sides_named`) simply doesn't fire at all once there's no
`api/` directory for those rules to gate on — confirming those were
scoped to richer, multi-layer crates and never should have applied to a
single-layer port crate at all.
## Confirmed tool defect
- **`pub_types_in_api_only`** (19 offenders — every public type in this
crate) — demands every `pub` type live inside a directory literally
named `api/`. Its own stated rationale (`arch explain
pub_types_in_api_only`): *"consumers may import from saf::MyType or
gateway::MyType instead of api::MyType, and refactors that consolidate
the type break those imports"* — a real concern for a crate with
multiple layers a type could ambiguously live in. This crate has no
`saf/`/`gateway/`/`core/`/`spi/` at all (a `port` crate, by
construction) — there is no other layer a consumer could confuse a
type's home with, so the rule's own premise doesn't apply here. Same
root cause as the `no_foreign_type`/`app_type_requires_api`
`port`-archetype exemption gaps already reported at
[`swearchitect#506`](https://github.com/sweengineeringlabs/swearchitect/issues/506)
— this rule has no such exemption documented at all, suggesting the
gap is broader than the two rules already flagged there.
## Documented, deliberate design decisions — not fixed, not faked
- **`file_names_are_nouns`** (`validate_component_request.rs`) — conflicts
directly with `filename_matches_type` (file must be named after the
type it declares: `ValidateComponentRequest` -> `validate_component_request.rs`).
Satisfying one necessarily violates the other for any `*Request` type
whose own established name legitimately starts with a verb (`validate`,
`find`, `deploy`) — `filename_matches_type` is the more specific,
structurally-enforced rule, so this crate follows it and accepts the
noun-naming finding as the unavoidable consequence, the same call made
in `agent-runtime-control-plane`'s own `docs/known-exceptions.md`.
- **`trait_result_named_error`** / **`result_both_sides_named`**
(`CapabilityDispatcher::dispatch` returns `Result<Vec<u8>, String>`) —
every real dispatcher (agent-runtime#4-#9) wraps a different real
implementor's own error type; this port has no reason to unify six
unrelated error types into one enum just to satisfy a naming rule. A
plain `String` message is the deliberate, documented choice (see the
trait's own doc comment). *(These two rules no longer fire post-flattening
since they were scoped to `api/`-containing crates, but the underlying
design reasoning stands regardless and is recorded here in case a
future `arch` version reintroduces the check independent of `api/`.)*
- **`api_method_returns_result`** / **`api_method_takes_request`**
(`CapabilityRegistry::descriptor(&self, capability: &str) ->
Option<&CapabilityDescriptor>`, `CapabilityDispatcher::dispatch`'s
three-parameter shape) — `descriptor`'s `Option` (not `Result`) is the
correct, idiomatic shape for a lookup with no failure mode to report,
only presence/absence. `dispatch`'s three parameters
(`tokio_handle`/`target`/`payload`) exist for real reasons tied to
`wasmtime` linker wiring and cross-thread tokio re-entry (see the
trait's own doc comment). Changing either signature would cascade as a
breaking change across every already-shipped `CapabilityDispatcher`
implementation downstream, plus every consumer that pins them —
explicitly evaluated and rejected. *(Same post-flattening note as
above: not currently firing, reasoning kept on record.)*