|
1 | 1 | # Changelog |
2 | 2 |
|
3 | | -## [Unreleased] |
| 3 | +## [0.5.0] - 2026-04-29 — Production, quality, and security hardening — upgrade encouraged |
4 | 4 |
|
5 | | -### Changed |
| 5 | +**Upgrade strongly recommended.** Over the past month we've shipped substantial production, quality, and security hardening across the AxonFlow plugin and platform — upgrade to the latest version for a more secure, reliable, and bug-free experience. |
| 6 | + |
| 7 | +**Security highlights from this release cycle:** |
| 8 | +- **Plugin cache and credential-file permission hardening** (this release). `~/.config/axonflow/` and `~/.cache/axonflow/` are tightened to mode `0700` on every invocation (was: only set on creation, leaving pre-existing world-readable directories unchanged); `try-registration.json` is written with mode `0600`. Pre-existing world-readable credential files are detected and refused on first load. Documented in [`GHSA-8wrg-fpx5-87f7`](https://github.com/getaxonflow/axonflow-codex-plugin/security/advisories/GHSA-8wrg-fpx5-87f7). |
| 9 | +- **Cross-platform bootstrap reliability** (this release). macOS Community-SaaS bootstrap was silently no-op'ing because `flock(1)` is Linux-only; now uses a portable `mkdir`-based atomic lock with stale-lock reclamation, so first-install registration runs on macOS too. |
| 10 | +- **Telemetry opt-out reliability** (this release). `DO_NOT_TRACK` was unreliable because Codex CLI itself injects `DO_NOT_TRACK=1` into hook subprocesses regardless of user intent; the canonical opt-out is now `AXONFLOW_TELEMETRY=off`, an AxonFlow-scoped signal hosts can't unilaterally set. |
| 11 | + |
| 12 | +The full set of platform-side security fixes shipped alongside this release — including multi-tenant isolation in MAP execution, cross-tenant audit-log isolation, and SQLi enforcement on the Community SaaS endpoint — is documented in the consolidated platform advisory [`GHSA-9h64-2846-7x7f`](https://github.com/getaxonflow/axonflow/security/advisories/GHSA-9h64-2846-7x7f). |
6 | 13 |
|
7 | | -- **Plugin defaults to AxonFlow Community SaaS on first run** when neither `AXONFLOW_ENDPOINT` nor `AXONFLOW_AUTH` is set. Existing self-hosted installs (anyone who has set either env var) are honoured untouched — no silent endpoint override. Hooks emit a one-line canary on stderr every invocation: `[AxonFlow] Connected to AxonFlow at <URL> (mode=community-saas|self-hosted)`. A required CI gate parses this canary and asserts it matches the actual outbound destination so users can never be misled about which AxonFlow they're connected to. |
8 | | -- **Anonymous telemetry switched to a 7-day heartbeat** with stamp-on-delivery semantics. Previously: a single stamp at install time, then silence forever. Now: at most one ping per machine per 7 days, gated by an in-flight `flock` so concurrent hook invocations don't stampede, and the stamp file mtime advances ONLY after the HTTP POST returns 2xx. A transient network failure no longer silences telemetry for 7 days. |
| 14 | +**Reliability and bug-fix highlights:** |
| 15 | +- **7-day delivered-heartbeat with stamp-on-success** (this release). Telemetry stamp advances only after the POST returns 2xx, so a transient network failure no longer silences telemetry until the next 7-day window. Concurrent invocations are de-duplicated by an in-flight gate. |
| 16 | +- **Mode-clarity canary log line** on every hook init (this release). Stderr emits `[AxonFlow] Connected to AxonFlow at <URL> (mode=...)` and a PR-blocking CI gate asserts the canary matches the actual outbound destination, guarding against silent endpoint drift. |
| 17 | +- **PR-blocking install-to-use smoke against the live community stack** (this release). Catches plugin-side regressions against `try.getaxonflow.com` before they reach a user's terminal. |
| 18 | + |
| 19 | +### BREAKING |
| 20 | + |
| 21 | +- **`DO_NOT_TRACK` is no longer honored as an AxonFlow telemetry opt-out.** Use `AXONFLOW_TELEMETRY=off` instead. Host tools and CLIs commonly inject `DO_NOT_TRACK=1` regardless of user intent, which makes it unreliable as a signal. |
9 | 22 |
|
10 | 23 | ### Added |
11 | 24 |
|
12 | | -- **First-run Community-SaaS bootstrap** (`scripts/community-saas-bootstrap.sh`) registers against `try.getaxonflow.com/api/v1/register` and persists `{tenant_id, secret, expires_at, endpoint}` to `~/.config/axonflow/try-registration.json` (mode 0600 inside a 0700 directory). The Basic-auth credential is loaded into `AXONFLOW_AUTH` for the rest of the hook lifecycle. Refuses to load a registration file with non-0600 permissions to prevent silent credential leak via a world-readable file. Honours HTTP 429 with a 1-hour backoff stamp. |
13 | | -- **One-time setup disclosure** on first Community-SaaS connection: a positive, journey-based message recommending self-host for real workflows. Stamped at `~/.cache/axonflow/codex-plugin-disclosure-shown` so it fires exactly once per install. |
14 | | -- **Mode-clarity gate** (`tests/mode-clarity.sh`) covers all 5 input combinations of `AXONFLOW_ENDPOINT` × `AXONFLOW_AUTH`. Anti-spoof: parses the URL and compares scheme + host + port (a lookalike domain like `try.getaxonflow.com.attacker.com` cannot pass a substring check). |
15 | | -- **Plugin/platform version compatibility check.** A new `scripts/version-check.sh` runs once per install (stamp-file guard) on the first hook invocation. It queries the AxonFlow agent's `/health` endpoint and reads the new `plugin_compatibility.min_plugin_version["codex"]` field. If the plugin's runtime version is below the floor the platform expects, the script logs a single upgrade hint to stderr; below recommended-but-above-min logs an info-level note; at or above recommended is silent. Fire-and-forget; failures never block hook execution. Skippable via `AXONFLOW_PLUGIN_VERSION_CHECK=off`. Mirrors the SDK-side downgrade-warning gate that has run since v4.8.0. |
| 25 | +- **First-run Community-SaaS bootstrap** — plugin connects to AxonFlow Community SaaS at `https://try.getaxonflow.com` when neither `AXONFLOW_ENDPOINT` nor `AXONFLOW_AUTH` is set. Registers via `/api/v1/register` on first run and persists `{tenant_id, secret, expires_at, endpoint}` to `~/.config/axonflow/try-registration.json` (mode 0600 inside a 0700 directory). Refuses to load a registration file with non-0600 permissions. HTTP 429 → 1-hour backoff. Existing self-hosted installs (`AXONFLOW_ENDPOINT` or `AXONFLOW_AUTH` set) are honoured untouched. |
| 26 | +- **Mode-clarity canary** on every hook init: `[AxonFlow] Connected to AxonFlow at <URL> (mode=community-saas|self-hosted)` on stderr. A CI gate parses this canary and asserts it matches the actual outbound destination. |
| 27 | +- **One-time setup disclosure** on first Community-SaaS connection. Stamped at `~/.cache/axonflow/codex-plugin-disclosure-shown` so it fires exactly once per install. |
| 28 | +- **Plugin/platform version compatibility check** (`scripts/version-check.sh`). Queries the agent's `/health` endpoint and warns if the plugin runtime is below the platform's expected floor. Skippable via `AXONFLOW_PLUGIN_VERSION_CHECK=off`. |
16 | 29 |
|
17 | | -### Removed |
| 30 | +### Changed |
18 | 31 |
|
19 | | -- **BREAKING:** `DO_NOT_TRACK=1` is no longer honored as an AxonFlow telemetry opt-out in this plugin. Use `AXONFLOW_TELEMETRY=off` instead. The Codex CLI injects `DO_NOT_TRACK=1` into every hook subprocess regardless of user intent, so it cannot represent a real user choice in this context. |
| 32 | +- **Telemetry switched to a 7-day delivered-heartbeat.** At most one anonymous ping per environment every 7 days, with the stamp advanced only after the POST returns 2xx — a transient network failure doesn't silence telemetry until the next window. Concurrent invocations are de-duplicated by an in-flight gate. |
20 | 33 |
|
21 | 34 | ### Fixed |
22 | 35 |
|
23 | | -- Telemetry ping now fires once per install on Codex. The previous behavior silently exited at the `DO_NOT_TRACK=1` check (injected by Codex), so the install ping never reached the stamp-file guard. |
24 | | -- The deprecation warning no longer leaks to stderr on every `PreToolUse` hook invocation, eliminating the noise that was getting concatenated with `AxonFlow policy violation` messages on blocked commands. |
25 | | -- Telemetry heartbeat now correctly classifies Community-SaaS sessions. The previous endpoint resolution fell into the localhost branch after the Community-SaaS bootstrap exported `AXONFLOW_AUTH` but intentionally left `AXONFLOW_ENDPOINT` unset; `/health` probes targeted localhost, `platform_version` shipped as `null`, and `deployment_mode` was tagged `production`. Resolution now keys off `AXONFLOW_MODE` first, so Community-SaaS users see the canonical endpoint and a dedicated `deployment_mode=community-saas` value. |
26 | | -- Community-SaaS bootstrap and telemetry heartbeat now run on macOS. Both scripts gated their in-flight lock on `flock(1)`, which ships in stock Linux but not in stock macOS; a missing `flock` short-circuited the entire bootstrap, leaving Community-SaaS users unauthenticated, and silenced the telemetry heartbeat. Both paths now fall back to a `mkdir`-based atomic lock with stale-lock reclamation when `flock` is unavailable. |
| 36 | +- The `DO_NOT_TRACK=1 is deprecated...` warning is no longer emitted on every hook invocation when `DO_NOT_TRACK=1` is set. |
| 37 | +- Telemetry heartbeat now correctly classifies Community-SaaS sessions (was tagged `production` because the bootstrap-injected `AXONFLOW_AUTH` shadowed the resolver, sending `/health` probes to localhost and `platform_version=null` with the wrong `deployment_mode`). |
| 38 | +- Bootstrap and heartbeat now run on macOS — `flock(1)` isn't on stock macOS, so the in-flight lock falls back to a `mkdir`-based atomic lock with stale-lock reclamation when `flock` is unavailable. |
27 | 39 |
|
28 | 40 | ### Security |
29 | 41 |
|
30 | | -- `~/.config/axonflow/` and `~/.cache/axonflow/` now have their permissions restored to `0700` on every invocation (was: only set on creation via `mkdir -m 0700`). A user who already had `~/.config/` at the conventional `0755` would otherwise hold the `0600` registration credential file inside a traversable directory. |
| 42 | +- `~/.config/axonflow/` and `~/.cache/axonflow/` permissions tightened to `0700` on every invocation (was: only set on creation via `mkdir -m 0700`, which left existing 0755 dirs unchanged). |
31 | 43 |
|
32 | 44 | ## [0.4.2] - 2026-04-22 |
33 | 45 |
|
|
0 commit comments