What's changed
Features (33)
-
api: add new endpoints for asset counts (#6853)
Add new endpoints for determining the count of draft, deployed, and
archived assets for a user, an organization, and a project view.Adds three new endpoints:
/api/v2/assets/counts
api/v2/organizations/{org_id}/assets/counts
api/v2/project-views/{pv_id}/assets/counts
each returning the number of draft, deployed, and archived assets in the
relevant scope. -
api: add assets minimal-list endpoints (#6909)
New lightweight API endpoints return only
uid,name, and
deployment_statusfor assets, with noCOUNT(*)query.Three new read-only endpoints are available:
GET /api/v2/assets/minimal-list/GET /api/v2/organizations/{id}/assets/minimal-list/GET /api/v2/project-views/{id}/assets/minimal-list/
Each returns a paginated list of assets with only
uid,name, and
deployment_status(draft,deployed,archived). Responses omit
thecountfield. Use?q=asset_type:survey AND _deployment_status:statusto filter by type. Supportslimitand
startpagination parameters. -
auditLog: log superuser admin actions to
AuditLog(#6856)This PR introduces functionality to automatically capture actions
performed by superusers in the Django Admin interface and record them in
theAuditLogtable using native Django signals.This change ensures a complete and reliable audit trail for all actions
performed by superusers within the Django Admin interface.It leverages Django’s built-in
LogEntrysignal to capture admin events
globally, eliminating the need for custom mixins or per-model
ModelAdminmodifications. This approach guarantees consistent coverage
across all current and future admin-managed models.Additionally, the implementation extracts and stores a concise,
human-readable summary of each action, improving log readability while
keeping storage efficient. Audit logs are also exposed via the
/api/v2/audit-logs/API for easy access and inspection. -
auditLog: log Constance config changes to
AuditLog(#6870)This PR adds audit logging for configuration changes made via
django-constance by capturing updates through signals and recording them
in theAuditLogtable.This change ensures that all configuration updates made through
django-constance are properly tracked, providing a reliable audit trail
for system-level changes performed by superusers.It leverages Constance’s native
config_updatedsignal to detect
changes and logs them centrally without requiring modifications to
existing config logic.Each update is recorded with relevant context, including the config key,
previous value, and updated value.The implementation also safely handles edge cases by skipping logging
when no request context is available or when the user is
unauthenticated. -
auth: allauth openapi docs (#6961)
This PR exposes the django-allauth headless authentication API and
automatically merges its API docs into our core drf-spectacular OpenAPI
schemas. This allows our frontend generators (like Orval) to natively
build TypeScript interfaces for login, MFA, and profile management
flows.I've explicitly mounted
allauth.headless.urlsat/api/v2/allauth/so
that Django can successfully perform reverse route-lookups. Since
allauth's engine uses standard Python views instead of DRF ViewSets,
drf-spectacular cannot natively autodiscover them. A custom
postprocessing hook (merge_allauth_headless_schema) that fetches the
internal allauth dictionary, ingests all components, and manually
patches them into the final DRF schema payload.The custom hook automatically flattens ambiguous path templates (like
_allauth/{client}/v1/login) into discrete, concrete endpoints
(/browser/v1/loginand/app/v1/login) and automatically injects
unique operationId handles to avoid conflicts with other endpoints
definitions. -
autoQA: add verification checkbox (#6835)
Adds a checkbox for users to indicate when a manual or automatic QA
response has been verified. -
autocomplete: add custom Autocomplete and styles (#6957)
Add theming to a new Autocomplete component
-
autoqa: informative error for autoqa requests on unapproved transcripts (#6930)
Returns a more informative error when users request an AI generated
response for a transcript that has not been approved. -
autoqa: remove feature flag (#6935)
Remove feature flag for automatic qualitative analysis in preparation
for release. -
bulkProcessing: update google transcription and translation flow to accept
bulk_action_uid(#7058) -
copyTeamPermissions: remove allAssets (#6893)
Make Copy Team Permissions feature properly load all available projects
and allow for searching particular one within the project selection
dropdown. Also stop using deprecatedallAssetsstore. -
frontend: introduce tabler icons (#6952)
Introduces
KoboIconcomponent for displaying new icons. Adds a future
friendly way of using old icons as SVGs in new component. -
frontend: setup default invalidations (#6985)
-
languages: extend
languagesto support region, model and location configuration for ASR/MT services (#6953)This PR extends the languages app to support service-specific
configuration required by Google Speech-to-Text v2 and modern
translation APIs.The change introduces region-based language configurations and allows
ASR/MT services to define model and location settings per language
region.Google Speech-to-Text v2 and translation services require additional
configuration beyond the base language code, such as region, model, and
service location. The existing languages app only stored basic language
codes and did not
support service-specific regional configurations.This PR extends the languages infrastructure to support region-aware
configurations for ASR and MT services. -
menu: style Mantine's component (#6963)
Change Menu component looks.
-
metadata: expose extra project metadata fields in the
/environmentendpoint (#6817)Expose the extra project metadata fields via the
/environmentendpoint
to allow the frontend to dynamically fetch and display this data. -
metadata: ensure extra metadata fields are nested in asset settings (#7027)
Added extra project metadata fields to the asset settings under a
dedicated section to ensure a more organized and reliable data structure -
metadata: add extra project metadata inputs to project settings (#6895)
Superuser-defined custom project metadata fields are now supported on
the frontend and appear in the project settings. -
metadata: update library form to include extra project metadata inputs (#6902)
Allow users to customize the details of library templates and
collections by adding the same project metadata used in the standard
project settings. -
metadata: update project summary to include extra project metadata (#6923)
Update the Project Summary page to show the custom metadata fields
configured during the project setup process. -
nlp: upgrade automatic Google transcription to Speech-to-Text v2 batch API (#6955)
This PR upgrades the automatic Google transcription service from the
Speech-to-Text v1 API to the v2 API.The implementation uploads audio files to Google Cloud Storage, submits
a batch recognition job, and retrieves the resulting transcripts from
JSON output files written by Google.The service now dynamically resolves the correct region and model using
the new languages configuration introduced in the languages app.The new implementation follows the v2 architecture:
- Audio files are uploaded to Google Cloud Storage
- A BatchRecognize job is created
- Google processes the audio asynchronously
- Transcription results are written as JSON files to Cloud Storage
- The service reads the output JSON and returns the transcript
The implementation supports two mechanisms for tracking long-running
operations:- Cache-based tracking: Used for single transcription requests.
- Database-based tracking: Future bulk transcription operations will
store the Google operation id onSubsequenceBulkActionItem.
-
nlp: add bulk-aware async workflow to
GoogleTranslationService(#6976)Enhance
GoogleTranslationServiceto support bulk-aware translation
workflows by reusing and polling existing asynchronous operations
instead of creating duplicate jobs.This PR updates the translation workflow to align with the bulk-aware
processing model introduced for transcription.The implementation introduces support for an optional
bulk_action_uid
parameter inprocess_data(). When provided, the service reuses or
polls an existing Google batch translation operation instead of creating
a new one. This prevents duplicate jobs and enables consistent tracking
across retries. -
nlp: add placeholder bulk actions API with drf-spectacular schema (#7029)
This PR introduces placeholder API endpoints for bulk job management,
enabling frontend integration and API contract alignment before full
backend implementation.This PR adds placeholder endpoints for managing bulk transcription and
translation actions on assets. It includes support for listing,
retrieving, creating, and cancelling bulk actions.The endpoints are intended to support frontend development through
generated API hooks, while the underlying business logic and database
models will be implemented in a later phase. At this stage, all
endpoints return a “Not Implemented” response, except for the cancel
operation which follows the agreed API contract.This setup ensures that frontend and backend development can proceed in
parallel while maintaining a stable and well-defined API structure. -
nlp: add models for subsequence bulk action and item tracking (#7043)
This PR introduces the database tables required to support bulk
transcription and translation jobs within the subsequences app.This PR implements the models necessary for orchestrating and tracking
bulk processing tasks.-
SubsequenceBulkAction: A parent model is created to represent a
batch execution, storing deterministic parameters and global status. -
SubsequenceBulkActionItem: A child model is implemented to track
individual submission processing within a bulk job, including an
externalservice_idfor tracking Google operations. -
Idempotency via Hashing: A deterministic SHA-256 hash of job
parameters is utilized to prevent duplicate active jobs for the same
submission and action. -
Integrity Guarantees: Atomic creation logic is provided via
create_with_items, and status propagation is implemented to
synchronize parent and child states. -
Database Constraints: A
UniqueConstraintis enforced to ensure only
one active job item exists per submission/action/hash combination.
-
-
notification: add new notification with themes and stories (#6947)
Adds mantine Notification component and apply our theme to it
-
qual: escape xml in questions and transcripts (#6874)
Escape user-entered xml before using it in an LLM prompt.
-
qual: get model id from settings (#6877)
-
qualitativeAnalysis: add hints handling to UI (#6871)
For qualitative analysis questions (and choices) add way to create and
display hints for. -
qualitativeAnalysis: show hints toggle (#6892)
Add a persistent "Show hints" toggle in the Analysis UI.
-
subsequences: implement
SubsequenceBulkActionViewSet and Serializer (#7063)Users can now create bulk transcription and translation jobs that
process multiple audio submissions at once, with full validation to
prevent duplicate or conflicting work.This PR adds the backend API for bulk NLP processing. Users can submit a
list of submission UUIDs for a single audio question and request
transcription or translation in bulk. The API validates that submissions
exist, that results don't already exist for the requested language, and
that no conflicting active job is already running for the same
submissions and parameters. All records are created atomically, if
anything fails, nothing is saved. Cancellation of bulk jobs will follow
in a separate task. -
subsequences: implement subsequence bulk action cancellation (#7064)
Users can now cancel ongoing bulk transcription and translation jobs
directly through the interface, preventing unwanted automated
processing.This PR introduces a cancellation endpoint for bulk processing tasks.
When a bulk job is cancelled, all pending sub-tasks are halted before
they begin, and any active requests currently processing with Google
Cloud are instructed to stop. Completed sub-tasks are preserved exactly
as they are, and the system safely logs who performed the cancellation. -
table: add non-functional bulk processing UI (#6975)
Add bulk processing buttons to Project → Data → Table, in the header
dropdowns (hidden behind feature flags). They are non-functional,
introduced for future PRs. -
feat(autoqa) update log action labels (#6898)
Add human-friendly text for automatic QA log actions.
Bug Fixes (37)
-
CI: switch all automatic uses npm install to npm ci (#7062)
Switch all automated uses of
npm installtonpm cito ensure version
consistency and security. -
auth: remove email verification contact links (#7083)
Removes links inviting users to contact support on the verification_sent
and email_confirm view templates. -
autoQA: hide AI-related UI behind feature flag (#6880)
Fix components where UI changes tied to the auto-qa feature were showing
up even without feature flag enabled. -
autoqa: improve over-limit error handling for NLP (#6922)
Identify 402 errors from the backend and display the over-limit modal
instead of a generic error message when automatic NLP requests are
rejected. -
autoqa: unify naming for automatic analysis (#6929)
Updates naming for automatic analysis request across the frontend UI.
-
connectProjects: unhelpful error message (#6956)
Provides a helpful error message with a list of invalid fields when
using Project → Settings → Connect Projects. -
connectProjects: deleted imported project issue (#6971)
Fixes a problem with Connect Projects UI when an imported project was
removed before the import-link was deleted. The problem was causing an
infinite loading spinner (or crash).Also migrated few old icons and buttons to latest components. Also
introduced a confirmation for imported project removing. -
dataTable: verified column doesn't use modal (#6916)
Verified column in Project → Data → Table no longer displays option to
show a modal with full value. We always display "Yes", "No" or empty
cell, no need for modal. -
formBuilder: don't modify existing text operators (#6921)
textquestions with comparison operators will no longer get their
conditions modified (unknowlingy!) when saving in Form Builder. -
formbuilder: force select2 compatibility with jquery (#7061)
Fixes incompatibility between outdated select2 dependency and jquery v4
via polyfills -
frontend: update links to support pages (#6984)
-
icon: change way of identifying legacy icons (#6983)
Fixes a problem with some icon rendering.
-
icons: missing legacy icon mapping (#6982)
Resolve linting error on LegacyIcon mapping.
-
map: enable map settings button when were are no geopoint responses (#6828)
Allows the map settings button to show on top of the overlay if there
are no geopoint responses -
map: allow multiple queries on map display (#6924)
Fixes a bug where the frontend was only displaying one page of results
(1000) regardless of the limit placed -
map: multiple UI issues (#6962)
Fix few different UI issues in Project → Data → Map. Migrate old
components to new ones. Allow zooming map with pinch zoom gesture on
touchpad, and with ctrl + mouswheel. -
map: blank map for questions in group fix (#7034)
Fixed the Project → Data → Map so geopoint answers inside groups are now
shown correctly instead of incorrectly showing "No geopoint responses
have been received". -
menu: item background on hover (#7035)
-
mfa: prevent superusers from deactivating MFA when
SUPERUSER_AUTH_ENFORCEMENTis active (#6928)Ensure administrative accounts remain protected by preventing superusers
from disabling two-factor authentication when a security enforcement
configuration is enabled. -
nlp: suggest languages in language selector (#7059)
Enabled a previously missing feature in the single processing view.
Users can now see a recently used language for transcripts/translations
in the language selector for those steps in the single processing view. -
notification: paddings (#7012)
-
projects: change delete and bulk delete button permissions (#6903)
Enable delete/bulk delete buttons only if user has
delete_asset
permission. -
qual: update LLM prompts for consistency (#6859)
Aligns LLM prompts with the current wording and formatting in POC
implementation and fixes a bug where hints were silently dropped on
select_one questions.- Fix: select_one prompt was missing
{{hint}}placeholder - Tune: select_multiple example now shows 2 TRUEs to better represent
the expected multi-select response format - Tune: temperature 0.1 → 0
- Style: numbered choices, consistent hint/rule formatting
Summary by CodeRabbit
- Improvements
- Set model temperature to 0 for more deterministic LLM responses
- Reformatted prompt text to tighten spacing and line breaks
- Enumerated choice display with indices (e.g., "1.", "2.")
- Changed hint formatting from parenthetical to dash-separated notation
- Refined example response generation for select-one and select-multiple
questions
- Fix: select_one prompt was missing
-
qual: fix automatic qualitative analysis throttling tests (#6862)
Updates
TestAutomaticQAThrottlingto use method-level decorators for
boto3.clientmocks, ensuring that all requests including those
expected to be throttled are covered by the mock to prevent
environment-driven crashes. -
qual: do not allow deleting all choices (#6873)
Forbid users from deleting all choices in a multiple choice QA question
-
qual: graceful timeout handling for automatic qualitative analysis (#6894)
This PR introduces strict timeout configurations for AWS Bedrock
requests to prevent unhandled 504 Gateway Timeout errors during
automatic qualitative analysis.This PR addresses an issue where slow responses from the LLM via AWS
Bedrock were causing the web server to sever the connection, resulting
in a 504 Gateway Timeout for the client.- A strict timeout of 50 seconds (read) and 5 seconds (connect) is now
enforced on theboto3client viabotocore.config.Config. - The
run_external_processloop is updated to catch
ReadTimeoutError. - If a timeout occurs on the primary model, this PR ensures the system
gracefully falls back to the backup model. - If all models time out, a clean JSON response with a failed status is
returned to the frontend rather than crashing the request. - Unit tests have been updated and added to verify the timeout fallback
behavior.
- A strict timeout of 50 seconds (read) and 5 seconds (connect) is now
-
qual: remove explicit credentials from call to LLM (#6886)
-
qual: update Automated Qualitative Analysis primary bedrock model (#6900)
This PR updates the primary AWS Bedrock model used for automatic
qualitative analysis to the standard, non-safeguarded version.This PR is introduced to replace the
openai.gpt-oss-safeguard-120b
model with the standardopenai.gpt-oss-120b-1:0model. The previous
safeguard model was found to be unsupported in the primary private
instance region, requiring cross-region routing, and was unnecessarily
costly for this specific feature. -
qual: add prompt guardrails and improve text response formatting, closes (#6860)
Adds prompt guardrails for all question types; improves prompt
formatting for text questions.- Wrap interview responses and analysis questions in XML tags to sandbox
untrusted input - Add post-data reminders scoping each tagged section's role
- Add "plain text only" and "no sections" rule to text prompt as default
- Wrap interview responses and analysis questions in XML tags to sandbox
-
qual: default to false if verification missing (#6943)
Fix an error loading the data table with older submissions
Loading a data table for a survey with older submissions that had QA
data from before verification was released caused a 500 and displayed a
long error message. -
select: clear button styles (#7014)
Fixes Select UI when clearable option is enabled.
-
settings: apply AWS settings without explicit credentials (#7017)
-
sidebar: use counts and minimal-list APIs (#6918)
Use new API for Sidebar lists of projects (Deployed, Draft, and
Archived). This fixes a problem when user with more than 200 projects
was unable to see all of their projects in the Sidebar (previously it
was limited to 200 latest projects, prioritizing Deployed ones). Now
three groups use infinite scroll loading. We also fixed a problem with
sidebar serving always "My Projects" projects - now when user switches
to organization projects or a custom view, the sidebar reflects this
properly. -
submissions: return 400 error message from OpenRosa for an invalid deprecatedID (#6942)
🗒️ Checklist
- run linter locally
- update developer docs (API, README, inline, etc.), if any
- for user-facing doc changes create a Zulip thread at
#Support Docs Updates, if any - draft PR with a title
<type>(<scope>)<!>: <title> - assign yourself, tag PR: at least
Front endand/orBack end
orworkflow - fill in the template below and delete template comments
- review thyself: read the diff and repro the preview as written
- open PR & confirm that CI passes & request reviewers, if needed
- delete this section before merging
Updated the submission process to return a clear error message when an
edit is attempted with an invalid ID, preventing a system crash when a
record cannot be found. -
subsequences: track LLM usage counters even when Stripe is disabled (#6920)
Ensure AI qualitative analysis requests are tracked in usage counters
even when Stripe billing is disabled.Previously, requests to the AI qualitative analysis service were only
recorded in NLP usage counters when Stripe was enabled. This prevented
usage metrics from being tracked in environments where Stripe billing is
disabled.This PR removes the Stripe dependency from the LLM request tracking
logic so that NLP usage counters are always recorded. Stripe remains
responsible only for billing and limit enforcement, while usage tracking
now works consistently across all deployments. -
subsequences: bypass usage limits for LLM answer verification (#6938)
This PR ensures that users can verify or delete existing automated
qualitative analysis responses without triggering LLM usage limit
checks, as these actions do not invoke external APIs or consume tokens. -
fix missing map item (938985f)
Continous Integration (8)
-
enketo: update non-prod deploy pipeline with required enketo version input INFRA-439 (#6949)
Updates nonprod release pipeline to input enketo version in the helm
deploy step.This modifies the nonprod release pipeline to set enketo version as it
is now a required input from the helm chart. Adds the org-wide variableENKETO_VERSIONto manage running enketo version for non-prod
environments.
-
ephemeral_envs: add ability to deploy an ephemeral environment off of a branch INFRA-461 (#6950)
-
locale: automate pushing to transifex (#6827)
-
main: check for openapi as well (#6944)
-
npm: Turn off dependabot automerge, don't open new PR's (#7048)
-
packages: Schedule weekly deletion of kpi images older than 90 days INFRA-431 (#7016)
-
packages: Clean up old GCHR packages INFRA-431 (#7047)
-
ci (kfmain): remove duplicate kfmain notifications (#6882)
📖 Description
The success notification was firing for kfmain even though the actual
deployment happens in the devops repo pipeline, which has its own
notifications. Now notify-success only runs for feature branches and
public-beta.
📣 Summary
Remove redundant success notification for main deploys since the actual
deployment and notifications are handled in the devops pipeline.
Build & Dependencies (26)
- deps: bump the minor-and-patch group across 1 directory with 2 updates (#6883)
- deps: bump the actions-deps group across 1 directory with 7 updates (#6889)
- deps: bump aws-actions/configure-aws-credentials from 6.0.0 to 6.1.0 in the actions-deps group (#6934)
- deps: bump the actions-deps group across 1 directory with 2 updates (#6967)
- deps: bump @tanstack/react-query from 5.85.5 to 5.100.9 (#6988)
- deps: bump @fontsource/roboto from 4.5.8 to 5.2.10 (#6768)
- deps: bump fuse.js from 6.6.2 to 7.3.0 (#6996)
- deps: bump pretty-bytes from 7.0.0 to 7.1.0 (#7003)
- deps: bump react-copy-to-clipboard from 5.1.0 to 5.1.1 (#7013)
- deps: bump mobx from 6.15.0 to 6.15.2 (#7023)
- deps: bump the actions-deps group with 2 updates (#7038)
- deps-dev: bump brace-expansion from 1.1.12 to 1.1.13 (#6884)
- deps-dev: bump @eslint/eslintrc from 3.3.1 to 3.3.5 (#6989)
- deps-dev: bump playwright from 1.56.1 to 1.59.1 (#6992)
- deps-dev: bump postcss from 8.4.49 to 8.5.13 (#6994)
- deps-dev: bump style-loader from 3.3.4 to 4.0.0 (#6991)
- deps-dev: bump wait-on from 9.0.4 to 9.0.5 (#7002)
- deps-dev: bump ts-loader from 9.5.1 to 9.5.7 (#7005)
- deps-dev: bump @jest/create-cache-key-function from 30.0.5 to 30.3.0 (#7010)
- deps-dev: bump cheerio from 1.1.2 to 1.2.0 (#7008)
- deps-dev: bump jest and @types/jest (#7007)
- deps-dev: bump eslint-import-resolver-webpack from 0.13.10 to 0.13.11 (#7021)
- deps-dev: bump @testing-library/react from 16.3.0 to 16.3.2 (#7022)
- frontend: delete unused webpack-dev-middleware (again) (#6998)
- jquery: bump to v4 (#7015)
- mantine: upgrade to v8 (#6986)
Upgrades Mantine UI library from v7 to v8 and Sentry from v7 to v10
(required for Mantine v8). Both are dependency-only upgrades with no
user-visible changes. Required as a stepping stone toward Mantine v9.
Refactor (9)
-
bigModal: drop allAssets usage (#6872)
-
connectProjects: functional component (#6931)
Internal code improvements
-
dataTable: stop relying on allAssets (#6897)
Data Table already had access to asset data, no need to request it again
through (deprecated)allAssets. -
dataTable: move around and group cell related files (#7052)
-
dropzone: update react-dropzone and migrate out of mixin (#6987)
Upgrade react-dropzone to v15, migrate all Dropzone usages to the
current API, remove legacy droppable mixin usage. -
formBuilder: merge surveyCompanionStore into surveyScope (#6888)
-
frontend: use start in API calls (#6908)
Internal code improvement.
-
frontend: migrate pageState out of Reflux (#6981)
-
notification: adjust story and add wrapper file (#7037)
Chores (4)
Other (1)
- frontend: update background audio warning link (#7054)
Full Changelog: https://github.com/kobotoolbox/kpi/compare/2.026.13a..2.026.21