Skip to main content

Security

Solutions run inside a hard security envelope. The eight platform rules are not guidelines — they are architectural properties enforced at publish time, install time and render time.

The rules and their enforcement

RuleEnforcement
No arbitrary JavaScriptPackages contain YAML, JSON and images only; script/js file kinds are rejected at publish; the portal never evaluates package content
No direct DOM accessThere is no package-side runtime in the browser — the portal's own components render everything
No iframe executionSolution UIs are rendered natively; the renderer contains no iframe host and iframe assets are rejected
No direct database accessSolutions have no database handles; persistence happens only through the runtime and connector bridge
No direct Redis accessCaching infrastructure is platform-internal; no capability exposes it
No direct network accessThe only outbound paths are capability-gated source fetches and workflow tool calls, both mediated by the platform
Capability mediation is mandatoryEvery host interaction is negotiated at install and re-checked on every call — see Capabilities
Event-driven communication is mandatoryAll signaling rides the platform event bus; there is no side channel — see Events

Supply chain

  1. Signing. Every package is Ed25519-signed over id|version|checksum; the registry verifies the signature before storing, and the installer re-verifies before activating. See Packaging.
  2. Immutability. Published versions cannot change; tenants are never surprised by content drift. See Publishing.
  3. Publisher attribution. Packages carry publisher_id and signature_kid, so every installed version traces to a publisher and a verification key. Catalog writes (publish / yank) are restricted to platform admins (QEFRO_PLATFORM_ADMIN_IDS).

Tenant isolation

  • Installations, settings, granted capabilities, workflow executions and UI events are stored tenant-scoped; every query filters by tenant.
  • Connector containers are a shared pool, but every routed call carries the tenant context and credentials are fetched per-tenant from the secret manager.
  • UI bundles are served per installation; one tenant's bundle is never visible to another.

See Tenant isolation.

Secrets

  • Connector credentials are collected at install time, encrypted with AES-256-GCM at rest, and cached with tenant-prefixed keys.
  • Plaintext credentials are never logged or audited.
  • Packages and workflows never see credentials — the platform injects them at the bridge.

See Secrets.

Render-time containment

Even a malformed definition cannot take down the portal:

  • Error boundaries isolate every page and widget; failures degrade to a scoped error card and emit ui.error.
  • Schema coercion normalizes degenerate shapes before render; spans and columns are clamped.
  • Capability gates mean a widget missing its capability never fires a request at all.

Design checklist for publishers

  • Declare the fewest capabilities and permissions that work; the install wizard shows tenants exactly what you asked for.
  • Keep sensitive business logic in connectors and workflows, not in widget payloads.
  • Never encode tenant-specific values, URLs or credentials in package files — they are global, signed and public within the registry.
  • Treat a permission escalation (adding customer.read, new connectors) as a major-version event and communicate it in your README.