Skip to content

7.7.1

Latest

Choose a tag to compare

@thekevinm thekevinm released this 24 Sep 21:29

Overview

DreamFactory v7.7.1 is a security-and-correctness release with one major component update. The database ?filter= pipeline gets a full sweep — filter values are now bound as query parameters (SQL-injection hardening), bare AND/OR filters parse correctly instead of silently matching nothing, BETWEEN works, and DELETE/PATCH-by-filter on system resources no longer 500s. The MCP Server jumps to 1.4.0 with lazy mode, merged tool styles, Exposed Services scoping, opt-in API-key auth, and a round of OAuth/daemon hardening. The release also adds platform-wide access-usage auditing, outbound OAuth2 for Remote Web Services, fixes an RBAC bypass in the AMQP/MQTT subscribe consumers, brings the single-connector editions onto the Laravel 13 stack they missed in 7.7.0, and open-sources the System API MCP daemon (df-system-mcp-server, Apache-2.0), now included in every full edition.

New Features

MCP Server (df-mcp-server 1.4.0) — OPEN SOURCE

  • Lazy mode — a search/describe/call facade with hot tools, result paging, and a token-savings ledger, for clients that can't afford a large tools/list. Per-service lazy_mode setting: auto / on / off, default auto — the facade engages automatically when the service's full tool catalog would exceed roughly 8k tokens.
  • Exposed Services scoping — tools/list is scoped to each MCP service's Exposed Services selection, cutting token cost; existing services are backfilled on upgrade.
  • Merged tool style — database tools register once behind a service argument instead of once per service (now the default for new services), extended to file tools; existing services keep their configured style.
  • Exposure controls — per-service "Require Role Access" switch, a server-wide allow_writes switch that returns permission errors on role denials, catalog preview (tools/list for a chosen role without a session), stateless sessions as the new daemon default, snake_case tool arguments with camelCase aliases and tool annotations, aggregate pushdown with paged grouped results, and an admin daemon health check at GET /_internal/ai/mcp-health.
  • Opt-in API-key authentication — per-service static X-DreamFactory-API-Key auth on the MCP endpoint, for clients that can't do OAuth.
  • Configurable redirect URIs — supports MCP clients that skip dynamic client registration.
  • System API MCP Server (system_mcp) — a new service type that exposes DreamFactory's own admin/system API over MCP, with a secret-field manifest and daemon launcher. The System API daemon makes its first public release alongside 7.7.1: dreamfactory/df-system-mcp-server 0.5.1, open source (Apache-2.0), included in every full edition's 7.7.1 composer build as a vendor sibling. Start it with df-mcp-server's scripts/start-system-daemon.sh (requires Node.js on the host), or point MCP_SYSTEM_DAEMON_URL at a daemon running as a sidecar. Until the daemon is started, requests to a system_mcp service return a clear 503 with setup instructions.

Access Usage Auditing (df-system, df-admin-interface) — OPEN SOURCE

  • Last-used and last-denied timestamps recorded for apps, roles, and users (new access_usage table + middleware; tune via DF_ACCESS_USAGE_ENABLED, DF_ACCESS_USAGE_THROTTLE_SECONDS).
  • Read-only GET /api/v2/system/access_usage audit report with never_used, stale, disabled_but_attempted, and role_unreferenced flags — find dormant credentials and orphaned roles at a glance.
  • Admin UI: last-used column and "Not used in" filter on the Apps, Roles, Users, and Admins tables; get_access_audit added to the System API MCP tool catalog.

Remote Web Services outbound OAuth2 (df-rws) — OPEN SOURCE

  • Client-credentials authentication for proxied backends that require bearer tokens — token acquisition, caching, refresh, and one automatic retry on backend 401 are handled inside the service, no event scripts needed. Six optional rws_config fields (token URL, client id/secret, grant type, scope, auth method); the client secret is encrypted at rest and masked in API responses. Supports Basic-header (e.g. Oracle OIDS/IDCS) and RFC 6749 post-body client authentication.

SQL whole-set aggregates (df-sqldb) — OPEN SOURCE

  • Aggregate fields (MIN/MAX/COUNT, etc.) are now allowed without a GROUP BY, returning whole-set aggregates from _table queries.

