ecrecover needs an EOA key). So if your agents are contracts / headless / mass-onboarded → only (a) works. If they're all wallets (EOAs) → either works, (b) is simpler to ship.registerExternalAuxSigner(agent, key)).primaryMachineConsentHelperAddress) calls setAttestation as the MCH; the auto-runner auto-signs the agent's consent.Agents need no gas, no key, no interaction. Mass / headless onboarding, fully automated. This is the "generalized trust channel" UX.
Nothing — works for contract agents AND wallets.
setAttestation / signs its own consent (direct path, line 254).Every agent must be a funded, transacting, signing wallet, self-onboarding one at a time. No operator automation of consent.
Contract agents — entirely. They can't self-consent. Also: no headless/mass onboarding; not automatable.
One thin RMT-layer contract. Per Codex: the current MachineConsentHelper is a pure registry (no setAttestation forwarder), so the new controlling contract must be set as primaryMachineConsentHelperAddress and forward the setAttestation/consent calls (so msg.sender == the MCH) while implementing the aux-signer registry interface. Plus the off-chain auto-runner that holds aux-signer keys. Shyft core stays untouched. It goes through the same CODE_REVIEW + AUDIT gate as everything else.
Codex flagged a guard at Attestations.sol:234 (consent runs only when userSignatureRS[0] != 0) that looks inverted for fresh consent. Our attest-infra proof test already drives a real attestation → citation successfully, so the path works as-deployed — but I'll confirm the exact line-234 semantics before shipping (a). No core change implied — just verification.