license: relicense to AGPL-3.0-only with commercial dual-license

- LICENSE -> verbatim GNU AGPL-3.0; add LICENSE-COMMERCIAL.md + SECURITY.md
- CLA -> exclusive-license grant (contributors keep copyright); add README
  anti-rugpull covenant + relicense record
- NOTICE / README / CONTRIBUTING / CLAUDE.md / package.json x5 updated;
  contact routed through GitHub (no email placeholders)
- AGPL section 13 source offer: operator-configurable BACKSPACE_SOURCE_URL +
  build-injected commit; sourceCodeUrl+commit on /api/instance/info;
  SourceCodeLink on login/register/settings/desktop; docs + .env.example updated
This commit is contained in:
Jannis Braun
2026-07-01 16:38:22 +02:00
parent 16d75f2806
commit f481e1fe9e
34 changed files with 1084 additions and 165 deletions
@@ -1,6 +1,9 @@
import { useState, useEffect } from 'react';
import { Modal } from '../ui/Modal';
import { Avatar } from '../ui/Avatar';
import { SourceCodeLink } from '../ui/SourceCodeLink';
import { api } from '../../api/client';
import type { InstanceInfoResponse } from '@backspace/shared';
import { useUIStore } from '../../stores/uiStore';
import { useAuthStore } from '../../stores/authStore';
import { AccountPanel } from './settingsPanels/AccountPanel';
@@ -59,9 +62,21 @@ export function UserSettingsModal() {
const [tab, setTab] = useState<SettingsTab>('account');
const [mobileView, setMobileView] = useState<'tabs' | 'content'>('tabs');
// AGPL § 13: home-instance source offer. Fetched from the public info endpoint
// so the source link reflects the version this instance is actually running.
const [instanceInfo, setInstanceInfo] = useState<InstanceInfoResponse | null>(null);
const isOpen = activeModal === 'userSettings';
useEffect(() => {
if (!isOpen) return;
let cancelled = false;
api.instance.info()
.then((info) => { if (!cancelled) setInstanceInfo(info); })
.catch(() => { /* Non-critical — link falls back to hidden if unreachable. */ });
return () => { cancelled = true; };
}, [isOpen]);
// Deep-linking: read modalData.tab when opening
useEffect(() => {
if (isOpen) {
@@ -148,6 +163,12 @@ export function UserSettingsModal() {
>
Log Out
</button>
{instanceInfo && (
<div className="px-3 pt-2">
<SourceCodeLink sourceCodeUrl={instanceInfo.sourceCodeUrl} version={instanceInfo.version} commit={instanceInfo.commit} />
</div>
)}
</div>
</div>
@@ -196,6 +217,12 @@ export function UserSettingsModal() {
>
Log Out
</button>
{instanceInfo && (
<div className="px-3 pt-2">
<SourceCodeLink sourceCodeUrl={instanceInfo.sourceCodeUrl} version={instanceInfo.version} commit={instanceInfo.commit} />
</div>
)}
</div>
</div>
)}