115 lines
3.1 KiB
JavaScript
115 lines
3.1 KiB
JavaScript
export function createFirefoxValidationPlugin() {
|
|
return {
|
|
manifest: {
|
|
id: "org.browsec.firefox-validation",
|
|
name: "Firefox validation",
|
|
role: "advisor",
|
|
},
|
|
collectEvidence({ facts }) {
|
|
if (facts.validation === "success") {
|
|
return {
|
|
entries: [
|
|
{
|
|
kind: "vote",
|
|
code: "firefox-validation-succeeded",
|
|
message: "Firefox constructed a valid path to a configured trust anchor.",
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
return {
|
|
entries: facts.errors.map((error) => ({
|
|
kind: "warning",
|
|
code: error,
|
|
message: explainValidationError(error),
|
|
})),
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createVillageCommunityPlugin() {
|
|
return {
|
|
manifest: {
|
|
id: "community.village.observer",
|
|
name: "Village community observer",
|
|
role: "advisor",
|
|
},
|
|
collectEvidence({ facts }) {
|
|
if (facts.hostname !== "library.village") return;
|
|
return {
|
|
entries: [
|
|
{
|
|
kind: "evidence",
|
|
code: "community-key-continuity",
|
|
message: "This certificate has appeared in the synthetic community record for 184 days.",
|
|
data: { observers: 7, independentOperators: 3, ageDays: 184 },
|
|
},
|
|
{
|
|
kind: "vote",
|
|
code: "community-recommends-trust",
|
|
message: "The configured community recommends trusting this exact host certificate.",
|
|
},
|
|
],
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createCommunityAdvicePlugin({
|
|
id,
|
|
name,
|
|
trusted,
|
|
message,
|
|
}) {
|
|
return {
|
|
manifest: { id, name, role: "advisor" },
|
|
collectEvidence() {
|
|
return {
|
|
entries: [
|
|
{
|
|
kind: "vote",
|
|
code: trusted ? "community-votes-trusted" : "community-votes-not-trusted",
|
|
message,
|
|
data: { trusted },
|
|
},
|
|
],
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
export function createUserDecisionPlugin(decision) {
|
|
if (decision !== true && decision !== false) return undefined;
|
|
return {
|
|
manifest: {
|
|
id: "local.user.decision",
|
|
name: "Local user decision",
|
|
role: "decision-authority",
|
|
},
|
|
decide({ facts, journal }) {
|
|
return {
|
|
trusted: decision,
|
|
scope: { hostname: facts.hostname, port: facts.port },
|
|
reasonEntryIds: journal.entries
|
|
.filter((entry) => entry.kind === "evidence" || entry.kind === "warning")
|
|
.map((entry) => entry.id),
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
function explainValidationError(error) {
|
|
const explanations = {
|
|
"unknown-issuer":
|
|
"Firefox cannot construct a path from this certificate to a configured trust anchor.",
|
|
expired: "At least one certificate in the validation path is outside its validity period.",
|
|
"hostname-mismatch":
|
|
"The leaf certificate does not identify the requested hostname.",
|
|
"explicitly-distrusted-authority":
|
|
"The chain reaches an authority rejected by an explicit local Browsec rule.",
|
|
};
|
|
return explanations[error] ?? `Firefox reported certificate error: ${error}.`;
|
|
}
|