diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ea281d..2b25756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,16 @@ ## [Unreleased] -## [1.4.0] - 2026-05-08 +## [1.4.0] - 2026-05-09 ### Added -- **V1.1 `list-recent-decisions` skill** (axonflow-enterprise#1982). Drives the new `list_recent_decisions` MCP tool from Codex; Free-tier cap-hits render the V1 upgrade envelope verbatim. Plus `runtime-e2e/list-recent-decisions/` and a 7th over-cap scenario in `tests/e2e/runtime-mcp-tools.sh`. +- **V1.1 `list-recent-decisions` skill**. Drives the new `list_recent_decisions` MCP tool from Codex; Free-tier cap-hits render the V1 upgrade envelope verbatim. ### Telemetry -- v1 schema (axonflow-enterprise#2008): heartbeat now emits `telemetry_type: "plugin"`, `endpoint_type` (`localhost | private_network | remote | unknown`), and `AXONFLOW_TRY=1` to force `deployment_mode=community_saas` for tenants behind custom hostnames. -- `deployment_mode` allowlist normalised to `self_hosted | community_saas | unknown` (was `production`/`development`/`community-saas`). Analytics queries on the legacy values must update. +- **`AXONFLOW_TELEMETRY=off` is the sole opt-out** for the plugin heartbeat — same single-lever model as the SDKs. +- **Heartbeat payload v1 schema additions**: `telemetry_type: "plugin"`, `endpoint_type` (`localhost | private_network | remote | unknown`), `deployment_mode` (`self_hosted | community_saas | unknown`). Set `AXONFLOW_TRY=1` if your stack proxies a custom hostname into try.getaxonflow.com so heartbeats classify as `community_saas` correctly. ## [1.3.0] - 2026-05-07 — V1 Plugin Pro upgrade-prompt envelope + 5 new MCP tools surfaced @@ -22,62 +22,62 @@ SaaS rate-limit hits and documents 5 new agent-callable MCP tools. ### Added - **V1 Plugin Pro upgrade-prompt envelope handling** in both - `pre-tool-check.sh` (PreToolUse-equivalent) and `post-tool-audit.sh` - (PostToolUse-equivalent) hooks. When the agent returns a 429 - (daily-quota) or 403 (graduated / Pro-only) with the structured - envelope shape, the plugin: - - Parses `upgrade.wording` + `upgrade.buy_url` and prints a single-line - nudge to stderr (e.g. `[AxonFlow] Daily limit reached on Free tier - (200 events). Pro raises this to 2,000/day. Resets at midnight UTC.`). - Surfaced at most once per UTC day so it doesn't spam every hook. - - Honours `Retry-After` / `resets_at` by stamping a back-off file at - `${XDG_CACHE_HOME:-~/.cache}/axonflow/throttle-until`. Subsequent hook - fires fall open locally without re-hammering the agent until the - deadline passes. Prevents the silent-retry pattern (581 retries in - 18h pre-envelope) that motivated this work. + `pre-tool-check.sh` (PreToolUse-equivalent) and `post-tool-audit.sh` + (PostToolUse-equivalent) hooks. When the agent returns a 429 + (daily-quota) or 403 (graduated / Pro-only) with the structured + envelope shape, the plugin: + - Parses `upgrade.wording` + `upgrade.buy_url` and prints a single-line + nudge to stderr (e.g. `[AxonFlow] Daily limit reached on Free tier + (200 events). Pro raises this to 2,000/day. Resets at midnight UTC.`). + Surfaced at most once per UTC day so it doesn't spam every hook. + - Honours `Retry-After` / `resets_at` by stamping a back-off file at + `${XDG_CACHE_HOME:-~/.cache}/axonflow/throttle-until`. Subsequent hook + fires fall open locally without re-hammering the agent until the + deadline passes. Prevents the silent-retry pattern (581 retries in + 18h pre-envelope) that motivated this work. - **References to the 5 new agent-callable MCP tools** in the README. - The agent can answer `"what's my tenant ID?"`, `"what would I get on - Pro?"`, and related questions directly via: - - `axonflow_get_tenant_id` — Free + Pro, no gate. - - `axonflow_list_pro_features` — Free + Pro, locked feature list. - - `axonflow_request_approval` — Free 1/7d rolling, Pro unlimited. - - `axonflow_create_tenant_policy` — Free 2 active max, Pro unlimited. - - `axonflow_get_cost_estimate` — Pro-only, hidden from Free `tools/list`. + The agent can answer `"what's my tenant ID?"`, `"what would I get on + Pro?"`, and related questions directly via: + - `axonflow_get_tenant_id` — Free + Pro, no gate. + - `axonflow_list_pro_features` — Free + Pro, locked feature list. + - `axonflow_request_approval` — Free 1/7d rolling, Pro unlimited. + - `axonflow_create_tenant_policy` — Free 2 active max, Pro unlimited. + - `axonflow_get_cost_estimate` — Pro-only, hidden from Free `tools/list`. - Auto-discovered via the existing MCP HTTP transport — no client-side - registration needed. + Auto-discovered via the existing MCP HTTP transport — no client-side + registration needed. ### Changed - **README "Pro tier license token" section** corrected to the locked V1 - numbers: 2,000 events/day (was 1,000), unlimited custom policies, - unlimited HITL approvals, and the LLM cost pre-flight feature added. + numbers: 2,000 events/day (was 1,000), unlimited custom policies, + unlimited HITL approvals, and the LLM cost pre-flight feature added. - **README MCP-tools section** renumbered from "10 MCP tools" to "15 MCP - tools" to include the new V1 Pro tier-identity / tier-capability tools. + tools" to include the new V1 Pro tier-identity / tier-capability tools. - **`pro-tier-status` skill — prefer the local - `scripts/recover.sh status` over the MCP tool** for tenant_id / tier - queries. The local script reads state directly and answers without - an agent round-trip. Faster, works offline, and works exactly when - the user typically asks ("the agent isn't reachable, what's my - tenant ID for Stripe Checkout?"). The MCP tool stays as a - documented fallback for the rare cases where server-truth matters - (revocation, clock skew, server-side overrides). Same flip applied - to claude / cursor sister plugins. + `scripts/recover.sh status` over the MCP tool** for tenant_id / tier + queries. The local script reads state directly and answers without + an agent round-trip. Faster, works offline, and works exactly when + the user typically asks ("the agent isn't reachable, what's my + tenant ID for Stripe Checkout?"). The MCP tool stays as a + documented fallback for the rare cases where server-truth matters + (revocation, clock skew, server-side overrides). Same flip applied + to claude / cursor sister plugins. ### Internal -- `runtime-e2e/v1_pro_envelope_surface/` — drives a fresh Free-tier - tenant past the 200/day cap on `try.getaxonflow.com`, asserts the - plugin's envelope helper prints the locked V1 wording to stderr - and stamps a throttle deadline. +- the runtime test bundle — drives a fresh Free-tier + tenant past the 200/day cap on `try.getaxonflow.com`, asserts the + plugin's envelope helper prints the locked V1 wording to stderr + and stamps a throttle deadline. - Added `tests/test-upgrade-prompt.sh` — 21 unit assertions across 8 - scenarios for every branch of the envelope handler. + scenarios for every branch of the envelope handler. - Added `tests/test-skill-status-prefers-local.sh` — 4 content assertions - locking the local-first SKILL.md ordering in; wired into - `.github/workflows/test.yml`. The sister `axonflow-claude-plugin` - ships the runtime proof that the wording flip changes downstream - LLM behaviour (structurally identical wording across the three - plugins). + locking the local-first SKILL.md ordering in; wired into + `.github/workflows/test.yml`. The sister `axonflow-claude-plugin` + ships the runtime proof that the wording flip changes downstream + LLM behaviour (structurally identical wording across the three + plugins). ## [1.2.0] - 2026-05-06 — V1 paid Pro tier wire-up + X-Axonflow-Client header @@ -89,45 +89,45 @@ the agent-side scope-validation header on every governed request via ### Added - **`X-Axonflow-Client: codex/` header** on every governed - agent request. Declared via `.mcp.json`'s `http_headers` block (set up - by `scripts/install-mcp-with-headers.sh` at install time) and exported - as `${AXONFLOW_CLIENT_HEADER}` by `pre-tool-check.sh` on every - hook-invoke. Agents at v7.7.0+ derive request scope from this header - and reject cross-quadrant token misuse (e.g. a SaaS Plugin Pro token - paired with an SDK request) at the validator boundary. Older agents - (pre-v7.7.0) ignore the header and continue to work unchanged. + agent request. Declared via `.mcp.json`'s `http_headers` block (set up + by `scripts/install-mcp-with-headers.sh` at install time) and exported + as `${AXONFLOW_CLIENT_HEADER}` by `pre-tool-check.sh` on every + hook-invoke. Agents at v7.7.0+ derive request scope from this header + and reject cross-quadrant token misuse (e.g. a SaaS Plugin Pro token + paired with an SDK request) at the validator boundary. Older agents + (pre-v7.7.0) ignore the header and continue to work unchanged. ### Changed - **`scripts/recover.sh status` tier line now surfaces Pro license expiry date.** The status output's `tier` line parses the JWT `exp` claim from the configured Pro license token and renders one of three shapes: `Pro tier active (expires YYYY-MM-DD, N days remaining)` when active, `Free tier (Pro expired YYYY-MM-DD — visit https://getaxonflow.com/pricing/ to renew)` when the token is on disk but its `exp` has passed (plugin will not forward an expired token), or `Free tier (no AXON- license token configured)` when no token is loaded. Lets users see their renewal date without hitting the agent and catches the lapsed-token state before their next governed call. Display only — JWT signature validation remains the platform's job. Pre-existing `Pro tier active` and `Free tier` substring assertions still hold. -- **`scripts/recover.sh status` now surfaces tenant_id + upgrade URL.** Free-tier users need to find their `tenant_id` (`cs_`) to paste into the Stripe Checkout custom field at `getaxonflow.com/pricing/`. The status output now reads `~/.config/axonflow/try-registration.json` (the auto-bootstrap registration file) and prints the tenant_id alongside endpoint + license-token state. Adds an `upgrade` line (default `https://getaxonflow.com/pricing/`, override via `AXONFLOW_UPGRADE_URL`) and copy-paste-ready upgrade instructions. Token still redacted to last 4 chars (no full bearer credential in stdout — see PR #41). +- **`scripts/recover.sh status` now surfaces tenant_id + upgrade URL.** Free-tier users need to find their `tenant_id` (`cs_`) to paste into the Stripe Checkout custom field at `getaxonflow.com/pricing/`. The status output now reads `~/.config/axonflow/try-registration.json` (the auto-bootstrap registration file) and prints the tenant_id alongside endpoint + license-token state. Adds an `upgrade` line (default `https://getaxonflow.com/pricing/`, override via `AXONFLOW_UPGRADE_URL`) and copy-paste-ready upgrade instructions. Token still redacted to last 4 chars (no full bearer credential in stdout — see this release). ### Added -- **V1 paid Pro tier — `X-License-Token` wire-up.** When `AXONFLOW_LICENSE_TOKEN` is set in the environment, or `license_token = "AXON-..."` is present in `~/.codex/axonflow.toml`, the plugin forwards the token as the `X-License-Token` HTTP header on every governed request (pre-tool policy check, post-tool audit + scan, and the long-lived MCP session). The agent's plugin-claim middleware validates the token's Ed25519 signature and database row, then enriches the request context with Pro-tier capabilities (longer audit retention, larger payload caps, higher daily quotas). Token absence is the free tier — no header is sent. Tokens that don't carry the canonical `AXON-` prefix are filtered out before the request leaves the plugin so the agent never sees garbage. +- **V1 paid Pro tier — `X-License-Token` wire-up.** When `AXONFLOW_LICENSE_TOKEN` is set in the environment, or `license_token = "AXON-."` is present in `~/.codex/axonflow.toml`, the plugin forwards the token as the `X-License-Token` HTTP header on every governed request (pre-tool policy check, post-tool audit + scan, and the long-lived MCP session). The agent's plugin-claim middleware validates the token's Ed25519 signature and database row, then enriches the request context with Pro-tier capabilities (longer audit retention, larger payload caps, higher daily quotas). Token absence is the free tier — no header is sent. Tokens that don't carry the canonical `AXON-` prefix are filtered out before the request leaves the plugin so the agent never sees garbage. - **Credential & license-token recovery surface — `scripts/recover.sh`.** Four sub-flows for users who need to manage credentials without leaving Codex: - - `request` — POSTs `/api/v1/recover` with the user's email so the agent emails a magic link with a one-time token. - - `verify` — POSTs `/api/v1/recover/verify` with the pasted token, then atomically persists the returned `tenant_id`, `secret`, `endpoint`, and `email` into `~/.codex/axonflow.toml` (mode `0600`, inside a `0700` parent). An existing `license_token` line is preserved so credential recovery never silently downgrades a Pro-tier user to the free tier. - - `apply-token` — persists a freshly-issued `AXON-...` Pro-tier license token into the same TOML file. - - `status` — reports the active endpoint, config file presence, license token presence, and current tier. - The same script powers two new agent-callable skills (`recover-credentials`, `pro-tier-status`) so Codex can guide a user through the flow when they say "I lost my credentials" or "am I on Pro?". For automation and runtime tests the script also reads `AXONFLOW_RECOVER_EMAIL`, `AXONFLOW_RECOVER_TOKEN`, and `AXONFLOW_LICENSE_TOKEN` from the environment instead of prompting. + - `request` — POSTs `/api/v1/recover` with the user's email so the agent emails a magic link with a one-time token. + - `verify` — POSTs `/api/v1/recover/verify` with the pasted token, then atomically persists the returned `tenant_id`, `secret`, `endpoint`, and `email` into `~/.codex/axonflow.toml` (mode `0600`, inside a `0700` parent). An existing `license_token` line is preserved so credential recovery never silently downgrades a Pro-tier user to the free tier. + - `apply-token` — persists a freshly-issued `AXON-.` Pro-tier license token into the same TOML file. + - `status` — reports the active endpoint, config file presence, license token presence, and current tier. + The same script powers two new agent-callable skills (`recover-credentials`, `pro-tier-status`) so Codex can guide a user through the flow when they say "I lost my credentials" or "am I on Pro?". For automation and runtime tests the script also reads `AXONFLOW_RECOVER_EMAIL`, `AXONFLOW_RECOVER_TOKEN`, and `AXONFLOW_LICENSE_TOKEN` from the environment instead of prompting. - **Runtime E2E coverage** for both surfaces: - - `runtime-e2e/v1-paid-tier/test.sh` — drives the pre-tool hook against a local capture server and asserts the `X-License-Token` header is sent (env, TOML, env-overrides-TOML, absence, malformed) plus the live agent middleware path when `/health` advertises `plugin_claim_license`. - - `runtime-e2e/recovery/test.sh` — drives `recover.sh` against a local fake recovery agent and asserts the full request → verify → persist → status path, including replay rejection and `license_token` preservation across credential re-recovery. + - the runtime test bundle — drives the pre-tool hook against a local capture server and asserts the `X-License-Token` header is sent (env, TOML, env-overrides-TOML, absence, malformed) plus the live agent middleware path when `/health` advertises `plugin_claim_license`. + - the runtime test bundle — drives `recover.sh` against a local fake recovery agent and asserts the full request → verify → persist → status path, including replay rejection and `license_token` preservation across credential re-recovery. ### Fixed -- **Upgrade-pointer URL aligned with the canonical pricing page.** `AXONFLOW_UPGRADE_URL` default (the URL surfaced by `scripts/recover.sh status` and the `pro-tier-status` skill to free-tier users, plus embedded in the `tier Free tier (Pro expired ... — visit ... to renew)` line) is now `https://getaxonflow.com/pricing/`. The previous default `https://getaxonflow.com/pro` returned 404 — that page was referenced in PRDs but never built. The pricing page already resolves and carries the Plugin Pro $9.99 tier card with the Stripe buy button, so plugin status output now points free-tier users at a working URL. Override via `AXONFLOW_UPGRADE_URL` env var if needed. Same fix landed in companion plugin releases (openclaw-plugin v2.2.0, claude-plugin v1.2.0, cursor-plugin v1.2.0). +- **Upgrade-pointer URL aligned with the canonical pricing page.** `AXONFLOW_UPGRADE_URL` default (the URL surfaced by `scripts/recover.sh status` and the `pro-tier-status` skill to free-tier users, plus embedded in the `tier Free tier (Pro expired. — visit. to renew)` line) is now `https://getaxonflow.com/pricing/`. The previous default `https://getaxonflow.com/pro` returned 404 — that page was referenced in PRDs but never built. The pricing page already resolves and carries the Plugin Pro $9.99 tier card with the Stripe buy button, so plugin status output now points free-tier users at a working URL. Override via `AXONFLOW_UPGRADE_URL` env var if needed. Same fix landed in companion plugin releases (openclaw-plugin v2.2.0, claude-plugin v1.2.0, cursor-plugin v1.2.0). ## [1.1.0] - 2026-05-04 — 4 read-side governance skills ### Added - **4 new agent-callable governance skills.** Codex agents can use the - AxonFlow read-side governance surface directly in conversation: - `explain-decision`, `list-overrides`, `create-override`, and - `revoke-override`. Joins the existing `audit-search` skill for full - read-side parity. + AxonFlow read-side governance surface directly in conversation: + `explain-decision`, `list-overrides`, `create-override`, and + `revoke-override`. Joins the existing `audit-search` skill for full + read-side parity. ## [1.0.0] - 2026-04-29 — Production, quality, and security hardening — upgrade encouraged @@ -142,7 +142,7 @@ The full set of platform-side security fixes shipped alongside this release — **Reliability and bug-fix highlights:** - **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. -- **Mode-clarity canary log line** on every hook init (this release). Stderr emits `[AxonFlow] Connected to AxonFlow at (mode=...)` and a PR-blocking CI gate asserts the canary matches the actual outbound destination, guarding against silent endpoint drift. +- **Mode-clarity canary log line** on every hook init (this release). Stderr emits `[AxonFlow] Connected to AxonFlow at (mode=.)` and a PR-blocking CI gate asserts the canary matches the actual outbound destination, guarding against silent endpoint drift. - **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. ### BREAKING @@ -162,7 +162,7 @@ The full set of platform-side security fixes shipped alongside this release — ### Fixed -- The `DO_NOT_TRACK=1 is deprecated...` warning is no longer emitted on every hook invocation when `DO_NOT_TRACK=1` is set. +- The `DO_NOT_TRACK=1 is deprecated.` warning is no longer emitted on every hook invocation when `DO_NOT_TRACK=1` is set. - 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`). - 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. @@ -180,32 +180,32 @@ The full set of platform-side security fixes shipped alongside this release — ### Added -- **Smoke E2E scenario** at `tests/e2e/smoke-block-context.sh` — runs - `pre-tool-check.sh` against a reachable AxonFlow stack and asserts the - hook exits 2 with `AxonFlow policy violation` + Plugin Batch 1 - richer-context markers on stderr. Exits 0 (`SKIP:`) when no stack is - reachable. +- **Smoke E2E scenario** at the e2e test suite — runs + `pre-tool-check.sh` against a reachable AxonFlow stack and asserts the + hook exits 2 with `AxonFlow policy violation` + Plugin Batch 1 + richer-context markers on stderr. Exits 0 (`SKIP:`) when no stack is + reachable. - **`.github/workflows/smoke-e2e.yml`** — `workflow_dispatch` triggered job running the smoke scenario. - Requires an operator-supplied endpoint (GitHub-hosted runners have no - local stack), so not wired to PR events — PR smoke gating needs a - self-hosted runner with a live stack. + Requires an operator-supplied endpoint (GitHub-hosted runners have no + local stack), so not wired to PR events — PR smoke gating needs a + self-hosted runner with a live stack. -Full install-and-use matrix lives in `axonflow-enterprise/tests/e2e/plugin-batch-1/codex-install/`. +Install-and-use matrix is exercised in the platform integration tests. ## [0.4.0] - 2026-04-18 ### Added - **Richer block reason surfaced to Codex on exec_command blocks.** When - the AxonFlow platform is v7.1.0+, the stderr message accompanying the - `exit 2` block now includes `[decision: , risk: , active - override: ]` or a pointer to the `explain_decision` MCP tool. Older - platforms see the prior v0.3.0 message — fields are omitted when not - returned. + the AxonFlow platform is v7.1.0+, the stderr message accompanying the + `exit 2` block now includes `[decision: , risk: , active + override: ]` or a pointer to the `explain_decision` MCP tool. Older + platforms see the prior v0.3.0 message — fields are omitted when not + returned. - **Access to platform MCP tools** `explain_decision`, `create_override`, - `delete_override`, `list_overrides` — available via the agent's MCP - server when connected to a v7.1.0+ platform. Codex's existing `audit-search` - skill pattern applies analogously for these new tools. + `delete_override`, `list_overrides` — available via the agent's MCP + server when connected to a v7.1.0+ platform. Codex's existing `audit-search` + skill pattern applies analogously for these new tools. ### Compatibility