@apitap/core 1.0.0
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/LICENSE +60 -0
- package/README.md +362 -0
- package/SKILL.md +270 -0
- package/dist/auth/crypto.d.ts +31 -0
- package/dist/auth/crypto.js +66 -0
- package/dist/auth/crypto.js.map +1 -0
- package/dist/auth/handoff.d.ts +29 -0
- package/dist/auth/handoff.js +180 -0
- package/dist/auth/handoff.js.map +1 -0
- package/dist/auth/manager.d.ts +46 -0
- package/dist/auth/manager.js +127 -0
- package/dist/auth/manager.js.map +1 -0
- package/dist/auth/oauth-refresh.d.ts +16 -0
- package/dist/auth/oauth-refresh.js +91 -0
- package/dist/auth/oauth-refresh.js.map +1 -0
- package/dist/auth/refresh.d.ts +43 -0
- package/dist/auth/refresh.js +217 -0
- package/dist/auth/refresh.js.map +1 -0
- package/dist/capture/anti-bot.d.ts +15 -0
- package/dist/capture/anti-bot.js +43 -0
- package/dist/capture/anti-bot.js.map +1 -0
- package/dist/capture/blocklist.d.ts +6 -0
- package/dist/capture/blocklist.js +70 -0
- package/dist/capture/blocklist.js.map +1 -0
- package/dist/capture/body-diff.d.ts +8 -0
- package/dist/capture/body-diff.js +102 -0
- package/dist/capture/body-diff.js.map +1 -0
- package/dist/capture/body-variables.d.ts +13 -0
- package/dist/capture/body-variables.js +142 -0
- package/dist/capture/body-variables.js.map +1 -0
- package/dist/capture/domain.d.ts +8 -0
- package/dist/capture/domain.js +34 -0
- package/dist/capture/domain.js.map +1 -0
- package/dist/capture/entropy.d.ts +33 -0
- package/dist/capture/entropy.js +100 -0
- package/dist/capture/entropy.js.map +1 -0
- package/dist/capture/filter.d.ts +11 -0
- package/dist/capture/filter.js +49 -0
- package/dist/capture/filter.js.map +1 -0
- package/dist/capture/graphql.d.ts +21 -0
- package/dist/capture/graphql.js +99 -0
- package/dist/capture/graphql.js.map +1 -0
- package/dist/capture/idle.d.ts +23 -0
- package/dist/capture/idle.js +44 -0
- package/dist/capture/idle.js.map +1 -0
- package/dist/capture/monitor.d.ts +26 -0
- package/dist/capture/monitor.js +183 -0
- package/dist/capture/monitor.js.map +1 -0
- package/dist/capture/oauth-detector.d.ts +18 -0
- package/dist/capture/oauth-detector.js +96 -0
- package/dist/capture/oauth-detector.js.map +1 -0
- package/dist/capture/pagination.d.ts +9 -0
- package/dist/capture/pagination.js +40 -0
- package/dist/capture/pagination.js.map +1 -0
- package/dist/capture/parameterize.d.ts +17 -0
- package/dist/capture/parameterize.js +63 -0
- package/dist/capture/parameterize.js.map +1 -0
- package/dist/capture/scrubber.d.ts +5 -0
- package/dist/capture/scrubber.js +38 -0
- package/dist/capture/scrubber.js.map +1 -0
- package/dist/capture/session.d.ts +46 -0
- package/dist/capture/session.js +445 -0
- package/dist/capture/session.js.map +1 -0
- package/dist/capture/token-detector.d.ts +16 -0
- package/dist/capture/token-detector.js +62 -0
- package/dist/capture/token-detector.js.map +1 -0
- package/dist/capture/verifier.d.ts +17 -0
- package/dist/capture/verifier.js +147 -0
- package/dist/capture/verifier.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +930 -0
- package/dist/cli.js.map +1 -0
- package/dist/discovery/auth.d.ts +17 -0
- package/dist/discovery/auth.js +81 -0
- package/dist/discovery/auth.js.map +1 -0
- package/dist/discovery/fetch.d.ts +17 -0
- package/dist/discovery/fetch.js +59 -0
- package/dist/discovery/fetch.js.map +1 -0
- package/dist/discovery/frameworks.d.ts +11 -0
- package/dist/discovery/frameworks.js +249 -0
- package/dist/discovery/frameworks.js.map +1 -0
- package/dist/discovery/index.d.ts +21 -0
- package/dist/discovery/index.js +219 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/openapi.d.ts +13 -0
- package/dist/discovery/openapi.js +175 -0
- package/dist/discovery/openapi.js.map +1 -0
- package/dist/discovery/probes.d.ts +9 -0
- package/dist/discovery/probes.js +70 -0
- package/dist/discovery/probes.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect/report.d.ts +52 -0
- package/dist/inspect/report.js +191 -0
- package/dist/inspect/report.js.map +1 -0
- package/dist/mcp.d.ts +8 -0
- package/dist/mcp.js +526 -0
- package/dist/mcp.js.map +1 -0
- package/dist/orchestration/browse.d.ts +38 -0
- package/dist/orchestration/browse.js +198 -0
- package/dist/orchestration/browse.js.map +1 -0
- package/dist/orchestration/cache.d.ts +15 -0
- package/dist/orchestration/cache.js +24 -0
- package/dist/orchestration/cache.js.map +1 -0
- package/dist/plugin.d.ts +17 -0
- package/dist/plugin.js +158 -0
- package/dist/plugin.js.map +1 -0
- package/dist/read/decoders/deepwiki.d.ts +2 -0
- package/dist/read/decoders/deepwiki.js +148 -0
- package/dist/read/decoders/deepwiki.js.map +1 -0
- package/dist/read/decoders/grokipedia.d.ts +2 -0
- package/dist/read/decoders/grokipedia.js +210 -0
- package/dist/read/decoders/grokipedia.js.map +1 -0
- package/dist/read/decoders/hackernews.d.ts +2 -0
- package/dist/read/decoders/hackernews.js +168 -0
- package/dist/read/decoders/hackernews.js.map +1 -0
- package/dist/read/decoders/index.d.ts +2 -0
- package/dist/read/decoders/index.js +12 -0
- package/dist/read/decoders/index.js.map +1 -0
- package/dist/read/decoders/reddit.d.ts +2 -0
- package/dist/read/decoders/reddit.js +142 -0
- package/dist/read/decoders/reddit.js.map +1 -0
- package/dist/read/decoders/twitter.d.ts +12 -0
- package/dist/read/decoders/twitter.js +187 -0
- package/dist/read/decoders/twitter.js.map +1 -0
- package/dist/read/decoders/wikipedia.d.ts +2 -0
- package/dist/read/decoders/wikipedia.js +66 -0
- package/dist/read/decoders/wikipedia.js.map +1 -0
- package/dist/read/decoders/youtube.d.ts +2 -0
- package/dist/read/decoders/youtube.js +69 -0
- package/dist/read/decoders/youtube.js.map +1 -0
- package/dist/read/extract.d.ts +25 -0
- package/dist/read/extract.js +320 -0
- package/dist/read/extract.js.map +1 -0
- package/dist/read/index.d.ts +14 -0
- package/dist/read/index.js +66 -0
- package/dist/read/index.js.map +1 -0
- package/dist/read/peek.d.ts +9 -0
- package/dist/read/peek.js +137 -0
- package/dist/read/peek.js.map +1 -0
- package/dist/read/types.d.ts +44 -0
- package/dist/read/types.js +3 -0
- package/dist/read/types.js.map +1 -0
- package/dist/replay/engine.d.ts +53 -0
- package/dist/replay/engine.js +441 -0
- package/dist/replay/engine.js.map +1 -0
- package/dist/replay/truncate.d.ts +16 -0
- package/dist/replay/truncate.js +92 -0
- package/dist/replay/truncate.js.map +1 -0
- package/dist/serve.d.ts +31 -0
- package/dist/serve.js +149 -0
- package/dist/serve.js.map +1 -0
- package/dist/skill/generator.d.ts +44 -0
- package/dist/skill/generator.js +419 -0
- package/dist/skill/generator.js.map +1 -0
- package/dist/skill/importer.d.ts +26 -0
- package/dist/skill/importer.js +80 -0
- package/dist/skill/importer.js.map +1 -0
- package/dist/skill/search.d.ts +19 -0
- package/dist/skill/search.js +51 -0
- package/dist/skill/search.js.map +1 -0
- package/dist/skill/signing.d.ts +16 -0
- package/dist/skill/signing.js +34 -0
- package/dist/skill/signing.js.map +1 -0
- package/dist/skill/ssrf.d.ts +27 -0
- package/dist/skill/ssrf.js +210 -0
- package/dist/skill/ssrf.js.map +1 -0
- package/dist/skill/store.d.ts +7 -0
- package/dist/skill/store.js +93 -0
- package/dist/skill/store.js.map +1 -0
- package/dist/stats/report.d.ts +26 -0
- package/dist/stats/report.js +157 -0
- package/dist/stats/report.js.map +1 -0
- package/dist/types.d.ts +214 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
- package/src/auth/crypto.ts +92 -0
- package/src/auth/handoff.ts +229 -0
- package/src/auth/manager.ts +140 -0
- package/src/auth/oauth-refresh.ts +120 -0
- package/src/auth/refresh.ts +300 -0
- package/src/capture/anti-bot.ts +63 -0
- package/src/capture/blocklist.ts +75 -0
- package/src/capture/body-diff.ts +109 -0
- package/src/capture/body-variables.ts +156 -0
- package/src/capture/domain.ts +34 -0
- package/src/capture/entropy.ts +121 -0
- package/src/capture/filter.ts +56 -0
- package/src/capture/graphql.ts +124 -0
- package/src/capture/idle.ts +45 -0
- package/src/capture/monitor.ts +224 -0
- package/src/capture/oauth-detector.ts +106 -0
- package/src/capture/pagination.ts +49 -0
- package/src/capture/parameterize.ts +68 -0
- package/src/capture/scrubber.ts +49 -0
- package/src/capture/session.ts +502 -0
- package/src/capture/token-detector.ts +76 -0
- package/src/capture/verifier.ts +171 -0
- package/src/cli.ts +1031 -0
- package/src/discovery/auth.ts +99 -0
- package/src/discovery/fetch.ts +85 -0
- package/src/discovery/frameworks.ts +231 -0
- package/src/discovery/index.ts +256 -0
- package/src/discovery/openapi.ts +230 -0
- package/src/discovery/probes.ts +76 -0
- package/src/index.ts +26 -0
- package/src/inspect/report.ts +247 -0
- package/src/mcp.ts +618 -0
- package/src/orchestration/browse.ts +250 -0
- package/src/orchestration/cache.ts +37 -0
- package/src/plugin.ts +188 -0
- package/src/read/decoders/deepwiki.ts +180 -0
- package/src/read/decoders/grokipedia.ts +246 -0
- package/src/read/decoders/hackernews.ts +198 -0
- package/src/read/decoders/index.ts +15 -0
- package/src/read/decoders/reddit.ts +158 -0
- package/src/read/decoders/twitter.ts +211 -0
- package/src/read/decoders/wikipedia.ts +75 -0
- package/src/read/decoders/youtube.ts +75 -0
- package/src/read/extract.ts +396 -0
- package/src/read/index.ts +78 -0
- package/src/read/peek.ts +175 -0
- package/src/read/types.ts +37 -0
- package/src/replay/engine.ts +559 -0
- package/src/replay/truncate.ts +116 -0
- package/src/serve.ts +189 -0
- package/src/skill/generator.ts +473 -0
- package/src/skill/importer.ts +107 -0
- package/src/skill/search.ts +76 -0
- package/src/skill/signing.ts +36 -0
- package/src/skill/ssrf.ts +238 -0
- package/src/skill/store.ts +107 -0
- package/src/stats/report.ts +208 -0
- package/src/types.ts +233 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// src/capture/verifier.ts
|
|
2
|
+
import type { SkillFile, SkillEndpoint, Replayability } from '../types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Heuristic tier classification for non-GET endpoints (or when verification is skipped).
|
|
6
|
+
* Based on header analysis only.
|
|
7
|
+
*/
|
|
8
|
+
export function classifyHeuristic(endpoint: SkillEndpoint): Replayability {
|
|
9
|
+
const signals: string[] = [];
|
|
10
|
+
|
|
11
|
+
const hasAuth = Object.values(endpoint.headers).some(v => v === '[stored]');
|
|
12
|
+
if (hasAuth) signals.push('auth-required');
|
|
13
|
+
|
|
14
|
+
const hasCsrf = Object.keys(endpoint.headers).some(k => {
|
|
15
|
+
const lower = k.toLowerCase();
|
|
16
|
+
return lower.includes('csrf') || lower.includes('xsrf');
|
|
17
|
+
});
|
|
18
|
+
if (hasCsrf) signals.push('csrf-token');
|
|
19
|
+
|
|
20
|
+
let tier: Replayability['tier'];
|
|
21
|
+
if (hasCsrf) {
|
|
22
|
+
tier = 'orange';
|
|
23
|
+
} else if (hasAuth) {
|
|
24
|
+
tier = 'yellow';
|
|
25
|
+
} else {
|
|
26
|
+
tier = 'green';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return { tier, verified: false, signals };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Verify a single GET endpoint by replaying it with raw fetch().
|
|
34
|
+
* Compares status and response shape.
|
|
35
|
+
*/
|
|
36
|
+
async function verifySingle(
|
|
37
|
+
endpoint: SkillEndpoint,
|
|
38
|
+
): Promise<Replayability> {
|
|
39
|
+
const url = endpoint.examples.request.url;
|
|
40
|
+
if (!url) return classifyHeuristic(endpoint);
|
|
41
|
+
|
|
42
|
+
// Build headers: use endpoint headers but exclude [stored] auth placeholders
|
|
43
|
+
const headers: Record<string, string> = {};
|
|
44
|
+
for (const [k, v] of Object.entries(endpoint.headers)) {
|
|
45
|
+
if (v !== '[stored]') {
|
|
46
|
+
headers[k] = v;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(url, {
|
|
52
|
+
headers,
|
|
53
|
+
signal: AbortSignal.timeout(5000),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (response.ok) {
|
|
57
|
+
const signals: string[] = ['status-match'];
|
|
58
|
+
|
|
59
|
+
// Check if response shape matches
|
|
60
|
+
const ct = response.headers.get('content-type') ?? '';
|
|
61
|
+
if (ct.includes('json')) {
|
|
62
|
+
try {
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
const responseType = Array.isArray(data) ? 'array' : typeof data === 'object' && data !== null ? 'object' : typeof data;
|
|
65
|
+
if (responseType === endpoint.responseShape.type) {
|
|
66
|
+
signals.push('shape-match');
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// JSON parse failure — still count status match
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { tier: 'green', verified: true, signals };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (response.status === 401 || response.status === 403) {
|
|
77
|
+
return { tier: 'yellow', verified: true, signals: ['auth-required'] };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { tier: 'orange', verified: true, signals: [`status-${response.status}`] };
|
|
81
|
+
} catch {
|
|
82
|
+
return { tier: 'red', verified: true, signals: ['connection-failed'] };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Verify a single POST/PUT/PATCH endpoint by replaying it with the captured body.
|
|
88
|
+
* Same classification logic as verifySingle but includes the request body.
|
|
89
|
+
*/
|
|
90
|
+
async function verifySinglePost(
|
|
91
|
+
endpoint: SkillEndpoint,
|
|
92
|
+
): Promise<Replayability> {
|
|
93
|
+
const url = endpoint.examples.request.url;
|
|
94
|
+
if (!url || !endpoint.requestBody) return classifyHeuristic(endpoint);
|
|
95
|
+
|
|
96
|
+
const headers: Record<string, string> = {};
|
|
97
|
+
for (const [k, v] of Object.entries(endpoint.headers)) {
|
|
98
|
+
if (v !== '[stored]') {
|
|
99
|
+
headers[k] = v;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const body = typeof endpoint.requestBody.template === 'object'
|
|
104
|
+
? JSON.stringify(endpoint.requestBody.template)
|
|
105
|
+
: endpoint.requestBody.template;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const response = await fetch(url, {
|
|
109
|
+
method: endpoint.method,
|
|
110
|
+
headers,
|
|
111
|
+
body,
|
|
112
|
+
signal: AbortSignal.timeout(5000),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (response.ok) {
|
|
116
|
+
const signals: string[] = ['status-match'];
|
|
117
|
+
|
|
118
|
+
const ct = response.headers.get('content-type') ?? '';
|
|
119
|
+
if (ct.includes('json')) {
|
|
120
|
+
try {
|
|
121
|
+
const data = await response.json();
|
|
122
|
+
const responseType = Array.isArray(data) ? 'array' : typeof data === 'object' && data !== null ? 'object' : typeof data;
|
|
123
|
+
if (responseType === endpoint.responseShape.type) {
|
|
124
|
+
signals.push('shape-match');
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
// JSON parse failure — still count status match
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { tier: 'green', verified: true, signals };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (response.status === 401 || response.status === 403) {
|
|
135
|
+
return { tier: 'yellow', verified: true, signals: ['auth-required'] };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return { tier: 'orange', verified: true, signals: [`status-${response.status}`] };
|
|
139
|
+
} catch {
|
|
140
|
+
return { tier: 'red', verified: true, signals: ['connection-failed'] };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface VerifyOptions {
|
|
145
|
+
/** Verify POST/PUT/PATCH endpoints by replaying them (opt-in, may cause side effects). */
|
|
146
|
+
verifyPosts?: boolean;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Verify all GET endpoints in a skill file by replaying them.
|
|
151
|
+
* Non-GET endpoints get heuristic classification by default.
|
|
152
|
+
* With verifyPosts: true, POST/PUT/PATCH endpoints are also replayed.
|
|
153
|
+
* Returns a new skill file with replayability tags on all endpoints.
|
|
154
|
+
*/
|
|
155
|
+
export async function verifyEndpoints(skill: SkillFile, opts?: VerifyOptions): Promise<SkillFile> {
|
|
156
|
+
const verifiedEndpoints = await Promise.all(
|
|
157
|
+
skill.endpoints.map(async (ep) => {
|
|
158
|
+
let replayability: Replayability;
|
|
159
|
+
if (ep.method === 'GET') {
|
|
160
|
+
replayability = await verifySingle(ep);
|
|
161
|
+
} else if (opts?.verifyPosts) {
|
|
162
|
+
replayability = await verifySinglePost(ep);
|
|
163
|
+
} else {
|
|
164
|
+
replayability = classifyHeuristic(ep);
|
|
165
|
+
}
|
|
166
|
+
return { ...ep, replayability };
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return { ...skill, endpoints: verifiedEndpoints };
|
|
171
|
+
}
|