Repository navigation
Releases: fireflyframework/flyquery
Release list
v26.10.4
Table and schema reads keep the requested tenant and workspace through their parent joins. Snapshot metadata is returned only when its table, dataset, tenant and workspace match; an invalid pointer no longer exposes metadata from another scope.
The Python SDK includes AgentReadClient for bounded, GET-only dataset, table and schema-object reads. Its scope is fixed when constructed. It validates parent snapshots and rejects incomplete catalogs, redirects and oversized responses. It cannot execute queries. See the SDK guide.
Server and SDK versions are 26.10.4. Both Java JARs include the Apache license; protocol shapes and third-party dependencies are unchanged.
Validation includes passing PR CI, independent source/security review and an additional local PostgreSQL exercise of snapshot-pointer and scope boundaries. The CI report retains 15 integration and 135 Java skips. The forge adapter and prepared-result agent mirror remain separate work.
flyquery 26.10.3
flyquery now interrupts each DuckDB execution attempt when its configured deadline expires. The budget covers queueing, setup, SQL, row fetching and copy-on-write export. Timed-out statements are recorded as FAILED with SQL state 57014; Critic does not repair this resource failure or restore an earlier success after a repair timeout.
Cancellation waits for the attempt's own worker and connection to close. Original snapshots remain unchanged, scratch output is removed even when native close reports a failure, and cleanup errors remain chained to cancellation. Transient interruption failures are retained and retried. Large positive integer budgets cannot overflow the watchdog's native wait.
This is a cooperative, per-attempt deadline—not a hard process kill or an end-to-end request SLA. Model calls, retrieval and object-store work outside the executor have separate budgets. Existing finite candidate policy, authorization, registered-file fences and the seven typed agent page APIs are preserved.
Python and Java SDK metadata report 26.10.3. The qualified framework pins and nineteen historical source contracts plus two reviewed variants remain unchanged. Operational guides explain the implemented behavior and its limits.
Validation: 467 unit tests; 111 native integrations (15 optional storage skips and one paid-model deselection); native interruption, cancellation and cleanup regressions; SDK source and fresh-installed-wheel tests; actual authenticated seven-page SDK reads; Java 25 Maven validation; lint, types and exact-source CI. Paid providers and cloud deployment were not used. Public artifact verification is recorded separately from local server qualification.
What's Changed
Full Changelog: v26.10.2...v26.10.3
flyquery 26.10.2
flyquery 26.10.2 combines bounded query grounding, privacy fixes and adoption of fireflyframework-agentic 26.10.1. The qualified pyfly 26.06.113 runtime is retained.
- Query grounding uses bounded column-value catalogs and relation candidates; conversation turns preserve their snapshot selections. Candidate probes pass the registered-table fence before execution.
- Missing or unauthorized dataset scope is rejected before retrieval or model calls, with a caller-scoped audit record.
- PII scanning checks original samples before filtering and retained profile values before embedding. Redact/reject stores an explicit empty-list denial, preventing profiles from reintroducing protected values into schema knowledge. Original source files remain unchanged.
FLYQUERY_PROMPT_CACHEnow affects actual agent construction. Enabled mode adds Anthropic instruction-cache hints; user messages, tool results and answers are not memoized. Agentic supplies the default logging/observability middleware once.- Seven agent SDK list operations now deserialize their existing table, search, snapshot, object, change, dataset and conversation envelopes. Python and Java examples and response types match the API.
- The server dependency graph is tracked in
uv.lock, checked before frozen installation, with public first-party sources. Nineteen historical shared-source baselines and two reviewed service variants retain source-drift checks.
Local qualification: 451 unit tests; 109 native integration tests using PostgreSQL/pgvector, Redis and pinned-source MinIO; Python SDK 25 tests and type checks; Java 25 Maven verification. Both generated SDKs read all seven typed pages against the installed service. All fourteen changed Python and Java documentation examples compile and run against that API. Native token checks, foreign-tenant visibility, SUM60, SSE event ordering, persisted history and result Parquet contents were also checked.
Fifteen optional GCS/Azure storage scenarios remain unqualified, and paid-model tests were deliberately excluded. A nonempty executed candidate is a heuristic, not proof that its entities or filters match the question. The engine does not enforce its statement-timeout setting or provide an operating system sandbox. Remote object-store DuckDB reads are not accepted by these local registered-file tests. PII detection is limited to sampled or retained profile values and the configured scanner.
User-route authentication belongs to the deployment gateway; tenant/workspace headers select scope and are not credentials. Agent routes verify issued agent tokens and scopes.
flyquery 26.10.1
Corrected Python authentication instructions
The SDK guide and package metadata now show how to send a bearer token explicitly:
api.default_headers["Authorization"] = "Bearer " + tokenThe generated client's current OpenAPI authentication schemes cover context headers and agent tokens; Configuration.access_token alone does not emit an Authorization header. A real TCP check confirms the documented header behavior. Configure the deployment's issuer, authentication and permissions separately.
This patch also includes the corrected streaming example: *_without_preload_content returns the raw aiohttp ClientResponse, so use stream.raise_for_status(), stream.content and stream.release().
Version alignment and compatibility
Service and Python/Java SDK metadata, user-agent/debug versions, embedded API version and current installation links now use 26.10.1. APIs, DTOs, SQL boundaries and framework pins are unchanged from 26.10.0. Its original assets and tag remain intact.
The SDK's mandatory lint, formatting, type checks and 18 HTTP/import tests pass. The built wheel contains the corrected instructions. Source CI and the publication workflow check this release before uploading its packages. No paid model-provider calls or cloud application deployments were used.
Client timeouts do not establish server-side cancellation or an operating system sandbox. Remote object-store extensions and distributed execution isolation remain separate qualification boundaries.
What's Changed
- Correct the generated client's bearer authentication guide by @ancongui in #8
- Publish corrected SDK authentication documentation in 26.10.1 by @ancongui in #9
Full Changelog: v26.10.0...v26.10.1
flyquery 26.10.0
Python client and installation
The Python convenience client now passes the required tenant and workspace context when looking up or creating workspaces and datasets. Creation is attempted only after an HTTP 404. Authorization errors, server failures, transport disconnects and malformed responses propagate without an additional write. Concurrent creation conflicts remain visible as HTTP 409.
Install the Python wheel from this release:
uv add https://github.com/fireflyframework/flyquery/releases/download/v26.10.0/flyquery_sdk-26.10.0-py3-none-any.whlImport the convenience client with from flyquery_sdk.client import FlyqueryClient. For a bearer-protected deployment, explicitly set api.default_headers["Authorization"] = "Bearer " + token on the generated ApiClient; Configuration.access_token alone is not consumed by the current OpenAPI authentication schemes. The current SDK guide includes this checked header recipe. The client installs independently of the server and its frameworks. The updated guides explain workspace UUIDs, explicit generated parameters, user and agent routes, streaming responses and the different generated/HTTPX error types. Service and client metadata use 26.10.0, including runtime headers and the embedded API contract. Existing release assets are preserved.
Registered-data SQL boundary
Read execution now restricts SQL to registered dataset views. Scope checks reject external file readers and unregistered sources, including through nested queries; registered joins and CTEs remain supported. The query path enforces this boundary before execution and before passing query material to downstream agents. Regression tests cover external-read and scope failures.
Build and verification
PR and SDK publication workflows require the Python SDK's lint, formatting, type checks and HTTP-contract tests to pass. Fresh service clones resolve pyfly and fireflyframework-agentic from published framework tags. Integration tests use a pinned official MinIO source build rather than an unavailable historical container image.
The release was checked with source and installed-wheel SDK tests, native pyfly workspace/dataset controllers and PostgreSQL repositories over TCP, SDK-only installation on Python 3.9 and 3.13, Java 25 Maven verification, and all seven service CI checks. Native Direct SQL checks also covered registered Parquet queries, rejected unregistered sources, successful and denied SSE streams, query history, persisted result objects and the workspace enable/disable setting. Original dataset snapshots remained unchanged. Framework-family banners now cover the SDK guides in desktop/mobile and light/dark variants.
Deployment boundaries
The native PostgreSQL test role bypassed RLS; that check validates repository filtering, not database RLS enforcement. The SDK's generated calls accept _request_timeout; the convenience client's constructor timeout applies to HTTPX helpers. Client timeouts do not establish server-side cancellation or an operating system sandbox. Remote object-store extensions and distributed execution isolation require separate qualification. No model-provider calls or cloud application deployments were used for this release validation.
v26.6.0
v26.5.14
flyquery 26.5.14 — Apache 2.0 open-source release
flyquery is now open source under the Apache License 2.0 (© 2024-2026 Firefly Software Foundation); the repository is public.
Changed
- Replaced the proprietary notice with the full Apache 2.0
LICENSE(root + Python/Java SDKs) and added an Apache 2.0 header to every source file. - Set the OpenAPI
info.license, the imagelicenseslabel, the README badge, the bundled SDK spec/setup.py, andpyprojectmetadata to Apache-2.0. - Aligned all version references to
26.5.14; refreshed the lock-step SHA pins.
SDKs
- Python: wheel + sdist attached below.
- Java:
com.firefly:flyquery-sdk:26.5.14on GitHub Packages.
v26.5.13
Full Changelog: v26.5.12...v26.5.13
v26.5.12
Full Changelog: v26.5.11...v26.5.12
v26.5.11
Added — Webhook callbacks for every async ingest job
A receiver-side push channel for the async ingest pipeline. The
caller attaches callback_url (+ optional secret + custom
headers) to POST /api/v1/ingest-jobs or to
POST /api/v1/datasets/{ds}/files:async; on terminal status
(SUCCEEDED / FAILED / CANCELLED) the worker POSTs the
canonical IngestJobRead payload to the configured URL.
- Transactional outbox -- a new
flyquery_callback_outboxtable
(migration0013_job_callbacks) is written in the SAME transaction
as the job's status flip. A process crash between the two writes is
impossible, so a "succeeded" job ALWAYS has its callback queued. CallbackWorkerdrains the outbox withFOR UPDATE SKIP LOCKED
so N peer workers scale horizontally without colliding. Five-attempt
exponential backoff (0s, 30s, 5m, 1h, 6h), thenDEAD. New CLI
subcommandflyquery worker callbackandflyquery worker allnow
includes it alongside ingest + retention.- HMAC-SHA256 signing -- when a
secretis provided, every
request carriesX-Flyquery-Signature: sha256=<hmac>computed over
the raw body. Dispatcher applies reserved headers (Content-Type,
X-Flyquery-Event,X-Flyquery-Job-Id,X-Flyquery-Signature)
LAST so a misconfigured or malicious extra-header bag cannot shadow
the signature header. - Per-request OR per-configuration -- the per-request bundle takes
precedence, butFLYQUERY_DEFAULT_CALLBACK_URL/
FLYQUERY_DEFAULT_CALLBACK_SECRET/
FLYQUERY_DEFAULT_CALLBACK_HEADERSprovide a process-wide default
receiver so an operator can wire every async job to a central hub
without touching every caller. Whole-bundle precedence (URL +
secret + headers move together) prevents accidentally leaking the
default secret to a different receiver. GET /api/v1/ingest-jobs/{id}/callbacks-- paginated audit
trail. One row per delivery attempt with URL, event type
(ingest.succeeded/ingest.failed), status (PENDING/
DELIVERED/FAILED/DEAD), attempt count, last HTTP status
code + last error, and next scheduled retry. Supports?status=
filter.- SDK helpers:
- Python:
client.upload_async(..., callback_url=, callback_secret=, callback_headers=)+client.list_job_callbacks(job_id, ...)
(and_syncmirrors). The auto-generatedIngestJobsApi.list_callbacksCallbackConfig/CallbackDeliveryRead/
CallbackDeliveryListResponsemodels are also exposed.
- Java:
client.ingestJobs().listCallbacks(...)from the
regeneratedIngestJobsApi.CallbackConfigmodel can be set
onIngestJobCreate.callbackforcreateJob(...).
- Python:
- New docs:
docs/callbacks.md-- full
contract, receiver example with signature verification, retry
schedule, ops runbook for DEAD rows. Cross-linked from
docs/async-ingest.md+docs/workers.md.
Fixed — Critical correctness bugs surfaced by end-to-end testing
- Publisher DI was silently in-memory --
core/configuration.py
had a stale@bean ingest_publisherfactory that called
_resolve_eda_publisher()at factory-eval time (before
EdaAutoConfigurationwired the EventPublisher). The factory won
precedence over the@serviceregistration onIngestPublisher,
so every running process heldself._publisher = Noneand every
publish_ingest_requestedsilently hit the in-memory branch.
Workers never receivedIngestRequestedevents; async jobs sat in
PENDINGforever and were only rescued by the orphan-PENDING
reaper 10 minutes later. Factory deleted; the@service
registration now resolvesEventPublishervia constructor
injection like flycanon / flyradar. - Pyfly DI param-name mismatches -- pyfly's resolver is name-first
with type-fallback.IngestService(publisher: IngestPublisher, ...)
did not match the snake-cased bean nameingest_publisher. Renamed
toingest_publisheronIngestService+IngestJobService. Also
renamedrepository/repo-> snake-cased bean name on
SchemaObjectService,SchemaChangeService,RelationService,
SemanticService,SemanticDimensionsService,WorkspaceService
for forward-safety. triggered_by="WORKER"violatedck_snapshots_trigger-- the
CHECK constraint accepts onlyUSER/AGENT/SCHEDULED/
REPARSE. Every async PARSE_AND_INGEST job failed at reconcile
withCheckViolationError. Worker now writesREPARSEfor the
by-worker path (workers.py:488).governance_json/synonyms_jsonDTO polymorphism -- legacy
rows from a priorNULL || dictjsonb-concat bug stored
governance_jsonas[null, {...}]. The DTO had been widened to
dict | list | Noneas a band-aid; that ambiguity leaked into
every consumer and brokeGET /tables/{id}/objectswith a Pydantic
422. Fixed properly:- DTOs tightened to
synonyms_json: list[str]/
governance_json: dict[str, Any]. - New normaliser
core/services/storage/jsonb_normalize.pycoerces
any historical shape to canonical at every consumer + producer
seam (DTOfield_validator+reconcilestage write path). - Migration
0012_normalize_jsonb_shapesheals existing polluted
rows.
- DTOs tightened to
flyquery_examplesinsert syntax --:embedding::vector
confused SQLAlchemy's bind parser (text parsed the second:as a
new bind), so asyncpg received a literal:embeddingtoken and
raisedPostgresSyntaxError. Every successful NL query crashed
with a 500 after the SQL executed (auto-learning save path).
Changed toCAST(:embedding AS vector).- CallbackWorker triggered pyfly's ApplicationRunner convention
-- a bean method namedrun()is auto-invoked at API startup with
a positionalargsparameter. Renamed torun_forever()so the
callback drain runs ONLY under the dedicated CLI command. - Callback dispatcher header ordering -- caller-supplied extra
headers were applied AFTER our reserved keys, allowing
extra_headers={"X-Flyquery-Signature": "evil"}to shadow the real
signature. Reversed: reserved keys are applied LAST.
Changed
POST /api/v1/ingest-jobsnow declares its request body via
Valid[Body[IngestJobCreate]](was: manualrequest.json()decode).
This publishesIngestJobCreate+ the nestedCallbackConfig
schemas intoopenapi.jsonso SDK generators see them. Wire
contract unchanged; existing 200/422 behaviour identical.pyfly.yaml,pyproject.toml,Taskfile.yml, both SDK
pyproject.toml/setup.py/pom.xml/build.gradle, README
badge, andapp.pydecorator all now read26.5.11. (Also fixed
theapp.pydrift from26.5.0.)
Full Changelog: v26.5.10...v26.5.11