Skip to content

feat: add E2EE transport preflight - #392

Closed
Lokesh7025 wants to merge 8 commits into
Observal:mainfrom
Lokesh7025:feature/e2ee-transport
Closed

feat: add E2EE transport preflight#392
Lokesh7025 wants to merge 8 commits into
Observal:mainfrom
Lokesh7025:feature/e2ee-transport

Conversation

@Lokesh7025

@Lokesh7025 Lokesh7025 commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Purpose

Establish the reviewed transport-first boundary for Axl remote control without implementing or enabling production cryptography. This gives the repository a separately deployable TypeScript control plane, an Elixir/OTP opaque WebSocket relay, language-neutral framing fixtures, and an explicit authorization design for future remote permission responses.

Approach

  • Record PQXDH plus Triple Ratchet as the approved direction while leaving every cryptographic encoding, algorithm, state transaction, and interoperability vector to Person 1's reviewed library.
  • Add dependency-free remote transport schemas, nominal identifiers, fixed limits, stable receipt/failure semantics, and exact TypeScript/Elixir byte fixtures in packages/protocol.
  • Revise transport-v1 framing to use the WebSocket message boundary as the payload boundary. There is no duplicate attacker-controlled inner payload length.
  • Add services/control-plane/ with injected authentication, authorization, clock, proof-verification, and persistence boundaries; SHA-256 ticket storage; and atomic one-use ticket consumption.
  • Add services/relay/ with Bandit/WebSock admission, fail-closed control-plane calls, installation-scoped in-memory routing, bounded queued bytes, rate limits, heartbeats, lease expiry, revocation, draining, and compression disabled.
  • Define forwarded as enqueue into the destination WebSocket process after route and queue checks. It does not imply a network write, endpoint receipt, decryption, or daemon acceptance.
  • Keep production service authentication unselected. The architecture recommends short-lived mTLS workload identities, or audience-bound cloud workload tokens when the deployment platform provides them. Static long-lived bearer secrets are explicitly rejected as the production design.
  • Draft the daemon-owned remote permission contract in docs/architecture/remote-permission-authorization.md. Initial remote decisions are limited to allow_once and deny for already-pending sandboxed tool actions within the current policy ceiling. This draft does not enable remote approval.

Security impact:

  • The relay never decrypts payloads, imports daemon RPC behavior, reads the control-plane datastore, owns canonical history, or stores attachment bodies.
  • Tickets and service credentials are excluded from URLs and safe errors.
  • Cryptographic authentication will identify a sender but will not authorize a daemon command.
  • Ordinary-session remote access remains disabled pending Person 1's library and independent review.

Architecture review resolutions

  • Added role-filtered route snapshots and updates. Devices discover only the daemon; the daemon sees authorized device routes.
  • Enforced strict device -> daemon and daemon -> device topology. Newer same-identity connections replace older routes.
  • Added monotonic inbound liveness tracking with 20-second pings and a 60-second inbound-idle close.
  • Added 512 KiB queue saturation tracking, a 256 KiB recovery threshold, and 10-second slow_consumer eviction.
  • Bound tickets and active routes to hosted grant generations. Tickets issued before revocation now fail consumption, and stale routes cannot reconnect.
  • Updated protocol fixtures and documentation to match the implemented semantics.

How was this tested?

Passed:

  • pnpm build
  • pnpm format:check
  • pnpm lint
  • pnpm typecheck
  • pnpm check:boundaries
  • pnpm check:generated
  • node --test scripts/check-generated.test.ts scripts/check-boundaries.test.ts
  • pnpm --filter @axl/protocol test (44 passed)
  • pnpm --filter @axl/control-plane test (4 passed)
  • mix format --check-formatted
  • mix compile --warnings-as-errors
  • mix test (12 passed)
  • mix credo --strict
  • mix dialyzer
  • mix deps.audit
  • pnpm audit --audit-level high
  • reuse lint
  • node scripts/check-dco.ts 57bd31b7e718a125fc51a0fcf3a554cb100ea708 HEAD
  • GitHub CI after rebasing onto current main: TypeScript build/test, relay build/test, workflow lint, CodeQL, REUSE, DCO, dependency review, lockfile audit, and Gitleaks all passed

The full pnpm test run completed 835 tests successfully, skipped 8 platform tests, and timed out in the existing unchanged TUI case editing, /quit, and busy notices behave. A focused rerun of that unchanged TUI test also timed out. This change does not modify TUI code.

actionlint could not run locally because Go is not installed. The pinned workflow-lint CI job passed on this PR.

Learning

One binary WebSocket message already provides an authenticated transport message boundary at the relay layer. Removing a duplicate inner payload-length field simplifies both parsers and removes an unnecessary inconsistent-length input. Exact cross-language fixtures remain the compatibility authority.

Cowboy was evaluated first, but its resolved dependency set reported active security advisories. The relay uses the audited Bandit/WebSock path instead.

Checklist

  • I reviewed the complete diff.
  • I added or updated the smallest relevant test for behavior changes.
  • I ran the relevant formatting, lint, type-check, test, boundary, and license checks.
  • Every new file has SPDX metadata, directly or through REUSE.toml.
  • Every commit has a matching DCO Signed-off-by trailer.
  • UI changes include screenshots attached to the pull request, not committed to the repository. (N/A: no UI changes.)

Licenses

Resource Source and version License Use
Bandit Hex 1.12.5 MIT Relay HTTP/WebSocket server
Plug Hex 1.20.3 Apache-2.0 Relay HTTP boundary
WebSock Adapter Hex 0.6.0 MIT WebSocket upgrade adapter
Credo Hex 1.7.12 MIT Development-only static analysis
Dialyxir Hex 1.4.6 Apache-2.0 Development-only type analysis
mix_audit Hex 2.1.5 BSD-3-Clause Development-only dependency audit

AI assistance

  • Generative AI materially assisted this change. Tool and model/version: pi coding agent with Azure OpenAI gpt-5.6-sol.
  • I manually reviewed, understood, and tested the generated work.

Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
@Lokesh7025
Lokesh7025 force-pushed the feature/e2ee-transport branch from e665fba to 6ea73a0 Compare September 12, 2026 17:07
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
Signed-off-by: Lokesh <lokeshselvam7025@gmail.com>
@Lokesh7025
Lokesh7025 marked this pull request as ready for review September 13, 2026 08:24
@Lokesh7025

Copy link
Copy Markdown
Contributor Author

Integrated into the shared RC branch via signed merge commit 24e776d3247b8aa5c5c13e41d3d1d608fcec2d2c. The forthcoming RC -> main PR supersedes this checkpoint PR and preserves its full history.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant