Skip to content
CAI
Software that uses CAICheck a score

sndnv/stasis

47.5

Weak · 20 September 2026

85.1k

lines of production code

Scala

with Kotlin, Dart, Python

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a distributed backup and recovery platform that manages data protection across multiple client devices and a central server infrastructure. It provides secure, encrypted backup and restore operations with support for scheduled tasks, granular file filtering, and resumable transfers, while maintaining a robust identity service for OAuth 2.0 authentication and device management. The platform exposes its functionality through a background service, a command-line interface, and desktop/mobile user interfaces built with Flutter and Scala.

How it got here

2018–2019 — Pekko migration and core architecture

76 changes.

This period focused on migrating the entire codebase from Akka to Apache Pekko, establishing a new streaming-based architecture for networking, persistence, and client operations. It introduced foundational components for the identity service, server API, and client backup/recovery workflows, alongside comprehensive gRPC and HTTP contract definitions.

2020 — Client CLI and Pekko migration

51 changes.

This period focused on introducing the stasis-client-cli tool for managing the Stasis client, including its API layer, rendering, and filtering capabilities. Concurrently, the client backend underwent a significant migration to Apache Pekko, updating HTTP APIs, stream processing for backups and recovery, and service architecture.

2022 — Android client and Identity UI migration

49 changes.

This period focused on the initial development of the Android client, establishing its core architecture, backup and recovery capabilities, and comprehensive test coverage. Simultaneously, the Identity UI was migrated from Vue.js to Flutter, and a new Flutter-based Server UI was introduced to manage platform resources.

2023–2026 — Persistence migration and client architecture

18 changes.

This period focused on migrating the identity and server persistence layers from in-memory stores to Slick-based SQL implementations, introducing comprehensive database migrations and ownership-based access controls. Concurrently, the project established a robust client architecture featuring a new desktop UI, a command processing subsystem, and service discovery mechanisms, supported by extensive mock-based testing across Android and server components.

Features

Add Dockerfile for client-cli development environment

A new Dockerfile (client-cli.Dockerfile) has been added to the deployment/dev/dockerfiles directory to support the development and testing of the client-cli component. This image is based on the existing stasis-client:dev-latest image and installs Python 3, pip, and libffi-dev. It configures the environment for a specific user (demiourgos728), sets up necessary directories for logs, configuration, and certificates with appropriate permissions, and installs the client-cli package via pip. The container is configured to start with a shell, facilitating interactive development and testing.

deployment/dev/dockerfiles · high confidence

Add OAuth 2.0 error model classes for authorization and token endpoints

The identity service now includes structured error types for OAuth 2.0 flows. AuthorizationError defines specific cases (such as invalid\_request, unauthorized\_client, and access\_denied) that can be converted into query parameters for authorization responses, while TokenError provides distinct cases (including invalid\_client, invalid\_grant, and unsupported\_grant\_type) for token endpoint failures. These models standardize how the service reports and handles authentication and authorization errors.

identity/src/main/scala/stasis/identity/model/errors · high confidence

Add common filtering and sorting utilities for CLI entries

The CLI now supports filtering and sorting of retrieved entries through new common utility modules. Users can apply complex filter expressions using the \-f\ flag, supporting operators like \==\, \!=\, \\>=\, \like\, and \is\, as well as logical aggregations (\AND\, \OR\). Entries can be sorted by a specific field using the \--order-by\ flag, with an optional \--ordering\ flag to specify ascending or descending order. These features rely on type coercion and normalization functions to handle memory sizes, durations, booleans, and numeric values correctly during comparison and sorting operations.

_client-cli/client\cli/cli/common · high confidence

Add comprehensive development configuration for client, server, and identity services

This change introduces a new set of configuration files in the \deployment/dev/config\ directory to support local development and testing of the Stasis platform. It adds \client.conf\ to define HTTP API endpoints with optional TLS termination for client services, \server-bootstrap.conf\ to initialize test datasets, devices, users, and remote nodes (including those with storage disabled), and \identity-bootstrap.conf\ to configure OAuth2 clients and owner accounts for the identity UI and smoke tests. Additionally, it includes \server-actions.conf\ for defining dataset action policies, \server-discovery.conf\ for service endpoint discovery, and supporting files for backup schedules and file exclusion rules.

deployment/dev/config · high confidence

Add development deployment scripts for client installation and artifact generation

New scripts have been added to the development deployment environment to streamline local setup and testing. The \client\_install.sh\ and \client\_uninstall.sh\ scripts now allow users to build and install the stasis-client, stasis-client-cli, and stasis-client-ui components for the current user on Linux and macOS, handling directory structure, virtual environments, and binary symlinks. Additionally, \generate\_artifacts.py\ automates the creation of Docker images for core services (identity, server, client, etc.) using either SBT or custom build scripts, while \prepare\_deployment.sh\ orchestrates the generation of self-signed certificates and device secrets required for a functional dev environment. A comprehensive \run\_smoke\_test.sh\ script has also been introduced to validate the deployment by testing OAuth token retrieval, crate push/pull operations, and API endpoints for users, devices, and nodes.

deployment/dev/scripts · high confidence

Added bootstrap code retrieval script for Android client development

A new shell script, get\_bootstrap\_code.sh, has been added to the client-android/dev directory to assist with the Android client's initial setup. This tool automates the process of obtaining a device bootstrap code by authenticating with the OAuth server using hardcoded client and user credentials, and then requesting a bootstrap code for a specific device ID from the server API. It outputs the necessary bootstrap parameters, including the server URL, user password, and the retrieved device code, to facilitate local development and testing of the device key management flow.

client-android/dev · high confidence

Added client configuration and platform-specific backup rules

The client now ships with a new configuration template (client.conf.template) that defines HTTP/TLS endpoints, secrets derivation parameters, and authentication settings for connecting to the server. Additionally, platform-specific backup rule templates have been added for Linux, macOS, and Windows to automatically include user directories (such as Desktop, Documents, and SSH keys) while excluding version control artifacts, build outputs, caches, and IDE files.

client/src/main/resources/templates · high confidence

Added mock API clients for local development and testing

The Android client now includes a suite of mock implementations for its server communication interfaces, including OAuth, server API endpoints, bootstrap, core, and service discovery clients. These components provide deterministic, in-memory responses for datasets, schedules, and user data, allowing developers to test client-side logic and UI flows without requiring a live backend server.

_client-android/app/src/main/java/stasis/client\android/api/clients · high confidence

Backup and recovery operations now persist state for resume support

The client now tracks and persists the detailed progress of backup and recovery operations, enabling users to resume interrupted tasks. New state models (BackupState and RecoveryState) record entity-level details such as discovered, processed, and failed files, along with metadata collection and application timestamps. These states are serialized to disk via protocol buffers, allowing the client to recover operation status after restarts or crashes rather than starting over.

client/src/main/scala/stasis/client/tracking/state · high confidence

Centralized asset management with synchronization script

The \assets\ directory now serves as the single source of truth for shared brand assets, including the main logo (\stasis.logo.svg\), Android launcher icon (\stasis.logo.xml\), and store descriptions. A new \refresh\_assets.py\ script automates the distribution of these assets to specific subprojects (client, client-ui, client-android, identity-ui, and server-ui), ensuring consistency across the codebase.

assets · high confidence

Client API and core endpoint implementations with caching and service discovery

The client now includes new implementations for server API and core endpoint communication, introducing a cached API client that stores dataset definitions, entries, and metadata to reduce redundant network calls, and a bootstrap endpoint client that supports device initialization via bootstrap codes with optional self-signed certificate acceptance. A unified Clients abstraction allows the client to operate with either static endpoint configuration or dynamic service discovery, while specific exception types are added to distinguish between API and bootstrap failures.

client/src/main/scala/stasis/client/api/clients · high confidence

Client bootstrap now supports device key management and secrets configuration

The client bootstrap process has been expanded to handle device-specific secrets and keys. During initialization, the client now retrieves or generates a device secret, encrypts it, and stores it locally. It also communicates with the server to pull existing device keys or generate new ones, ensuring the client is properly authenticated and configured with the necessary cryptographic material before starting. This change introduces a new layer of security and configuration management during the initial setup phase.

client/src/main/scala/stasis/client/service/components/bootstrap · high confidence

Client command processing and state management

The client now includes a new command processing subsystem located in \client/src/main/scala/stasis/client/ops/commands\. This introduces a \CommandProcessor\ interface and a \DefaultCommandProcessor\ implementation that uses an Akka Typed actor to periodically retrieve commands from the server API, filter them based on the last processed sequence ID, and execute them. The system persists the last processed command sequence ID to the local application directory (using JSON serialization) to ensure commands are not re-processed after restarts, and provides methods to retrieve all or the latest commands for the client.

client/src/main/scala/stasis/client/ops/commands · high confidence

Client operations now expose OpenTelemetry metrics and parallelism configuration

The client's backup and recovery operations now collect and export performance metrics via OpenTelemetry, tracking counters for entities handled, bytes processed, and chunks processed across steps like examination, collection, and metadata application. This includes specific instrumentation for backup and recovery subsystems, allowing users to monitor operational throughput and resource usage. Additionally, a new \ParallelismConfig\ class has been introduced to allow configuration of parallelism levels for entity processing and entity parts.

client/src/main/scala/stasis/client/ops · high confidence

Define gRPC service contracts and command protocol buffers

This change introduces the Protocol Buffers definitions for the system's networking and command layers. It establishes the \StasisEndpoint\ gRPC service with RPCs for reserving, pushing, pulling, and discarding data chunks, alongside a new \Command\ message structure that supports user logout actions. The definitions include common types like UUIDs and scalapb configuration options to ensure correct serialization of Java types such as \UUID\, \Instant\, and \CommandSource\.

proto · high confidence

Implement user authentication and authorization directives for the identity API

The identity API now includes dedicated directives for handling user authentication and authorization. The new UserAuthentication directive validates OAuth2 Bearer tokens against the ResourceOwnerAuthenticator, rejecting requests with invalid, unsupported, or missing credentials by returning a 401 Unauthorized status (including a WWW-Authenticate header for missing tokens). The UserAuthorization directive checks if an authenticated user possesses the required scope, returning a 403 Forbidden if access is denied. Both directives integrate with the EntityDiscardingDirectives trait from the sndnv.layers library to ensure request entities are properly discarded.

identity/src/main/scala/stasis/identity/api/manage/directives · high confidence

Initial Android client architecture and configuration management

The Android client introduces its foundational application structure, including a Dagger/Hilt dependency injection setup (ServiceComponent, StasisClientDependencies) to manage core services like API clients, caching, and command processing. It adds a new configuration system (ConfigRepository, ConfigViewModel) that handles device bootstrap parameters, persists authentication and secrets settings, and supports resetting user and device credentials. Additionally, it establishes a ProviderContext to aggregate these services and tracks backup, recovery, and server states.

_client-android/app/src/main/java/stasis/client\android · high confidence

Initial Android client release with core backup, recovery, and settings capabilities

This release introduces the initial implementation of the Stasis Android client, establishing the primary user-facing activities and navigation structure. Users can now access the main application interface (MainActivity) and a welcome flow that guides them through bootstrap, login, or direct entry based on their configuration state. The app provides core data management features, including a Home screen to monitor backup and recovery operations, a Backup section to view, create, and manage dataset definitions, and a Settings area to configure credentials, analytics, and caching. Additionally, the client includes a crash reporting mechanism that captures and caches exception details for telemetry, and an About screen displaying the application version.

_client-android/app/src/main/java/stasis/client\android/activities · high confidence

Initial identity service configuration and logging setup

The identity service now includes its primary configuration and logging resources. A new \example-bootstrap.conf\ provides a sample setup for defining API endpoints, clients, and owners. The \reference.conf\ introduces comprehensive configuration options for the identity service, including API and metrics endpoints, TLS settings, JWT token generation (with support for generated or stored JWKs), and secret hashing algorithms. Additionally, \logback.xml\ configures structured console logging with adjustable log levels for the identity service, Slick, and Pekko via environment variables.

identity/src/main/resources · high confidence

Initial implementation of Android credentials and device secret management

The Android client now includes a new security module that handles the storage, encryption, and synchronization of user authentication passwords and device secrets. This change introduces \DefaultCredentialsManagementBridge\ and \Secrets\ to manage local credential persistence via SharedPreferences, support for both hashed and unhashed user passwords, and the ability to push and pull encrypted device keys to and from the server API. It also ensures cryptographically secure generation of device secrets using \SecureRandom\.

_client-android/app/src/main/java/stasis/client\android/security · high confidence

Initial production deployment configuration and client installation scripts

This change introduces the foundational production deployment setup for the Stasis platform. It adds a \docker-compose.yml\ defining the core services (identity, server, UIs, databases, and Prometheus exporters) along with bootstrap configuration files (\identity.conf\, \server.conf\) for initial service setup. Additionally, it provides cross-platform client installation and uninstallation scripts (PowerShell for Windows, Bash for Linux/macOS) and utility scripts for generating TLS certificates and hashed user passwords, enabling users to deploy and manage the system from scratch.

deployment/production · high confidence

Initial release of the Android backup client library

This change introduces the \client-android/lib\ module, providing the core Android backup client library. It includes implementations for server communication (API and Core endpoints), service discovery, and a caching layer with refresh handling. The library also adds functionality for file analysis (checksums, metadata collection), encryption/decryption, and analytics, enabling the Android application to perform backup, recovery, and maintenance operations against the server.

client-android/lib/src/main · high confidence

Initial release of the Identity API service

This change introduces the core identity management and OAuth 2.0 API endpoints. It provides a new HTTP service built on Apache Pekko HTTP that exposes OAuth flows (Authorization Code with PKCE, Client Credentials, Implicit, Refresh Token, and Resource Owner Password Credentials), a JWKS endpoint for public key distribution, and a management API for administering APIs, clients, owners, codes, and tokens. The implementation includes JSON serialization formats, CORS support, and a health-check endpoint.

identity/src/main/scala/stasis/identity/api · high confidence

Initial release of the stasis-client-cli tool

Introduces the \stasis-client-cli\ command-line interface for interacting with the \client\ background service. The package includes the core CLI logic, API interaction modules, and output rendering components, along with configuration files for linting, coverage, and Docker builds. It establishes the initial dependency set (including \click\, \requests\, and \cryptography\) and provides a \qa.py\ script for running tests and code quality checks.

client-cli · high confidence

Initial server API route implementation

The server now exposes a comprehensive set of REST API endpoints for managing core platform resources. This includes full CRUD operations for users, devices (with key management and command execution), dataset definitions and entries, nodes, schedules, and analytics entries. Additional endpoints support device bootstrap code generation and execution, manifest and staging management, and service health checks. The routes are built on a new Pekko-based HTTP layer with a unified resource provider pattern for access control.

server/src/main/scala/stasis/server/api/routes · high confidence

Initial server configuration and logging setup

The server now includes a comprehensive set of configuration files to define its runtime behavior. The main application.conf introduces configurable endpoints for the main API (port 9090) and the core data exchange API (port 9091), both with optional TLS support, alongside settings for service discovery, bootstrap modes, and authentication via JWT issuers. Example configuration files are provided to demonstrate how to define dataset definitions, devices, users, schedules, and remote nodes for static discovery. Additionally, logback.xml is added to configure console logging with asynchronous appending and environment-variable-driven log levels for the server, Slick, and Pekko components.

server/src/main/resources · high confidence

Introduce HTTP-based crate storage and retrieval endpoints

The core networking layer now exposes HTTP endpoints for managing crate storage, allowing nodes to reserve storage space and push or pull crate data streams. This change adds an HTTP server implementation (HttpEndpoint) that handles authentication, reservation management, and crate transfer via PUT/GET routes, alongside an HTTP client (HttpEndpointClient) that manages credential provisioning, storage reservation requests, and streaming data operations. The implementation uses Apache Pekko HTTP for both server and client sides, replacing previous networking mechanisms with a standardized HTTP API for crate persistence operations.

core/src/main/scala/stasis/core/networking/http · high confidence

Introduce PKCE-supporting authorization code model and generator

The identity service now includes a new data model for authorization codes that supports PKCE (Proof Key for Code Exchange). This change adds the \AuthorizationCode\ value class, a \StoredAuthorizationCode\ case class that includes an optional \Challenge\ field (holding the code verifier and method) alongside standard fields like client ID, owner, and scope, and a \DefaultAuthorizationCodeGenerator\ that creates cryptographically secure random codes. This enables the system to store and process PKCE challenges during the authorization flow.

identity/src/main/scala/stasis/identity/model/codes · high confidence

Introduce Stasis client CLI with bootstrap, maintenance, and service management commands

The client-cli module now provides a new command-line interface for managing the Stasis client. Users can perform bootstrap and maintenance operations, view logs, and manage the client service. The CLI includes options for verbose logging, insecure TLS connections, and JSON output, with a default API request timeout of 30 seconds. It also handles API certificate validation and automatic regeneration if expired.

_client-cli/client\cli · high confidence

Introduce centralized credentials persistence and management

The Android client now includes a dedicated \CredentialsRepository\ and \CredentialsViewModel\ to handle the storage and lifecycle of user and device authentication tokens. This change adds support for logging in and out, verifying user passwords, updating user credentials, and managing device secrets (including pushing, pulling, and re-encrypting device secrets). Users benefit from a unified mechanism for maintaining secure access to the service, with tokens persisted in \SharedPreferences\ and exposed via LiveData for UI consumption.

_client-android/app/src/main/java/stasis/client\android/persistence/credentials · high confidence

Introduce client-side dataset metadata search capability

Added a new search operation to the client that allows users to query dataset metadata using pattern matching. The implementation defines a Search trait and a DefaultSearch implementation that retrieves dataset definitions and their latest entries, then filters results based on filesystem metadata patterns. The search query parsing supports both plain text and regular expressions, enabling flexible metadata discovery across defined datasets.

client/src/main/scala/stasis/client/ops/search · high confidence

Introduce command persistence store with database migration support

The system now includes a new command store implementation located in core/src/main/scala/stasis/core/persistence/commands. This adds a trait (CommandStore) and a default Slick-based implementation (DefaultCommandStore) that persists commands to a database table, supporting operations to put, delete, truncate, and list commands. The implementation includes a database migration layer (version 1) to automatically create the required schema if it does not exist, and integrates with telemetry for metrics collection.

core/src/main/scala/stasis/core/persistence/commands · high confidence

Introduce crate packaging model with ID generation and manifest tracking

The core packaging layer now includes a dedicated Crate ID type and a Manifest data structure to track crate metadata. Users can generate unique crate identifiers via the new Crate object, while the Manifest case class records essential details such as crate size, copy count, origin and source nodes, destination nodes, and creation timestamp. This provides the foundational data model for managing crate lifecycle and distribution information within the system.

core/src/main/scala/stasis/core/packaging · high confidence

Introduce dedicated ViewModels for datasets, device status, and user status

The Android client now exposes dedicated ViewModels (DatasetsViewModel, DeviceStatusViewModel, UserStatusViewModel) to manage API interactions and state. DatasetsViewModel provides lifecycle-aware access to dataset definitions, entries, and metadata, including explicit methods to manually refresh cached data. DeviceStatusViewModel and UserStatusViewModel centralize the retrieval of device and user information, leveraging a shared caching mechanism to ensure resilient access and automatic UI updates when underlying data changes.

_client-android/app/src/main/java/stasis/client\android/api · high confidence

Introduce default text-based rendering for client CLI data

Adds a new default rendering module for the client CLI that formats various data types into human-readable text tables and structured lists. This includes rendering analytics (runtime info, events, failures), backup rules (operations, directories, patterns), dataset definitions and entries (including size, changes, and metadata), device information (connections, commands, limits), operation progress (file trees, stages, failures), schedules, and user details. The implementation uses the \terminaltables\ library for ASCII tables and standard string formatting for detailed views, providing a consistent text-based output interface for the CLI.

_client-cli/client\cli/render/default · high confidence

Introduce desktop client UI for managing the background service

Adds a new Flutter-based desktop interface (\client-ui\) that serves as the primary control panel for the \client\ background service. This UI enables users to perform bootstrap operations, manage user credentials (password and salt), trigger backups, and monitor operation progress directly from the desktop. It includes platform-specific process handling for Windows and Linux, configurable API timeouts, and support for both light and dark themes.

client-ui · high confidence

Introduce file-based container persistence backend with atomic compaction

A new file-based persistence backend is added for storing binary data (crates) in self-describing container files. The implementation partitions data into fixed-size chunks, maintains a separate metadata log for tracking additions and removals, and supports streaming reads and writes via Pekko Streams. A key behavioral detail is that container compaction now uses an atomic file move (REPLACE\_EXISTING) instead of a destroy-and-copy approach, ensuring safer updates to the container file during maintenance.

core/src/main/scala/stasis/core/persistence/backends/file/container · high confidence

Introduce file-based persistence backends for streaming data and event logs

New file-backed implementations have been added to the core persistence layer: FileBackend provides a streaming backend that stores binary data as individual files in a specified directory, while EventLogFileBackend offers an event-sourced log backend that manages state transitions and persists state based on event counts or time intervals. Both backends are built on Apache Pekko actors and streams, integrate with the system's telemetry for metrics collection (recording reads, writes, and discards), and utilize blocking I/O dispatchers to handle file operations without blocking the main actor system.

core/src/main/scala/stasis/core/persistence/backends/file · high confidence

Introduce initial client CLI with backup, recovery, and maintenance commands

The client CLI is now available, providing commands to manage dataset definitions and entries, view and filter backup rules and specifications, and perform point-in-time or entry-based data recovery with custom destination directories. It also supports bootstrapping new devices, resetting user credentials, regenerating API certificates, and monitoring or controlling background service operations.

_client-cli/client\cli/cli · high confidence

Introduce local persistence for file-scan rules

The Android client now stores file-scan rules in a local Room database, enabling the app to manage and retrieve rule configurations independently of the server. This change introduces a new persistence layer (RuleEntity, RuleRepository, and RuleViewModel) that handles CRUD operations for rules, including a database migration to support an optional dataset definition field. It also establishes default rules that include all accessible user storage while excluding private app data and thumbnails, ensuring consistent initial behavior for file scanning.

_client-android/app/src/main/java/stasis/client\android/persistence/rules · high confidence

Introduce local schedule persistence with database migration

The Android client now supports defining and storing local schedules using a new Room-based persistence layer. This change introduces two distinct database tables: 'active\_schedules' for tracking currently running schedules and 'local\_schedules' for storing user-defined schedule definitions. To ensure a smooth upgrade, the system automatically migrates existing data by renaming the previous 'schedules' table to 'active\_schedules'. Users can now manage their scheduled tasks locally, with the new architecture providing repositories and ViewModels to handle data operations asynchronously.

_client-android/app/src/main/java/stasis/client\android/persistence/schedules · high confidence

Introduce new HTTP API endpoint and JSON serialization formats

The client now exposes a new HTTP API service built on Apache Pekko HTTP, replacing the previous Akka-based implementation. This change introduces a dedicated endpoint that handles authentication and routes requests to specific resource handlers for datasets, users, devices, services, schedules, and operations. To support this, a new JSON serialization layer (Formats.scala) has been added, defining custom formatters for complex domain models such as filesystem metadata, backup schedules, and search results, ensuring consistent snake\_case naming and proper handling of polymorphic types across the API.

client/src/main/scala/stasis/client/api/http · high confidence

Introduce new client service architecture with bootstrap, maintenance, and background service modes

The client application now uses a new service layer that supports three distinct operational modes: a background service mode that runs with a system tray icon, a bootstrap mode for initial device setup, and a maintenance mode for managing credentials and certificates. This change introduces a new entry point in Main.scala and a comprehensive set of service components in the client/src/main/scala/stasis/client/service directory, including ApplicationArguments for mode-specific configuration, ApplicationDirectory for file management, and ApplicationTray for system integration. The service also enforces a minimum Java 17 runtime requirement and utilizes Apache Pekko for its actor system.

client/src/main/scala/stasis/client/service · high confidence

Introduce per-definition backup and collection rules

The client now supports defining specific inclusion and exclusion rules for file and metadata collection, allowing users to target specific dataset definitions rather than relying on a single global set of rules. This change introduces a new rule engine in the \stasis.client.collection.rules\ package, featuring a \Rule\ model that parses include (+) and exclude (-) patterns, a \RuleSet\ factory that loads rules from configuration files (supporting \definition = \<id\>\ headers to scope rules to specific datasets), and a \Specification\ engine that walks the filesystem to match files against these rules. The system tracks discovered entities via a \BackupTracker\ and handles parsing and matching failures with dedicated exception types, enabling more granular control over which data is collected during backup operations.

client/src/main/scala/stasis/client/collection/rules · high confidence

Introduce server-ui web interface for server management

Adds a new Flutter-based web UI for the server service, enabling users to manage devices, datasets, users, nodes, and schedules through a browser. The implementation includes API clients for interacting with the server's REST endpoints, OAuth2 authentication flows, and device bootstrap code generation. Deployment is supported via Docker containers using Nginx, with configuration templates for both development and production environments.

server-ui · high confidence

Introduce service discovery for dynamic endpoint management

This change adds a service discovery system to the core module, allowing the application to dynamically locate and switch between API, Core, and Discovery service endpoints. It introduces a client-side provider that periodically queries a discovery service (via HTTP) to receive updated endpoint configurations, supporting both a 'SwitchTo' action to update connections and a 'KeepExisting' action to maintain current ones. On the server side, a static provider is implemented to respond to discovery requests by selecting endpoints from a configuration file based on a hash of the request attributes, enabling load balancing or environment-specific routing. The implementation includes the necessary request/response models, an HTTP client for querying the discovery service, and an HTTP endpoint to serve discovery responses.

core/src/main/scala/stasis/core/discovery · high confidence

Introduce structured rendering for backup rules, dataset definitions, and metadata

The client CLI now includes a new \render/flatten\ module that transforms complex, nested backend data into flat, tabular structures for display. This change adds support for querying and rendering backup rules (including matched/unmatched specifications), dataset definitions (showing retention policies and version counts), and dataset entries (displaying size, crates, and changes). It also enhances metadata rendering to explicitly show file compression status, crate/part information, and filesystem entity states, ensuring users see detailed, human-readable summaries of their backup configurations and data changes.

_client-cli/client\cli/render/flatten · high confidence

Introduce structured rendering layer for CLI output

The client CLI now includes a dedicated rendering module that standardizes how data is presented to users. This change introduces a \Writer\ abstract base class with implementations for both table-based (\DefaultWriter\) and JSON (\JsonWriter\) output formats. The module supports rendering a wide range of client data, including dataset definitions and entries, metadata changes and crates, device information and commands, active operations and their progress, backup rules and specifications, schedules, user details, and analytics state. Additionally, it provides utility functions for converting timestamps, durations, and memory sizes into human-readable strings, ensuring consistent formatting across the CLI interface.

_client-cli/client\cli/render · high confidence

Introduce structured token models and JWT generation for identity

The identity module now defines explicit domain models for access and refresh tokens, including \AccessToken\, \RefreshToken\, and \StoredRefreshToken\ (which persists client, owner, scope, and timestamps). A new \JwtBearerAccessTokenGenerator\ implements token creation using jose4j, supporting custom subjects for clients and resource owners and calculating expiration based on client-specific limits. Refresh tokens are generated via a \RandomRefreshTokenGenerator\ using a secure random source, and a \Bearer\ token type is established.

identity/src/main/scala/stasis/identity/model/tokens · high confidence

Introduces persistence metrics collection and storage request models

The persistence layer now includes built-in support for collecting operational metrics via OpenTelemetry, exposing counters for streaming backend operations (writes, reads, discards), event log events and failures, command store activity, manifest store usage, and reservation store activity. Additionally, new data models for crate storage requests and reservations have been added to the persistence domain, along with specific exception types (PersistenceFailure, ReservationFailure, StagingFailure) to handle storage-related errors.

core/src/main/scala/stasis/core/persistence · high confidence

Introduces protobuf schemas for backup metadata and state tracking

The client now defines the data structures for tracking backup and recovery operations. The new \metadata.proto\ file specifies how file and directory attributes (such as path, size, permissions, and compression) are recorded, including entity states to distinguish between new, existing, and updated items. The \state.proto\ file defines the persistence models for \BackupState\ and \RecoveryState\, enabling the client to track the progress of entity collection, processing, and failure handling for both backup and restore workflows.

client/src/main/protobuf · high confidence

Introduces server-side security infrastructure for authentication and authorization

This change adds the foundational security components for the server, including a \ResourceProvider\ that enforces permission checks against user data before granting access to resources, and an \HttpCredentialsProvider\ that generates OAuth2 Bearer tokens using JWTs. It also introduces a \CurrentUser\ context object to track the authenticated user's identity and a \CredentialsManagers\ trait to organize user and device credential handling.

server/src/main/scala/stasis/server/security · high confidence

Introduces streaming event log state updates via Pekko Streams

The EventLog trait now exposes a stateStream method that returns a Pekko Source, allowing users to subscribe to real-time updates of the event log's state. This change replaces the previous single-state retrieval with a continuous stream, leveraging the migration to Apache Pekko for reactive stream handling.

core/src/main/scala/stasis/core/persistence/events · high confidence

Introduction of local background scheduling via AlarmManager

The Android client now supports defining and executing local schedules. This change introduces a new SchedulerService that manages active schedules, integrates with the Android AlarmManager to trigger background tasks at specified times, and exposes schedule data through LiveData. The implementation includes extensions for setting and canceling alarms, a service to handle schedule execution logic, and data models to represent public, local, and configured schedules.

_client-android/app/src/main/java/stasis/client\android/scheduling · high confidence

Introduction of new persistence backend abstractions

The persistence layer now exposes three new core traits: EventLogBackend for managing state and streaming event updates, KeyValueBackend defining serialization/deserialization interfaces for key-value stores, and StreamingBackend providing operations for initializing, dropping, and streaming binary data by UUID. These abstractions are built on Apache Pekko streams and replace previous implementation-specific patterns, enabling more flexible and stream-based data access.

core/src/main/scala/stasis/core/persistence/backends · high confidence

Introduction of the Api domain model

A new Api case class has been added to the identity model layer to represent API entities, including fields for ID, creation time, and update time. The model enforces that API identifiers are non-empty strings containing only alphanumeric characters, hyphens, and underscores, and provides a factory method for creating new instances with current timestamps.

identity/src/main/scala/stasis/identity/model/apis · high confidence

New API endpoints for device bootstrap and service discovery

The server now exposes new API endpoints to support device bootstrap and service discovery. The ApiEndpoint class introduces a /discovery route that leverages the HttpServiceDiscoveryEndpoint to provide service discovery results, while the new BootstrapEndpoint class adds /devices/codes and /devices/execute routes to manage and execute device bootstrap operations. These endpoints are secured via user and bootstrap code authentication, enforce CORS policies, and are accessible under the /v1 prefix.

server/src/main/scala/stasis/server/api · high confidence

New API-based initialization endpoint for client credentials

The client service now exposes a new HTTP API route at /init to handle service initialization and credential retrieval. Users can query the initialization status via a GET request, which returns Pending, Completed, or Failed states based on the startup process. Credentials can be submitted via a POST request with username and password form fields, replacing or supplementing the previous stdin-based input method. This change introduces a programmatic interface for integrating with the client service's startup sequence.

client/src/main/scala/stasis/client/service/components/init · high confidence

New CrateStore abstraction for crate persistence

A new CrateStore class has been introduced in the core persistence layer to manage the storage, retrieval, and deletion of crate content. It acts as a facade over pluggable backends (StreamingMemoryBackend, ContainerBackend, and FileBackend), allowing the system to persist crate manifests and binary content via Akka Streams. The store supports configuration-driven backend selection and includes logic for automatic backend initialization and logging.

core/src/main/scala/stasis/core/persistence/crates · high confidence

New backup, recovery, and server tracking infrastructure

The Android client now includes a new tracking subsystem that monitors the state of backup and recovery operations as well as server connectivity. This change introduces default implementations for backup and recovery trackers that persist their state to local storage and expose real-time updates via LiveData, allowing the UI to reflect progress and status. The recovery tracker specifically notifies the Android media scanner when new files are created. A server tracker is also added to monitor and report server reachability status.

_client-android/app/src/main/java/stasis/client\android/tracking · high confidence

New bootstrap entity providers for core server entities

The server now includes new bootstrap entity providers for DatasetDefinitions, Devices, Nodes, Schedules, and Users. These components load initial configuration data from the application config, validate entities for uniqueness (e.g., by ID, node, or other fields), and persist them to their respective stores during server startup. This enables the server to initialize core domain entities automatically based on configuration, supporting features like device limits, user permissions, and node addresses (local, HTTP, or gRPC).

server/src/main/scala/stasis/server/service/bootstrap · high confidence

New client HTTP API routes for managing operations, datasets, and credentials

The client now exposes a comprehensive set of HTTP API routes to manage backup and recovery operations, dataset definitions and entries, device credentials, and user settings. Users can retrieve and update dataset definitions, list and delete dataset entries, search metadata, and manage backup rules (including per-definition specifications). The API supports starting backups and recoveries, tracking operation progress, and viewing scheduled tasks. Device management includes retrieving connection states, re-encrypting device secrets, and viewing processed commands. User management allows retrieving user details, updating passwords, and rotating salts. Additionally, the service provides endpoints for pinging the client, viewing and sending analytics, and terminating the service.

client/src/main/scala/stasis/client/api/http/routes · high confidence

New credential management and frontend authentication components

The client security module now includes a new CredentialsProvider trait and a DefaultCredentialsProvider implementation that manages core and API OAuth2 bearer tokens with automatic refresh logic using Pekko actors. Additionally, a FrontendAuthenticator trait and its DefaultFrontendAuthenticator implementation have been added to handle frontend-specific credential validation, ensuring that only valid OAuth2 bearer tokens matching a specific expected token are accepted.

client/src/main/scala/stasis/client/security · high confidence

New dataset metadata collection and recovery models

The client now introduces a new set of model classes in the \stasis.client.model\ package to handle dataset metadata collection and recovery. \DatasetMetadata\ serves as the central container for tracking content and metadata changes, integrating with \FilesystemMetadata\ to manage entity states (New, Existing, Updated) via a trie-based index for efficient lookups. \EntityMetadata\ distinguishes between File and Directory entities, capturing detailed attributes like size, checksum, and compression type, while \SourceEntity\ and \TargetEntity\ facilitate the comparison of local filesystem states against existing metadata to detect changes. These models support serialization, compression, and encryption, enabling the client to accurately track and recover dataset metadata during backup and restore operations.

client/src/main/scala/stasis/client/model · high confidence

New device bootstrap and credential management infrastructure

The server now includes new components to support device bootstrap workflows and centralized credential management. This change introduces a DeviceBootstrapCodeGenerator for creating time-limited bootstrap codes and a DeviceClientSecretGenerator for producing secure client secrets. It also adds a DeviceCredentialsManager (implemented by IdentityDeviceCredentialsManager) to handle the creation and updating of device client credentials via the identity service, alongside a new UserCredentialsManager (implemented by IdentityUserCredentialsManager) to manage user resource owner lifecycle operations such as creation, activation, deactivation, and password updates.

server/src/main/scala/stasis/server/security/devices · high confidence

New device bootstrap and user authentication mechanisms

The server now supports authenticating devices via bootstrap codes and users via JWT tokens. A new BootstrapCodeAuthenticator validates OAuth2 bearer tokens against a device bootstrap code store to establish a device's identity, while the UserAuthenticator validates JWT claims to identify active users. These changes introduce the underlying infrastructure for device onboarding and user access control within the server's security layer.

server/src/main/scala/stasis/server/security/authenticators · high confidence

New file analysis and platform-agnostic metadata collection

The client now includes a new analysis module that collects detailed file metadata (such as ownership, permissions, timestamps, and links) and calculates checksums (CRC32, MD5, SHA-1, SHA-256) for source and target entities. This module introduces platform-specific handling for both Posix and Windows systems, allowing the client to correctly extract and apply file attributes across different operating systems. The implementation uses Apache Pekko streams for efficient file processing and integrates with the existing compression and crate tracking logic to provide a comprehensive view of file state during backup and recovery operations.

client/src/main/scala/stasis/client/analysis · high confidence

New identity management API endpoints for APIs, clients, owners, codes, and tokens

The identity service now exposes a comprehensive set of management routes for administering APIs, clients, resource owners, authorization codes, and refresh tokens. Administrators can list, create, update, and delete APIs and clients, with clients supporting search by subject and credential updates. Resource owners can be managed by username or subject, including activation/deactivation and credential rotation. Authorization codes and refresh tokens are now viewable and deletable via the management API, allowing administrators to inspect and revoke these credentials directly.

identity/src/main/scala/stasis/identity/api/manage · high confidence

New in-memory persistence backends for event logs and streaming data

The system now includes dedicated in-memory backends for event logging and streaming storage. EventLogMemoryBackend provides an actor-based event log that tracks state updates, publishes state changes via streams, and records metrics for both successful and failed event stores. StreamingMemoryBackend offers a memory-backed store for binary data, supporting chunked reading and writing with configurable size limits and built-in telemetry metrics for reads, writes, and discards.

core/src/main/scala/stasis/core/persistence/backends/memory · high confidence

New maintenance mode for certificate regeneration and credential management

The client now includes a maintenance mode that allows administrators to regenerate the client API certificate (with Subject Alternative Name support) and reset user credentials via the CLI or interactive console. This mode also supports pushing, pulling, and re-encrypting device secrets to synchronize them with the server, handling authentication via OAuth2 and managing the underlying encryption keys and salts.

client/src/main/scala/stasis/client/service/components/maintenance · high confidence

New scheduled backup and recovery execution engine

The client now includes a new scheduling subsystem that allows users to define and execute backup and recovery operations based on time-based schedules. This change introduces a new \OperationScheduler\ and \DefaultOperationScheduler\ that load schedule definitions from a file, resolve them against the API, and execute the corresponding backup or recovery operations at the specified times. The \DefaultOperationExecutor\ enforces that only one operation of the same type (e.g., backup) can run at a time, preventing conflicts. It also supports resuming interrupted backups and tracking active and completed operations. The scheduler handles delays with jitter to avoid thundering herd issues and provides telemetry for schedule execution status.

client/src/main/scala/stasis/client/ops/scheduling · high confidence

New shared API layer with request/response models and JSON serialization

The shared submodule now provides a comprehensive API layer for the server and client, introducing structured request and response models for managing users, devices, nodes, datasets, schedules, and analytics. This includes new data models for device bootstrapping (codes and parameters) and device keys, alongside JSON serialization formats in Formats.scala that ensure consistent field naming across the system. The change also introduces a SecretsConfig model to centralize and validate password hashing and encryption settings, and adds an Operation model to track background tasks like backups and key rotations.

shared · high confidence

New staging store with delayed, scheduled destaging

The core persistence layer now includes a new StagingStore component that manages the temporary holding of crates before they are distributed. This store accepts a manifest and content, persists the crate to the underlying store, and then schedules a delayed destaging operation to push the content to specified destination nodes after a configurable delay. It tracks pending operations in an in-memory store, allowing schedules to be cancelled via a drop method, and handles the actual distribution by retrieving the crate content and broadcasting it to the target nodes via proxies.

core/src/main/scala/stasis/core/persistence/staging · high confidence

New streaming cipher stage for Pekko

A new CipherStage has been added to the client's encryption stream pipeline, implementing a Pekko GraphStage that processes ByteString chunks through a javax.crypto.Cipher. This component allows the client to perform streaming encryption or decryption with configurable algorithms, modes, and padding, integrating directly into the Pekko Streams infrastructure previously used by Akka.

client/src/main/scala/stasis/client/encryption/stream · high confidence

New structured tracking for backup, recovery, and server operations

The client now exposes a unified tracking system that allows users to monitor the state and progress of backup, recovery, and server connectivity operations. This change introduces dedicated trackers for each operation type, providing real-time state updates and the ability to view or remove specific operations, thereby improving the user experience by offering clearer visibility into background tasks.

client/src/main/scala/stasis/client/tracking · high confidence

New utility libraries for lifecycle-aware data handling, fragment communication, and permission management

This change introduces several new utility classes in the client Android app to improve code structure and user experience. DynamicArguments provides a type-safe mechanism for passing data between parent and child fragments using LiveData. LiveDataExtensions adds helper functions for combining streams, throttling updates to reduce UI jitter, and simplifying asynchronous data loading. NotificationManagerExtensions standardizes how the app creates and displays notifications for scheduling and operation statuses, including specific fallback messages for failures. Finally, the Permissions utility centralizes logic for requesting Android permissions and checking network restrictions, ensuring operations are appropriately handled or blocked on metered or disconnected networks.

_client-android/app/src/main/java/stasis/client\android/utils · high confidence

Server introduces event recording and configurable action framework

The server now records domain events (such as device creation, dataset definition updates, and crate pushes) via a new Events module, and the ServerRouter emits these events for crate operations. Additionally, a new action framework allows defining actions triggered by events or schedules, with an initial implementation that automatically creates a dataset definition when a new device is created.

server/src/main/scala/stasis/server/events, server/src/main/scala/stasis/server/routing, server/src/main/scala/stasis/server/service/actions · high confidence

Security

Refined self-signed certificate handling in insecure trust manager

The internal InsecureX509TrustManager now specifically targets self-signed certificates for bypassing verification, rather than accepting all certificates unconditionally. When a server presents a single certificate that is self-signed, the client logs a warning and skips trust verification; for all other certificates, it delegates to the underlying default trust manager. This change reduces the security risk associated with the insecure trust manager by limiting its scope to only self-signed scenarios.

client/src/main/scala/stasis/client/api/clients/internal · high confidence

Behavioural changes

Backup operation refactored to support resumption and streaming via Pekko

The backup operation has been restructured to support resuming interrupted backups and to utilize the Pekko streaming library for entity discovery, collection, and metadata handling. This change introduces a supervision strategy that allows the backup stream to resume processing after individual entity failures, rather than stopping entirely. It also replaces the previous Akka-based implementation with Pekko actors and streams, improving resilience and resource management during large-scale backups.

client/src/main/scala/stasis/client/ops/backup · high confidence

Backup operations now split large files into encrypted, compressed parts

The backup process has been updated to handle large files by splitting them into smaller, manageable parts. This change introduces internal stream processing components that partition byte streams by size, apply compression where appropriate, and encrypt each part individually before staging them to temporary storage. This ensures that large datasets can be backed up without excessive memory usage or single-file size limitations.

client/src/main/scala/stasis/client/ops/backup/stages/internal · high confidence

Backup operations restructured into distinct collection, processing, and metadata stages

The backup workflow in the client has been refactored from a monolithic structure into a series of dedicated Pekko stream stages: EntityDiscovery, EntityCollection, EntityProcessing, MetadataCollection, and MetadataPush. This change introduces explicit tracking for discovered, examined, collected, skipped, and processed entities, allowing the system to record metrics and state changes at each step. EntityProcessing now handles content staging, compression, and chunking for large files, while MetadataPush manages the encrypted upload of dataset metadata and entry creation. This restructuring supports improved observability, better memory handling, and lays the groundwork for resuming interrupted backups by maintaining granular state throughout the operation.

client/src/main/scala/stasis/client/ops/backup/stages · high confidence

Client bootstrap now generates API certificates with Subject Alternative Names

The client service's bootstrap component now includes a new internal certificate generator that creates self-signed certificates including a Subject Alternative Name (SAN) matching the certificate's common name. This change ensures that generated API certificates are valid for the specific hostname or domain they are issued for, improving compatibility with strict TLS validation requirements during the device bootstrap process.

client/src/main/scala/stasis/client/service/components/bootstrap/internal · high confidence

Client compression now supports identity (no-op) encoding

The client's compression subsystem has been refactored to support an 'identity' (no-op) compression mode alongside existing Deflate and Gzip options. This change allows the system to explicitly track and handle files that are not compressed, ensuring that file types with disabled extensions or specific metadata are processed without unnecessary transformation. The implementation leverages Apache Pekko streams for the underlying encoding and decoding flows.

client/src/main/scala/stasis/client/compression · high confidence

Configurable initial delay for server monitoring

The server monitoring logic in the client has been refactored to support a configurable initial delay before the first health check ping is sent. The new DefaultServerMonitor implementation accepts an initialDelay parameter, allowing the system to adjust the startup timing of monitoring tasks rather than using a fixed or immediate start.

client/src/main/scala/stasis/client/ops/monitoring · high confidence

Disable exception obfuscation to preserve stack traces

The app now preserves class names and line number information for analytics entries, operations, and all Throwable subclasses. This change ensures that stack traces and error messages remain readable and useful for debugging and analytics, rather than being obfuscated by ProGuard.

client-android/app · high confidence

Flutter-based authorization UI with optional password hashing

The identity-ui authorization pages have been rewritten in Flutter, replacing the previous Vue.js implementation. This update introduces a new credentials form that supports optional user password hashing via PBKDF2 (SHA-512) when enabled, requiring a username, password, and optional user salt. The interface handles OAuth authorization requests and callbacks, displaying error states, processing indicators, and scope details, while allowing users to explicitly reject authorization requests.

identity-ui/lib/pages/authorize · high confidence

Identity UI default pages rewritten in Flutter

The default identity-ui pages (home, not-found, and shared components) have been reimplemented in Flutter, replacing the previous Vue.js implementation. This change introduces new Flutter widgets for the home page (displaying OAuth 2.0 info and an RFC link), a 404 page with navigation back to home, and shared UI components for error handling and layout, marking a shift in the underlying UI framework for this module.

identity-ui/lib/pages/default · high confidence

Identity UI migrated to Flutter with Material 3 theming

The identity-ui component has been rewritten from Vue.js to Flutter, introducing a new codebase in the lib directory. This change implements a modernized visual design using Material 3 (enabled via useMaterial3: true) and defines specific light and dark color schemes in color\_schemes.dart. The application entry point in main.dart initializes the Flutter app with path URL strategy and integrates environment variable loading via flutter\_dotenv.

identity-ui/lib · high confidence

Identity UI model layer migrated to Flutter with Freezed data classes

The identity-ui model layer has been rewritten in Dart using the Flutter framework, replacing the previous Vue.js implementation. This change introduces immutable data classes for core identity entities (Api, Client, ResourceOwner, StoredAuthorizationCode, StoredRefreshToken) and their corresponding create/update request payloads, all generated via the Freezed package for type-safe JSON serialization.

identity-ui/lib/model · high confidence

