From 73196b2bcd59baddd45189e08cc8e2ea358f1918 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Wed, 13 May 2026 11:15:15 +0200 Subject: [PATCH 1/4] chore(brand): align app-store hex to canonical cobalt #21468B The icon hex was filled with the legacy '#4376FC' (the conduction-design-tokens 'Conduction Cobalt'). The design-system has retired this in preview/colors.html with the caption > Our legacy blue (#4376FC) read as 'cloud / SaaS', light, frisky, > lacking weight. Cobalt is the official blue of the Dutch flag, > Dutch by birthright, dark enough to feel serious, light enough > to stay blue, and AAA-contrast on white so it can carry body > text. Swap to #21468B (--c-blue-cobalt in tokens.css) so the app-store hex matches the navbar wordmark and the rest of the brand chrome. Fleet sweep 2026-05-13. --- img/app-store.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/img/app-store.svg b/img/app-store.svg index 4e9caa6..7aa43de 100644 --- a/img/app-store.svg +++ b/img/app-store.svg @@ -1,5 +1,5 @@ - + From 17e14bc33f3c8cc87a4871f24c0394183f434a1c Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Wed, 20 May 2026 14:28:09 +0200 Subject: [PATCH 2/4] chore(security): bump symfony/yaml + twig/twig past advisories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit composer audit was flagging 14 vulnerabilities across symfony/yaml + twig/twig: - symfony/yaml v6.4.34 → v6.4.40 (CVE-2026-45304/45305 + others) - twig/twig v3.24.0 → v3.26.0 (sandbox-escape advisories chain) Lock-only update; no composer.json changes (both come in transitively via Symfony deps + edgedesign/phpqa). --- composer.lock | 76 +++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/composer.lock b/composer.lock index 53afe12..4ec3f55 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5064b96f4ff50d18a4d16f97fd9353e7", + "content-hash": "ad1ed9c33354cdacaaf77f13e9e9abf6", "packages": [], "packages-dev": [ { @@ -6207,16 +6207,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -6229,7 +6229,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -6254,7 +6254,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -6265,12 +6265,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "symfony/event-dispatcher", @@ -6572,16 +6576,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -6631,7 +6635,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -6651,7 +6655,7 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -6822,16 +6826,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -6883,7 +6887,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0" }, "funding": [ { @@ -6903,11 +6907,11 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -6963,7 +6967,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.37.0" }, "funding": [ { @@ -7309,16 +7313,16 @@ }, { "name": "symfony/yaml", - "version": "v6.4.34", + "version": "v6.4.40", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f" + "reference": "68dcd1f1602dac9d9221e25729683e0ce8733f3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7bca30dabed7900a08c5ad4f1d6483f881a64d0f", - "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f", + "url": "https://api.github.com/repos/symfony/yaml/zipball/68dcd1f1602dac9d9221e25729683e0ce8733f3b", + "reference": "68dcd1f1602dac9d9221e25729683e0ce8733f3b", "shasum": "" }, "require": { @@ -7361,7 +7365,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.34" + "source": "https://github.com/symfony/yaml/tree/v6.4.40" }, "funding": [ { @@ -7381,7 +7385,7 @@ "type": "tidelift" } ], - "time": "2026-02-06T18:32:11+00:00" + "time": "2026-05-19T20:33:22+00:00" }, { "name": "theseer/tokenizer", @@ -7435,16 +7439,16 @@ }, { "name": "twig/twig", - "version": "v3.24.0", + "version": "v3.26.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a6769aefb305efef849dc25c9fd1653358c148f0" + "reference": "1fcae487b180d78e6351f4e0afa91f9eab96a2bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0", - "reference": "a6769aefb305efef849dc25c9fd1653358c148f0", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/1fcae487b180d78e6351f4e0afa91f9eab96a2bc", + "reference": "1fcae487b180d78e6351f4e0afa91f9eab96a2bc", "shasum": "" }, "require": { @@ -7499,7 +7503,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.24.0" + "source": "https://github.com/twigphp/Twig/tree/v3.26.0" }, "funding": [ { @@ -7511,7 +7515,7 @@ "type": "tidelift" } ], - "time": "2026-03-17T21:31:11+00:00" + "time": "2026-05-20T07:31:59+00:00" }, { "name": "vimeo/psalm", @@ -7692,9 +7696,9 @@ "platform": { "php": "^8.1" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { "php": "8.1" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } From 518b0dc615933f06b7bce0cb93454c183ace0a59 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Wed, 20 May 2026 14:42:57 +0200 Subject: [PATCH 3/4] =?UTF-8?q?fix(tests):=20rename=20OCA\AppTemplate=20?= =?UTF-8?q?=E2=86=92=20OCA\DeskDesk=20in=20PHPUnit=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5 test files still carried the nextcloud-app-template scaffold's `OCA\AppTemplate\*` namespace + class names — never updated when the app was renamed to DeskDesk. PHPUnit was failing with 25 errors: "Class OCA\AppTemplate\Service\ItemService not found". Renames: - tests/Unit/AppTemplateTest.php → DeskDeskTest.php (class + namespace) - tests/unit/Controller/SettingsControllerTest.php — namespace + 'use' - tests/unit/Controller/ItemControllerTest.php — namespace + 'use' - tests/unit/Service/ItemServiceTest.php — namespace + 'use' - tests/unit/Service/SettingsServiceTest.php — namespace + 'use' Production classes already use `OCA\DeskDesk\*`; this just brings the tests in line so PHPUnit can resolve the classes under test. --- tests/Unit/{AppTemplateTest.php => DeskDeskTest.php} | 4 ++-- tests/unit/Controller/ItemControllerTest.php | 8 ++++---- tests/unit/Controller/SettingsControllerTest.php | 8 ++++---- tests/unit/Service/ItemServiceTest.php | 6 +++--- tests/unit/Service/SettingsServiceTest.php | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) rename tests/Unit/{AppTemplateTest.php => DeskDeskTest.php} (78%) diff --git a/tests/Unit/AppTemplateTest.php b/tests/Unit/DeskDeskTest.php similarity index 78% rename from tests/Unit/AppTemplateTest.php rename to tests/Unit/DeskDeskTest.php index 57f1b73..0f139c8 100644 --- a/tests/Unit/AppTemplateTest.php +++ b/tests/Unit/DeskDeskTest.php @@ -2,14 +2,14 @@ declare(strict_types=1); -namespace OCA\AppTemplate\Tests\Unit; +namespace OCA\DeskDesk\Tests\Unit; use PHPUnit\Framework\TestCase; /** * Placeholder unit test — replace with real tests for your app logic. */ -class AppTemplateTest extends TestCase +class DeskDeskTest extends TestCase { public function testPlaceholder(): void diff --git a/tests/unit/Controller/ItemControllerTest.php b/tests/unit/Controller/ItemControllerTest.php index 2d3202b..736b55d 100644 --- a/tests/unit/Controller/ItemControllerTest.php +++ b/tests/unit/Controller/ItemControllerTest.php @@ -8,7 +8,7 @@ * (the actual auth check) lives in ItemService. * * @category Test - * @package OCA\AppTemplate\Tests\Unit\Controller + * @package OCA\DeskDesk\Tests\Unit\Controller * * @author Conduction Development Team * @copyright 2026 Conduction B.V. @@ -23,10 +23,10 @@ declare(strict_types=1); -namespace OCA\AppTemplate\Tests\Unit\Controller; +namespace OCA\DeskDesk\Tests\Unit\Controller; -use OCA\AppTemplate\Controller\ItemController; -use OCA\AppTemplate\Service\ItemService; +use OCA\DeskDesk\Controller\ItemController; +use OCA\DeskDesk\Service\ItemService; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; diff --git a/tests/unit/Controller/SettingsControllerTest.php b/tests/unit/Controller/SettingsControllerTest.php index e551d94..7e81eb5 100644 --- a/tests/unit/Controller/SettingsControllerTest.php +++ b/tests/unit/Controller/SettingsControllerTest.php @@ -4,7 +4,7 @@ * Unit tests for SettingsController. * * @category Test - * @package OCA\AppTemplate\Tests\Unit\Controller + * @package OCA\DeskDesk\Tests\Unit\Controller * * @author Conduction Development Team * @copyright 2026 Conduction B.V. @@ -17,10 +17,10 @@ declare(strict_types=1); -namespace OCA\AppTemplate\Tests\Unit\Controller; +namespace OCA\DeskDesk\Tests\Unit\Controller; -use OCA\AppTemplate\Controller\SettingsController; -use OCA\AppTemplate\Service\SettingsService; +use OCA\DeskDesk\Controller\SettingsController; +use OCA\DeskDesk\Service\SettingsService; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use PHPUnit\Framework\MockObject\MockObject; diff --git a/tests/unit/Service/ItemServiceTest.php b/tests/unit/Service/ItemServiceTest.php index 259ec3f..d2cbd69 100644 --- a/tests/unit/Service/ItemServiceTest.php +++ b/tests/unit/Service/ItemServiceTest.php @@ -8,7 +8,7 @@ * security-critical branches. * * @category Test - * @package OCA\AppTemplate\Tests\Unit\Service + * @package OCA\DeskDesk\Tests\Unit\Service * * @author Conduction Development Team * @copyright 2026 Conduction B.V. @@ -23,9 +23,9 @@ declare(strict_types=1); -namespace OCA\AppTemplate\Tests\Unit\Service; +namespace OCA\DeskDesk\Tests\Unit\Service; -use OCA\AppTemplate\Service\ItemService; +use OCA\DeskDesk\Service\ItemService; use OCP\App\IAppManager; use OCP\IAppConfig; use OCP\IGroupManager; diff --git a/tests/unit/Service/SettingsServiceTest.php b/tests/unit/Service/SettingsServiceTest.php index 58152b7..064c034 100644 --- a/tests/unit/Service/SettingsServiceTest.php +++ b/tests/unit/Service/SettingsServiceTest.php @@ -10,7 +10,7 @@ * Throwable-caught per ADR-005). * * @category Test - * @package OCA\AppTemplate\Tests\Unit\Service + * @package OCA\DeskDesk\Tests\Unit\Service * * @author Conduction Development Team * @copyright 2026 Conduction B.V. @@ -25,9 +25,9 @@ declare(strict_types=1); -namespace OCA\AppTemplate\Tests\Unit\Service; +namespace OCA\DeskDesk\Tests\Unit\Service; -use OCA\AppTemplate\Service\SettingsService; +use OCA\DeskDesk\Service\SettingsService; use OCP\App\IAppManager; use OCP\IAppConfig; use OCP\IGroupManager; From ac710e687056612c111874561646dbef3537a4f7 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Wed, 20 May 2026 14:53:48 +0200 Subject: [PATCH 4/4] fix(tests): update PHPUnit tests to match deskdesk production state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three PHPUnit failures after the namespace fix were real assertion mismatches between tests and production: 1. testGetSettingsReturnsIsAdminTrueForAdminUser + testUpdateSettings… — mocks expected IAppConfig calls to use 'app-template' app-id; production uses 'deskdesk' (Application::APP_ID). Updated both ->with(...) matchers. 2. testLoadConfigurationSuccessPathWithForce — - Stubbed configurationService had importFromApp($appId, $force) but production calls importFromFilePath($appId, $filePath, $version, $force). Replaced the stub method signature. - appManager mock was missing getAppPath() — needed for the bundle path resolution. Added stub returning a non-existent path so production falls back to the default version '0.2.0'. - Asserted version '0.1.0' but with no register file present production returns the '0.2.0' fallback. Updated assertion. Bootstrap tests/bootstrap.php — \OC_App::loadApp('app-template') also updated to 'deskdesk' so functional bootstrap matches the app ID. --- tests/bootstrap.php | 2 +- tests/unit/Service/ItemServiceTest.php | 2 +- tests/unit/Service/SettingsServiceTest.php | 24 ++++++++++++++-------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index bcb6c46..eff1570 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -19,6 +19,6 @@ } \OC_App::loadApps(); - \OC_App::loadApp('app-template'); + \OC_App::loadApp('deskdesk'); OC_Hook::clear(); } diff --git a/tests/unit/Service/ItemServiceTest.php b/tests/unit/Service/ItemServiceTest.php index d2cbd69..7f55eb0 100644 --- a/tests/unit/Service/ItemServiceTest.php +++ b/tests/unit/Service/ItemServiceTest.php @@ -209,7 +209,7 @@ public function markObjectDeleted(): void private function arrangeOpenRegister(): void { $this->appManager->method('isInstalled')->willReturn(true); - $this->appConfig->method('getValueString')->willReturn('app-template'); + $this->appConfig->method('getValueString')->willReturn('deskdesk'); $this->container->method('get')->willReturn($this->objectService); }//end arrangeOpenRegister() diff --git a/tests/unit/Service/SettingsServiceTest.php b/tests/unit/Service/SettingsServiceTest.php index 064c034..aa7cd96 100644 --- a/tests/unit/Service/SettingsServiceTest.php +++ b/tests/unit/Service/SettingsServiceTest.php @@ -172,7 +172,7 @@ public function testGetSettingsReturnsIsAdminTrueForAdminUser(): void $this->appConfig->expects($this->once()) ->method('getValueString') - ->with('app-template', 'register', '') + ->with('deskdesk', 'register', '') ->willReturn('some-register-uuid'); $this->userSession->method('getUser')->willReturn($user); @@ -249,7 +249,7 @@ public function testUpdateSettingsPersistsKnownKeysAndReturnsSettings(): void { $this->appConfig->expects($this->once()) ->method('setValueString') - ->with('app-template', 'register', 'new-register-uuid'); + ->with('deskdesk', 'register', 'new-register-uuid'); // getSettings() re-read after update. $this->appConfig->method('getValueString')->willReturn('new-register-uuid'); @@ -320,19 +320,25 @@ public function testLoadConfigurationReturnsFailureWhenOpenRegisterMissing(): vo public function testLoadConfigurationSuccessPathWithForce(): void { $this->appManager->method('isInstalled')->willReturn(true); + // getAppPath() is called to resolve the bundled register file path. + // The path won't exist in the test FS so production falls back to + // the default version '0.2.0' (see SettingsService::loadConfiguration). + $this->appManager->method('getAppPath')->willReturn('/tmp/deskdesk-test-app'); $configurationService = new class { /** - * Stub importFromApp mirroring OpenRegister's ConfigurationService. + * Stub importFromFilePath mirroring OpenRegister's ConfigurationService. * - * @param string $appId The app ID. - * @param bool $force Whether to force re-import. + * @param string $appId The app ID. + * @param string $filePath The bundle path relative to the NC root. + * @param string $version The register version string. + * @param bool $force Whether to force re-import. * - * @return array + * @return array A non-empty array on success. */ - public function importFromApp(string $appId, bool $force): array + public function importFromFilePath(string $appId, string $filePath, string $version, bool $force): array { - return ['version' => '0.1.0', 'imported' => true]; + return ['version' => $version, 'imported' => true]; } }; @@ -346,7 +352,7 @@ public function importFromApp(string $appId, bool $force): array $result = $this->service->loadConfiguration(force: true); self::assertTrue($result['success']); - self::assertSame('0.1.0', $result['version']); + self::assertSame('0.2.0', $result['version']); }//end testLoadConfigurationSuccessPathWithForce()