Admin UI (df-admin-interface 1.8.0) — OPEN SOURCE

  • MCP service editor, redesigned — Connect, Tools, Settings, and Create surfaces with a tool grid; an Access section on the Tools rail to create/add/edit roles and API keys without leaving the MCP page; allow_writes / "Require Role Access" wired up; daemon health and server-backed tool/context catalog sizes; a merged database-tool matrix when the tool style is "merged".
  • System API MCP Server (system_mcp) service details UI.
  • API Docs show the full instance URL in Swagger curl examples and Request URL (relative server URLs are absolutized).

Editions & packaging

  • Everything new in this release is open source except the df-agents and df-schema-contracts fixes (commercial packages, tier placement unchanged from 7.7.0).
  • New package: df-system-mcp-server 0.5.1 — the System API MCP daemon is now open source (Apache-2.0) and ships in every full edition, including OSS, alongside df-mcp-server.
  • The eleven single-connector editions, last refreshed at 7.6.0, catch up to the 7.7.0 platform: Laravel 13 root constraints, the symfony 8 conflict guard, and seven package pins aligned to their 7.7.0 tags — plus all applicable 7.7.1 bumps. Single-connector installs now resolve Laravel 13.33 like every other edition.

Security Hardening

  • df-sqldb: SQL injection hardening in _table filters. Filter and {"expression"} values are now bound as query parameters instead of interpolated into SQL; a recognized set of no-argument SQL functions (NOW(), CURRENT_TIMESTAMP(), …) remains inline.
  • df-amqp / df-mqtt: subscribe-consumer RBAC bypass fixed. The subscription callback previously dispatched the triggered service request with permission checks disabled, so any user with pub/sub access on a queue could invoke admin-only endpoints. Callbacks now run permission-checked under the identity captured at subscribe time.
  • df-amqp: unserialize() of queue payloads is constrained to the Subscribe job class (allowed_classes + instanceof guard), blocking PHP gadget-chain attacks via crafted payloads.
  • df-mqtt: publish topics are validated — non-empty strings up to 64 KiB, no NUL bytes, no subscribe-only wildcards (+/#).
  • df-core: curl SSRF/TLS defaults hardened — redirects are no longer followed automatically, each opted-in redirect hop is validated and pinned to its resolved IP, and SSL peer/host verification is on by default. The installed service-type list at the API root now requires authentication.
  • df-system: import-URL SSRF validator blocks 0.0.0.0/8, IPv4-mapped/compatible IPv6, and alternate IPv4 encodings (decimal, hex, octal, short-dotted); security-question password-reset attempts are throttled and the reset response envelope is unified to blunt account enumeration.
  • df-rws: caller-supplied query parameters and pass-from-client header values expand public lookups only — private/secret lookups are expanded solely for admin-configured values; the service no longer follows HTTP redirects from the remote endpoint unless explicitly configured.
  • df-mcp-server: the daemon shared secret is required on every /mcp route; custom function tools are opt-in via MCP_ALLOW_FUNCTION_TOOLS; /register no longer persists caller-supplied redirect_uris and redirect_uri is validated on /login; loopback OAuth redirects follow RFC 8252 §7.3; plus config/OAuth hardening found during 7.7.1 testing.

Fixes

Platform (df-core, df-system)

  • DELETE and PATCH with ?filter= on system resources no longer return a 500 (Call to undefined method ...::deleteByFilter()). The filter now resolves to matching ids through the same criteria translation and model scoping as GET, then delegates to the existing by-ids batch paths; an empty match returns an empty resource set.
  • Filters with unparenthesized AND/OR (a='x' OR b='y') parse correctly instead of silently matching nothing; BETWEEN / NOT BETWEEN are implemented by expansion to range comparisons. (df-core + companion df-sqldb parsing fixes, including bare operators inside parenthesized groups.)
  • _spec is listed in the service access list, so roles can be granted it.
  • Package import resolves service ids without the cached id/name map — role service-access rows for services created in the same import are no longer skipped.
  • Validation errors from record updates return 400 instead of 500; a service description may be null; ?model=true builds from the caller's _table listing.
  • MCP query templates use snake_case arguments and aggregate_data for group counts.

MCP (df-mcp-server)

  • The MCP proxy no longer starves the PHP-FPM worker pool; the daemon's DreamFactory request timeout is raised to 60s.
  • get_data_model query templates match the active tool style; global tools read the stateless per-request config; mcp:prune-request-logs runs daily.

Agents (df-agents) — COMMERCIAL

  • Approving an access request for a bare-service target now actually grants it — approval previously OR-ed verbs into existing table-scoped rows only, so a role with rows for other tables got nothing and the agent kept being denied.
  • The activity ledger is indexed by (app_id, occurred_at) and (role_id, occurred_at), and gets retention: a daily agents:prune-ledger command (default 90 days, DF_AGENTS_LEDGER_RETENTION_DAYS, 0 disables).

Schema Contracts (df-schema-contracts) — COMMERCIAL

  • Fresh installs using SQL Server as the system database no longer fail migrations: the user-audit foreign keys use NO ACTION on sqlsrv (error 1785, multiple cascade paths).

API Builder (df-api-builder)

  • Generated OpenAPI specs for built APIs emit valid paths — endpoint paths previously rendered without separators (e.g. /test_buildersample_1) or without a leading slash, breaking spec importers.

Admin UI (df-admin-interface)

  • Login page no longer scrolls the auth pane.
  • An existing grant's requestor_mask is preserved when the MCP access editor changes its level; all_list_files is counted only with two or more file services, matching the daemon.

Platform & Compatibility

  • No platform baseline change: Laravel 13 / PHP 8.4+ as in 7.7.0. Shipped lockfiles refresh to Laravel 13.33.
  • df-amqp, df-mqtt, and df-rws now declare php ^8.3 explicitly and build against the Laravel 13 stack; df-mqtt widens php-mqtt/client to allow v2 (shipped lockfiles resolve v2; same public surface as used by the service).

Upgrade Notes

  • Run database migrations — 7.7.1 adds the access_usage table (df-system), agent activity-ledger indexes (df-agents), and MCP schema updates including the Exposed Services backfill and lazy_mode column (df-mcp-server). mcp:prune-request-logs and agents:prune-ledger are scheduled daily once migrated.
  • Agent activity-ledger retention begins: rows older than 90 days start pruning daily after upgrade. Set DF_AGENTS_LEDGER_RETENTION_DAYS to widen the window, or 0 to disable, before upgrading if you keep the ledger as a long-term audit trail.
  • Outbound HTTP behavior change (intended): requests made through the platform curl wrapper no longer follow redirects automatically and verify SSL peer/host by default. HTTP-backed services that relied on silent redirect-following or unverified/self-signed certificates need their service config updated after upgrade.
  • Filter behavior changes (intended): filters that previously returned silently empty results because of bare AND/OR now match rows; inline SQL in filter values (beyond the recognized no-argument functions) no longer executes — it is bound as a parameter value. Review any filters that depended on either behavior.
  • AMQP/MQTT subscribers now run permission-checked under the subscribing identity. Flows that (improperly) relied on the unchecked dispatch will now receive permission errors — grant the subscriber's role the required access.
  • MCP defaults: existing MCP services with large tool catalogs will start serving the lazy facade after upgrade (lazy_mode defaults to auto) — set lazy_mode to off per service to keep the full tools/list. New MCP services default to the merged database tool style; existing services keep their configured style. The daemon now runs stateless sessions by default on every install — set MCP_STATELESS=false to restore warm, process-pinned sessions on single-node deployments. Custom function tools are disabled unless MCP_ALLOW_FUNCTION_TOOLS=true, and the daemon shared secret is now required on every /mcp route.
  • system_mcp requires its daemon to be running: composer install/update on the 7.7.1 full-edition manifests brings in dreamfactory/df-system-mcp-server (single-connector editions carry neither the MCP server nor system_mcp); start the daemon with df-mcp-server's scripts/start-system-daemon.sh (Node.js required on the host) or set MCP_SYSTEM_DAEMON_URL to a running sidecar. Service creation succeeds without it, but requests return 503 with setup instructions until the daemon is reachable.
  • df-rws: remote endpoints that redirect now require explicitly enabling redirect-following in the service config; caller-supplied parameters no longer expand private lookups.
  • df-mqtt publishes now reject empty, oversized (>64 KiB), NUL-containing, or wildcard topics.
  • The service-type catalog at the API root now requires authentication; unauthenticated integrations reading it must send credentials.
  • Password-reset endpoints are rate-limited and return a uniform envelope; automation that parsed the old distinct responses should be updated.
  • Security fixes are cumulative — upgrade promptly if you expose _table filters to end users, run AMQP/MQTT subscriptions, or expose the MCP or RWS surfaces.