Identity UI page router now escapes redirect\_uri and supports optional password derivation

The identity-ui page router now correctly escapes the redirect\_uri parameter in navigation queries to prevent issues with special characters, and introduces support for optional user password hashing via a configurable derivation setup (enabled by environment variables for secret size, iterations, and salt prefix). This change is implemented in the new Flutter-based page\_router.dart file, which also sets up OAuth configuration, login/logout flows, and UI components like the app bar and drawer for managing APIs, clients, owners, codes, and tokens.

identity-ui/lib/pages · high confidence

Identity UI web frontend migrated to Flutter

The web-based user interface for the identity service has been rebuilt using Flutter, replacing the previous implementation. This change introduces a new HTML entry point that loads the Flutter engine and a custom JavaScript helper to handle authorization callbacks, along with updated assets and a web manifest to support the new application structure.

identity-ui/web · high confidence

Identity management UI migrated to Flutter

The identity management interface in the \identity-ui\ application has been rewritten from Vue.js to Flutter. This change introduces new Flutter-based pages for managing APIs, clients, authorization codes, resource owners, and refresh tokens, replacing the previous implementation. The new UI provides consistent CRUD capabilities for these identity entities, including creation, editing, and deletion, with specific behaviors such as preventing modification of the currently active client or owner and supporting optional user password hashing for resource owners.

identity-ui/lib/pages/manage, identity-ui/lib/pages/manage/components · high confidence

Identity persistence layer migrated from in-memory KV store to Slick/SQL

The identity service's persistence backend has been replaced with a Slick-based SQL implementation for APIs, clients, resource owners, and refresh tokens, replacing the previous in-memory key-value store. This change introduces database migrations that automatically transfer existing data from the legacy KV format to the new relational schema, ensuring continuity for current users. Additionally, the refresh token store now enforces a unique index on the client-owner pair and uses atomic consume operations to improve data integrity.

identity/src/main/scala/stasis/identity/persistence · high confidence

Identity service refactored to use Pekko and configurable database persistence

The identity service has been rewritten to run on Apache Pekko instead of Akka and now uses a new persistence layer backed by Slick. This change introduces configurable database connection settings, including the ability to set the number of executor threads and queue size, and supports multiple Slick database profiles. The service now handles database migrations automatically on startup and manages the lifecycle of API, client, and resource owner stores. Additionally, the service now supports generating stored JWKs if they do not exist and allows configuring the number of database threads and queue size for better performance tuning.

identity/src/main/scala/stasis/identity/service · high confidence

Introduce Flutter-based Identity UI

The identity-ui module has been replaced with a new web-based user interface built using Flutter, providing a cross-platform frontend for the identity service. This change introduces a complete Flutter application structure, including API client implementations for managing APIs, clients, and resource owners, as well as OAuth 2.0 authentication flows. The new UI supports multiple platforms (Android, iOS, Linux, macOS, Web, Windows) and includes development tooling such as a QA script for linting, testing, and coverage reporting.

identity-ui · high confidence

Introduce Slick-based manifest persistence with legacy data migration

The manifest store implementation has been replaced with a new Slick-backed database layer that persists crate metadata (crate ID, size, copies, origin, source, destinations, and creation time) directly to a relational database. This change introduces a migration path from the previous key-value store storage format, ensuring existing manifest data is automatically converted to the new schema upon initialization. The new implementation also integrates telemetry metrics for store operations (put, get, delete, list) and relies on the Pekko actor system for execution context.

core/src/main/scala/stasis/core/persistence/manifests · high confidence

Introduce client CLI API layer with TLS certificate handling and operation management

The client CLI now includes a dedicated API module that manages communication with the backend service. This update adds support for querying and rendering backup rules, resuming stopped or failed operations, and following operation progress via event streams. It also introduces custom recovery directory support and allows users to update or remove dataset definitions and entries. To ensure secure connectivity, the API layer validates TLS certificates, automatically regenerating them if they are expired or invalid, and supports custom PKCS\#12 certificate contexts. Additionally, the CLI can now handle device commands, re-encrypt device secrets, update user passwords and salts, and retrieve analytics information.

_client-cli/client\cli/api · high confidence

Introduce configurable logging and client settings via Logback and reference.conf

The client now uses a new Logback configuration (logback.xml) to manage logging, writing logs to a platform-independent user home directory with size-based rolling, and supports environment variables to control log levels for Pekko, system tray, and the client itself. Additionally, a new reference.conf provides extensive default configuration for client behavior, including API connection details (HTTP/TLS), compression rules, backup and recovery parameters, secret derivation settings, and server authentication endpoints, all of which can be overridden via environment variables.

client/src/main/resources · high confidence

Introduce reservation store with Pekko integration and memory backend

The core persistence layer for crate storage reservations has been implemented with a new \ReservationStore\ trait and \DefaultReservationStore\ class. This change migrates the actor system foundation from Akka to Pekko, as evidenced by the imports of \org.apache.pekko\ components. The default implementation utilizes an in-memory key-value store backend (\MemoryStore\) and integrates with the telemetry system to record reservation metrics. It supports setting expiration durations for reservations, automatically triggering deletion logic after the specified timeout.

core/src/main/scala/stasis/core/persistence/reservations · high confidence

Introduce structured client service component initialization

The client service now initializes its core capabilities through a set of dedicated component modules (ApiClients, ApiEndpoint, Base, Init, Ops, Secrets, Tracking) rather than ad-hoc construction. This change centralizes the wiring of HTTP/gRPC API clients with retry and buffering logic, establishes a configurable HTTP API endpoint with token-based authentication, and implements a dual-mode credential initialization flow (stdin for interactive use, HTTP API for headless environments). It also introduces persistent state tracking for backup and recovery operations, manages device and user secrets via OAuth2 token retrieval and re-encryption, and configures telemetry (metrics and analytics) within the base service context.

client/src/main/scala/stasis/client/service/components · high confidence

Introduce structured networking exception hierarchy

The core networking module now provides a dedicated exception hierarchy for handling client-side failures. A new base class, NetworkingFailure, serves as the parent for specific failure types including ClientFailure, CredentialsFailure, EndpointFailure, and ReservationFailure. This change allows users to catch and distinguish between different categories of networking errors more precisely than before.

core/src/main/scala/stasis/core/networking/exceptions · high confidence

Introduce structured secrets management for user and device encryption

The client now uses a dedicated secrets hierarchy to handle cryptographic material for user authentication and device data. User passwords are converted into either hashed or unhashed authentication passwords depending on configuration, and into hashed encryption passwords that derive separate keys for local and key-store encryption via HKDF. Device secrets are generated from user and device identifiers, allowing the creation of distinct file and metadata secrets with unique keys and IVs to prevent reuse across files with the same names. This structured approach ensures that encryption keys are derived deterministically and isolated by context (user, device, file, metadata).

client/src/main/scala/stasis/client/encryption/secrets · high confidence

Introduces configurable authentication delay to mitigate brute-force attacks

The authentication logic in the identity service now enforces a configurable delay on all authentication attempts, including failures. This is implemented in the \EntityAuthenticator\ trait via \org.apache.pekko.pattern.after\, which applies a delay defined in the \Secret.Config\ before returning the authentication result. This change affects both client and resource owner authentication flows, ensuring that even incorrect credentials trigger the delay, thereby slowing down automated brute-force attempts.

identity/src/main/scala/stasis/identity/authentication · high confidence

Introduces file staging abstraction with stricter permission handling

The client now uses a new FileStaging trait and DefaultFileStaging implementation to manage temporary files during the staging process. This change introduces stricter file permissions by applying owner-only attributes to temporary files, enhancing security during the staging phase. The implementation leverages Apache Pekko for asynchronous operations and adapts to platform-specific metadata for file attribute handling.

client/src/main/scala/stasis/client/staging · high confidence

Introduction of server-specific security exception classes

The server now defines specific exception types for security failures, including AuthorizationFailure and CredentialsManagementFailure. AuthorizationFailure extends the SecurityFailure class from the layers 1.0.0 library, while CredentialsManagementFailure extends the standard Exception class, providing structured error handling for authorization and credential management issues.

server/src/main/scala/stasis/server/security/exceptions · high confidence

Migrate gRPC client infrastructure from Akka to Pekko

The internal gRPC networking layer has been migrated from Akka to Apache Pekko. This change updates the gRPC client implementation to use Pekko actors and Pekko gRPC settings, introduces new internal components for handling HTTP credentials (Basic and OAuth2 Bearer) and request marshalling, and adds implicit conversions for UUID and ByteString types to support the new runtime environment.

core/src/main/scala/stasis/core/networking/grpc/internal · high confidence

Migrate gRPC networking layer from Akka to Pekko

The gRPC endpoint implementation and client in the core networking module have been migrated from Akka to Apache Pekko. This change updates the underlying actor system and stream processing libraries (e.g., \pekko.stream\, \pekko.grpc\) used by \GrpcEndpoint\ and \GrpcEndpointClient\, ensuring compatibility with the new runtime while maintaining existing functionality for pushing, pulling, and discarding crates over gRPC.

core/src/main/scala/stasis/core/networking/grpc · high confidence

New Flutter-based development environment for Identity UI

The Identity UI development setup has been migrated from Vue.js to Flutter, introducing a new suite of deployment scripts and configuration files for local testing. Developers can now use \build.py\ to manage Flutter dependencies and build artifacts, \run\_server.py\ to launch the web server on port 8080, and \run\_browser.py\ to open a compatible browser instance. The environment is configured via a new \.env\ file and \bootstrap.conf\, which defines test APIs, clients, and owner accounts for the identity service, while \docker-compose.yml\ orchestrates the identity service container with the necessary environment variables and volume mounts.

