v0.7.0 — security-audit remediation, supply-chain hardening, and committee governance
Status: ready for the
v0.7.0tag. The blocker is cleared — ADR 0025 (release versioning policy and pipeline ordering) was accepted by the committee at the 2026-08-09 weekly call and merged as #487, so theversion-consistencygate and the backend-before-frontend pipeline this release is cut under are live onmain. This PR marks ADR 0025 Accepted, bumpsapiandgateway__version__to0.7.0, and regenerates the committed OpenAPI export, which carries the api version. This is the first release cut under ADR 0025.
This is a hardening release, not a feature milestone. It is the first substantial remediation
of the 22-finding 360° security audit (#288, Claude Fable 5), and it lands supply-chain, CI, and
governance work alongside it. Its headline is that all three High-severity audit findings are
closed, together with three Mediums. Per ADR 0025 the number is computed from what has accumulated
on main: three of these changes (#396, #399, #400) require operator action, so the next release is
a minor — v0.7.0, not a patch. The through-line is the audit’s own verdict — LQ.AI is “a
codebase worth hardening, not rewriting.”
It is also the first release whose headline is community work. Every audit-remediation PR here
was written by an external contributor, and four people landed their first commit on main in this
range. See Who built this release.
Headline — security-audit remediation (#288)
Section titled “Headline — security-audit remediation (#288)”The audit surfaced 22 findings (3 High, 10 Medium, 8 Low, 1 Info). None is exploitable by a raw
external attacker in the shipped default (every service binds to 127.0.0.1); all sit on the
platform’s core promise — cross-tenant data sovereignty for privileged legal material. This release
closes all three Highs plus three Mediums:
High — all three closed
- GW-01 — the gateway inference/embeddings endpoints now require a key.
POST /v1/chat/completionsand/v1/embeddingspreviously accepted requests with no gateway key while every sibling router enforced one, contradicting the gateway’s own OpenAPI contract; on the flat compose network any co-located container could drive the crown-jewel egress path directly. Both now require the key. (#396) - API-01 — the cross-tenant IDOR at chat creation is closed. An authenticated user could bind a new chat to another user’s project UUID, pulling the victim’s knowledge-base documents into the response and forwarding them to the external LLM with anonymization disabled. Chat creation now validates project ownership. This was the finding most directly on the data-sovereignty guarantee. (#397)
- D-01 — stored XSS in the skill source viewer is closed.
SkillSourceView.svelterendered skill markdown throughmarkedwith no DOMPurify — the one LQ-authored{@html}sink that skipped the sanitization applied elsewhere by convention (a malicious skill body → JS in a viewer’s authenticated session → account takeover). Skill markdown is now sanitized before render. (#398)
Medium — three closed
- GW-04 — LLM provider
base_urlegress is guarded. The providerbase_urlhad no SSRF/allowlist/HTTPS guard, asymmetric with the hardened tool-egress path; it is now validated at adapter-build time, and a violation is fatal at gateway startup rather than skipped (skipping would let the router fall through and send prompts somewhere the operator did not choose).httpsis always allowed; plaintexthttponly to a loopback/private host. (#400) Related: provider egress refusals are now a typedProviderEgressRefusedunder theLQAIErrorhierarchy. (#488) - AG-01 — autonomous
retrieve_chunksis scoped to the session owner. Model-suppliedkb_id/file_idin the autonomous layer previously carried no ownership scoping; retrieval is now bound to the session owner. (#401) - API-04 — the api refuses to boot on the published dev JWT secret. A deployment left on the
documented dev
JWT_SECRETwill now refuse to start in production (set the secret, orLQ_AI_DEV_MODE). (#399) — This addresses audit finding API-04; the commit was not tagged with the finding ID, so it will not appear in aRefs #288grep.
Operator note — three behavior changes (the reason this is a minor, per ADR 0025 decision 3). All three carry the
breaking-changelabel, so theversion-consistencygate sees them. #396 — a deployment calling the gateway directly without a key gets401on every inference call after upgrading (in the default topology the api already sends the key, so no action is expected). #399 — an install still on the devJWT_SECRETwill refuse to start until the operator sets a real secret (orLQ_AI_DEV_MODE). #400 — the gateway refuses to start if any configured providerbase_urlis plaintexthttpto a non-local host, or uses a scheme other thanhttp/https. A local Ollama onhttp://localhostor a private IP is unaffected; a remotehttp://endpoint must move tohttps. Read before upgrading.
Supply-chain & build hardening
Section titled “Supply-chain & build hardening”- uv-managed lockfiles for
gateway/andapi/(ADR 0023). Both services build fromuv-managed lockfiles — reproducible, fully-pinned resolution across the SBOM. (#312, #441) - Stack-boot CI smoke test. CI builds and boots the whole compose stack on every run, catching a break in the 7-service bring-up before merge. (#297)
- GitHub Actions pinned to commit SHAs. Release-relevant actions no longer float on mutable tags
(partial remediation of audit E-02; the signing/
packages:writesplit remains open). (#296) - The release pipeline is staged and gated (ADR 0025).
release.ymlsplits its single unordered matrix intobuild-backend→build-frontend, so a backend failure structurally blocks the frontend from publishing under the same tag, and adds aversion-consistencyjob that fails the tag push ifapiandgatewaydisagree with each other or with the tag, or if a patch tag is cut while abreaking-change-labelled PR merged since the previous release. ADR 0025 is Accepted (committee, 2026-08-09), and this is the first release cut under it. (#487) - Windows entrypoint line-endings forced to LF, fixing a class of Windows-checkout boot failures. (#259)
- Gateway test fixture pins
OLLAMA_BASE_URL, closing an ambient-environment leak that let a developer’s shell change test behaviour. (#443) - Dependency bumps, including starlette
0.48.0 → 1.3.1(a major bump) and cryptography44.0.3 → 49.0.0in the gateway, FastAPI, uvicorn, aioboto3, sqlalchemy, ruff, and several GitHub Actions to current majors — several swept into single lock/CI writes. (#468, #454, #449, #469, #472, #452, #476, #477, #467, #463, #180, #250, #124, #123, #248, #249)
Correctness & governance
Section titled “Correctness & governance”- Knowledge bases listed by the
project_knowledge_basesjunction, with a backfill. Replaces the legacy single-column association; ships migration 0066 to backfill existing rows. No operator step (the backfill runs on migrate). (#442) - Committee governance framework (ADR 0022). New
GOVERNANCE.mdplus ADR 0022 formalize the LQAI committee’s decision process and meeting-record convention. (#311); ADR 0022 is now marked Accepted (committee, 2026-07-26). (#507) - Expansion-contribution routing (ADR 0024 + direction paper). A direction paper and ADR 0024 give jurisdiction- and practice-area-expansion contributions a documented route, so proposals stop stalling for want of a place to go. Both Accepted (2026-08-09). (#313)
- Native frontend dev flow (Vite HMR) documented for
web/. (#281) - caddy-tailscale deployment recipe cleaned up. (#261)
- DE-385 filed — desktop
package-lock.jsonversion stale at 0.5.2, tracked for follow-up. (#276) - DE-386 filed — tool providers have no client-credentials auth path; the five missing pieces are enumerated in PRD §9 rather than left implicit. (#508)
- compose: forward
LQ_AI_GATEWAY_MASTER_KEYinto the gateway service (Donna #3 follow-up) — fixes encrypted-key startup in the default stack. (#278) - desktop: pull images before
upso the launcher picks up published releases (shipped as thedesktop-v0.6.2tag). (#277)
Who built this release
Section titled “Who built this release”The entire security-audit remediation in this release was written by a contributor from outside the maintainer team. All three High findings (#396, #397, #398), all three Mediums (#399, #400, #401), the two follow-ups that tidied up after them (#443, #488), and the SHA-pinning of GitHub Actions (#296) are @SaifAlYounan’s work — nine PRs, the first of which landed on 2026-07-08. The headline of this release is not maintainer work.
Four people landed their first commit on main in this release:
Contributor What they landed
- @SaifAlYounan
- the whole #288 remediation (9 PRs), plus SHA-pinned Actions
- @mkorpela
- LF line-endings on the Windows entrypoint, fixing a class of Windows-checkout boot failures (#259)
- @sgbooth
- the native Vite-HMR frontend dev flow, documented (#281)
- @sergiomaldo
- knowledge bases listed by the junction table rather than the legacy column (#442)
And one came back: @ThurgyThurg, whose caddy-tailscale recipe first landed in #134, returned to clean it up in #261.
The project’s contributor base is genuinely widening. Seven distinct human identities had landed
commits on main by v0.6.1; twelve had by the time this release was cut. Concentration is still
real — one person authored roughly 95% of all human-authored commits in the project’s history, and
ADR 0025’s Cadence section is honest about what that means for release cadence and for the
desktop signing identity. But the security-critical work in this release came from the community,
and that is a different shape of project than the one the last release shipped from.
Worth recording alongside the credit: none of these landed on the first pass. The security PRs went through review rounds that sent work back — a missing loop-path test on #401, a corrected diagnosis of which guard was actually failing on #443 — and they are better for it. Review capacity is the other half of a widening contributor base, and it is the half that does not scale by itself.
Schema
Section titled “Schema”Migration head 0066 (0066_backfill_project_knowledge_bases, #442) — reversible, applied on
make migrate, no operator action. This is the only schema change in the release.
Version
Section titled “Version”Per ADR 0025 decision 1, api, gateway, web, and proxy share one release version — the
image tag. This PR bumps the two project-owned strings, api and gateway __version__ →
0.7.0. The drift ADR 0025 records (api 0.6.1, gateway lagging at 0.5.1) was already
closed by #487, which moved gateway to 0.6.1; both now move together, as the policy requires.
web/package.json stays 0.9.2 (OpenWebUI fork, per ADR 0001) and proxy carries no version
string; neither is retitled.
The api version is also stamped into the committed OpenAPI export
(docs/api/backend-openapi.generated.yaml → info.version), so the bump requires a make openapi
regeneration; the test_generated_openapi_export_is_current drift-guard fails otherwise. That step
is not yet in the release checklist — see Follow-ups below.
Per ADR 0025 decision 3, this is a minor: #396, #399, and #400 each require operator action,
so a patch tag would fail the version-consistency breaking-change gate. The number is not chosen
from a milestone — it is what has accumulated on main.
Honest scope — what did not ship
Section titled “Honest scope — what did not ship”Six of the 22 audit findings are closed here (all 3 High; GW-04, AG-01, API-04). The remainder of
#288 stays open and should each land with its finding ID in the commit subject (GW-02, Refs #288)
so the next narrative assembles the same way:
- Medium: GW-02 (client-settable anonymization/tier flags), GW-03 (embeddings egress enforces
neither anonymization nor tier floor), API-02 (
viewerrole defined but unenforced), API-03 (no login/MFA rate-limiting), AG-02 (MCP trusts server-attested safety metadata), D-02 (Electron navigation allowlist /sandbox:false), E-05 (EOL Electron 31). - Low: GW-05 (Presidio recognizers off by default), AG-03 (autonomous
max_allowed_tier=None), AG-04 (emit_artifactre-embeds model content), D-03 (Teamsid_tokenunverified), E-03 (root containers), E-02 remainder (signing +packages:writestill in the release job), E-04 (*_BIND_ADDRexposure), E-06 (floating community submodule ref). - Info: GW-06 (master key + gateway secret via plaintext env).
Release readiness
Section titled “Release readiness”Unblocked. ADR 0025 merged as #487, and this branch is rebased onto it — the
version-consistency gate and the staged pipeline are live and will run on the tag push.
Gates (maintainer, before tagging): api ruff/mypy + pytest; gateway ruff/mypy --strict +
pytest; web check:lq-ai + vitest; the stack-boot smoke; and the version-consistency job
(api == gateway == tag; not a patch while a breaking-change-labelled PR merged since v0.6.1).
Pre-flight, already satisfied:
apiandgateway__version__are both0.7.0; the OpenAPI export is regenerated to match.- #396, #399, and #400 carry the
breaking-changelabel, so the gate sees them andv0.7.0(a minor overv0.6.1) satisfies it.
Steps (maintainer):
- Merge this PR to
legalquants/main. - Tag
v0.7.0(annotated) on the merge commit and push it tolegalquants— the Release workflow builds + signs the four images and attaches the SBOM. Do not use[allow-version-drift]or[allow-breaking-in-patch]; neither is needed. - Verify the published image set before going further (ADR 0025 decision 4 gates backend before frontend, but the intra-stage guarantee is partial — confirm all four images carry the tag).
- Cut
desktop-v0.7.0after the image set is live and verified, recording the image tag it ships against (ADR 0025 decision 2).
Follow-ups this release surfaced
Section titled “Follow-ups this release surfaced”- The release checklist does not mention regenerating the OpenAPI export.
docs/BUILD-AND-RELEASE.md§“Versioning policy” tells the maintainer to bumpapiandgateway__version__, but the api version is also stamped intodocs/api/backend-openapi.generated.yaml, so a bump alone leaves CI red ontest_generated_openapi_export_is_current. It cost a red CI run on this release. Worth a one-line addition to the checklist. - The 2026-08-09 committee minutes are not published yet. ADR 0025’s Accepted status (and ADR 0024’s, from the same call) rests on the maintainer’s record of the call until they are. The minutes backlog is tracked separately — only two of the recent calls have public notes.
- ADR 0025’s contributor-concentration figures do not reconcile. Its Cadence section states
655 non-merge commits, ~642 (~98%) by one person across two identities, and “five distinct human
identities”; recounting at
b060ae2f— the SHA the ADR says it verified against — gives 704 commits, 665 (~94%) and eleven identities. The argument the section makes is unaffected: 94% is still overwhelming concentration, and the desktop signing bottleneck is unchanged. But the numbers should be corrected so this document and that one do not disagree on a countable fact.
Drafted from the v0.6.1..legalquants/main inventory on 2026-08-06 (35 commits) and refreshed
2026-08-10 against 460997b5 (40 commits), which added #313, #443, #487, #507, and #508. Security
context from #288 (Claude Fable 5). Remediation coverage verified against finding-ID commit subjects
on legalquants/main: GW-01 (#396), API-01 (#397), D-01 (#398), GW-04 (#400), AG-01 (#401) carry
Refs #288; API-04 is #399 (untagged). Version numbering per ADR 0025.
- Upgrade — the runbook for taking this release.
- Release versioning — what a patch and a minor each commit to.
- All release notes — every tag, and which have notes.