Skip to content

Releases: olafkfreund/AIFactory

v3.10.12

Choose a tag to compare

@github-actions github-actions released this 27 Oct 15:17
ec354c0

Five behaviour changes: acw_ API keys authenticate for the first time
(with expiry, owner status, a live role cap and org binding), viewers can
no longer mint write-scoped keys, a JWT role=admin no longer bypasses org
checks, GET /api/admin/access-review takes only ?org_id, and
GET /api/audit/export needs org admin. Remote MCP now authorizes each call
as the calling key; it stays off by default (AIFACTORY_MCP_REMOTE_ENABLED).
A task needing plan review now always pauses after its planner, and
auto-fix routes need project roles. One new env var:
AIFACTORY_AGENT_COMMIT_TRAILERS (default off). The model
gateway ships as a separate -gateway image that nothing deploys. No
migrations.

Changed

  • acw_ keys authenticate (#1914, closes #1913). Before, every real key
    failed (REST 401, stdio and remote MCP 500). The lookup now refuses a key
    whose owner is missing or deactivated, a key past expires_at, a key whose
    org is deleted, and a key with no effective scopes. Effective scopes follow
    the owner's current role in key.org_id (below member: mcp:read only; no
    membership: none). REST needs the explicit api scope. Key principals are
    bound to key.org_id for project access, list filters, project create,
    org-role routes and git-credential routes. Mint with expires_in_days now
    works on Postgres.
  • Viewers cannot mint write-scoped keys (#1911, closes #1908).
    POST /api/keys gives a caller below member a 403 for any scope other
    than mcp:read. Existing keys are not revoked (#1914 caps them live).
  • is_service_principal trusts only is_service (#1911, closes #1909).
    A JWT with role=admin no longer bypasses org checks. Auth-disabled dev
    principals are marked is_service, so dev mode is unchanged.
  • GET /api/admin/access-review streams only the gated org (#1916, closes
    #1915).
    It takes only ?org_id; ?org is gone. Before,
    ?org_id=A&org=B let an admin of A read B's roster.
  • GET /api/audit/export requires org admin (#1916). Non-service callers
    must pass org_id and hold admin in it (read from the DB). An acw_ key
    can export only its own org. Service principals are unchanged.
  • Remote MCP authorizes each tool call as the calling key (#1917, closes
    #1910).
    Read tools need viewer and write tools need member on the
    project the call proxies to; list_projects is filtered to the key's org;
    ids are validated against path escapes; an SSE session accepts messages
    only from the key that opened it. Remote MCP stays off unless
    AIFACTORY_MCP_REMOTE_ENABLED is set; it is not set in factory-gitops.
  • Plan-review gate decided from pre-planner state (#1926, closes #1922).
    A task that needs plan review always pauses after its planner session; a
    planner clearing the flag or forging review_state.json has no effect.
    An approval without spec_hash no longer counts. Start passes --force
    only on a hash-valid approval or the server's task_control.planApproved
    record (set by approve-plan, cleared by reject-plan and any plan-review
    pause); otherwise the task is held in plan review.
  • Auto-fix routes need project roles; reused specs are not forced past
    review (#1928, closes #1925).
    GET queue needs viewer; GET config,
    check-new and {N}/start need member; PUT config needs admin. GET
    config returns the bot token masked (********); PUT keeps the stored
    token on the mask or a missing field, and "" clears it. Starting an
    issue whose spec already exists no longer forces past plan review.
    requireHumanApproval now sets requireReviewBeforeCoding on created
    specs.
  • Worktree spec sync mirrors only allowlisted build files (#1923, closes
    #1921).
    On the subprocess backend an agent could overwrite canonical
    task_metadata.json, review_state.json, COMPLETED.json and others
    from its worktree. Only token_usage.json, guardrail_halt.json and
    handback_received.json are mirrored now. Kubejob builds never ran this
    sync.

Added

  • Agent commit trailers, off by default (#1907, Factory#1960 slice 3).
    AIFACTORY_AGENT_COMMIT_TRAILERS adds Agent-Identity, Autonomy-Tier
    and Originator trailers to AIFactory's parallel-wave and safety-net
    commits. Off leaves the commit argv unchanged. With the flag on, the
    local merge --no-ff, the Approve squash and the PR-endgame auto-merge
    carry them too, and the squash body becomes only the trailer block
    (#1918).
  • Model gateway image (#1912, Factory#1959 stage 0a).
    ghcr.io/olafkfreund/aifactory:{sha-*,latest,v*}-gateway, built and
    Trivy-scanned on PRs, cosign-signed by digest on deploy and release, and
    SBOM-attested on release. Its own env vars (GATEWAY_UPSTREAM_URL,
    GATEWAY_UPSTREAM_API_KEY, GATEWAY_CLIENT_TOKEN, GATEWAY_PORT) apply
    to the gateway container only. Nothing deploys it.

Deprecated

  • The LiteLLM sub-chart (#1912). Chart comments and a docs admonition
    only; removal is a later slice.

v3.10.11

Choose a tag to compare

@github-actions github-actions released this 27 Oct 09:24
89db686

Four behaviour changes: APP_DEBUG no longer relaxes the disable-auth or
wildcard-CORS boot guards (each has its own opt-in), and
POST /api/tasks/from-issue now checks project membership and binds a
declared repo to the project's own repo.
Four new env vars: APP_ALLOW_INSECURE_AUTH, APP_ALLOW_WILDCARD_CORS
(both default false), AIFACTORY_ROUTE_RESOLUTION (default off) and
AIFACTORY_MODEL_CATALOG_PATH (default unset). No migrations.

Changed

  • APP_DISABLE_AUTH off loopback needs APP_ALLOW_INSECURE_AUTH (#1895,
    Factory#312).
    APP_DEBUG=true alone no longer lets the server boot with
    auth disabled on a non-loopback host. Same name as PFactory and TFactory.
    Never set in production.
  • A wildcard CORS origin needs APP_ALLOW_WILDCARD_CORS (#1902,
    Factory#312).
    APP_DEBUG=true alone no longer lets the server boot with
    * in APP_CORS_ORIGINS. With the opt-in it still warns and turns off
    credentialed CORS. An explicit allowlist is unchanged.
  • POST /api/tasks/from-issue requires member on the target project
    (#1899, closes #1898).
    A foreign acw_ key gets 403. The legacy service
    token (intake poller) is unaffected.
  • A repo declared to POST /api/tasks/from-issue must be the project's
    own repo (#1901, closes #1900).
    Host, path and provider are compared
    against the project's gitRepo, clonedFrom and checkout origin;
    anything else, or a declaration on a project with no known repo, gets 400.
    A request without repo is unchanged.

Added

  • Catalog route resolution, off by default (#1896, Factory#1959 slice 5).
    AIFACTORY_ROUTE_RESOLUTION (off/shadow/on) resolves a contract
    route tier to a model from the RFC-0014 catalog at
    AIFACTORY_MODEL_CATALOG_PATH, replacing only the built-in DEFAULT_TIERS
    fallback. Run shadow first: the catalog must mark superseded models
    available: false.
  • Task originator recorded at intake (#1897, Factory#1960 slice 2).
    originator and agent_identity are stored in the spec's
    requirements.json for MCP, REST/CLI, project and GitHub-import intake
    (from-issue only when fetched through the project's provider), and returned
    by GET /api/tasks/{id}. Unknown stays null. No migration.

Fixed

  • Comma-separated APP_CORS_ORIGINS no longer crashes boot; a null
    origin is treated like * (#1904, closes #1903).
    An empty
    APP_CORS_ORIGINS= now means no origins; unset keeps the localhost
    defaults.

CI and tests

  • Triage tests import server.config one way (#1894, clears a CodeQL note
    from #1892).

v3.10.10

Choose a tag to compare

@github-actions github-actions released this 26 Oct 20:39
81da17d

Two behaviour changes: the stdio-MCP task proxies now enforce project access,
and an acw_ key can no longer mint keys.
One alembic migration (7a1f3c9e2b50, adds api_keys.autonomy_ceiling).

Changed

  • MCP task proxies enforce project access (#1885, closes #1882; #1891).
    /api/mcp-stdio/... routes now check the acw_ key owner's project role as
    the REST routes do, after the scope check. Write routes (create-and-run,
    start, stop, recover, approve-plan, apply-correction, create-pr, merge) need
    member; read routes (task details, status, logs, diff) need viewer and
    return 403/404 for a foreign project. /projects, /tasks and
    /tasks/running are filtered to the key owner's orgs. The legacy service
    token and an acw_ key with no user stay service principals and are
    unaffected.
  • An acw_ key can no longer mint keys (#1887). POST /api/keys with an
    acw_ key gets a 403; mint keys with a user session.

Added

  • Autonomy ceiling and agent identity on acw_ keys (#1887,
    Factory#1960 slice 1).
    New nullable ApiKey.autonomy_ceiling
    (low/medium/hard, no default) via alembic 7a1f3c9e2b50, and a derived
    agent_identity (agent:aifactory/<key_id>). The key create and list routes
    accept and return them. Only an org admin can set a ceiling (403
    otherwise). Not wired into the merge path yet, so no merge
    decision changes.
  • MCP task_apply_correction passes triage through (#1881, closes #1874).
    Adds the missing POST /api/mcp-stdio/tasks/{task_id}/apply-correction
    proxy route (gated by task:write), so the MCP tool works again under the
    3.10.9 triage default. A 422 without triage now explains both fixes.
  • TFactory ingest forwards the pre-overlay signed contract (#1883,
    TFactory#1432).
    Sent as top-level signed_contract for signed, non-held
    contracts; contract is unchanged. Warn mode only on the TFactory side.

Fixed

  • Completion webhook sends APP_API_TOKEN to CFactory (#1888,
    CFactory#501).
    Completion and outbox POSTs to /api/events carry
    Authorization: Bearer $APP_API_TOKEN, only when the target matches the
    configured webhook origin. No token, no header. CFactory is in warn mode.
  • GET /api/tasks?project_id=<unknown> returns 404, not 500 (#1890, closes
    #1889).
    Also fixes the MCP task_list proxy.
  • SBOM attestation fits rekor's size limit (#1884, closes #1879). Each
    image's SPDX SBOM is attested without file entries (packages kept), after
    the 3.10.9 -nix attestation exceeded rekor's 24 MiB request limit.

CI and tests

  • P0 acceptance image build is cached in a gha layer cache (#1880, closes
    #1875).
  • Test pins the provider credentials that reach dispatched Jobs (#1886,
    Factory#1959).

Chores

  • Baked agent-CLI pins: claude-code 2.1.310, gemini-cli 0.65.0, codex 0.164.0
    (#1871).

v3.10.9

Choose a tag to compare

@github-actions github-actions released this 26 Oct 13:36
f9c74a8

Two behaviour changes: the runtime image moves to CPython 3.15, and
apply-correction now requires a triage block by default.

Changed

  • Runtime image moves to CPython 3.15 (#1873, closes #1842). The image is
    built on the current cgr.dev/chainguard/python:latest-dev digest
    (CPython 3.15.0). A new py-build stage compiles the venv; lxml, xmlsec and
    real-ladybug build from sdist with --require-hashes kept, and runtime
    adds the system xmlsec/libxml2-16/libxslt libraries. The lock is
    recompiled for 3.15 (pydantic 2.14, asyncpg 0.32, grpcio 1.84.1, uvloop 0.23
    and others). The CI P0 docker job now allows a 1800 s image build in a
    50-minute job.
  • Apply-correction requires a triage block by default (#1872,
    TFactory#1431).
    APP_REQUIRE_CORRECTION_TRIAGE now defaults to on: a
    POST /api/tasks/{id}/apply-correction with no triage block, including a
    markdown-only call, gets a 422 before anything is written. TFactory 0.9.42
    sends triage on every handback path (TFactory#1436). Opt out with
    APP_REQUIRE_CORRECTION_TRIAGE=false. Known gap: the MCP
    task_apply_correction tool has no triage input yet, so it also gets the 422
    until #1874 lands.

Security

  • Outbound PII scrub on direct claude --print spawns (#1870, closes
    #1860).
    Clarification and insights task-from-chat now scrub the prompt
    before building argv, honouring the kill-switch and the project data
    classification as in #1862. Clarification fails closed to its skip default.

v3.10.8

Choose a tag to compare

@github-actions github-actions released this 24 Oct 14:17
3d98a46

Security

  • Outbound PII scrub is mandatory for regulated projects (#1862,
    Factory#320).
    A new project setting dataClassification
    (public|internal|confidential|regulated) is stored as
    AIFACTORY_DATA_CLASSIFICATION. Projects classified regulated now always
    get outbound PII scrubbing: the LITELLM_AUDIT_SCRUB_OUTBOUND=false
    kill-switch and per-adapter _scrub_outbound pins are ignored for them, and
    an unreadable settings store fails closed to regulated. The default
    classification stays internal, and the other tiers are unchanged. A bad
    value is a 422. Direct claude --print spawns are a known gap, tracked in
    #1860.

Added

  • Verify verdict and vote split as PR evidence (#1863, Factory#1963).
    Auto-merge PRs get a "Verify evidence" section in the body with the verify
    verdict, TFactory's vote split and the floor signals (host CI, VAL against
    the floor, CI parity). The verdict is evidence; the deterministic floor still
    decides, and a write failure never changes the gate result.
  • Optional APP_REQUIRE_CORRECTION_TRIAGE gate (#1861, closes #1858). When
    on, POST /api/tasks/{id}/apply-correction rejects a request with no
    triage block with a 422 before anything is written. Default off until
    TFactory skills post a triage block (TFactory#1430).
  • Memory duplicate-rate baseline (#1856, RFC-0021, #389).
    scripts/memory_dup_baseline.py and the first measured baseline in
    docs/dev/memory-baseline-2026-10.md.

Chores

  • Weekly CodeQL ratchet caller and baseline (#1857, Factory#813).
  • vite 7.3.6 -> 7.3.7 (#1849); @vitest/mocker and vitest bump (#1850).

v3.10.7

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:49
d769f47

Fixed

  • Four real CodeQL hygiene alerts (#1853, Factory#813). The
    _refresh_to_remote_base log lines now pass branch, path and git stderr
    through sanitize_log (log injection), a no-op terminal_status
    self-assignment is gone, and _WrappedResponseStream._capture initialises
    msg_type before its try, with a regression test.

Tests

  • A pass verdict cannot merge past a red floor (#1854, Factory#1963). An
    end-to-end test through run_pr_endgame and the real watch_and_finish
    proves that red host CI, VAL below the floor, or ci_parity false never
    calls merge_pr.

Chores

  • follow-redirects 1.16.0 -> 1.16.1 in /docs (#1845).

v3.10.6

Choose a tag to compare

@github-actions github-actions released this 24 Oct 11:03
1864519

Security

  • npm-bundled undici 6.29.1 and brotli floors (#1851). The npm
    vendored-deps overlay moves undici 6.28.1 -> 6.29.1 (CVE-2026-109869) and apk
    floors pull libbrotlicommon1/libbrotlidec1/libbrotlienc1 to 1.2.0-r7
    (CVE-2026-111497), clearing the new HIGH CVEs the Trivy P0 gate reported.
  • dompurify 3.4.17 (#1851). The override floor moves to ^3.4.17, past
    GHSA-cg2g-xh64-v4q7 (critical) and GHSA-mrv2-3pqr-j5jr, which failed the
    Trivy P0 gate on the frontend lockfile.

v3.10.5

Choose a tag to compare

@github-actions github-actions released this 22 Oct 15:58
2296368

Security

  • Runtime image floors (#1841). apk floors pull curl and
    libcurl-openssl4 to 8.23.0-r0 and ca-certificates-bundle to
    20260909-r3, and certifi moves to 2026.10.19, clearing the new HIGH CVEs the
    Trivy P0 gate reported.
  • apk del no longer pretends to remove py3-pip-wheel (#1844,
    TFactory#1350).
    python-3.14 depends on it, so apk refused and exited 0. It
    now ships deliberately, and the build asserts the pip packages that are
    removed really are gone.

Fixed

  • An unmeasured value is not a definite answer (#1557). The merge baseline
    and the bwrap probe no longer treat a missing measurement as a pass or a
    fail.

Documentation

  • Kubejob is the supported isolated host for trusted plans (#1846, closes
    #1760 and #1724).
    host_isolated() stays kubejob + durable store only; the
    PID-namespaced sandbox is not widened, because a same-uid agent could read the
    per-call GitHub token.

Chores

  • Dependabot ignores chainguard/python digests until the CPython 3.15 move
    (#1843, tracked in #1842).

v3.10.4

Choose a tag to compare

@github-actions github-actions released this 20 Oct 09:24
6231576

Security

  • aiohttp 3.14.3 -> 3.14.5 (#1836). Fixes CVE-2026-111064 (no initial
    request/header timeout) and GHSA-2g87-pp6c-29x5 (unbounded memory and CPU
    on crafted requests). yarl moves 1.24.5 -> 1.25.1 with it. The Trivy gate
    on PRs to dev failed until this landed.
  • Server-side git no longer runs repo filters, and a late baseline is
    visible (#1832, PR #1837).
    merge_driver_pins now also pins
    filter.<x>.clean, .smudge and .process empty for every configured
    filter, and every server-side git status, git add, worktree-reading
    git diff and the unforced git worktree remove use the pins. A
    required filter is left unpinned, so git exits 128 and the call fails
    closed; if the pins cannot be read the call refuses and a status probe
    reports "has changes". The git metadata baseline is now recorded before
    the spec pipeline's agents and before a build's first agent session, which
    covers direct mode and builds without workspaces. A baseline taken late
    still passes, but the build output now prints WARNING: git metadata baseline taken late for <repo>; changes made before now are not detected.
  • Git metadata baseline follow-ups (#1832). The baseline now also
    tracks lfs.customtransfer.*.path, lfs.*standalonetransferagent and
    submodule.*.update set to !cmd, so a change to any of them fails the
    check. With extensions.worktreeConfig, each worktree's
    config.worktree is compared with its own baseline, so one worktree's
    config no longer reads as drift in another, and a change to it is still
    reported. A project slug of .git-baselines is refused, and
    resolve_pr_conflicts removes a baseline file it created for a build
    clone. A repo whose old baseline holds per-worktree keys reports drift
    once; rebaseline with python -m core.git_metadata --rebaseline <path>.

Changed

  • Baked agent-CLI pins (#1411): @anthropic-ai/claude-code 2.1.303,
    @openai/codex 0.163.0, @google/gemini-cli 0.64.0. PFactory and
    TFactory pin the same versions.
  • Dependency bumps: GitHub Actions group (#1744: setup-uv 10.3.0,
    kind-action 1.15.1, setup-node 7.1.0, sbom-action 0.24.3, codeql-action
    4.39.0, upload-artifact 7.0.2, download-artifact 8.0.2); npm
    source-map-js 1.2.2 (#1739); and in /docs source-map-js 1.2.2 (#1654),
    shell-quote 1.12.0 (#1653), proxy-addr 2.0.8 (#1655) and compression
    1.8.2 (#1656).

v3.10.3

Choose a tag to compare

@github-actions github-actions released this 17 Oct 16:58
faac52a

Added

  • Opt-in repo lint gate (#1742). With AIFACTORY_REPO_LINT_GATE=1, the
    trailing gates run the target repo's CI linters that AIFactory has a
    curated command for (ruff check ., flake8, ktlint), never the CI
    step text. A lint that fails goes to GATE_FAILURES.md and the QA fix
    loop; a missing tool reads skipped. The planner prompt also names the
    linters CI runs. Off by default, because it can fail builds that pass
    today. ci_linters now refuses a repo with more than 64 workflow files.

Security

  • Legacy and from-issue tasks need a real verified green to auto-merge (#1697).
    Tasks without a signed contract (including MODE 0 from-issue tasks) now
    go through the same merge-time gate as signed ones: auto-merge needs a
    TFactory pass and green host CI on the head commit. A missing verdict or
    missing CI now counts as not passed, and task_metadata.json can only
    tighten these signals, never loosen them. The path risk floor is always
    enforced for these tasks, whatever AIFACTORY_PATH_RISK_FLOOR_ENFORCE
    says. Breaking for projects without TFactory or without CI: their
    legacy and from-issue tasks no longer auto-merge. The PR stays open and
    the watcher times out to a human stop.
  • Agent children can no longer read the parent's secrets through /proc or $HOME (#1762).
    Each agent CLI spawn (Claude SDK paths, codex, copilot, gemini/antigravity,
    opencode and the tool-loop Bash) gets a private 0700 HOME that holds only
    that CLI's login file and a .gitconfig with user.* and safe.directory.
    A refreshed login is written back only if the real file is unchanged. If
    the private HOME cannot be built the spawn fails; nothing falls back to the
    real HOME. Agent children also get an env allowlist (#1757), so
    SSH_AUTH_SOCK and other inherited names are dropped. Breaking for
    operators: agents lose ~/.ssh and home-folder tool configs; add needed
    env names with AIFACTORY_AGENT_ENV_EXTRA, and name an MCP server's host
    vars with env_keys. On local runners the /proc window stays open (#1724).