identity-ui/deployment/dev · high confidence

New JSON serialization formats and HTTP client with retry logic

The core API layer now includes a new Formats object that defines JSON serialization and deserialization for network endpoints (HTTP and gRPC), node descriptors (local, remote HTTP, remote gRPC), crate storage backends, and service discovery endpoints. Additionally, a new PoolClient has been introduced to handle HTTP requests via an Akka HTTP super pool, featuring automatic retry logic with exponential backoff for specific transient error codes (such as 424 Failed Dependency, 408 Request Timeout, and various 5xx errors).

core/src/main/scala/stasis/core/api · high confidence

New Pekko-based AES-GCM encryption implementation

The client's encryption layer has been replaced with a new implementation using Apache Pekko Streams and AES-GCM mode. This change introduces dedicated Encoder and Decoder traits and an Aes object that handles file and metadata encryption via Pekko Flow stages, replacing the previous mechanism.

client/src/main/scala/stasis/client/encryption · high confidence

New core routing layer with Pekko streams and telemetry

The core routing subsystem has been replaced with a new implementation built on Apache Pekko streams, introducing the DefaultRouter, NodeProxy, and Node models to manage crate distribution. This change adds comprehensive metrics collection for push, pull, discard, reserve, and stage operations via OpenTelemetry, and introduces specific failure types (PushFailure, PullFailure, etc.) to provide detailed error reporting for routing operations.

core/src/main/scala/stasis/core/routing · high confidence

New event-sourced backup, recovery, and server trackers

The client now uses new DefaultBackupTracker, DefaultRecoveryTracker, and DefaultServerTracker implementations that persist operation and server states via an EventLog backend. Users gain durable tracking for backup and recovery operations (including support for removing operations and resuming backups) and real-time server reachability updates, with state changes streamed to consumers via Pekko Sources.

client/src/main/scala/stasis/client/tracking/trackers · high confidence

New exception types for client operations

The client now introduces a set of specific exception classes in the \stasis.client.ops.exceptions\ package to handle distinct failure scenarios. These include \EntityDiscardFailure\, \EntityMergeFailure\, \OperationExecutionFailure\, \ScheduleAssignmentParsingFailure\, and \ScheduleRetrievalFailure\ for general operation and schedule errors, as well as \EntityProcessingFailure\ which captures the specific entity path and cause. Additionally, \OperationStopped\ is added with an extractor to facilitate pattern matching on stopped operations, allowing for more precise error handling and reporting in client-side operations.

client/src/main/scala/stasis/client/ops/exceptions · high confidence

New persistence layer for devices, datasets, and analytics

The server's persistence layer has been refactored to introduce dedicated stores for device management, dataset definitions and entries, and analytics. This change adds new database schemas and migration paths (including a migration from the legacy key-value store for devices, keys, and dataset definitions) and enforces strict ownership-based access controls, ensuring users can only view, create, or delete resources associated with their own devices. Additionally, dataset entries now track size and change counts, and device bootstrap code consumption has been switched to an atomic operation to prevent race conditions.

server/src/main/scala/stasis/server/persistence · high confidence

New request models for managing APIs, clients, and owners with custom subjects

The identity management API now includes dedicated request models for creating and updating APIs, clients, and resource owners. These models introduce support for optional custom subjects on both clients and owners, allowing for more flexible identity mapping. Creation requests for clients and owners now handle credential derivation with salt generation, while update requests allow modification of token expiration, active status, allowed scopes, and credentials.

identity/src/main/scala/stasis/identity/api/manage/requests · high confidence

OAuth2 grant handlers migrated to Pekko and standardized on JSON responses

The OAuth2 grant implementation in the identity service has been rewritten to use Apache Pekko instead of Akka, and all token and authorization responses are now returned as JSON rather than plaintext. This change introduces dedicated handlers for Authorization Code, PKCE Authorization Code, Client Credentials, Implicit, Refresh Token, and Resource Owner Password Credentials grants, ensuring consistent JSON serialization for all OAuth2 interactions.

identity/src/main/scala/stasis/identity/api/oauth · high confidence

Persistent file-based caching for dataset definitions, entries, and metadata

The Android client now persists dataset-related data to local storage, ensuring that dataset definitions, individual entries, and metadata remain available across app restarts. This change introduces specific serialization logic for these objects, allowing the application to cache and retrieve this information from the file system rather than relying solely on in-memory storage.

_client-android/app/src/main/java/stasis/client\android/persistence/cache · high confidence

Production deployment configuration for Flutter-based Identity UI

The production deployment setup for the Identity UI has been updated to support the new Flutter web application. This includes a new Dockerfile based on nginx:stable-alpine, build and staging scripts (build.py, stage.py) that utilize Flutter and Dart tooling, and an entrypoint script that configures nginx with environment variables for identity server integration, CORS, and optional TLS termination. The nginx configuration also includes a fix to redirect URLs containing double slashes.

identity-ui/deployment/production · high confidence

Project version bump to 1.7.6-SNAPSHOT and build configuration updates

The project version has been updated from 0.0.1-SNAPSHOT to 1.7.6-SNAPSHOT. Additionally, the build configuration has been adjusted: the \.sbtopts\ file now sets specific JVM memory limits (1G metaspace, 1536m heap), and the Scala formatting configuration (\.scalafmt.conf\) has been updated to use the Scala 2.13 dialect, increased max column width to 130, and refined rewrite rules.

(repo-wide) · high confidence

Recovery operation now tracks entity collection, processing, and metadata application metrics

The client's backup recovery workflow now explicitly records telemetry at each stage of the process. As entities are collected from the source, the system logs which ones are examined and collected. During processing, it tracks when entities are examined, collected, and processed, including details on decompression steps. Finally, when metadata is applied to the recovered files, the system records this completion. This provides users with granular visibility into the progress and status of recovery operations.

client/src/main/scala/stasis/client/ops/recovery/stages · high confidence

Recovery operation refactored with Pekko streams and new providers

The recovery operation in the client has been rewritten to use Apache Pekko streams instead of the previous Akka implementation, introducing a new Providers case class to manage dependencies like checksums, staging, compression, and encryption. The Recovery class now utilizes a staged stream pipeline (EntityCollection, EntityProcessing, MetadataApplication) with supervision strategies that resume on entity processing failures while tracking them, and supports path-based queries for filtering files during recovery.

client/src/main/scala/stasis/client/ops/recovery · high confidence

Refactor node authentication to support JWT and Pre-Shared Key credentials

The core security module now introduces a pluggable authentication layer for nodes, replacing previous implementations with distinct authenticators for JWT-based and Pre-Shared Key (PSK) credentials. The new JwtNodeAuthenticator validates OAuth2 Bearer tokens by extracting node identities from JWT claims and verifying them against the node store, while the PreSharedKeyNodeAuthenticator handles credential pairs using constant-time secret comparison to prevent timing attacks. Corresponding traits (NodeAuthenticator, NodeCredentialsProvider) and a JwtNodeCredentialsProvider have been added to standardize how node identities are authenticated and how credentials are generated for remote endpoints.

core/src/main/scala/stasis/core/security · high confidence

Refactor recovery stages to use Pekko Streams and internal wrapper classes

The internal recovery stages have been rewritten to use Apache Pekko Streams instead of the previous Akka implementation. New internal wrapper classes—DecompressedByteStringSource, DecryptedCrates, DestagedByteStringSource, and MergedCrates—encapsulate the streaming logic for decompression, decryption, destaging, and merging of file parts. This change updates the underlying stream library and restructures how recovery operations process byte streams, ensuring compatibility with the Pekko ecosystem while maintaining the existing recovery behavior.

client/src/main/scala/stasis/client/ops/recovery/stages/internal · high confidence

Refactored OAuth directives to use Pekko and PKCE support

The OAuth directive layer has been rewritten to migrate from Akka to Pekko and to introduce support for PKCE (Proof Key for Code Exchange) in authorization code grants. The new implementation splits functionality into focused traits: AccessTokenGeneration, AudienceExtraction, AuthorizationCodeConsumption, AuthorizationCodeGeneration, ClientAuthentication, ClientRetrieval, RefreshTokenConsumption, RefreshTokenGeneration, and ResourceOwnerAuthentication. Authorization code generation and consumption now handle optional challenges (S256 and Plain methods) for PKCE compliance. Audience extraction supports both client and API audiences via URN prefixes in scopes. Client and resource owner authentication remain basic HTTP-based but are now integrated with the new Pekko-based directive structure. Refresh token generation is now configurable via a refreshTokensAllowed flag.

identity/src/main/scala/stasis/identity/api/oauth/directives · high confidence

Refactored backup and recovery metadata collection into dedicated collectors

The backup and recovery metadata collection logic has been restructured into new, dedicated components: BackupCollector, BackupMetadataCollector, RecoveryCollector, and RecoveryMetadataCollector. This change introduces a clearer separation of concerns where BackupCollector handles the parallel collection of source entities and their metadata for backups, while RecoveryCollector manages the collection of target entities for file recovery. The metadata collection steps are now encapsulated in their respective metadata collectors, which leverage checksum and compression analysis for backups and checksum verification for recoveries. This refactoring improves the modularity of the client's collection operations and aligns the implementation with the new Pekko stream-based architecture.

client/src/main/scala/stasis/client/collection · high confidence

