Skip to content

GA audit follow-ups: non-blocker High/Medium/Low findings (API/CLI/MCP/SDK/DX) #496

Description

@cyj-git-0825

Follow-up to the GA-readiness audit in #493. These are the High/Medium/Low findings that are not GA-critical blockers (no data-loss/security-boundary/breaking-contract issue) and were intentionally kept out of the focused blocker PRs. All are additive / non-breaking — safe to land before or after the v1 freeze. Verified on main @ b43bad44.

The two headline pre-GA items are tracked separately:

API

  • Non-uniform filtering/sorting across collections. Rich on listMessages/listEvents; listAgents/listDomains/listWebhooks/listTemplates are cursor+limit only. Real large-tenant usability gap (add optional query params — additive).
  • Enumerate 401/403/404 per authenticated operation (currently only the catch-all default); broaden explicit 400s.
  • Location header on 202 send/reply/forward responses.
  • Product decision: keep the custom error envelope or adopt literal RFC 7807 (application/problem+json + type/title) — document either way.

CLI

  • listen --once --forward exits 0 even when the forward POST fails — a blocking harness can't detect delivery failure (set process.exitCode = ERROR).
  • No automated coverage for the top-level error→exit-code mapping (main()'s catch is gated behind isTestImport) or the listen TIMEOUT(6)/premature-close→ERROR(1) paths — frozen-contract regression protection.

MCP

  • Dead agentIds filter type in client.ts createWebhook/updateWebhook (wire field is agentEmails; masked by an as cast) — a future refactor populating it per the declared type would silently drop the filter. Retype to agentEmails.

SDK (Python)

  • Webhook/WS TypeGuards don't narrow — event.data stays Any, so the Email*Data/Domain*Data TypedDicts are unreachable (TS narrows genuinely). Biggest cross-SDK inconsistency.
  • AsyncE2AClient.listen() annotated -> Any vs -> WSStream in TS.
  • Retry ignores an HTTP-date Retry-After (seconds-only); TS honors both.
  • from_api_exception can leak raw response body/headers into .message when the envelope is unparseable and reason is empty; TS avoids this.
  • Align bounce_type/source to Literal[...] (plain str today); type the sync facade (__getattr__ -> Any).

Webhooks

  • Delivery record next_retry_at is not advanced as River reschedules (stays at the initial value while the real next attempt moves forward) — polling clients see a stale timestamp.

Repo / DX

  • Add a .gitattributes pinning api/openapi.yaml and the generated SDK dirs to eol=lf. On Windows (core.autocrlf=true) the LF-committed golden files check out as CRLF, so spec-check/generate-sdk-check/TestSpecGoldenNoDrift false-fail locally and a contributor can accidentally commit CRLF. Pinning eol=lf hardens the "handler is the spec" gate off the CI-only Linux path.
  • CLAUDE.md is stale on the module path — it says github.com/Mnexa-AI/e2a, but the Go module was renamed to github.com/tokencanopy/e2a (commit 4b4beea6). (GitHub org/remote is unchanged.)

Full re-test evidence: AgentDrive audits/e2a-ga/retest-latest-b43bad44.md (see the supplement comment on #493).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions