Changelog
Generated from root CHANGELOG.md (Keep a Changelog). Protocol versions are the protocolVersion field; product releases are separate.
All notable changes to qLLM are documented here.
The format follows Keep a Changelog.
Protocol versions are the protocolVersion field (planning/). Runtime responses advertise 0.2.0; 0.1.0 preset/catalog/IR files remain valid. Latest product release: 0.3.5.
[Unreleased]
Added
- Link to the end-to-end demo repo jpandrade30/SmallDemo from the README and product site (home, Get started, Docs).
- Home page embeds the SmallDemo walkthrough video (YouTube) before 01 — What.
[0.3.5] - 2026-10-04
Added
- Explicit experimental / no-liability disclaimer in the root README and on the product site (home note + footer on every page).
[0.3.4] - 2026-10-04
Changed
- Product site primary nav follows a reader journey: Get started → Configure → Connectors → Query → Security → Docs → Protocol → Decisions → Changelog → Contribute.
[0.3.3] - 2026-10-04
Added
- GitHub Pages product site (
site/, English): overview, get started, connectors, configure (side menu for preset/catalog/config/env), query, security, Docs index, Decisions (plain-language D17–D22), and Contribute — deployed via Actions to https://jpandrade30.github.io/qLLM/ - Site pages for protocol 0.1.0 → 0.2.0 (
protocol.html) and a generated Changelog (changelog.htmlfrom rootCHANGELOG.mdviascripts/dev/render_site_md.py, also in the Pages workflow). - Docs clarify units on time/size/row limits (
ms,bytes,rows) indocs/en/field-reference.mdandproject-files.md; decision ids point atplanning/01-decisions.mdinstead of bareD##shorthand. CONTRIBUTING.mdandCODE_OF_CONDUCT.md(Contributor Covenant 2.1): fork/PR workflow, contract-change checklist, changelog/README expectations.- Standalone generator (
scripts/standalone/init-standalone.py) copiesplanning/into the slim folder so LLMs/humans can author config against the contract; Get started / install docs stress thatconfig/and monorepodeploy/are examples to replace.
Changed
- Home-page flow sketch sits inside 01 — What as the example diagram (no longer a separate band above that stage).
- Documentation type labels for
protocolVersionsay No version instead of “semver” (field-reference / from-scratch in en/pt/es/zh, plus planning D11 / protocol field table).
Fixed
- Standalone
config/qllm.env.yamltemplate now uses the required rootenv:map.
[0.3.2] - 2026-10-04
Added
- Experimental source type
graphql(no harness): HTTP POST tobaseUrlEnv, catalog bindinggraphql_operation+options.operations.<name>(document,itemsPath, optionalvariables/limitVariable). Documents must be GraphQLqueryonly —mutation/subscriptionand write keywords (INSERT,UPDATE,DELETE, …) fail at open/fetch withCONFIG_ERRORbefore any HTTP. Not a GraphQL agent API (D17 unchanged).
Changed
- Docs and root README Quick start recommend downloading the GitHub Release
qllm-standalone-<ver>.zipinstead of cloning the monorepo to run qLLM.
[0.3.1] - 2026-10-03
Added
- GitHub Actions CI (
go vet/go test,-tags duckdbjob, generate + build + validate the slim folder). - GitHub Release workflow on tags
v: buildsqllm-standalone-<ver>.zipfromscripts/standalone/init-standalone.py(LICENSE included) and attaches it using the matchingCHANGELOG.mdsection as the release body. Release notes warn that GitHub’s automatic Source code archives are the full monorepo — use only theqllm-standalone-.zipasset.
Fixed
- DuckDB dialect unit tests: parenthesize
UNION ALLarms that useLIMIT, use a window inQUALIFY, and express boolean XOR as<>(DuckDB has no booleanXOR/xor(bool,bool)).
[0.3.0] - 2026-10-03
Product release. Protocol stays 0.2.0 (additive: D19–D22, extra sources[].type values).
Added
- Source
typevalues in this release (harness still only postgres / mysql / mongodb / rest): - Stable:
postgres,mysql,mongodb,rest. - Experimental (in the binary, no compose/goldens):
mssql,sqlite,clickhouse,dynamodb,cassandra,ksql(from 0.2.0), plusredisandkafka(D19). - Experimental wire aliases (same driver and connection as the parent): MySQL family
mariadb,tidb,vitess,aurora_mysql,planetscale; Postgres familycockroach,yugabyte,alloydb,aurora_postgres,neon,supabase,timescale,redshift. - Redis (D19):
binding.kind: key+keyPattern; allowlisted GET/HGETALL/LRANGE/SSCAN/ZRANGE/XRANGE only. Missing key predicate isUNSUPPORTED. Never deletes, pops, orKEYS. - Kafka (D19):
binding.kind: topic; fetch without a consumer group or offset commit (read_committed). Missing partition/offset, key, or time predicate isUNSUPPORTED. Never produces. - REST
getByIdruns when every{name}in the path has aneqfilter.list.itemsKey(or resource-level) picks the JSON array key;maxPages/pageSize/limitParam/offsetParamwalk offset pages (capped at 20). - REST catalog field
fromFilter(D20): when the API omits a key it already received aseq, qLLM fills that column soGROUP BYand joins work. MissingeqisINVALID_IR; a mismatched body value isSOURCE_ERROR. - Catalog field
shape(D22): optional free-text hint of the inner structure of atype: jsonfield, shown indescribe_catalog. - Parsed
jsoncells (objects and arrays) in query responses; SQL column types come from DuckDB instead of labeling every columnstring. - Scoped keys (D21): one
qllm.access.yamlentry per app type; derived Bearerapp.user.expiry.hmac(or a staticscopemap) forceseqon catalogentities[].scope. Conflicting Query IR filters returnFORBIDDEN_SCOPE(scopeMode: reject, default). Query tools gain no extra field. - Example stack
Dockerfile.enforced+docker-compose.enforced.yml+deploy/prd/enforced/(Postgres seed, LangGraph agent that mints keys and opens an MCP session perexecute_sql). deploy/prdsplit intodefault/(product image) andenforced/(scoped-key demo).- REST entity
api_profiles(nestedaddress/tags/prefs) plus SQL goldensrest_json_*and datasetfixtures/datasets/v1/api_profiles.json. - Docs:
responses.md(en/pt/es/zh) for the query envelope, column types, and parsed json cells. scripts/standalone/init-standalone.py(.ps1/.sh) writes a slim folder (qllm-<user>) with the Go runtime, blank SQLite YAML, and a Dockerfile.scripts/dev/check-live.ps1/.shruns SQL goldens against a live MCP (-Filter rest_jsonfor nested JSON).
Changed
- Root README is reorganized (why, how it works, connector table, quick start, configuration, serving, containers, behavior, development).
- Operator scripts live under
scripts/dev/,scripts/prd-tst/, andscripts/standalone/(old flatscripts/*.ps1paths no longer exist). - Compose mounts
deploy/image/configon/configandfixtures/test-api/data.jsonon the fake API so catalog/seed changes apply without rebuilding those images. - Enforced demo compose project is
qllm-enforced(does not reuse harness container names). The LangGraph node isformat_answerso it no longer collides with theanswerstate key.
Fixed
- Kafka connector no longer sets
DisableAutoCommit(invalid without a consumer group), which madeOpen()fail whenever a Kafka source was in the preset. Still no group, no commits. - Catalog SQL (
execute_sql/POST /v1/sql) applies entityscopeon each source fetch (inject). A spoofWHERE user_id = '…'does not leak other users' rows.
[0.2.0] - 2026-09-30
Added
- Docs (en/pt/es/zh): REST
options.resourcesexplained in detail (list,getById,method,path,queryParams, how queries map to HTTP, response shapes) and everyoptionskey with defaults;getByIdis documented as not called by the runtime. Root README gains a "Why qLLM" section. - Experimental source types (no compose/goldens):
mssql,sqlite,clickhouse,dynamodb,cassandra,ksql(pull only). - Catalog
binding.accessPath(pk/partition,sk/sort,ksqlKey). Queries without the required key equality returnUNSUPPORTED(no Dynamo Scan / CassandraALLOW FILTERING/ ksqlEMIT CHANGES). qllm.env.yamlvalues may be exactly${ENV_NAME}; empty names are not written as the placeholder string. Compose injects harness secrets viaenvironment:.- SQL catalog path: CTE aliases, richer dialect
"2"coverage in goldens (fixtures/sqlcheck). scripts/prd-tst/prd-tst-up/prd-tst-down(.ps1/.sh) to apply or remove the fleet-ops Kubernetes sim.deploy/prd/example YAML baked by the productDockerfile(copy of harness shapes). Fleet-ops K8s sim lives indeploy/prd-tst/.- POSIX twins:
scripts/.shfor seed, CGO shell, andprd-tst-port-forward/Argo. docs/implementer manual in four languages (docs/en,docs/pt,docs/es,docs/zh): from-scratch, field reference,Dockerfilevs.dev, and more. The README links to each language.execute_sqllogs a multiline block on stderr (status, queryId, SQL as written). MCP logshow_to_use_me/describe_catalogthe same way.- Cursor rules: keep
README.mdand this changelog in the same change set as user-visible work.
Changed
- Runtime
protocolVersionis 0.2.0. Query IR shape is unchanged from 0.1.0. - Go module toolchain requirement is 1.26 (deps). Image/harness still demo postgres, mysql, mongodb, REST only.
- Compose builds
Dockerfile.dev(deploy/image/config). DefaultDockerfilebakesdeploy/prd. - K8s sim scripts renamed
prd-tst-.ps1(oldprd-.ps1names removed). - Production Go functions have Godoc comments.
- The manual moved from a flat
docs/folder into per-language folders, with clearer English and Brazilian Portuguese text.
Fixed
- Docker build image is
golang:1.26.6-bookwormsogo mod downloadmatchesgo.mod(was 1.25 withGOTOOLCHAIN=local). - PRD sim:
qllm:localusesimagePullPolicy: Neverso kubelet does not pulldocker.io/library/qllm:local. Build withnerdctl --namespace k8s.io.
Security
- Toolchain is Go 1.26.6 (
go.mod+golang:1.26.6-bookworm) sogovulncheckstdlib findings on 1.26.0 (url/tls/http/x509/net/mail/xml/asn1) are closed.golang.org/x/cryptois v0.56.0 (SSH DoS). Remaining module-only advisory GO-2026-5932 isx/crypto/openpgp(unmaintained, no fix; qLLM does not import it). - Bearer compare uses HMAC-SHA256 +
hmac.Equal(fixed-size digest; nolenshort-circuit). ACL lookup always compares against every app key. - Demo tokens/passwords are not baked as literals in
deploy/image/config/qllm.env.yaml; they come from process/compose env.
[0.1.0] - 2026-09
Baseline shipped in this repo before the 0.2.0 source-type bump:
- Preset + logical catalog + JSON Query IR + HTTP
/v1and MCP (how_to_use_me,describe_catalog,execute_sql). - Connectors in the harness: postgres, mysql, mongodb, REST; DuckDB local join /
execute_sql(-tags duckdb). qllm.access.yaml, SQL dialect"1"/"2", catalogintrospect/from-openapi, D17 (no GraphQL API), D18 (harness isolated from the binary).
Protocol bump notes
See what changed between protocol 0.1.0 and 0.2.0.