@keytrace/runner 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -0
- package/dist/actions/css-select.d.ts +6 -0
- package/dist/actions/css-select.d.ts.map +1 -0
- package/dist/actions/css-select.js +14 -0
- package/dist/actions/css-select.js.map +1 -0
- package/dist/actions/dns-txt.d.ts +6 -0
- package/dist/actions/dns-txt.d.ts.map +1 -0
- package/dist/actions/dns-txt.js +17 -0
- package/dist/actions/dns-txt.js.map +1 -0
- package/dist/actions/http-get.d.ts +6 -0
- package/dist/actions/http-get.d.ts.map +1 -0
- package/dist/actions/http-get.js +19 -0
- package/dist/actions/http-get.js.map +1 -0
- package/dist/actions/index.d.ts +6 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +6 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/json-path.d.ts +12 -0
- package/dist/actions/json-path.d.ts.map +1 -0
- package/dist/actions/json-path.js +26 -0
- package/dist/actions/json-path.js.map +1 -0
- package/dist/actions/regex-match.d.ts +6 -0
- package/dist/actions/regex-match.d.ts.map +1 -0
- package/dist/actions/regex-match.js +14 -0
- package/dist/actions/regex-match.js.map +1 -0
- package/dist/claim.d.ts +38 -0
- package/dist/claim.d.ts.map +1 -0
- package/dist/claim.js +253 -0
- package/dist/claim.js.map +1 -0
- package/dist/constants.d.ts +17 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +17 -0
- package/dist/constants.js.map +1 -0
- package/dist/expect.d.ts +12 -0
- package/dist/expect.d.ts.map +1 -0
- package/dist/expect.js +33 -0
- package/dist/expect.js.map +1 -0
- package/dist/fetchers/activitypub.d.ts +25 -0
- package/dist/fetchers/activitypub.d.ts.map +1 -0
- package/dist/fetchers/activitypub.js +32 -0
- package/dist/fetchers/activitypub.js.map +1 -0
- package/dist/fetchers/dns.d.ts +21 -0
- package/dist/fetchers/dns.d.ts.map +1 -0
- package/dist/fetchers/dns.js +61 -0
- package/dist/fetchers/dns.js.map +1 -0
- package/dist/fetchers/http.d.ts +10 -0
- package/dist/fetchers/http.d.ts.map +1 -0
- package/dist/fetchers/http.js +30 -0
- package/dist/fetchers/http.js.map +1 -0
- package/dist/fetchers/index.d.ts +16 -0
- package/dist/fetchers/index.d.ts.map +1 -0
- package/dist/fetchers/index.js +22 -0
- package/dist/fetchers/index.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +12 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +23 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/profile.d.ts +42 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +176 -0
- package/dist/profile.js.map +1 -0
- package/dist/recipes/dns-txt.d.ts +9 -0
- package/dist/recipes/dns-txt.d.ts.map +1 -0
- package/dist/recipes/dns-txt.js +45 -0
- package/dist/recipes/dns-txt.js.map +1 -0
- package/dist/recipes/github-gist.d.ts +9 -0
- package/dist/recipes/github-gist.d.ts.map +1 -0
- package/dist/recipes/github-gist.js +52 -0
- package/dist/recipes/github-gist.js.map +1 -0
- package/dist/recipes/index.d.ts +3 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +3 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/runner.d.ts +7 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +100 -0
- package/dist/runner.js.map +1 -0
- package/dist/serviceProviders/activitypub.d.ts +10 -0
- package/dist/serviceProviders/activitypub.d.ts.map +1 -0
- package/dist/serviceProviders/activitypub.js +73 -0
- package/dist/serviceProviders/activitypub.js.map +1 -0
- package/dist/serviceProviders/bsky.d.ts +10 -0
- package/dist/serviceProviders/bsky.d.ts.map +1 -0
- package/dist/serviceProviders/bsky.js +63 -0
- package/dist/serviceProviders/bsky.js.map +1 -0
- package/dist/serviceProviders/dns.d.ts +10 -0
- package/dist/serviceProviders/dns.d.ts.map +1 -0
- package/dist/serviceProviders/dns.js +65 -0
- package/dist/serviceProviders/dns.js.map +1 -0
- package/dist/serviceProviders/github.d.ts +10 -0
- package/dist/serviceProviders/github.d.ts.map +1 -0
- package/dist/serviceProviders/github.js +100 -0
- package/dist/serviceProviders/github.js.map +1 -0
- package/dist/serviceProviders/index.d.ts +26 -0
- package/dist/serviceProviders/index.d.ts.map +1 -0
- package/dist/serviceProviders/index.js +55 -0
- package/dist/serviceProviders/index.js.map +1 -0
- package/dist/serviceProviders/npm.d.ts +10 -0
- package/dist/serviceProviders/npm.d.ts.map +1 -0
- package/dist/serviceProviders/npm.js +99 -0
- package/dist/serviceProviders/npm.js.map +1 -0
- package/dist/serviceProviders/types.d.ts +106 -0
- package/dist/serviceProviders/types.d.ts.map +1 -0
- package/dist/serviceProviders/types.js +2 -0
- package/dist/serviceProviders/types.js.map +1 -0
- package/dist/types.d.ts +165 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
- package/src/actions/css-select.ts +14 -0
- package/src/actions/dns-txt.ts +16 -0
- package/src/actions/http-get.ts +19 -0
- package/src/actions/index.ts +5 -0
- package/src/actions/json-path.ts +29 -0
- package/src/actions/regex-match.ts +13 -0
- package/src/claim.ts +293 -0
- package/src/constants.ts +19 -0
- package/src/expect.ts +36 -0
- package/src/fetchers/activitypub.ts +53 -0
- package/src/fetchers/dns.ts +82 -0
- package/src/fetchers/http.ts +38 -0
- package/src/fetchers/index.ts +30 -0
- package/src/index.ts +57 -0
- package/src/interpolate.ts +20 -0
- package/src/profile.ts +229 -0
- package/src/recipes/dns-txt.ts +46 -0
- package/src/recipes/github-gist.ts +53 -0
- package/src/recipes/index.ts +2 -0
- package/src/runner.ts +116 -0
- package/src/serviceProviders/activitypub.ts +84 -0
- package/src/serviceProviders/bsky.ts +73 -0
- package/src/serviceProviders/dns.ts +75 -0
- package/src/serviceProviders/github.ts +112 -0
- package/src/serviceProviders/index.ts +65 -0
- package/src/serviceProviders/npm.ts +116 -0
- package/src/serviceProviders/types.ts +121 -0
- package/src/types.ts +181 -0
package/dist/profile.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { AtpAgent } from "@atproto/api";
|
|
2
|
+
import { createClaim, verifyClaim } from "./claim.js";
|
|
3
|
+
import { ClaimStatus } from "./types.js";
|
|
4
|
+
import { COLLECTION_NSID, PUBLIC_API_URL, PLC_DIRECTORY_URL } from "./constants.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the PDS endpoint from a DID document.
|
|
7
|
+
* For did:plc, fetches from plc.directory.
|
|
8
|
+
* For did:web, fetches from the well-known DID path.
|
|
9
|
+
* Falls back to PUBLIC_API_URL on failure.
|
|
10
|
+
*/
|
|
11
|
+
export async function resolvePds(did) {
|
|
12
|
+
try {
|
|
13
|
+
let url;
|
|
14
|
+
if (did.startsWith("did:plc:")) {
|
|
15
|
+
url = `${PLC_DIRECTORY_URL}/${did}`;
|
|
16
|
+
}
|
|
17
|
+
else if (did.startsWith("did:web:")) {
|
|
18
|
+
const host = did.replace("did:web:", "").replaceAll(":", "/");
|
|
19
|
+
url = `https://${host}/.well-known/did.json`;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return PUBLIC_API_URL;
|
|
23
|
+
}
|
|
24
|
+
const response = await globalThis.fetch(url, {
|
|
25
|
+
headers: { Accept: "application/json" },
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
return PUBLIC_API_URL;
|
|
29
|
+
}
|
|
30
|
+
const doc = (await response.json());
|
|
31
|
+
const pdsService = doc.service?.find((s) => s.id === "#atproto_pds" || s.type === "AtprotoPersonalDataServer");
|
|
32
|
+
return pdsService?.serviceEndpoint ?? PUBLIC_API_URL;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return PUBLIC_API_URL;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Parse an AT URI and extract the rkey (record key).
|
|
40
|
+
* AT URIs have the format: at://did/collection/rkey
|
|
41
|
+
*/
|
|
42
|
+
function parseAtUriRkey(atUri) {
|
|
43
|
+
const match = atUri.match(/^at:\/\/[^/]+\/[^/]+\/(.+)$/);
|
|
44
|
+
return match?.[1] ?? "";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Internal: fetch profile data using an already-configured agent
|
|
48
|
+
*/
|
|
49
|
+
async function fetchWithAgent(agent, did) {
|
|
50
|
+
// Fetch Bluesky profile for display info via public API (not PDS)
|
|
51
|
+
// The PDS doesn't serve app.bsky.actor.getProfile - only the AppView does
|
|
52
|
+
let bskyProfile = null;
|
|
53
|
+
try {
|
|
54
|
+
const publicAgent = new AtpAgent({ service: PUBLIC_API_URL });
|
|
55
|
+
const profileRes = await publicAgent.getProfile({ actor: did });
|
|
56
|
+
bskyProfile = {
|
|
57
|
+
handle: profileRes.data.handle,
|
|
58
|
+
displayName: profileRes.data.displayName,
|
|
59
|
+
avatar: profileRes.data.avatar,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
// Profile fetch is optional - user may not have a Bluesky profile
|
|
64
|
+
// 404 is expected; log other errors at debug level
|
|
65
|
+
if (err instanceof Error && !err.message.includes("404")) {
|
|
66
|
+
console.debug(`Failed to fetch profile for ${did}: ${err.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// List all claim records with cursor-based pagination
|
|
70
|
+
const claims = [];
|
|
71
|
+
try {
|
|
72
|
+
let cursor;
|
|
73
|
+
do {
|
|
74
|
+
const records = await agent.com.atproto.repo.listRecords({
|
|
75
|
+
repo: did,
|
|
76
|
+
collection: COLLECTION_NSID,
|
|
77
|
+
limit: 100,
|
|
78
|
+
cursor,
|
|
79
|
+
});
|
|
80
|
+
for (const record of records.data.records) {
|
|
81
|
+
const value = record.value;
|
|
82
|
+
if (value.claimUri) {
|
|
83
|
+
claims.push({
|
|
84
|
+
uri: value.claimUri,
|
|
85
|
+
did,
|
|
86
|
+
type: value.type,
|
|
87
|
+
comment: value.comment,
|
|
88
|
+
createdAt: value.createdAt ?? new Date().toISOString(),
|
|
89
|
+
rkey: parseAtUriRkey(record.uri),
|
|
90
|
+
identity: value.identity,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
cursor = records.data.cursor;
|
|
95
|
+
} while (cursor);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
// 404 means no records yet; log other errors
|
|
99
|
+
if (err instanceof Error && !err.message.includes("404")) {
|
|
100
|
+
console.debug(`Failed to list claim records for ${did}: ${err.message}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
did,
|
|
105
|
+
handle: bskyProfile?.handle ?? did,
|
|
106
|
+
displayName: bskyProfile?.displayName,
|
|
107
|
+
avatar: bskyProfile?.avatar,
|
|
108
|
+
claims,
|
|
109
|
+
claimInstances: claims.map((c) => createClaim(c.uri, did)),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Fetch a profile from ATProto by DID or handle
|
|
114
|
+
*/
|
|
115
|
+
export async function fetchProfile(didOrHandle, serviceUrl) {
|
|
116
|
+
// Resolve PDS from DID document unless an explicit serviceUrl was provided
|
|
117
|
+
let resolvedServiceUrl;
|
|
118
|
+
let did = didOrHandle;
|
|
119
|
+
if (serviceUrl) {
|
|
120
|
+
resolvedServiceUrl = serviceUrl;
|
|
121
|
+
}
|
|
122
|
+
else if (didOrHandle.startsWith("did:")) {
|
|
123
|
+
resolvedServiceUrl = await resolvePds(didOrHandle);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// Handle - we need to resolve via the public API first, then resolve PDS
|
|
127
|
+
resolvedServiceUrl = PUBLIC_API_URL;
|
|
128
|
+
}
|
|
129
|
+
const agent = new AtpAgent({ service: resolvedServiceUrl });
|
|
130
|
+
// Resolve handle to DID if needed
|
|
131
|
+
if (!didOrHandle.startsWith("did:")) {
|
|
132
|
+
const resolved = await agent.resolveHandle({ handle: didOrHandle });
|
|
133
|
+
did = resolved.data.did;
|
|
134
|
+
// Now that we have the DID, resolve the actual PDS if no explicit serviceUrl
|
|
135
|
+
if (!serviceUrl) {
|
|
136
|
+
const pdsUrl = await resolvePds(did);
|
|
137
|
+
if (pdsUrl !== resolvedServiceUrl) {
|
|
138
|
+
resolvedServiceUrl = pdsUrl;
|
|
139
|
+
// Re-create agent pointed at the user's actual PDS
|
|
140
|
+
const pdsAgent = new AtpAgent({ service: pdsUrl });
|
|
141
|
+
return fetchWithAgent(pdsAgent, did);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return fetchWithAgent(agent, did);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Verify all claims in a profile
|
|
149
|
+
*/
|
|
150
|
+
export async function verifyAllClaims(profile, opts) {
|
|
151
|
+
await Promise.all(profile.claimInstances.map((claim) => verifyClaim(claim, opts)));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get verification summary for a profile
|
|
155
|
+
*/
|
|
156
|
+
export function getProfileSummary(profile) {
|
|
157
|
+
const claims = profile.claimInstances;
|
|
158
|
+
return {
|
|
159
|
+
total: claims.length,
|
|
160
|
+
verified: claims.filter((c) => c.status === ClaimStatus.VERIFIED).length,
|
|
161
|
+
failed: claims.filter((c) => c.status === ClaimStatus.FAILED || c.status === ClaimStatus.ERROR).length,
|
|
162
|
+
pending: claims.filter((c) => c.status === ClaimStatus.INIT || c.status === ClaimStatus.MATCHED).length,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get claims grouped by status
|
|
167
|
+
*/
|
|
168
|
+
export function getClaimsByStatus(profile) {
|
|
169
|
+
const claims = profile.claimInstances;
|
|
170
|
+
return {
|
|
171
|
+
verified: claims.filter((c) => c.status === ClaimStatus.VERIFIED),
|
|
172
|
+
failed: claims.filter((c) => c.status === ClaimStatus.FAILED || c.status === ClaimStatus.ERROR),
|
|
173
|
+
pending: claims.filter((c) => c.status === ClaimStatus.INIT || c.status === ClaimStatus.MATCHED),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAmB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AA4BpF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,IAAI,GAAW,CAAC;QAChB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,GAAG,GAAG,GAAG,iBAAiB,IAAI,GAAG,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9D,GAAG,GAAG,WAAW,IAAI,uBAAuB,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE;YAC3C,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;SACxC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,MAAM,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgB,CAAC;QACnD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,IAAI,CAAC,CAAC,IAAI,KAAK,2BAA2B,CAAC,CAAC;QAE/G,OAAO,UAAU,EAAE,eAAe,IAAI,cAAc,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACzD,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,KAAe,EAAE,GAAW;IACxD,kEAAkE;IAClE,0EAA0E;IAC1E,IAAI,WAAW,GAAqE,IAAI,CAAC;IACzF,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,QAAQ,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAChE,WAAW,GAAG;YACZ,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM;YAC9B,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW;YACxC,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM;SAC/B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,kEAAkE;QAClE,mDAAmD;QACnD,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,sDAAsD;IACtD,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,IAAI,MAA0B,CAAC;QAC/B,GAAG,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;gBACvD,IAAI,EAAE,GAAG;gBACT,UAAU,EAAE,eAAe;gBAC3B,KAAK,EAAE,GAAG;gBACV,MAAM;aACP,CAAC,CAAC;YAEH,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAMpB,CAAC;gBACF,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACnB,MAAM,CAAC,IAAI,CAAC;wBACV,GAAG,EAAE,KAAK,CAAC,QAAQ;wBACnB,GAAG;wBACH,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACtD,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;wBAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;qBACzB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAC/B,CAAC,QAAQ,MAAM,EAAE;IACnB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,6CAA6C;QAC7C,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,KAAK,CAAC,oCAAoC,GAAG,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG;QACH,MAAM,EAAE,WAAW,EAAE,MAAM,IAAI,GAAG;QAClC,WAAW,EAAE,WAAW,EAAE,WAAW;QACrC,MAAM,EAAE,WAAW,EAAE,MAAM;QAC3B,MAAM;QACN,cAAc,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;KAC3D,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,UAAmB;IACzE,2EAA2E;IAC3E,IAAI,kBAA0B,CAAC;IAC/B,IAAI,GAAG,GAAG,WAAW,CAAC;IAEtB,IAAI,UAAU,EAAE,CAAC;QACf,kBAAkB,GAAG,UAAU,CAAC;IAClC,CAAC;SAAM,IAAI,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,kBAAkB,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,yEAAyE;QACzE,kBAAkB,GAAG,cAAc,CAAC;IACtC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAE5D,kCAAkC;IAClC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QACpE,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAExB,6EAA6E;QAC7E,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;gBAClC,kBAAkB,GAAG,MAAM,CAAC;gBAC5B,mDAAmD;gBACnD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnD,OAAO,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAuB,EAAE,IAAoB;IACjF,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IAMvD,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IACtC,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM;QACxE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM;QACtG,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM;KACxG,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAuB;IAKvD,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IACtC,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,QAAQ,CAAC;QACjE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,KAAK,CAAC;QAC/F,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,OAAO,CAAC;KACjG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Recipe } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in recipe: Domain verification via DNS TXT record.
|
|
4
|
+
*
|
|
5
|
+
* The user adds a TXT record to their domain containing their DID,
|
|
6
|
+
* then provides the domain name for verification.
|
|
7
|
+
*/
|
|
8
|
+
export declare const dnsTxtRecipe: Recipe;
|
|
9
|
+
//# sourceMappingURL=dns-txt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dns-txt.d.ts","sourceRoot":"","sources":["../../src/recipes/dns-txt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,MAqC1B,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in recipe: Domain verification via DNS TXT record.
|
|
3
|
+
*
|
|
4
|
+
* The user adds a TXT record to their domain containing their DID,
|
|
5
|
+
* then provides the domain name for verification.
|
|
6
|
+
*/
|
|
7
|
+
export const dnsTxtRecipe = {
|
|
8
|
+
$type: "dev.keytrace.recipe",
|
|
9
|
+
type: "dns",
|
|
10
|
+
version: 1,
|
|
11
|
+
displayName: "Domain (via DNS TXT)",
|
|
12
|
+
params: [
|
|
13
|
+
{
|
|
14
|
+
key: "domain",
|
|
15
|
+
label: "Domain name",
|
|
16
|
+
type: "domain",
|
|
17
|
+
placeholder: "example.com",
|
|
18
|
+
pattern: "^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)+$",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
instructions: {
|
|
22
|
+
steps: [
|
|
23
|
+
"Log into your domain's DNS management panel",
|
|
24
|
+
"Add a new TXT record to the root domain (or _keytrace subdomain)",
|
|
25
|
+
"Set the value to the verification text below",
|
|
26
|
+
"Wait for DNS propagation (may take a few minutes)",
|
|
27
|
+
],
|
|
28
|
+
proofTemplate: "keytrace-verification={did}",
|
|
29
|
+
proofLocation: "DNS TXT record on your domain",
|
|
30
|
+
},
|
|
31
|
+
verification: {
|
|
32
|
+
steps: [
|
|
33
|
+
{
|
|
34
|
+
action: "dns-txt",
|
|
35
|
+
url: "{domain}",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
action: "regex-match",
|
|
39
|
+
pattern: "keytrace-verification=({did})",
|
|
40
|
+
expect: "equals:{did}",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=dns-txt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dns-txt.js","sourceRoot":"","sources":["../../src/recipes/dns-txt.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC,KAAK,EAAE,qBAAqB;IAC5B,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,sBAAsB;IACnC,MAAM,EAAE;QACN;YACE,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,aAAa;YAC1B,OAAO,EAAE,4FAA4F;SACtG;KACF;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL,6CAA6C;YAC7C,kEAAkE;YAClE,8CAA8C;YAC9C,mDAAmD;SACpD;QACD,aAAa,EAAE,6BAA6B;QAC5C,aAAa,EAAE,+BAA+B;KAC/C;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL;gBACE,MAAM,EAAE,SAAS;gBACjB,GAAG,EAAE,UAAU;aAChB;YACD;gBACE,MAAM,EAAE,aAAa;gBACrB,OAAO,EAAE,+BAA+B;gBACxC,MAAM,EAAE,cAAc;aACvB;SACF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Recipe } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Built-in recipe: GitHub Account verification via public Gist.
|
|
4
|
+
*
|
|
5
|
+
* The user creates a public gist named keytrace.json containing
|
|
6
|
+
* their claim ID and DID, then provides the gist URL for verification.
|
|
7
|
+
*/
|
|
8
|
+
export declare const githubGistRecipe: Recipe;
|
|
9
|
+
//# sourceMappingURL=github-gist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-gist.d.ts","sourceRoot":"","sources":["../../src/recipes/github-gist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MA4C9B,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in recipe: GitHub Account verification via public Gist.
|
|
3
|
+
*
|
|
4
|
+
* The user creates a public gist named keytrace.json containing
|
|
5
|
+
* their claim ID and DID, then provides the gist URL for verification.
|
|
6
|
+
*/
|
|
7
|
+
export const githubGistRecipe = {
|
|
8
|
+
$type: "dev.keytrace.recipe",
|
|
9
|
+
type: "github-gist",
|
|
10
|
+
version: 1,
|
|
11
|
+
displayName: "GitHub Account (via Gist)",
|
|
12
|
+
params: [
|
|
13
|
+
{
|
|
14
|
+
key: "gistUrl",
|
|
15
|
+
label: "Gist URL",
|
|
16
|
+
type: "url",
|
|
17
|
+
placeholder: "https://gist.github.com/octocat/abc123...",
|
|
18
|
+
pattern: "^https://gist\\.github\\.com/([^/]+)/([a-f0-9]+)$",
|
|
19
|
+
extractFrom: "^https://gist\\.github\\.com/([^/]+)/",
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
instructions: {
|
|
23
|
+
steps: [
|
|
24
|
+
"Go to https://gist.github.com",
|
|
25
|
+
"Create a new public gist",
|
|
26
|
+
"Name the file `keytrace.json`",
|
|
27
|
+
"Paste the verification content below into the file",
|
|
28
|
+
"Save the gist and paste the URL below",
|
|
29
|
+
],
|
|
30
|
+
proofTemplate: '{\n "keytrace": "{claimId}",\n "did": "{did}"\n}',
|
|
31
|
+
proofLocation: "Public gist with keytrace.json",
|
|
32
|
+
},
|
|
33
|
+
verification: {
|
|
34
|
+
steps: [
|
|
35
|
+
{
|
|
36
|
+
action: "http-get",
|
|
37
|
+
url: "{gistUrl}/raw/keytrace.json",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
action: "json-path",
|
|
41
|
+
selector: "$.keytrace",
|
|
42
|
+
expect: "equals:{claimId}",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
action: "json-path",
|
|
46
|
+
selector: "$.did",
|
|
47
|
+
expect: "equals:{did}",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=github-gist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-gist.js","sourceRoot":"","sources":["../../src/recipes/github-gist.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAW;IACtC,KAAK,EAAE,qBAAqB;IAC5B,IAAI,EAAE,aAAa;IACnB,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,2BAA2B;IACxC,MAAM,EAAE;QACN;YACE,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,KAAK;YACX,WAAW,EAAE,2CAA2C;YACxD,OAAO,EAAE,mDAAmD;YAC5D,WAAW,EAAE,uCAAuC;SACrD;KACF;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL,+BAA+B;YAC/B,0BAA0B;YAC1B,+BAA+B;YAC/B,oDAAoD;YACpD,uCAAuC;SACxC;QACD,aAAa,EAAE,oDAAoD;QACnE,aAAa,EAAE,gCAAgC;KAChD;IACD,YAAY,EAAE;QACZ,KAAK,EAAE;YACL;gBACE,MAAM,EAAE,UAAU;gBAClB,GAAG,EAAE,6BAA6B;aACnC;YACD;gBACE,MAAM,EAAE,WAAW;gBACnB,QAAQ,EAAE,YAAY;gBACtB,MAAM,EAAE,kBAAkB;aAC3B;YACD;gBACE,MAAM,EAAE,WAAW;gBACnB,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,cAAc;aACvB;SACF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recipes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/recipes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Recipe, ClaimContext, RunnerConfig, VerificationResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute a recipe's verification steps against a claim context.
|
|
4
|
+
* Returns a full result with per-step details. Stops on first failure.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runRecipe(recipe: Recipe, context: ClaimContext, config?: RunnerConfig): Promise<VerificationResult>;
|
|
7
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAyC,MAAM,YAAY,CAAC;AAWhI;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuCzH"}
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { interpolate } from "./interpolate.js";
|
|
2
|
+
import { checkExpect } from "./expect.js";
|
|
3
|
+
import { httpGet } from "./actions/http-get.js";
|
|
4
|
+
import { jsonPath } from "./actions/json-path.js";
|
|
5
|
+
import { cssSelect } from "./actions/css-select.js";
|
|
6
|
+
import { regexMatch } from "./actions/regex-match.js";
|
|
7
|
+
import { dnsTxt } from "./actions/dns-txt.js";
|
|
8
|
+
const DEFAULT_TIMEOUT = 10_000;
|
|
9
|
+
/**
|
|
10
|
+
* Execute a recipe's verification steps against a claim context.
|
|
11
|
+
* Returns a full result with per-step details. Stops on first failure.
|
|
12
|
+
*/
|
|
13
|
+
export async function runRecipe(recipe, context, config) {
|
|
14
|
+
const fetchFn = config?.fetch ?? globalThis.fetch;
|
|
15
|
+
const timeout = config?.timeout ?? DEFAULT_TIMEOUT;
|
|
16
|
+
const steps = [];
|
|
17
|
+
// Extract subject from params if a param defines extractFrom
|
|
18
|
+
let subject;
|
|
19
|
+
if (recipe.params) {
|
|
20
|
+
for (const param of recipe.params) {
|
|
21
|
+
if (param.extractFrom && context.params[param.key]) {
|
|
22
|
+
const regex = new RegExp(param.extractFrom);
|
|
23
|
+
const match = context.params[param.key].match(regex);
|
|
24
|
+
if (match?.[1]) {
|
|
25
|
+
subject = `${recipe.type.split("-")[0]}:${match[1]}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Tracks the last "fetch" output (http-get, dns-txt) for extraction steps to use.
|
|
31
|
+
// Extraction steps (json-path, css-select, regex-match) always operate on the
|
|
32
|
+
// last fetch output, not on each other's output.
|
|
33
|
+
let lastFetchOutput = undefined;
|
|
34
|
+
for (const step of recipe.verification.steps) {
|
|
35
|
+
const isFetchAction = step.action === "http-get" || step.action === "dns-txt";
|
|
36
|
+
const result = await executeStep(step, context, lastFetchOutput, fetchFn, timeout);
|
|
37
|
+
steps.push(result);
|
|
38
|
+
if (!result.success) {
|
|
39
|
+
return { success: false, steps, subject, error: result.error };
|
|
40
|
+
}
|
|
41
|
+
if (isFetchAction) {
|
|
42
|
+
lastFetchOutput = result.data;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { success: true, steps, subject };
|
|
46
|
+
}
|
|
47
|
+
async function executeStep(step, context, previousOutput, fetchFn, timeout) {
|
|
48
|
+
try {
|
|
49
|
+
let data;
|
|
50
|
+
switch (step.action) {
|
|
51
|
+
case "http-get": {
|
|
52
|
+
const url = interpolate(step.url, context);
|
|
53
|
+
data = await httpGet(url, fetchFn, timeout);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "json-path": {
|
|
57
|
+
const selector = interpolate(step.selector, context);
|
|
58
|
+
const input = previousOutput ?? "";
|
|
59
|
+
data = jsonPath(input, selector);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "css-select": {
|
|
63
|
+
const selector = interpolate(step.selector, context);
|
|
64
|
+
const input = previousOutput;
|
|
65
|
+
if (typeof input !== "string") {
|
|
66
|
+
throw new Error("css-select requires string input from a previous step");
|
|
67
|
+
}
|
|
68
|
+
data = cssSelect(input, selector);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case "regex-match": {
|
|
72
|
+
const pattern = interpolate(step.pattern, context);
|
|
73
|
+
const input = typeof previousOutput === "string" ? previousOutput : String(previousOutput ?? "");
|
|
74
|
+
data = regexMatch(input, pattern);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "dns-txt": {
|
|
78
|
+
const domain = step.url ? interpolate(step.url, context) : interpolate(step.pattern, context);
|
|
79
|
+
data = await dnsTxt(domain);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Unknown action: "${step.action}"`);
|
|
84
|
+
}
|
|
85
|
+
// Check expect if defined
|
|
86
|
+
if (step.expect) {
|
|
87
|
+
const expectStr = interpolate(step.expect, context);
|
|
88
|
+
const result = checkExpect(expectStr, data);
|
|
89
|
+
if (!result.pass) {
|
|
90
|
+
return { action: step.action, success: false, data, error: result.message };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { action: step.action, success: true, data };
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
97
|
+
return { action: step.action, success: false, error: message };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ServiceProvider } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* ActivityPub (Mastodon/Fediverse) service provider
|
|
4
|
+
*
|
|
5
|
+
* Users prove ownership by adding their DID to their profile bio or fields.
|
|
6
|
+
* The claim URI is the profile URL (e.g., https://mastodon.social/@username)
|
|
7
|
+
*/
|
|
8
|
+
declare const activitypub: ServiceProvider;
|
|
9
|
+
export default activitypub;
|
|
10
|
+
//# sourceMappingURL=activitypub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activitypub.d.ts","sourceRoot":"","sources":["../../src/serviceProviders/activitypub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;GAKG;AACH,QAAA,MAAM,WAAW,EAAE,eAyElB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActivityPub (Mastodon/Fediverse) service provider
|
|
3
|
+
*
|
|
4
|
+
* Users prove ownership by adding their DID to their profile bio or fields.
|
|
5
|
+
* The claim URI is the profile URL (e.g., https://mastodon.social/@username)
|
|
6
|
+
*/
|
|
7
|
+
const activitypub = {
|
|
8
|
+
id: "activitypub",
|
|
9
|
+
name: "Mastodon",
|
|
10
|
+
homepage: "https://joinmastodon.org",
|
|
11
|
+
// Match Mastodon-style profile URLs: https://instance/@username
|
|
12
|
+
reUri: /^https:\/\/([^/]+)\/@([^/]+)\/?$/,
|
|
13
|
+
// Could match other ActivityPub software with same URL pattern
|
|
14
|
+
isAmbiguous: true,
|
|
15
|
+
ui: {
|
|
16
|
+
description: "Link your Mastodon or Fediverse account",
|
|
17
|
+
icon: "at-sign",
|
|
18
|
+
inputLabel: "Profile URL",
|
|
19
|
+
inputPlaceholder: "https://mastodon.social/@username",
|
|
20
|
+
instructions: [
|
|
21
|
+
"Go to your Mastodon instance and open **Edit profile**",
|
|
22
|
+
"Add your DID to your **bio** or create a new **profile metadata field**",
|
|
23
|
+
"For metadata fields, set the label to `keytrace` and paste your DID as the value",
|
|
24
|
+
"Save your profile changes",
|
|
25
|
+
"Paste your full profile URL below (e.g., `https://mastodon.social/@username`)",
|
|
26
|
+
],
|
|
27
|
+
proofTemplate: "{did}",
|
|
28
|
+
},
|
|
29
|
+
processURI(uri, match) {
|
|
30
|
+
const [, domain, username] = match;
|
|
31
|
+
return {
|
|
32
|
+
profile: {
|
|
33
|
+
display: `@${username}@${domain}`,
|
|
34
|
+
uri,
|
|
35
|
+
},
|
|
36
|
+
proof: {
|
|
37
|
+
request: {
|
|
38
|
+
uri,
|
|
39
|
+
fetcher: "activitypub",
|
|
40
|
+
format: "json",
|
|
41
|
+
},
|
|
42
|
+
target: [
|
|
43
|
+
// Check profile bio/summary (HTML content)
|
|
44
|
+
{ path: ["summary"], relation: "contains", format: "text" },
|
|
45
|
+
// Check profile fields (Mastodon-style verification fields)
|
|
46
|
+
{ path: ["attachment", "*", "value"], relation: "contains", format: "text" },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
postprocess(data) {
|
|
52
|
+
const actor = data;
|
|
53
|
+
return {
|
|
54
|
+
displayName: actor.name || actor.preferredUsername,
|
|
55
|
+
avatarUrl: actor.icon?.url,
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
getProofText(did) {
|
|
59
|
+
return did;
|
|
60
|
+
},
|
|
61
|
+
getProofLocation() {
|
|
62
|
+
return `Add to your profile bio or a profile metadata field`;
|
|
63
|
+
},
|
|
64
|
+
tests: [
|
|
65
|
+
{ uri: "https://mastodon.social/@alice", shouldMatch: true },
|
|
66
|
+
{ uri: "https://fosstodon.org/@bob/", shouldMatch: true },
|
|
67
|
+
{ uri: "https://hachyderm.io/@user", shouldMatch: true },
|
|
68
|
+
{ uri: "https://twitter.com/alice", shouldMatch: false },
|
|
69
|
+
{ uri: "https://mastodon.social/alice", shouldMatch: false },
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
export default activitypub;
|
|
73
|
+
//# sourceMappingURL=activitypub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activitypub.js","sourceRoot":"","sources":["../../src/serviceProviders/activitypub.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,GAAoB;IACnC,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,UAAU;IAChB,QAAQ,EAAE,0BAA0B;IAEpC,gEAAgE;IAChE,KAAK,EAAE,kCAAkC;IAEzC,+DAA+D;IAC/D,WAAW,EAAE,IAAI;IAEjB,EAAE,EAAE;QACF,WAAW,EAAE,yCAAyC;QACtD,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,aAAa;QACzB,gBAAgB,EAAE,mCAAmC;QACrD,YAAY,EAAE;YACZ,wDAAwD;YACxD,yEAAyE;YACzE,kFAAkF;YAClF,2BAA2B;YAC3B,+EAA+E;SAChF;QACD,aAAa,EAAE,OAAO;KACvB;IAED,UAAU,CAAC,GAAG,EAAE,KAAK;QACnB,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;QAEnC,OAAO;YACL,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI,QAAQ,IAAI,MAAM,EAAE;gBACjC,GAAG;aACJ;YACD,KAAK,EAAE;gBACL,OAAO,EAAE;oBACP,GAAG;oBACH,OAAO,EAAE,aAAa;oBACtB,MAAM,EAAE,MAAM;iBACf;gBACD,MAAM,EAAE;oBACN,2CAA2C;oBAC3C,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;oBAC3D,4DAA4D;oBAC5D,EAAE,IAAI,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;iBAC7E;aACF;SACF,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,IAAI;QACd,MAAM,KAAK,GAAG,IAA8E,CAAC;QAC7F,OAAO;YACL,WAAW,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,iBAAiB;YAClD,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG;SAC3B,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,GAAG;QACd,OAAO,GAAG,CAAC;IACb,CAAC;IAED,gBAAgB;QACd,OAAO,qDAAqD,CAAC;IAC/D,CAAC;IAED,KAAK,EAAE;QACL,EAAE,GAAG,EAAE,gCAAgC,EAAE,WAAW,EAAE,IAAI,EAAE;QAC5D,EAAE,GAAG,EAAE,6BAA6B,EAAE,WAAW,EAAE,IAAI,EAAE;QACzD,EAAE,GAAG,EAAE,4BAA4B,EAAE,WAAW,EAAE,IAAI,EAAE;QACxD,EAAE,GAAG,EAAE,2BAA2B,EAAE,WAAW,EAAE,KAAK,EAAE;QACxD,EAAE,GAAG,EAAE,+BAA+B,EAAE,WAAW,EAAE,KAAK,EAAE;KAC7D;CACF,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ServiceProvider } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bluesky service provider
|
|
4
|
+
*
|
|
5
|
+
* Users prove ownership of another Bluesky account by adding their DID to the profile bio.
|
|
6
|
+
* The claim URI is the bsky.app profile URL.
|
|
7
|
+
*/
|
|
8
|
+
declare const bsky: ServiceProvider;
|
|
9
|
+
export default bsky;
|
|
10
|
+
//# sourceMappingURL=bsky.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bsky.d.ts","sourceRoot":"","sources":["../../src/serviceProviders/bsky.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;;GAKG;AACH,QAAA,MAAM,IAAI,EAAE,eA8DX,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bluesky service provider
|
|
3
|
+
*
|
|
4
|
+
* Users prove ownership of another Bluesky account by adding their DID to the profile bio.
|
|
5
|
+
* The claim URI is the bsky.app profile URL.
|
|
6
|
+
*/
|
|
7
|
+
const bsky = {
|
|
8
|
+
id: "bsky",
|
|
9
|
+
name: "Bluesky",
|
|
10
|
+
homepage: "https://bsky.app",
|
|
11
|
+
// Match Bluesky profile URLs: https://bsky.app/profile/handle or did
|
|
12
|
+
reUri: /^https:\/\/bsky\.app\/profile\/([^/]+)\/?$/,
|
|
13
|
+
isAmbiguous: false,
|
|
14
|
+
ui: {
|
|
15
|
+
description: "Link another Bluesky account",
|
|
16
|
+
icon: "cloud",
|
|
17
|
+
inputLabel: "Profile URL",
|
|
18
|
+
inputPlaceholder: "https://bsky.app/profile/username.bsky.social",
|
|
19
|
+
instructions: [
|
|
20
|
+
"Log into the Bluesky account you want to link",
|
|
21
|
+
"Go to **Settings** → **Edit Profile**",
|
|
22
|
+
"Add your DID to your **bio** (the verification DID, not this account's DID)",
|
|
23
|
+
"Save your profile changes",
|
|
24
|
+
"Paste the profile URL below",
|
|
25
|
+
],
|
|
26
|
+
proofTemplate: "{did}",
|
|
27
|
+
},
|
|
28
|
+
processURI(uri, match) {
|
|
29
|
+
const [, handle] = match;
|
|
30
|
+
return {
|
|
31
|
+
profile: {
|
|
32
|
+
display: handle.startsWith("did:") ? handle : `@${handle}`,
|
|
33
|
+
uri,
|
|
34
|
+
},
|
|
35
|
+
proof: {
|
|
36
|
+
request: {
|
|
37
|
+
uri: `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${encodeURIComponent(handle)}`,
|
|
38
|
+
fetcher: "http",
|
|
39
|
+
format: "json",
|
|
40
|
+
},
|
|
41
|
+
target: [
|
|
42
|
+
// Check profile description/bio
|
|
43
|
+
{ path: ["description"], relation: "contains", format: "text" },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
getProofText(did) {
|
|
49
|
+
return did;
|
|
50
|
+
},
|
|
51
|
+
getProofLocation() {
|
|
52
|
+
return `Add to your profile bio`;
|
|
53
|
+
},
|
|
54
|
+
tests: [
|
|
55
|
+
{ uri: "https://bsky.app/profile/alice.bsky.social", shouldMatch: true },
|
|
56
|
+
{ uri: "https://bsky.app/profile/did:plc:abc123", shouldMatch: true },
|
|
57
|
+
{ uri: "https://bsky.app/profile/alice.bsky.social/", shouldMatch: true },
|
|
58
|
+
{ uri: "https://bsky.app/profile/alice/post/123", shouldMatch: false },
|
|
59
|
+
{ uri: "https://bsky.social/profile/alice", shouldMatch: false },
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
export default bsky;
|
|
63
|
+
//# sourceMappingURL=bsky.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bsky.js","sourceRoot":"","sources":["../../src/serviceProviders/bsky.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,IAAI,GAAoB;IAC5B,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,kBAAkB;IAE5B,qEAAqE;IACrE,KAAK,EAAE,4CAA4C;IAEnD,WAAW,EAAE,KAAK;IAElB,EAAE,EAAE;QACF,WAAW,EAAE,8BAA8B;QAC3C,IAAI,EAAE,OAAO;QACb,UAAU,EAAE,aAAa;QACzB,gBAAgB,EAAE,+CAA+C;QACjE,YAAY,EAAE;YACZ,+CAA+C;YAC/C,uCAAuC;YACvC,6EAA6E;YAC7E,2BAA2B;YAC3B,6BAA6B;SAC9B;QACD,aAAa,EAAE,OAAO;KACvB;IAED,UAAU,CAAC,GAAG,EAAE,KAAK;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;QAEzB,OAAO;YACL,OAAO,EAAE;gBACP,OAAO,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE;gBAC1D,GAAG;aACJ;YACD,KAAK,EAAE;gBACL,OAAO,EAAE;oBACP,GAAG,EAAE,oEAAoE,kBAAkB,CAAC,MAAM,CAAC,EAAE;oBACrG,OAAO,EAAE,MAAM;oBACf,MAAM,EAAE,MAAM;iBACf;gBACD,MAAM,EAAE;oBACN,gCAAgC;oBAChC,EAAE,IAAI,EAAE,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE;iBAChE;aACF;SACF,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,GAAG;QACd,OAAO,GAAG,CAAC;IACb,CAAC;IAED,gBAAgB;QACd,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED,KAAK,EAAE;QACL,EAAE,GAAG,EAAE,4CAA4C,EAAE,WAAW,EAAE,IAAI,EAAE;QACxE,EAAE,GAAG,EAAE,yCAAyC,EAAE,WAAW,EAAE,IAAI,EAAE;QACrE,EAAE,GAAG,EAAE,6CAA6C,EAAE,WAAW,EAAE,IAAI,EAAE;QACzE,EAAE,GAAG,EAAE,yCAAyC,EAAE,WAAW,EAAE,KAAK,EAAE;QACtE,EAAE,GAAG,EAAE,mCAAmC,EAAE,WAAW,EAAE,KAAK,EAAE;KACjE;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|