diff --git a/frontend/src/components/settings/__tests__/AboutSection.test.tsx b/frontend/src/components/settings/__tests__/AboutSection.test.tsx
new file mode 100644
index 00000000..75034ad9
--- /dev/null
+++ b/frontend/src/components/settings/__tests__/AboutSection.test.tsx
@@ -0,0 +1,67 @@
+import { describe, it, expect, vi, beforeAll } from 'vitest';
+import { render, screen } from '@testing-library/react';
+import { AboutSection } from '../AboutSection';
+import { ABOUT_LINK_URLS } from '../aboutLinks';
+
+beforeAll(() => {
+ // Vite injects this at build time; tests need a stand-in.
+ (globalThis as unknown as { __APP_VERSION__: string }).__APP_VERSION__ = '0.0.0-test';
+});
+
+vi.mock('@/context/LicenseContext', () => ({
+ useLicense: () => ({
+ license: {
+ tier: 'community',
+ status: 'community',
+ customerName: null,
+ productName: null,
+ maskedKey: null,
+ validUntil: null,
+ trialDaysRemaining: null,
+ instanceId: 'abcdef0123456789',
+ portalUrl: null,
+ isLifetime: false,
+ },
+ isPaid: false,
+ loading: false,
+ licenseStatus: 'ready',
+ licenseReady: true,
+ refresh: vi.fn(),
+ activate: vi.fn(),
+ deactivate: vi.fn(),
+ }),
+}));
+
+vi.mock('@/components/TierBadge', () => ({
+ TierBadge: () =>
Community,
+}));
+
+describe('AboutSection', () => {
+ it('renders Plan status and Source, License, and Licensing docs links with exact URLs', () => {
+ render(
);
+
+ expect(screen.getByText('Plan status')).toBeTruthy();
+ expect(screen.queryByText('License status')).toBeNull();
+
+ const source = screen.getByRole('link', { name: 'github.com/studio-saelix/sencho →' });
+ expect(source.getAttribute('href')).toBe(ABOUT_LINK_URLS.source);
+ expect(source.getAttribute('target')).toBe('_blank');
+ expect(source.getAttribute('rel')).toBe('noopener noreferrer');
+
+ const license = screen.getByRole('link', { name: 'LICENSE →' });
+ expect(license.getAttribute('href')).toBe(ABOUT_LINK_URLS.license);
+ expect(license.getAttribute('target')).toBe('_blank');
+ expect(license.getAttribute('rel')).toBe('noopener noreferrer');
+
+ const licensingDocs = screen.getByRole('link', {
+ name: 'docs.sencho.io/features/licensing →',
+ });
+ expect(licensingDocs.getAttribute('href')).toBe(ABOUT_LINK_URLS.licensingDocs);
+ expect(licensingDocs.getAttribute('target')).toBe('_blank');
+ expect(licensingDocs.getAttribute('rel')).toBe('noopener noreferrer');
+
+ expect(screen.getByText('Source code')).toBeTruthy();
+ expect(screen.getByText('AGPLv3 License')).toBeTruthy();
+ expect(screen.getByText('Licensing documentation')).toBeTruthy();
+ });
+});
diff --git a/frontend/src/components/settings/aboutLinks.ts b/frontend/src/components/settings/aboutLinks.ts
new file mode 100644
index 00000000..e784d990
--- /dev/null
+++ b/frontend/src/components/settings/aboutLinks.ts
@@ -0,0 +1,11 @@
+export const SOURCE_URL = 'https://github.com/studio-saelix/sencho';
+export const LICENSE_URL = 'https://github.com/studio-saelix/sencho/blob/main/LICENSE';
+export const LICENSING_DOCS_URL = 'https://docs.sencho.io/features/licensing';
+export const CHANGELOG_URL = 'https://github.com/studio-saelix/sencho/blob/main/CHANGELOG.md';
+
+export const ABOUT_LINK_URLS = {
+ source: SOURCE_URL,
+ license: LICENSE_URL,
+ licensingDocs: LICENSING_DOCS_URL,
+ changelog: CHANGELOG_URL,
+} as const;
diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts
index 576aa82c..a644f6e8 100644
--- a/frontend/vitest.config.ts
+++ b/frontend/vitest.config.ts
@@ -4,6 +4,9 @@ import path from 'path';
export default defineConfig({
plugins: [react()],
+ define: {
+ __APP_VERSION__: JSON.stringify('0.0.0-test'),
+ },
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
diff --git a/package-lock.json b/package-lock.json
index 1e13b021..26366d72 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,7 +7,7 @@
"": {
"name": "sencho",
"version": "0.95.0",
- "license": "SEE LICENSE IN LICENSE",
+ "license": "AGPL-3.0-only",
"devDependencies": {
"@commitlint/cli": "^21.2.1",
"@commitlint/config-conventional": "^21.0.2",
diff --git a/package.json b/package.json
index d67bbeca..82c2de31 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
},
"keywords": [],
"author": "Studio Saelix",
- "license": "SEE LICENSE IN LICENSE",
+ "license": "AGPL-3.0-only",
"type": "commonjs",
"engines": {
"node": ">=26.0.0"