content-explorer/ui/lib/attribution.ts
tegwick f8c94d3272
All checks were successful
synthetic / suite (push) Successful in 56s
Finish the computing-basics pilot and the local OnCo reference slice.
The single-operator pilot keeps static projection. Local OnCo use requires a CC BY-NC origin notice, and the slice stays out of public CI.

Assistant: grok
Assistant-Session: 01a15378-f601-7fe2-a143-8e1500a1d59c
2026-10-19 13:04:55 +02:00

47 lines
1.7 KiB
TypeScript

export type SourceCredit = {
title: string;
license: string;
uri?: string;
attribution?: string;
licenseUrl?: string;
retrievedAt?: string;
originSha?: string;
modificationNotice?: string;
};
const LICENSE_URLS: Record<string, string> = {
"CC0-1.0": "https://creativecommons.org/publicdomain/zero/1.0/",
"CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/",
"CC-BY-NC-4.0": "https://creativecommons.org/licenses/by-nc/4.0/",
MIT: "https://opensource.org/license/mit",
};
const ATTRIBUTION_LICENSES = new Set(["CC-BY-4.0", "CC-BY-NC-4.0", "MIT"]);
export function uniqueOriginNotices(sources: SourceCredit[]): SourceCredit[] {
const seen = new Set<string>();
const notices: SourceCredit[] = [];
for (const source of sources) {
if (!source.attribution?.trim()) continue;
const key = [source.attribution, source.license, source.licenseUrl ?? "", source.originSha ?? "", source.modificationNotice ?? ""].join("\n");
if (seen.has(key)) continue;
seen.add(key);
notices.push(source);
}
return notices;
}
export function attributionGaps(source: SourceCredit): string[] {
const gaps: string[] = [];
if (!source.license) gaps.push("license");
if (!source.title.trim()) gaps.push("title");
if (!source.uri?.trim()) gaps.push("uri");
if (ATTRIBUTION_LICENSES.has(source.license) && !source.attribution?.trim()) gaps.push("attribution");
if (source.license === "CC-BY-4.0" || source.license === "CC-BY-NC-4.0") {
if (source.licenseUrl !== LICENSE_URLS[source.license]) gaps.push("licenseUrl");
if (!source.retrievedAt?.trim()) gaps.push("retrievedAt");
if (!source.originSha?.trim()) gaps.push("originSha");
if (!source.modificationNotice?.trim()) gaps.push("modificationNotice");
}
return gaps;
}