/** * Verification utilities for standard.site records. * * Publications are verified via /.well-known/site.standard.publication * Documents are verified via in HTML */ /** * Verifies a publication by checking /.well-known/site.standard.publication * @param pubUrl The publication's base URL (e.g., "https://example.com") * @param siteUri The expected AT-URI of the publication (e.g., "at://did:plc:abc/site.standard.publication/rkey") * @returns true if the .well-known endpoint returns the matching AT-URI */ export async function verifyPublication( pubUrl: string, siteUri: string ): Promise { try { const baseUrl = pubUrl.startsWith("http") ? pubUrl : `https://${pubUrl}`; const wellKnownUrl = `${baseUrl.replace(/\/$/, "")}/.well-known/site.standard.publication`; const response = await fetch(wellKnownUrl, { headers: { Accept: "text/plain" }, }); if (!response.ok) return false; const body = await response.text(); return body.trim() === siteUri.trim(); } catch { return false; } } /** * Verifies a document by checking for a matching tag * @param viewUrl The document's canonical URL (e.g., "https://example.com/blog/post") * @param documentUri The expected AT-URI of the document (e.g., "at://did:plc:abc/site.standard.document/rkey") * @returns true if the HTML contains a matching link tag */ export async function verifyDocument( viewUrl: string, documentUri: string ): Promise { try { const response = await fetch(viewUrl, { headers: { Accept: "text/html" }, }); if (!response.ok) return false; const html = await response.text(); // Look for // Using regex to avoid heavy HTML parser dependency const linkPattern = /]+rel=["']site\.standard\.document["'][^>]+href=["']([^"']+)["'][^>]*>/i; const altPattern = /]+href=["']([^"']+)["'][^>]+rel=["']site\.standard\.document["'][^>]*>/i; const match = html.match(linkPattern) || html.match(altPattern); if (!match) return false; return match[1].trim() === documentUri.trim(); } catch { return false; } } /** * Combined verification for a document record. * Checks publication verification first (if applicable), then document verification. * * @param pubUrl The publication's base URL * @param siteUri The AT-URI of the publication (from document's site field) * @param viewUrl The document's canonical URL * @param documentUri The AT-URI of the document * @returns true if either publication or document verification passes */ export async function verifyDocumentRecord( pubUrl: string | null, siteUri: string | null, viewUrl: string | null, documentUri: string ): Promise { // Try publication verification first (if we have a publication AT-URI) if (pubUrl && siteUri && siteUri.startsWith("at://")) { const pubVerified = await verifyPublication(pubUrl, siteUri); if (pubVerified) return true; } // Fall back to document verification (if we have a view URL) if (viewUrl) { const docVerified = await verifyDocument(viewUrl, documentUri); if (docVerified) return true; } return false; }