A fullstack app for indexing standard.site documents
1/**
2 * Verification utilities for standard.site records.
3 *
4 * Publications are verified via /.well-known/site.standard.publication
5 * Documents are verified via <link rel="site.standard.document"> in HTML
6 */
7
8/**
9 * Verifies a publication by checking /.well-known/site.standard.publication
10 * @param pubUrl The publication's base URL (e.g., "https://example.com")
11 * @param siteUri The expected AT-URI of the publication (e.g., "at://did:plc:abc/site.standard.publication/rkey")
12 * @returns true if the .well-known endpoint returns the matching AT-URI
13 */
14export async function verifyPublication(
15 pubUrl: string,
16 siteUri: string
17): Promise<boolean> {
18 try {
19 const baseUrl = pubUrl.startsWith("http") ? pubUrl : `https://${pubUrl}`;
20 const wellKnownUrl = `${baseUrl.replace(/\/$/, "")}/.well-known/site.standard.publication`;
21
22 const response = await fetch(wellKnownUrl, {
23 headers: { Accept: "text/plain" },
24 });
25
26 if (!response.ok) return false;
27
28 const body = await response.text();
29 return body.trim() === siteUri.trim();
30 } catch {
31 return false;
32 }
33}
34
35/**
36 * Verifies a document by checking for a matching <link rel="site.standard.document"> tag
37 * @param viewUrl The document's canonical URL (e.g., "https://example.com/blog/post")
38 * @param documentUri The expected AT-URI of the document (e.g., "at://did:plc:abc/site.standard.document/rkey")
39 * @returns true if the HTML contains a matching link tag
40 */
41export async function verifyDocument(
42 viewUrl: string,
43 documentUri: string
44): Promise<boolean> {
45 try {
46 const response = await fetch(viewUrl, {
47 headers: { Accept: "text/html" },
48 });
49
50 if (!response.ok) return false;
51
52 const html = await response.text();
53
54 // Look for <link rel="site.standard.document" href="at://...">
55 // Using regex to avoid heavy HTML parser dependency
56 const linkPattern =
57 /<link[^>]+rel=["']site\.standard\.document["'][^>]+href=["']([^"']+)["'][^>]*>/i;
58 const altPattern =
59 /<link[^>]+href=["']([^"']+)["'][^>]+rel=["']site\.standard\.document["'][^>]*>/i;
60
61 const match = html.match(linkPattern) || html.match(altPattern);
62 if (!match) return false;
63
64 return match[1].trim() === documentUri.trim();
65 } catch {
66 return false;
67 }
68}
69
70/**
71 * Combined verification for a document record.
72 * Checks publication verification first (if applicable), then document verification.
73 *
74 * @param pubUrl The publication's base URL
75 * @param siteUri The AT-URI of the publication (from document's site field)
76 * @param viewUrl The document's canonical URL
77 * @param documentUri The AT-URI of the document
78 * @returns true if either publication or document verification passes
79 */
80export async function verifyDocumentRecord(
81 pubUrl: string | null,
82 siteUri: string | null,
83 viewUrl: string | null,
84 documentUri: string
85): Promise<boolean> {
86 // Try publication verification first (if we have a publication AT-URI)
87 if (pubUrl && siteUri && siteUri.startsWith("at://")) {
88 const pubVerified = await verifyPublication(pubUrl, siteUri);
89 if (pubVerified) return true;
90 }
91
92 // Fall back to document verification (if we have a view URL)
93 if (viewUrl) {
94 const docVerified = await verifyDocument(viewUrl, documentUri);
95 if (docVerified) return true;
96 }
97
98 return false;
99}