diff --git a/client/src/App.css b/client/src/App.css
index cc57c54..c85b7af 100644
--- a/client/src/App.css
+++ b/client/src/App.css
@@ -3046,10 +3046,14 @@ html.theme-cupertino .events-scroll-container {
.app-version-footer__copyright {
color: #94a3b8;
+}
+
+.app-version-footer__copyright a {
+ color: inherit;
text-decoration: none;
}
-.app-version-footer__copyright:hover {
+.app-version-footer__copyright a:hover {
color: #e2e8f0;
text-decoration: underline;
}
diff --git a/client/src/components/AppFooter.tsx b/client/src/components/AppFooter.tsx
index 456b2a0..437b2c0 100644
--- a/client/src/components/AppFooter.tsx
+++ b/client/src/components/AppFooter.tsx
@@ -7,9 +7,10 @@ export default function AppFooter() {
·
-
- © 2026 Markus F.J. Busche
-
+
+ © 2026 KnorrLabs/
+ Markus F.J. Busche
+
)
}
diff --git a/client/src/components/LogEntryEditor.tsx b/client/src/components/LogEntryEditor.tsx
index afefe39..9ae861e 100644
--- a/client/src/components/LogEntryEditor.tsx
+++ b/client/src/components/LogEntryEditor.tsx
@@ -13,7 +13,8 @@ import TrackMap from './TrackMap.tsx'
import { useDialog } from './ModalDialog.tsx'
import {
normalizeSignature,
- serializeSignature,
+ fingerprintSignature,
+ normalizedSerializedSignature,
isPasskeySignature,
isSignatureValidForEntry,
hasAnySignature
@@ -79,8 +80,8 @@ function fingerprintFromStoredEntry(decrypted: Record): string
return JSON.stringify({
...payload,
- signSkipper: serializeSignature(normalizeSignature(decrypted.signSkipper as SignatureValue | '') || '') ?? '',
- signCrew: serializeSignature(normalizeSignature(decrypted.signCrew as SignatureValue | '') || '') ?? ''
+ signSkipper: fingerprintSignature(decrypted.signSkipper),
+ signCrew: fingerprintSignature(decrypted.signCrew)
})
}
@@ -241,8 +242,8 @@ export default function LogEntryEditor({
const payload = buildPayloadForSigning()
return JSON.stringify({
...payload,
- signSkipper: serializeSignature(signSkipper) ?? '',
- signCrew: serializeSignature(signCrew) ?? ''
+ signSkipper: fingerprintSignature(signSkipper),
+ signCrew: fingerprintSignature(signCrew)
})
}, [buildPayloadForSigning, signSkipper, signCrew])
@@ -256,8 +257,8 @@ export default function LogEntryEditor({
const entryData = {
...buildPayloadForSigning(eventsOverride),
- signSkipper: serializeSignature(signSkipper),
- signCrew: serializeSignature(signCrew)
+ signSkipper: normalizedSerializedSignature(signSkipper),
+ signCrew: normalizedSerializedSignature(signCrew)
}
const encrypted = await encryptJson(entryData, masterKey)
@@ -285,8 +286,8 @@ export default function LogEntryEditor({
setSavedFingerprint(JSON.stringify({
...buildPayloadForSigning(eventsOverride),
- signSkipper: serializeSignature(signSkipper) ?? '',
- signCrew: serializeSignature(signCrew) ?? ''
+ signSkipper: fingerprintSignature(signSkipper),
+ signCrew: fingerprintSignature(signCrew)
}))
}, [
readOnly, logbookId, entryId, events, buildPayloadForSigning, signSkipper, signCrew
diff --git a/client/src/utils/signatures.ts b/client/src/utils/signatures.ts
index 339abe3..fd8b7f8 100644
--- a/client/src/utils/signatures.ts
+++ b/client/src/utils/signatures.ts
@@ -68,3 +68,12 @@ export function serializeSignature(value: SignatureValue | '' | undefined): Sign
const trimmed = value.trim()
return trimmed || undefined
}
+
+/** Normalize then serialize — canonical form for persistence and dirty-check fingerprints. */
+export function normalizedSerializedSignature(value: unknown): SignatureValue | undefined {
+ return serializeSignature(normalizeSignature(value) || '')
+}
+
+export function fingerprintSignature(value: unknown): string {
+ return normalizedSerializedSignature(value) ?? ''
+}