carp-dk/carp.core-kotlin
49.9
Weak · 7 October 2026
15.9k
lines of production code
Kotlin
primary language
4
measurements over time
What this system is
This system is the CARP Core Framework, a multiplatform Kotlin library designed to define, manage, and execute digital health studies across smartphones, web clients, and connected hardware. It provides a comprehensive domain model for structuring study protocols, including tasks, triggers, and sensor data collection, while handling the full lifecycle of participant recruitment and device deployment. The framework ensures robust data integrity through event-sourced state management, API versioning, and strict serialization, enabling researchers to configure complex, role-based studies that collect and synchronize physiological and behavioral data.
How it got here
2018–2020 — Core domain model and service implementation
29 changes.
This period established the foundational architecture of the CARP Core Framework, introducing the primary domain models for protocols and studies alongside their corresponding application services. Significant work focused on implementing study lifecycle management, including participant recruitment and group handling, while enforcing strict validation and versioning for protocol definitions. The effort was complemented by comprehensive test coverage across domain and infrastructure layers, as well as the creation of TypeScript declarations to support multiplatform interoperability.
2021 — Domain-driven study deployment architecture
62 changes.
This period established a comprehensive domain-driven design for the CARP platform, introducing core models for study deployments, participant roles, and device management across common, client, and deployment modules. It implemented a robust infrastructure for data streams, sensor collection, and event-sourced state management, supported by extensive serialization and testing utilities.
2022–2023 — API versioning and backward compatibility
24 changes.
This period focused on implementing a comprehensive API versioning infrastructure to ensure backward compatibility across core services, including DataStream, Deployment, Protocol, and Study services. The work involved creating automatic migration logic for requests, responses, and events, supported by extensive test suites to verify serialization stability and architectural constraints. Additionally, improvements were made to the NPM package exports and RPC tooling to enhance documentation and JavaScript interoperability.
Features
Add JVM-specific reflection utilities
New files in the \infrastructure.reflect\ package provide JVM-specific implementations for accessing internal object fields and checking reflection availability. This adds low-level infrastructure capabilities for runtime type inspection and field manipulation on the JVM platform.
carp.common/src/jvmMain/kotlin/dk/cachet/carp/common/infrastructure · high confidence
Add JavaScript-specific implementations for UUID generation and reflection utilities
The \carp.common\ module now includes platform-specific implementations for the JavaScript target to support unit testing and runtime operations that are not natively available in Kotlin/JS. A new \DefaultUUIDFactory\ provides a best-effort UUID generation using \Math.random()\ to allow tests to run, while \AccessInternals\ and \Reflection\ objects handle field access and reflection checks with appropriate fallbacks (such as throwing \UnsupportedOperationException\ for unavailable reflection features). These changes ensure the common application layer functions correctly in browser environments where full Kotlin reflection is not supported.
carp.common/src/jsMain · high confidence
Add custom detekt rules for brace placement and parentheses spacing
The carp.detekt module now includes two new lint rules: one enforcing that multi-line block curly braces are placed on separate lines and aligned with their definition, and another requiring spaces inside parentheses for standard function calls while excluding higher-order functions and empty accessors. These rules are registered via the standard detekt service provider mechanism to automatically enforce these style guidelines during static analysis.
carp.detekt/src/main · high confidence
Document known Kotlin facade types for TypeScript interop
A new file, \known-facade-types\, has been added to list specific Kotlin types that are exposed to TypeScript via facades. This includes standard library types like \kotlin.Pair\, \kotlin.time.Clock\, \kotlin.time.Duration\, and \kotlin.time.Instant\, as well as serialization and application-specific types such as \kotlinx.serialization.json.Json\ and \dk.cachet.carp.common.application.users.AccountIdentity\. This serves as a reference for the types available in the generated TypeScript bindings.
publish-npm-packages/src · high confidence
Expose Kotlin standard library and kotlinx serialization APIs to JavaScript
New export modules (KotlinExport.kt and KotlinxSerializationExport.kt) have been added to the commonMain source set to ensure that Kotlin standard library types (such as Duration, Clock, and Instant) and kotlinx serialization components (including Json and collection serializers) are preserved and accessible in the compiled JavaScript output. By using @JsExport annotations and referencing these APIs, the package prevents compiler optimizations from stripping these symbols, thereby making them available for use by JavaScript consumers of the published npm package.
publish-npm-packages/src/commonMain · high confidence
In-memory study storage implementation for client repository
An in-memory implementation of the ClientRepository has been added to the infrastructure layer, allowing studies to be stored and managed in memory during the client's runtime. This change introduces capabilities to register device information, add, retrieve, update, and remove studies using unique identifiers and deployment details, providing a concrete backend for study management operations without requiring persistent storage.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/infrastructure · high confidence
Initial TypeScript declarations and test suite for CARP Kotlin libraries
This change introduces the \typescript-declarations\ module, providing TypeScript type definitions and runtime facades for the project's Kotlin libraries (\carp-kotlin\, \carp-kotlinx-serialization\, \carp-kotlinx-datetime\) and domain modules (\carp-common\, \carp-data-core\, \carp-deployments-core\, \carp-protocols-core\, \carp-studies-core\). The facades bridge Kotlin types to JavaScript/TypeScript equivalents, such as mapping \Long\ to \bigint\ and providing \KtList\, \KtSet\, and \KtMap\ wrappers. It also includes a comprehensive test suite using Mocha and Chai to verify that the generated TypeScript declarations match the actual JavaScript implementations, ensuring type safety for consumers of these libraries.
typescript-declarations · high confidence
Initial project scaffolding and configuration
The repository is initialized with the foundational structure for the CARP Core Framework, including a comprehensive README describing the multiplatform Kotlin architecture (Protocols, Studies, Deployments, Clients, Data), a CONTRIBUTING guide detailing the release workflow and coding conventions, and an MIT license. Build and development tooling is established via Gradle wrapper scripts, a detekt static analysis configuration enforcing specific formatting rules (e.g., spacing in parentheses), and a .gitignore file tailored for Kotlin, Gradle, IntelliJ, and Node.js environments.
(repo-wide) · high confidence
Introduce DeploymentService and ParticipationService application interfaces
This change introduces the core application service interfaces for managing study deployments and participant interactions. The new DeploymentService allows creating study deployments with mandatory participant invitations, registering and unregistering devices, retrieving device deployment configurations, and tracking deployment status (Invited, DeployingDevices, Running, Stopped). The ParticipationService enables retrieving active participation invitations and managing participant-specific data input. These services coordinate with domain repositories and event buses to handle the full lifecycle of study deployments, including device preregistration for connected devices and participant group management.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/application · high confidence
Introduce Study domain model with live-locking and snapshot persistence
This change introduces the core domain model for studies, including the \Study\ aggregate root, its \StudyRepository\, and \StudySnapshot\ for persistence. Users can now create studies with an owner, name, description, and invitation details. A key behavioral addition is the ability to 'go live' on a study, which locks the study protocol (preventing further changes to the protocol or invitation) and enables deployment to participants. The model supports retrieving study status and details, and ensures that protocol snapshots are validated for deployability before being set.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/domain · high confidence
Introduce StudyService and RecruitmentService for study lifecycle and participant management
This change introduces two new application services, StudyService and RecruitmentService, to manage the full lifecycle of studies and their participants. StudyService allows owners to create studies, set internal descriptions and participant invitations, define study protocols, and transition studies to a 'live' state for deployment. RecruitmentService handles adding participants by email or username, organizing them into groups with specific roles, and inviting those groups to participate. The services expose detailed status information, including available actions (such as setting protocols or inviting participants) and deployment readiness, providing a structured API for study administration and recruitment workflows.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/application · high confidence
Introduce StudyStatus model to track deployment and running states
A new \StudyStatus\ sealed class hierarchy has been added to represent the lifecycle of a study on the client. This model tracks states from \DeploymentNotStarted\ through various \Deploying\ phases (such as \AwaitingDeviceDeployment\ and \RegisteringDevices\) to \Running\ or \Stopped\. It exposes the \StudyDeploymentStatus\ and \PrimaryDeviceDeployment\ information, allowing users to monitor device registration and deployment progress via the \devicesRegistrationStatus\ map.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/application/study · high confidence
Introduce application service event bus and API versioning
The application services layer now includes a dedicated event bus for publishing and subscribing to integration events, allowing services to communicate via domain events. Additionally, an \ApiVersion\ model has been added to enforce semantic versioning (major.minor) for service APIs, ensuring backwards compatibility within major versions. Integration events now carry an \apiVersion\ and an optional \aggregateId\ to support ordered processing of related events.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/services · high confidence
Introduce core Domain-Driven Design primitives for state management
The common domain module now includes foundational types for implementing event-sourced aggregates: \AggregateRoot\ provides a base class with a unique \UUID\ identifier, a creation timestamp (\Instant\), and built-in support for tracking domain events and generating versioned snapshots; \Snapshot\ defines the immutable structure for persisting and restoring aggregate state; \DomainEvent\ serves as the base interface for immutable events; and \ExtractUniqueKeyMap\ offers a specialized map implementation that automatically extracts keys from values and prevents duplicate key insertion.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/domain · high confidence
Introduce domain model and repository for study deployments
This change introduces the core domain model for managing study deployments, including the \StudyDeployment\ aggregate root, its \StudyDeploymentSnapshot\ for persistence, and the \DeploymentRepository\ interface for CRUD operations. It defines how deployments are initialized from participant invitations, tracks device registration and deployment states, and exposes required data streams configuration, providing the foundational data structures for the deployment subsystem.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/domain · high confidence
Introduce structured input data types and custom input serialization
The input data module now provides a centralized registry for input data types, starting with a predefined 'Sex' type (Male, Female, Intersex) and a mechanism for researchers to define custom inputs. This change introduces \InputDataTypeList\ to manage type definitions, associated UI elements, and data converters, while \CustomInput\ enables polymorphic serialization of arbitrary input data based on registered types, ensuring that custom inputs are correctly serialized and deserialized using their specific data type serializers.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/input · high confidence
Introduction of Account domain model for user identity
A new Account data class has been added to the common domain layer to uniquely identify user accounts and their associated identities. This model supports both email-based and username-based identity types, providing factory methods to create accounts from either string or specific identity objects, and includes functionality to compare account identities.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/domain/users · high confidence
New API versioning infrastructure for request, response, and event migration
The \carp.common\ module now includes a new versioning infrastructure that allows application service API requests, responses, and integration events to be automatically migrated between minor versions. This change introduces \ApplicationServiceApiMigrator\ to orchestrate migrations, \ApiMigration\ as the base class for defining specific version changes, and builder classes (\ApiJsonObjectMigrationBuilder\, \ApiJsonArrayMigrationBuilder\) to simplify the transformation of JSON structures. It also provides concrete migration implementations like \Major1Minor0To1Migration\ for handling specific schema changes (e.g., adding version fields) and \UnchangedMigration\ for versions with no structural changes. This enables backward compatibility when clients use older API versions while the server runs a newer one.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/versioning · high confidence
New RPC tool to generate and output JSON example requests and responses
A new \rpc\ module has been added to the project, providing a command-line tool that automatically generates JSON example requests and responses for all defined application service methods. By using reflection to discover services on the classpath, the tool serializes predefined example instances and writes the resulting JSON files to the \build/rpc-examples/\ directory, organized by service name. This aids in API documentation and testing by providing concrete, valid JSON payloads for every RPC endpoint.
rpc/src/main · high confidence
New application-layer primitives and utilities in the common module
The \carp.common\ module now introduces a suite of strongly-typed application primitives—including \NamespacedId\, \EmailAddress\, \MACAddress\, \UUID\, \TimeOfDay\, \ApplicationData\, and \Trilean\—alongside supporting infrastructure such as \EnumObjectMap\, \InstantExtensions\, \RangeExtensions\, and \RecurrenceRule\. These types replace loose string handling with validated, serializable models (all annotated with \@JsExport\ for JavaScript interop) and provide dedicated serializers, ensuring that identifiers, dates, and recurrence rules are strictly validated and consistently serialized across the platform.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application · high confidence
New data stream collection and synchronization model
This change introduces a new application-layer model for handling data streams, replacing previous mechanisms with a structured hierarchy of \DataStreamId\, \DataStreamPoint\, \DataStreamSequence\, and \DataStreamBatch\. It adds a \DataStreamService\ interface to manage the lifecycle of data streams (open, close, remove) and store/retrieve synchronized measurement batches. The model includes a \SyncPoint\ class to handle sensor clock synchronization to UTC time, ensuring accurate timestamping across devices. This provides a more robust and type-safe way to collect, organize, and retrieve study data.
carp.data.core/src/commonMain/kotlin/dk/cachet/carp/data/application · high confidence
New device data collection infrastructure for primary and connected devices
The client subsystem introduces a new set of classes to manage data collection from both the primary device and externally connected hardware. A new \DeviceDataCollector\ interface defines the contract for collecting specific data types, while \DeviceDataCollectorFactory\ abstracts the creation of collectors for the local device and connected peripherals. The \ConnectedDeviceDataCollector\ class handles the logic for connecting to and collecting data from external devices, including a check for connection availability. Finally, \DataListener\ provides a unified entry point for applications to subscribe to data streams, automatically managing the lifecycle and retrieval of collectors for both local and connected devices based on requested data types.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/domain/data · high confidence
New device types and sensor support for AltBeacon, BLE Heart Rate, and Website
Researchers can now configure AltBeacon, BLE Heart Rate, and Website devices in addition to the existing Smartphone. AltBeacon devices support signal strength data and require manufacturer, organization, major, and minor IDs for registration. BLE Heart Rate devices support heart rate, interbeat interval, and sensor skin contact data using MAC address or serial number registration. Website devices act as primary devices for web-based tasks, registering via URL and user agent. The Smartphone device now includes non-gravitational acceleration, acceleration, and angular velocity sensors, and supports Web tasks.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/devices · high confidence
New domain interfaces for client study and device management
The client core now exposes a \ClientRepository\ interface to manage the persistence of device registrations and study states, including methods to add, retrieve, update, and remove studies. A new \DeviceRegistrationStatus\ sealed class models whether a device is registered or unregistered within a study runtime. Additionally, a \SmartphoneClient\ class is introduced to manage studies on smartphones, implementing the \ClientManager\ interface with specific support for smartphone device registrations and data collection.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/domain · high confidence
New in-memory data stream service with validation and decorator support
The data infrastructure layer now includes an in-memory implementation of the DataStreamService, allowing study deployments to open, close, and remove data streams while appending and retrieving batches of measurements. This implementation includes strict validation to ensure data integrity, verifying that timestamps are correctly ordered and that measurement data types match expected configurations. To support testing and logging, a decorator pattern has been introduced via DataStreamServiceDecorator, which wraps the service to handle request invocation and logging. Additionally, helper functions have been added to derive data types from serializers and validate measurement sequences against registered data type metadata.
carp.data.core/src/commonMain/kotlin/dk/cachet/carp/data/infrastructure · high confidence
New protocol management and factory services
The application layer now exposes \ProtocolService\ and \ProtocolFactoryService\ to manage study protocols. \ProtocolService\ allows adding protocols and new versions (\add\, \addVersion\), retrieving specific versions or the latest by ID (\getBy\), listing protocols by owner (\getAllForOwner\), viewing version history, and updating expected participant data configurations. \ProtocolFactoryService\ provides a \createCustomProtocol\ method to generate study protocols for single-device deployments using custom protocol definitions. These services operate on \StudyProtocolSnapshot\ objects, which capture the full state of a protocol including devices, tasks, triggers, and participant data, and are backed by \ProtocolServiceHost\ and \ProtocolFactoryServiceHost\ implementations.
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/application · high confidence
New reflection utilities for runtime type inspection
Added \AccessInternals\ and \ReflectionAvailable\ components in the \reflect\ infrastructure package to enable runtime reflection capabilities. \ReflectionAvailable\ provides a safe wrapper for JVM-based type inspection (checking inheritance and listing members) that returns null when reflection is unavailable, while \AccessInternals\ exposes internal field-setting capabilities via platform-specific expectations, with a warning that it only functions on non-minified JavaScript sources and is intended for test automation rather than production use.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/reflect · high confidence
New sensor data types and task tracking models
The platform now supports several new sensor data types, including Acceleration (with gravity), NonGravitationalAcceleration, AngularVelocity, PPG, EDA, and SignalStrength, alongside existing types like ECG, HeartRate, Geolocation, and StepCount. It also introduces InterbeatInterval and SensorSkinContact. Additionally, task-related data is now modeled with TriggeredTask (for start/stop events linked to triggers) and CompletedTask (for interactive task results), enabling more granular tracking of user interactions and sensor events.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data · high confidence
New serialization infrastructure for unknown and custom types
The serialization module now includes a comprehensive set of custom serializers and wrapper classes (such as \UnknownPolymorphicSerializer\, \CustomData\, \CustomDeviceConfiguration\, and \ApplicationDataSerializer\) that enable the system to handle data types, device configurations, tasks, and triggers that are not known at compile time. This allows the application to gracefully deserialize and preserve JSON payloads for extending or custom types defined in protocols, ensuring that unknown data is not lost but wrapped for later processing. Additionally, it introduces utilities like \PolymorphicEnumSerializer\ to support enums in polymorphic hierarchies and \MapAsArraySerializer\ to handle map keys that violate JSON naming conventions.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/serialization · high confidence
New task types and data collection model
The task configuration model has been refactored to support new task types and a more structured approach to data collection. A new \BackgroundTask\ allows measures to run in the background for a specified duration. \WebTask\ enables studies to redirect users to a web page, with support for URL variables like participant ID. \CustomProtocolTask\ allows for custom protocol definitions. The \Measure\ class is now a sealed class with \DataStream\ and \TriggerData\ subclasses, allowing for more specific data collection configurations. \TaskConfiguration\ now includes a \description\ field to explain the reason for data collection.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/tasks · high confidence
New trigger configuration models and task control capabilities
The triggers module now introduces a new \TriggerConfiguration\ base class and specific implementations (\ElapsedTimeTrigger\, \ManualTrigger\, \ScheduledTrigger\) that define conditions for starting or stopping tasks. These triggers are associated with \TaskControl\ objects, which specify whether a task should be started or stopped on a destination device when a trigger condition is met. The changes also include the addition of \JsExport\ annotations to these classes to support JavaScript interoperability and use Kotlin's \Duration\ type for time-based triggers.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/triggers · high confidence
New user and invitation data models for study deployments
This change introduces a set of new serializable data classes in the \carp.deployments.core\ application layer to manage participant interactions. Specifically, it adds \ParticipantInvitation\ for defining participant roles and identities, \ActiveParticipationInvitation\ to link invitations with assigned primary devices, and \ParticipantStatus\ to track a participant's assigned roles and device roles. It also introduces \ParticipantData\ to store study data organized by common fields and specific roles, \Participation\ to uniquely identify a user's involvement in a deployment, and \StudyInvitation\ to carry study metadata and application-specific data shared with clients. These models form the core data structures for inviting and managing participants in study deployments.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/application/users · high confidence
Protocol management service requests and decorators
The protocol subsystem now exposes its operations through serializable application service requests and corresponding decorators. This change introduces \ProtocolServiceRequest\ and \ProtocolFactoryServiceRequest\ classes, which wrap actions such as adding protocols, adding versions, updating participant data configurations, and retrieving protocol details or history. These requests are executed via \ProtocolServiceDecorator\ and \ProtocolFactoryServiceDecorator\, enabling consistent invocation patterns and serialization support (including JS export) for the protocol management capabilities.
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/infrastructure · high confidence
Protocol validation warnings for deployment issues
The system now includes a set of deployment warnings that evaluate study protocols for potential configuration issues before deployment. These warnings alert users to problems such as background tasks without measures, protocols containing only optional primary devices, measures requested on devices that do not support the required data types, tasks that are never started by any trigger, devices that are never used in triggers or data relaying, and triggers that send multiple tasks to a single device (recommending composite tasks instead).
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/domain/deployment · high confidence
Architecture
Refactor deployment and participation services to use a unified request-based architecture
The deployment and participation service layers have been refactored to route operations through a new, unified request-based architecture. This change introduces \DeploymentServiceRequest\ and \ParticipationServiceRequest\ sealed classes, which are serializable and exported for JavaScript, allowing service calls to be decoupled from direct method invocations. Corresponding \DeploymentServiceDecorator\ and \ParticipationServiceDecorator\ classes now wrap the underlying services, intercepting calls to execute these requests via dedicated invokers. This structural shift supports centralized logging, deterministic testing, and consistent API versioning across service interactions, while also introducing in-memory implementations for account, deployment, and participation repositories to support this new infrastructure.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/infrastructure · high confidence
Behavioural changes
API migration support for Deployment and Participation services
The system now includes automatic API version migration for the Deployment and Participation services via new \DeploymentServiceApiMigrator\ and \ParticipationServiceApiMigrator\ components. For the Deployment service, requests and events are migrated from version 1.0 to 1.1 by adding a \protocol\ field, while responses from version 1.1 to 1.3 are adjusted to explicitly set \deviceDisplayName\ to \null\ where required and remove the \deviceRegistration\ field from \DeviceDeploymentStatus\ objects. The Participation service migrator is initialized to handle its specific API versioning, ensuring compatibility as the service evolves.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/infrastructure/versioning · high confidence
API migration support for Protocol and ProtocolFactory services
The Protocol and ProtocolFactory services now include built-in API migration logic to handle version transitions (specifically Major1Minor0To1Migration). This ensures that requests, responses, and integration events are automatically transformed when communicating with different API versions, such as adding version fields to 'Add' and 'AddVersion' requests or stripping them from snapshot responses.
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/infrastructure/versioning · high confidence
API migration support for Recruitment and Study services
The system now includes API migration logic for the Recruitment and Study services to handle version transitions. For the Recruitment service, requests to add participants are migrated from email-based to username-based identification (v0→v2), and response payloads are cleaned of newly added fields like \deviceRegistration\ and \representation\ when downgrading from v3 to v2. For the Study service, requests to set protocols are migrated to include a version field, and responses for study details are adjusted to remove the \protocolSnapshot\ field during downgrades from v1 to v0.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/infrastructure/versioning · high confidence
Centralized application service metadata and deterministic UUID generation
The application layer now includes an \ApplicationServiceInfo\ class that automatically discovers and manages metadata for application services, including API versions, request serializers, event serializers, and API migrators, ensuring consistent serialization and versioning across services. Additionally, a platform-specific \DefaultUUIDFactory\ is introduced to provide deterministic UUID generation for the JVM target, replacing previous random UUID implementations with a standardized factory approach.
carp.common/src/jvmMain/kotlin/dk/cachet/carp/common/application · high confidence
DataStreamService API migration removes sensor-specific data for compatibility
A new migrator for the DataStreamService API (version 1.0 to 1.1) has been added to handle backward compatibility. Specifically, when migrating responses for the GetDataStream request, the system now automatically removes the \sensorSpecificData\ field from measurement objects if the data type is recognized as a standard CARP type. This ensures that clients receiving migrated data do not encounter unexpected or redundant sensor-specific payloads.
carp.data.core/src/commonMain/kotlin/dk/cachet/carp/data/infrastructure/versioning · high confidence
Decoupled recruitment management and standardized service request serialization
The \RecruitmentService\ has been split off from \StudyService\, allowing participant recruitment data to be stored independently in a dedicated \ParticipantRepository\ (with an in-memory implementation provided) rather than directly within the study repository. This separation is supported by new \RecruitmentServiceDecorator\ and \RecruitmentServiceRequest\ classes that handle recruitment-specific operations like adding participants and managing groups. Additionally, both \StudyService\ and \RecruitmentService\ now use standardized, serializable request objects (\StudyServiceRequest\ and \RecruitmentServiceRequest\) with explicit API versioning and JavaScript export support, enabling consistent remote invocation and serialization across the application.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/infrastructure · high confidence
Improved timestamp precision on JavaScript platforms
The \SyncPoint.applyToTimestamp\ implementation for JavaScript now uses the \big.js\ library to perform high-precision arithmetic, replacing previous logic that was susceptible to floating-point inaccuracies. This change ensures that timestamp adjustments calculated on JS targets (such as web clients) maintain microsecond-level precision, aligning the behavior more closely with the JVM implementation which uses \BigDecimal\.
carp.data.core/src/jsMain · high confidence
Introduce account-based participation and role-based device assignment
The user-facing participation model has shifted from device-centric to account-centric: participants are now linked to study deployments via their account identity rather than a pseudonym, and invitations assign specific participant roles instead of fixed devices. This change enables participants to use any device that matches their assigned role, with the system tracking device registration status per role. The domain now exposes account invitations, active participation filtering, and participant group management through new services and repositories, allowing users to manage their study involvement based on their account and assigned roles.
carp.deployments.core/src/commonMain/kotlin/dk/cachet/carp/deployments/domain/users · high confidence
Introduces participant roles and role-based data assignment
The user model now supports participant roles, allowing study protocols to define specific roles (e.g., patient, caregiver) and assign expected data inputs to those roles rather than to generic participants or devices. New classes in the \users\ package—\ParticipantRole\, \AssignedTo\, and \ExpectedParticipantData\—enable configuring whether a data field applies to all participants (\AssignedTo.All\) or only to those with specific roles (\AssignedTo.Roles\). This change shifts the invitation and data collection logic from device-based assignment to role-based assignment, ensuring that participant attributes are correctly mapped to the intended user groups within the study.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/users · high confidence
New ClientManager and ConnectedDeviceManager APIs for study and device lifecycle management
The application layer now exposes \ClientManager\ and \ConnectedDeviceManager\ to handle study and device operations. \ClientManager\ allows users to configure the client device, add studies without immediate deployment, check study status lists, and explicitly trigger study deployments or stop data collection. \ConnectedDeviceManager\ provides access to the status of secondary devices connected to the primary client, including a method to check connectivity. These changes centralize the logic for managing study deployments and connected device interactions within the application namespace.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/application · high confidence
New Study domain model and deployment proxy
The client now uses a new \Study\ class to represent a study deployment, replacing the previous \StudyRuntime\. This class tracks deployment status and device information, exposing a \getStatus()\ method that maps internal deployment states to user-facing \StudyStatus\ values (e.g., Invited, Deploying, Running, Stopped). A new \StudyDeploymentProxy\ handles the actual deployment logic, including registering the device, retrieving deployment details, validating prerequisites via \DataListener\, and notifying the study of status changes. State persistence is supported through a new \StudySnapshot\ class.
carp.clients.core/src/commonMain/kotlin/dk/cachet/carp/clients/domain/study · high confidence
New participant recruitment and group management model
The system introduces a dedicated \ParticipantRepository\ and \Recruitment\ aggregate to manage study participants and their assignment to groups. Participants are now stored within the \Recruitment\ context rather than directly in the repository, and are organized into \StagedParticipantGroup\ entities that track role assignments and deployment status. This change enables recruiting participants by username or email, assigning specific roles to them within groups, and managing the lifecycle of these groups from staging to deployment, replacing the previous \Recruitment.addParticipation\ approach.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/domain/users · high confidence
Protocol configuration now supports device assignment and participant roles
The protocol configuration model has been refactored to support assigning devices to participants and defining participant roles. This change introduces new configuration interfaces and their empty implementations: \ProtocolDeviceConfiguration\ (and \EmptyProtocolDeviceConfiguration\) manages device relationships, including primary devices and connected/chained devices; \ProtocolParticipantConfiguration\ (and \EmptyProtocolParticipantConfiguration\) manages participant roles and expected data input; and \ProtocolTaskConfiguration\ (and \EmptyProtocolTaskConfiguration\) manages the set of tasks. The \StudyProtocolComposition\ class now composes these three configurations, allowing protocols to define which devices are used and which participant roles are involved in data collection.
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/domain/configuration · high confidence
Redesigned sampling configuration system with battery-aware and granular schemes
The sampling configuration framework in \carp.common\ has been refactored to introduce a new \DataTypeSamplingScheme\ hierarchy, replacing previous implementations. This change adds \BatteryAwareSamplingScheme\, which allows sampling configurations to adapt based on battery levels (normal, low, critical), and \AdaptiveGranularitySamplingScheme\, which automatically adjusts granularity (Detailed, Balanced, Coarse) to conserve power. The system now uses \GranularitySamplingConfiguration\ and \IntervalSamplingConfiguration\ with validation constraints, and introduces \NoOptionsSamplingScheme\ for data types that do not support configuration. These changes enable more intelligent, battery-efficient data collection strategies for device configurations.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/sampling · high confidence
Refactored application service invocation and logging infrastructure
The application service layer has been restructured to decouple request invocation from service logic and centralize logging. A new \ApplicationServiceDecorator\ and \ApplicationServiceInvoker\ interface replace the previous \ServiceInvoker\, allowing request decorators (such as logging) to wrap service calls more flexibly. The \ApplicationServiceRequest\ interface now includes an \apiVersion\ field and is annotated with \@JsExport\ for JavaScript interoperability. Logging is handled by a concrete \ApplicationServiceLogger\ and \ApplicationServiceRequestLogger\, which capture preceding and published events via a new \EventBusLog\ mechanism, providing detailed \LoggedRequest\ records for both successful and failed service calls. Additionally, a \ChannelConventionEventBus\ base class and a \SingleThreadedEventBus\ for testing have been introduced to standardize event bus implementations.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/services · high confidence
Refactored participant group status and role management models
The participant group status model has been restructured into a state machine with explicit Staged, Invited, Running, and Stopped states, introducing timestamps for when groups are invited, started, and stopped. Participant group metadata is now represented by a dedicated ParticipantGroupRepresentation class, and role assignments are managed via a new AssignedParticipantRoles model. These changes refine how participant groups are tracked and displayed within the study deployment lifecycle.
carp.studies.core/src/commonMain/kotlin/dk/cachet/carp/studies/application/users · high confidence
Renamed InputElement property from name to prompt
The \InputElement\ interface and its implementations (\SelectOne\, \Text\) in the \data.input.elements\ package now expose the user-facing label as \prompt\ instead of \name\. This change updates the public API for defining input constraints, ensuring that the property name accurately reflects its purpose as the text displayed to the user during data entry.
carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/input/elements · high confidence
Study protocol domain model refactored with explicit task control and versioning
The core study protocol model has been restructured to support explicit task lifecycle management and robust versioning. Users can now define specific start and stop actions for tasks on target devices via the new \TaskControl\ class, which is associated with triggers. The protocol repository has been updated to manage multiple versions of a protocol using \ProtocolVersion\, introducing methods like \addVersion\ and \getVersionHistoryFor\ to track changes over time. Additionally, the domain model now includes explicit support for participant roles, expected participant data, and device assignments, allowing for more granular configuration of who performs which tasks on which devices.
carp.protocols.core/src/commonMain/kotlin/dk/cachet/carp/protocols/domain · high confidence
Updated forced exports for Kotlin stdlib and serialization libraries
The forced exports configuration for the NPM package has been updated to reflect changes in the underlying Kotlin libraries. The \kotlin-kotlin-stdlib\ exports now include specific internal implementation symbols for \Duration\ (such as \inWholeMilliseconds\ and \inWholeMicroseconds\) and \Instant\, alongside standard collections and system utilities. Additionally, new forced exports have been added for \kotlinx-serialization-core\ (exposing \ListSerializer\, \MapSerializer\, and \SetSerializer\) and \kotlinx-serialization-json\ (exposing \Json\ and its default instance), ensuring these components are correctly available in the generated TypeScript declarations.
publish-npm-packages/src/forced-exports · high confidence
Test coverage
Added JVM-specific test utilities and annotations; Added architecture tests for core subsystems; Added architecture tests for subsystem boundaries and snapshot coverage; Added backward compatibility tests and request output utilities for protocol services; Added backwards compatibility tests for DataStreamService; Added backwards compatibility tests for Deployment and Participation services; Added backwards compatibility tests for Study and Recruitment services; Added centralized test protocol creation utilities; Added client integration code samples and test utilities; Added code samples for data stream configuration and upload; Added deployment code samples demonstrating the updated API; Added domain tests for study deployments and participant groups; Added infrastructure for API versioning and backward compatibility testing; Added infrastructure tests for deployment and participation services; Added infrastructure tests for protocol services and serialization; Added infrastructure tests for study and recruitment domain models; Added reflection-based tests for application configuration types; Added serialization tests for CARP common infrastructure; Added serialization tests for concrete types; Added test coverage for deployment and participation services; Added test helper for versioned API request logging; Added test infrastructure for application service decorators, requests, and snapshots; Added test infrastructure for stub data and configuration serialization; Added test to verify all deployment issues are registered in StudyProtocol; Added test utilities for deterministic testing and platform-specific test control; Added tests for API migration builders and migrator; Added tests for ApplicationServiceEventBus and IntegrationEvent serialization; Added tests for CarpDataTypes and Data serialization; Added tests for ClientManager configuration and study lifecycle; Added tests for ClientRepository study and device management; Added tests for DataListener and stub device collectors; Added tests for DataStreamServiceApiMigrator backwards compatibility; Added tests for ExtractUniqueKeyMap and Account domain classes; Added tests for InMemoryClientRepository and StudySnapshot serialization; Added tests for InputDataTypeList and SelectOne input elements; Added tests for ParticipantAttribute and Username; Added tests for ParticipantGroupStatus transitions; Added tests for Study deployment proxy and state transitions; Added tests for Study domain logic and repository contracts; Added tests for StudyProtocol and StudyProtocolRepository; Added tests for TaskConfiguration and WebTask; Added tests for application service infrastructure; Added tests for common application types and utilities; Added tests for data stream application components; Added tests for data stream infrastructure serialization and validation; Added tests for deployment validation warnings; Added tests for deterministic request generation and JSON schema validation; Added tests for device registration and configuration classes; Added tests for formatting check utilities; Added tests for participant recruitment and group management; Added tests for protocol configuration classes; Added tests for protocol service and factory implementations; Added tests for serialization registration of application types; Added tests for user participation and account management logic; Added unit and integration tests for study and recruitment service hosts; Added unit tests for detekt style rules; Added unit tests for sampling configuration and schemes; Updated code samples to reflect new study lifecycle and recruitment APIs; Updated protocol code samples to reflect new DSL and configuration APIs.
Dependencies
Upgrade Gradle wrapper to version 9.5.0
The Gradle wrapper has been updated to version 9.5.0, ensuring that builds use this specific distribution. This change standardizes the build environment by configuring the wrapper to download and use Gradle 9.5.0 from the official distribution URL.
gradle · high confidence
Upgrade to Kotlin 2.4.0 and update build toolchain dependencies
The project has upgraded its Kotlin version to 2.4.0, along with matching updates to kotlinx.serialization (1.11.0), coroutines (1.11.0), and kotlinx-datetime (0.8.0). The build toolchain has also been updated, including the Gradle Node plugin to 7.1.0, Dokka to 2.2.0, detekt to 1.23.8, and the Nexus publish plugin to 2.0.0. Additionally, the TypeScript declaration packages have been updated to version 1.2.1.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Baseline
- First survey — no prior run to compare against. CAI 50.
Lenses
- Code Health 95
- Architecture 89
- Maturity 65
- Readiness 32
- Security 66
- Domain Modelling 57
- Performance 85
Changes since last survey
- 300 commits — 254 feature/other, 46 fixes
By area
- carp.common/src — 78 commits
- (root) — 45 commits
- carp.deployments.core/src — 42 commits
- carp.studies.core/src — 28 commits
- carp.data.core/src — 18 commits
- rpc/schemas — 17 commits
- carp.protocols.core/src — 15 commits
- publish-npm-packages/src — 8 commits
- typescript-declarations/@types — 7 commits
- typescript-declarations/src — 7 commits
- typescript-declarations/carp-kotlin — 5 commits
- typescript-declarations/tests — 5 commits
- rpc/src — 4 commits
- carp.common.test/src — 3 commits
- .github/workflows — 2 commits
- carp.clients.core/src — 2 commits
- carp.test/src — 2 commits
- docs/carp-common.md — 2 commits
- gradle/wrapper — 2 commits
- typescript-declarations/carp-kotlinx-datetime — 2 commits
Notable commits
- fix: Build: fix README status badges
- fix: Build: upgrade to detekt 1.20.0-RC1; fix style issues.
- fix: Build: upgrade to detekt 1.20.0-RC2; fix style issues.
- fix: Fix "publish snapshots" workflow badge
- fix: Fix #437: incompatible TS types of duplicated types across modules
- fix: Fix #438: MeasurementSerializer didn't support unknown data types
- fix: Fix: JS/TS access to snapshot properties
- fix: Fix: JSON schema refs in DeviceDeploymentStatus
- fix: Fix: JSON schema validator upgrade; remove hack
- fix: Fix: TypeScript declarations for Kotlin 2.1.20
- fix: Fix: TypeScript for Instant.toEpochMilliseconds returned number instead of Long
- fix: Fix: CustomInput can only be serialized polymorphically
- fix: Fix: Json facade was exported in wrong TypeScript namespace
- fix: Fix: appendBatch with overlapping sequence range
- fix: Fix: generateExampleRequests should only consider kotlin methods
- fix: Fix: stopParticipantGroup verifies study membership using the wrong ID
- fix: Fix: stoppedOn reset after each load of StudyDeploymentSnapshot
- fix: Fix: align README with new file locations and use of "configuration".
- fix: Fix: allow failing before study invitation is sent on concurrent invites
- fix: Fix: deserialization got stuck in infinite loop on JS backend
- …and 280 more
Architecture
- 0 containers · 7 bounded contexts · 12 dependency edges (baseline)
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
carp-dk/carp.core-kotlin was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 7 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 8be96f8e95e9252e1661bdf24a0eeda9ba561c17 — the exact code this score is about.
- Scored under rubric-2026.10.1 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-8d8088103122.