uptrakit

Shared Surface Security

Shared Surface Security

Overview

Shared surfaces let plugins and connected services project UI capabilities through the controller. Security is enforced by a fail-closed contract admission model plus per-request authorization and transport controls.

Permission model

Permissions are evaluated at two levels:

  • descriptor-level: SurfaceDescriptor.required_permission
  • interaction-level: InteractionDescriptor.required_permission

Enforcement points:

  • GET /api/v1/surfaces — only tenant-visible surfaces are listed
  • GET /api/v1/surfaces/{surface_id}/read — descriptor permission check
  • POST /api/v1/surfaces/{surface_id}/interactions/{interaction_id} — descriptor and interaction permission checks

Frontend filtering is convenience only; server checks are authoritative.

Registration admission controls

Service and plugin providers are admitted through SurfaceRegistry with strict validation:

  • framework generation compatibility (supported_generation)
  • required capability coverage
  • slot ID validation against central slot registry
  • provider-kind/transport compatibility
  • tenant-binding correctness for authenticated service context
  • allowlist checks for controller queries, SSE topics, and direct built-in operations
  • contract shape and depth limits
  • payload and interaction count limits

Invalid registrations are rejected with structured rejection reasons.

Targeting and tenancy controls

Targeted surfaces require explicit target_provider_id at invocation time. Provider resolution is tenant-aware; cross-tenant providers are excluded from availability and dispatch.

For service providers:

  • tenant services must register tenant-scoped bindings matching authenticated tenant
  • system services must register global scope with no tenant binding

Sensitive parameter handling

Sensitive interaction values are not sent in plaintext params. Clients send encrypted_sensitive_params (ECIES P-256 metadata + ciphertext payload).

Controller behavior:

  • validates presence/shape requirements
  • forwards ciphertext opaquely to provider
  • never decrypts sensitive payloads

Provider behavior:

  • publishes encryption metadata in provider info
  • decrypts payload locally using provider private key

Action execution controls

Invocation path is mediated by SurfaceProxy:

  • idempotency key handling (duplicate_request protection)
  • per-request timeout handling
  • provider disconnect and unavailability handling
  • typed error-code mapping for caller-safe failure semantics

Capability gating

UI/surface runtime participation is gated on protocol capability negotiation. Incompatible providers are excluded from the active surface catalog; their registrations are rejected at admission time rather than silently degrading runtime behavior.

Trust boundaries

  • Browser never talks directly to services for surface actions.
  • Service-to-controller calls are authenticated over mTLS WebSocket.
  • Controller mediates all provider selection and dispatch.
  • NATS is not used for session-targeted surface action payload delivery.

Key files

FilePurpose
crates/shared/surfaces/src/Shared surface contract and validation policy types
crates/shared/wire/src/wire_validate_impls.rsWire-level payload validation
crates/ui/web-api/src/surface_registry.rsRegistration admission and tenant/provider indexing
crates/ui/surface-proxy/src/proxy.rsInvocation correlation, idempotency, timeout, and routing
crates/ui/web-api/src/routes/surfaces.rsAuthz enforcement and API error mapping
crates/ui/web-api/src/routes/service_ws/handler/mod.rsService message handling for surface registration and actions

See also