Production image releases 1.0.0 → 1.7.2 (72 releases, April 2026).
| service | image / pin | version span |
|---|---|---|
| dm | iblai-dm-pro | 4.212.1 → 4.241.5 |
| os | iblai-os-spa | 0.41.2 → 0.58.0 |
| lms | iblai-lms-spa | 0.10.7 → 0.19.0 |
| edx | iblai-edx-pro | sumac.2.12.4 → sumac.2.15.12 |
| cli | iblai/infra-cli | 1.3.0 |
iblai-dm-pro — 4.212.1 → 4.241.5
Abuse-resistant authentication. The backend added per-account login throttling on /oauth/token/ to blunt credential stuffing: failed attempts are tracked by username (case-insensitive) regardless of source IP, a successful login resets the counter, and an exhausted budget returns 429. The rate is tunable via ACCOUNT_LOGIN_THROTTLE_RATE (default 5/min).
SSRF and injection hardening across the agent app. ibl-ai-mentor-app closed several server-side request forgery and injection paths: RetrieverTrainView (/documents/retriever-train/) now runs validate_url_for_ssrf() before fetching, matching /documents/train/ (CWE-918); the type=google_drive short-circuit that bypassed URL validation was removed so is_url_scrapeable() always enforces strict hostname checks for Google Drive and Dropbox; and Git clone URLs pass through a new validate_github_token() that rejects dangerous characters enabling URL redirection or command injection (CWE-88/918).
Confused-deputy fix in chat sessions. ChatSessionView now authorizes the URL user_id against the authenticated caller (CWE-862) — only the owning user or a platform admin may create a session attributed to a given username, closing a spoofing path into downstream RBAC and paywall checks.
Bot integrations locked down. ibl-ai-bot-app 1.4.0 validates all Slack and Discord webhook URLs through SSRF checks and host-allowlist enforcement, routes outbound Slack responses through safe_post, and hardens Slack token verification to reject empty or None tokens.
MCP tool-output sanitization (zero trust). 4.241.5 shipped an MCPContentSanitizer interceptor that sanitizes every MCP tool result: HTML is stripped via Django's strip_tags() to prevent XSS, and content is wrapped with markers so the LLM can distinguish data from instructions (prompt-injection defense). The logic lives in the new ibl_ai_mentor/utils/mcp_security.py.
Provider-aware chat history. A pluggable chat-history transformer system (ChatHistoryTransformer + ChatHistoryTransformerRegistry) normalizes messages per provider/model. A GPT-5-family transformer strips Responses-API ephemeral kwargs (reasoning, tool_outputs, __openai_function_call_ids__) and flattens annotated content blocks to plain text to prevent 400 "missing index" errors on replay. The graph agent's ChatHistoryMiddleware now packs intermediate tool-calling messages and results into the final AIMessage's additional_kwargs["__intermediate_messages__"] and unpacks them on load, and session-detail/chat-history endpoints expose additional_kwargs and tool_calls so the frontend can render the full tool-call trace. ibl-ai-langchain-ext 1.6.0 resolves and applies the registered transformers on save/load based on the agent's llm_provider/llm_name.
Unified sellable-items search. ibl-dm-search-app 0.10.24 introduced a V2 endpoint GET /api/ai-search/sellable-items/ — a single cross-model search over courses, programs, pathways, and agents. It authenticates from the request token (not query params), requires platform_key for tenant scoping, enforces the Ibl.Billing/CanSellItems/action policy (agents additionally filtered by Ibl.Mentor/Mentors/read), hydrates paywall status from ItemPaywallConfig (lowest price, active pricing, Stripe product info), and returns faceted, paginated results filterable by item type and paywall status (none, enabled, disabled).
Fresh personalized data. ibl-dm-search-app 0.10.23 disabled the browser Cache-Control: max-age=300 on the personalized agents endpoint; responses now set Cache-Control: no-store so browsers always fetch fresh data, while the server-side Django cache is unchanged.
Reporting pipeline (ibl-dm-axd-app). The recommendation-history report is now capped at 1M rows with chunked DataFrame accumulation for bounded memory, drops the redundant fullname column, adds a created_at field to ReportTask to separate request time from Celery pickup time (started is now nullable), and gains a retry_selected_reports admin action for bulk retry of failed reports. Report-download views were refactored onto shared validation utilities (validate_task_state, validate_column_order, get_download_handler) with structured JSON error responses for invalid column requests.
Document-embedding performance. ibl-ai-mentor-app 3.203.5 fixed the document-embedding list endpoint to paginate at the queryset level before serialization (#1564) — previously the full queryset was serialized first, causing timeouts on agents with hundreds of documents.
Deployment-facing schema changes. DM 4.239.0 (shipped transitively via 4.240.0) added MentorSettings.enable_claw and AgentSkill.unique_id columns; because the chat consumer queries MentorSettings on every request, migrations must run before the new code goes live or chat crashes with UndefinedColumn. 4.233.0 also required a migration for the notification app. Housekeeping removed ibl-ai-finetuning-app and the deprecated export-chathistory endpoint.
iblai-os-spa — 0.41.2 → 0.58.0
Voice, screen share, and read-aloud in chat. The canvas view gained screen-sharing and voice-call modals (with mobile coverage), and chat added a speaker button that reads AI messages aloud, switching to a stop icon while speaking. A loading spinner now covers cached-session message retrieval.
Proactive and embedded messaging. The SPA added proactive messaging driven by the postMessage API on progress events, and now passes metadata from CONTEXT_UPDATE iframe messages — the plumbing that lets a host page steer an embedded agent.
Agent memory. Memory management was built out substantially: a new agent-memory API, memory categories, per-student memory, and support for anonymous users to retain memory (user schema relaxed so full name is optional/nullable).
RBAC and audit. The Access tab added an analytics-viewer role (with unit and Playwright coverage), and audit logs were added for analytics and edit-agent actions, wired to real usernames with RBAC on the audit view.
Datasets and prompts. Dataset ingestion added a CSV resource type in the edit-agent modal and Markdown file support; the suggested-prompts feature gained delete, run, and pagination with non-admin RBAC coverage.
Mentor → Agent rebrand. 0.58.0 replaced "Mentor" with "Agent" across the SPA UI and polished remaining "mentorAI" brand mentions, and 0.57.0 removed the "My Mentors" trigger from the header and platform navbar (dropping the associated modal, shortcut, and navigation helpers).
Desktop and build. The Windows build workflow added optional NSIS EXE and MSIX installer outputs (speeded up with rust-cache and pre-built cargo-binstall); 0.47.1 then removed electron/electron-builder as the desktop shell consolidated on Tauri. A playwright-e2e-engineer agent was added for E2E testing.
Security and dependencies. SSRF protection was added to WebCache's fetch_from_network, CodeQL alerts (SSRF, TLS, redirect, sanitization) were addressed, permissions: {} was locked onto all workflows, and Next.js was bumped through 15.5.15 with additional overrides for transitive vulnerabilities.
iblai-lms-spa — 0.10.7 → 0.19.0
Agent-aware courseware. The inner-courseware view added an agent-and-course tab mode, and switching a unit on the agent tab now sends a silent postMessage to the embedded agent iframe so the agent stays in sync with the learner's position; embedded-agent spacing was unified top and bottom.
Course outline and content. The course outline replaced its current-unit icon with per-unit progress checks, and a scrolling issue on the course-about page was fixed.
Analytics reporting. Analytics-report E2E helpers were imported from the SDK Playwright package, and an analytics-tab groups dropdown got its correct required action/RBAC.
Tenancy and resilience. Several tenant-switching bugs were resolved — suppressing spurious auth redirects during tenant switch and logout, removing a 100ms delay that caused double navigation, and setting the suppression flag synchronously before the first await. Client error boundaries (error.tsx, global-error.tsx) now redirect exceptions to /error/500, and courses accessed from the wrong tenant were fixed.
Accessibility. Icon-only buttons received aria-labels, a reusable AccessiblePaginate wrapper was added, "My Courses" moved to a semantic section, and viewport scaling and contrast were improved.
iblai-edx-pro — sumac.2.12.4 → sumac.2.15.12
Cross-site scripting fixes in XBlocks and LTI. 2.15.3 fixed a stored XSS in LTI deep-linking (render_link.html) where attrs.url/targetName/windowFeatures were interpolated into a JS-string context inside an onclick attribute; all three now pass through Django's escapejs (lti-consumer-xblock 7.4.2). 2.15.2 fixed stored XSS in the Ratings XBlock, where student_view/studio_view rendered via unescaped html_content.format(...); both now build an explicit context with html.escape() on every staff-editable field (rating-xblock 1.0.3).
Authentication and redirect hardening. 2.15.1 fixed an OAuth-SSO open redirect by validating state_data["next"] through is_safe_login_or_logout_redirect() against LOGIN_REDIRECT_WHITELIST. 2.15.0 made the SSO backend fail loudly on a missing/placeholder Fernet key — the LMS now raises ImproperlyConfigured at startup rather than defaulting to "BAD_FERNET_KEY", so operators must confirm every tenant has a generated IBL_FERNET_KEY before deploy. 2.13.0 replaced the startswith("auth.")/startswith("login.") magic-link Origin/Referer heuristic with a CsrfExemptDomain hostname allowlist, blocking account-takeover via crafted Origins like auth.iblai.app@evil.com.
Brute-force and DoS throttling. 2.15.6 swapped the magic-link verification-code generator from random.choice (Mersenne Twister) to secrets.choice (CSPRNG) and added a per-token failed_code_attempts counter that invalidates the token after MAGIC_LINK_MAX_FAILED_CODE_ATTEMPTS (default 3), preserving the 15-minute TTL. 2.15.7 wrapped the OIDC /openid/token view in a two-layer throttle — an outer per-IP cap (OIDC_TOKEN_RATE, default 200/m) and an inner failure-only counter keyed on (ip, client_id) (OIDC_TOKEN_FAILURE_RATE, default 10/m) — so client_secret brute force and DoS are mitigated without breaking corporate NAT or refresh_token traffic.
Payment-webhook removal. 2.14.0 removed the deprecated, unsigned POST /api/ibl/stripe/checkout/webhook/ endpoint (no Stripe-Signature verification, which allowed forged checkout.session.completed events to grant free enrollment); Stripe checkout is now handled exclusively by the Data Manager, and tenants must drop ENABLE_IBL_STRIPE_WEBHOOK_ENDPOINT from LMS settings. 2.14.1 added defense-in-depth to the Manager proxy URL construction (netloc-equality assertion, @ dropped from the proxy URL regex).
Redirector, enrollment, and completion fixes. 2.15.8 preserves the block id when jump_to URLs are rewritten to the SPA, redirecting deep links to {IBL_SPA_COURSE_UNIT_URL} instead of dumping every bookmark on the course-detail page. 2.15.9 fixed an ImportError from ugettext (removed in Django 4.0) that silently disabled the enrollment-API patches on Sumac — swapped to gettext with an AST-level regression test scanning post-Olive patch modules. A completion-API fix corrected section/subsection status that was stuck at not_started when a unit held completed leaves. 2.15.4 fixed a CMS /api-docs/ 500 on Sumac by monkey-patching the upstream ObjectTagSerializer and disambiguating shared v0/v1 grading serializer ref names for drf_yasg.
Diagnostics. 2.15.12 added minimal per-user trace logging for the DM user-platform proxy flow (/api/ibl/users/manage/platform/), with explicit response trace fields on ibl-edx-request-router-app (0.5.8) and ibl-edx-user-management-api (0.9.8) to speed cross-log debugging without behavior change.
iblai/infra-cli — 1.3.0
infra-cli 1.3.0. The standalone provisioning CLI added a resetup command (re-configure existing environments with a new domain and rotated secrets), a non-interactive AMI-based launch command for CI/CD, and launch-env (launch from a .env file with interactive confirmation). It integrates iblai-prod-images so ops is installed via iblai-images[sumac] with every image version pinned by the package rather than hardcoded tags, syncs PostgreSQL and MySQL passwords after secret rotation (capture-before-rotate), verifies all SPA launches over HTTP with retries, shows the current Ansible task description instead of just "Running," ships a .env.example template, and adds an ingress system for pre-provisioned domain-endpoint management with lock backends.
Companion ibl-cli-ops pin (bundled through the prod-images releases). The ops CLI advanced from 4.0.2 to 5.9.0 over the month. Highlights: an ECR image-mirroring command (ibl ecr list / ibl ecr sync with --dry-run) plus a switch of all third-party Docker images (edx, reverse-proxy, dm, prometheus stacks) to IBL's private ECR with previously untagged images pinned. 5.0.x purged leaked secrets from the entire git history and resolved code-scanning and Dependabot alerts (cryptography, pyopenssl, urllib3, etc.), and 5.0.0 made --node-id required on the memory-monitor commands. Later releases added DM resource tuning (ASGI backpressure via ASGI_BACKLOG, --preload, worker recycling, celery autoscale caps, and edX LMS/CMS --concurrency limits), Langfuse Sentry defaults, CORS_* defaults for ibl-dm-pro under IBL_DM, EDX Redis-TLS support (ENABLE_REDIS_TLS, REDIS_PASSWORD, rediss:// rewrite), tutor-plugin exposure of the new magic-link and OIDC throttle settings, and a fix for a parallel-update race where concurrent ibl dm update/ibl dm up runs could persist ENABLE_HTTPS: false and corrupt the request-router plugin. A new hq image was introduced at 1.6.8 and advanced to 1.0.109.