Refactored node persistence layer with Slick and Pekko integration

The node persistence implementation has been rewritten to use Slick for database operations and migrated from Akka to Pekko for the actor system. The new DefaultNodeStore introduces a caching layer backed by a generic KeyValueStore and integrates with the 'layers' library for metrics recording and telemetry context. Additionally, the store now includes built-in migration support to handle data transformation from the legacy KeyValueStore format to the new Slick-based schema, ensuring backward compatibility during the transition.

core/src/main/scala/stasis/core/persistence/nodes · high confidence

Secure secret derivation and comparison in identity model

The identity service now uses a dedicated Secret model to handle password hashing and verification. This implementation ensures that raw passwords are cleared from memory immediately after derivation via PBEKeySpec, and comparisons are performed using constant-time checks to mitigate timing attacks. Configuration for these cryptographic parameters (algorithm, iterations, key size, salt size, and authentication delay) is now explicitly managed for both client and resource owner contexts.

identity/src/main/scala/stasis/identity/model/secrets · high confidence

Server service component initialization framework

The server now initializes its core services through a new component-based loading system located in the service components package. This change introduces loaders for the action executor, authenticators (handling OAuth, user JWT, and node JWT), credentials managers, event collection, and the device bootstrap endpoint, alongside the underlying routing infrastructure. Users benefit from a structured, configuration-driven startup process where these services are instantiated and wired together via dependency context, replacing the previous initialization logic.

server/src/main/scala/stasis/server/service/components · high confidence

Server service initialization and persistence wiring via Layers library

The server service now initializes its core and server persistence layers using the new Layers library, wiring up database connections, migration executors, and specific stores (nodes, reservations, manifests, datasets, devices, users, analytics) via configuration. It also sets up the API and core HTTP endpoints, authenticators, actions, events, credentials managers, bootstrap logic, and service discovery, while logging build info and configuration details at startup.

server/src/main/scala/stasis/server/service · high confidence

Slick persistence backend refactored with metrics and profile resolution

The Slick persistence backend has been refactored to integrate with the 'layers' library, enabling automatic metrics collection for store operations (put, get, delete, consume, etc.) via TelemetryContext. The backend now supports configurable Slick database profiles through a new SlickProfile utility that resolves profile names (e.g., PostgresProfile, MySQLProfile) to actual JDBC implementations. Additionally, a LegacyKeyValueStore migration helper was added to support data migration between schema versions, and the consume operation now uses atomic transactional delete-and-read to ensure data consistency.

core/src/main/scala/stasis/core/persistence/backends/slick · high confidence

Standardized API error handling and logging via new Rejection and Sanitizing handlers

The server now uses dedicated handler objects in the API layer to manage validation errors and exceptions consistently. The new Rejection handler intercepts validation failures, logs the specific rejection message along with request details, and returns a structured BadRequest response using the layers library's MessageResponse. The Sanitizing handler manages exceptions by suppressing sensitive details for authorization failures (returning Forbidden) and providing a generic InternalServerError with a unique failure reference for unhandled exceptions, ensuring that internal stack traces and sensitive data are not exposed to clients while maintaining consistent logging across the application.

server/src/main/scala/stasis/server/api/handlers · high confidence

State persistence now uses timestamped files with random suffixes

The file-based state store has been updated to name state files using a timestamp and a random alphanumeric suffix (e.g., state\_1678886400000\_aB3c) instead of a static name. This change, combined with the existing retention logic that prunes older files, ensures that concurrent writes or restarts do not overwrite each other's state, improving reliability during state recovery.

core/src/main/scala/stasis/core/persistence/backends/file/state · high confidence

Support for custom subjects on clients and resource owners

The identity model now allows associating a custom subject identifier with both Client and ResourceOwner entities. This new optional field enables more flexible identity mapping for applications and users, allowing them to be identified by a specific subject string rather than relying solely on internal IDs.

identity/src/main/scala/stasis/identity/model/clients · high confidence

Test coverage

Added Android UI tests for API ViewModels; Added Android instrumentation test utilities and fixtures; Added Android instrumentation tests for rule persistence components; Added Android instrumentation tests for utility classes; Added Android instrumented tests for schedule persistence components; Added Flutter unit tests for identity-ui API client, OAuth, and UI components; Added Mockito inline mock maker configuration for tests; Added instrumentation tests for analytics collection and persistence; Added instrumentation tests for backup, recovery, and server tracking; Added instrumentation tests for credentials persistence and view models; Added mock implementations for client CLI API tests; Added mock server API client for testing; Added server API route tests; Added test configuration and logging resources for the client module; Added test configuration and resources for identity service; Added test configuration files for server actions and device bootstrap; Added test configuration resources for core module; Added test coverage for Android serialization and test utilities; Added test coverage for default CLI rendering modules; Added test coverage for identity API endpoints and serialization; Added test fixtures for analysis, collection, and encryption modules; Added test mocks for Android client infrastructure; Added test resources for backup scheduling and file operations; Added tests for CLI filtering, sorting, and type coercion; Added tests for dataset cache serialization and deserialization; Added tests for device configuration persistence and bootstrapping; Added unit tests and test mocks for client backup and recovery operations; Added unit tests and test utilities for the client module; Added unit tests for Android Settings preferences; Added unit tests for Android activity helpers and system receivers; Added unit tests for Android scheduling components; Added unit tests for Android security credential management; Added unit tests for DefaultFileStaging; Added unit tests for DefaultServerMonitor; Added unit tests for InsecureX509TrustManager; Added unit tests for backup and recovery state tracking; Added unit tests for backup operation stages; Added unit tests for backup operations and operation-stopped exceptions; Added unit tests for backup staging internals; Added unit tests for client API and core endpoint clients; Added unit tests for client CLI render flatten modules; Added unit tests for client HTTP API serialization and endpoint routing; Added unit tests for client collection rule specifications; Added unit tests for client command processing components; Added unit tests for client compression implementations; Added unit tests for client encryption secrets and streaming ciphers; Added unit tests for client model and encryption components; Added unit tests for client operation scheduling and execution; Added unit tests for client security components; Added unit tests for client service components; Added unit tests for core networking, discovery, and API serialization; Added unit tests for notification management utilities; Added unit tests for recovery stage operations; Added unit tests for the client CLI API layer; Added unit tests for the client CLI main entry point; Added unit tests for the client CLI render package; Added unit tests for the client's file collection rule walker; Initial test suite for client CLI commands; Initial test suite for the Android client library.

Dependencies

Initial dependency configuration for Android, Flutter, and Scala components

This change introduces the build configuration files for the Android client, Flutter-based UIs (client, identity, and server), and the core Scala services. It establishes the dependency graph for the Android app (using Kotlin 2.3.10, Hilt, Room, and Material 1.13.0), sets up the Flutter projects with SDK 3.8.0 and libraries like Freezed and OAuth2, and migrates the Scala backend to Scala 2.13.18 and Apache Pekko 1.6.0, replacing the previous Akka and Scala 2.12 stack.

(dependencies) · high confidence

Upgraded Gradle wrapper to version 9.3.1

The Android build system now uses Gradle 9.3.1 for project builds, replacing the previous wrapper configuration. This ensures consistent build environments across development and CI/CD pipelines by pinning the specific Gradle distribution version.

client-android/gradle · 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 47.

Lenses

  • Code Health 85
  • Architecture 87
  • Maturity 65
  • Readiness 41
  • Security 61
  • Domain Modelling 60
  • Accessibility 40

Changes since last survey

  • 300 commits — 245 feature/other, 55 fixes

By area

  • (root) — 58 commits
  • client-android/app — 47 commits
  • client/src — 31 commits
  • client-ui/lib — 20 commits
  • .github/workflows — 17 commits
  • client-android/lib — 17 commits
  • client-cli/client_cli — 16 commits
  • server/src — 12 commits
  • client-cli/setup.py — 11 commits
  • core/src — 11 commits
  • identity/src — 11 commits
  • server-ui/lib — 10 commits
  • deployment/production — 7 commits
  • deployment/dev — 6 commits
  • layers/src — 6 commits
  • shared/src — 5 commits
  • identity-ui/lib — 4 commits
  • client-ui/pubspec.yaml — 3 commits
  • client-android/fastlane — 2 commits
  • identity-ui/deployment — 2 commits

Notable commits

  • fix: Fix artifact upload during release/publish
  • fix: Fix broken github actions
  • fix: Fix broken release publishing
  • fix: Fix publish workflow
  • fix: Fix slick meta table queries to be more resilient
  • fix: Minor config docs fix
  • fix: Minor fixes
  • fix: Minor fixes for analytics entry failures
  • fix: Update dependencies and fix broken DefaultDatasetEntryStore migration
  • fix: [client-androi] Fix rendering bug in home fragment
  • fix: [client-android] Fix artifact build time calculation
  • fix: [client-android] Fix cache handling when removing definitions
  • fix: [client-android] Fix crash when viewing collected analytics info
  • fix: [client-android] Fix search result backup entry links and entry filtering
  • fix: [client-android] Fix user permissions layout
  • fix: [client-android] Update gradle and fix flaky tests
  • fix: [client-cli] Fix minor issues with bootstrap and maintenance commands
  • fix: [client-cli] Fix regex for matching memory-size sstrings during sorting/filtering
  • fix: [client-ui] Fix app process handling
  • fix: [client-ui] Fix deprecated color properties
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

sndnv/stasis 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 20 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 2413becda288e26be8d7e1e4ea1f8e4466600b24 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-b51f968c9b10.