@qulib/core 0.2.1 → 0.3.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/README.md +45 -3
- package/dist/analyze.d.ts +16 -4
- package/dist/analyze.d.ts.map +1 -1
- package/dist/analyze.js +98 -38
- package/dist/cli/cost-doctor.d.ts +2 -0
- package/dist/cli/cost-doctor.d.ts.map +1 -0
- package/dist/cli/cost-doctor.js +72 -0
- package/dist/cli/index.js +61 -0
- package/dist/harness/progress-log.d.ts +7 -0
- package/dist/harness/progress-log.d.ts.map +1 -0
- package/dist/harness/progress-log.js +1 -0
- package/dist/harness/run-options.d.ts +2 -0
- package/dist/harness/run-options.d.ts.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/llm/content-hash.d.ts +2 -0
- package/dist/llm/content-hash.d.ts.map +1 -0
- package/dist/llm/content-hash.js +4 -0
- package/dist/llm/context-builder.js +1 -1
- package/dist/llm/cost-intelligence.d.ts +29 -0
- package/dist/llm/cost-intelligence.d.ts.map +1 -0
- package/dist/llm/cost-intelligence.js +153 -0
- package/dist/llm/provider.d.ts +11 -1
- package/dist/llm/provider.d.ts.map +1 -1
- package/dist/llm/provider.js +43 -4
- package/dist/phases/act.d.ts.map +1 -1
- package/dist/phases/act.js +4 -1
- package/dist/phases/observe.js +1 -1
- package/dist/phases/think-finalize.d.ts +6 -0
- package/dist/phases/think-finalize.d.ts.map +1 -0
- package/dist/phases/think-finalize.js +164 -0
- package/dist/phases/think.d.ts +2 -0
- package/dist/phases/think.d.ts.map +1 -1
- package/dist/phases/think.js +16 -65
- package/dist/reporters/markdown-reporter.d.ts.map +1 -1
- package/dist/reporters/markdown-reporter.js +23 -3
- package/dist/schemas/config.schema.d.ts +364 -0
- package/dist/schemas/config.schema.d.ts.map +1 -1
- package/dist/schemas/config.schema.js +55 -1
- package/dist/schemas/cost-intelligence.schema.d.ts +229 -0
- package/dist/schemas/cost-intelligence.schema.d.ts.map +1 -0
- package/dist/schemas/cost-intelligence.schema.js +41 -0
- package/dist/schemas/decision-log.schema.d.ts +2 -2
- package/dist/schemas/gap-analysis.schema.d.ts +288 -49
- package/dist/schemas/gap-analysis.schema.d.ts.map +1 -1
- package/dist/schemas/gap-analysis.schema.js +7 -3
- package/dist/schemas/index.d.ts +3 -1
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +3 -1
- package/dist/schemas/public-surface.schema.d.ts +268 -0
- package/dist/schemas/public-surface.schema.d.ts.map +1 -0
- package/dist/schemas/public-surface.schema.js +15 -0
- package/dist/schemas/repo-analysis.schema.d.ts +6 -6
- package/dist/tools/auth-block-gap.d.ts +3 -0
- package/dist/tools/auth-block-gap.d.ts.map +1 -0
- package/dist/tools/auth-block-gap.js +19 -0
- package/dist/tools/auth-detector.d.ts +2 -1
- package/dist/tools/auth-detector.d.ts.map +1 -1
- package/dist/tools/auth-detector.js +28 -3
- package/dist/tools/auth-explorer.d.ts +4 -0
- package/dist/tools/auth-explorer.d.ts.map +1 -0
- package/dist/tools/auth-explorer.js +346 -0
- package/dist/tools/auth-surface-analyzer.d.ts +4 -0
- package/dist/tools/auth-surface-analyzer.d.ts.map +1 -0
- package/dist/tools/auth-surface-analyzer.js +154 -0
- package/dist/tools/cypress-explorer.d.ts +2 -1
- package/dist/tools/cypress-explorer.d.ts.map +1 -1
- package/dist/tools/cypress-explorer.js +1 -1
- package/dist/tools/explorer.interface.d.ts +2 -1
- package/dist/tools/explorer.interface.d.ts.map +1 -1
- package/dist/tools/gap-engine.d.ts +3 -1
- package/dist/tools/gap-engine.d.ts.map +1 -1
- package/dist/tools/gap-engine.js +39 -12
- package/dist/tools/oauth-providers.d.ts +7 -0
- package/dist/tools/oauth-providers.d.ts.map +1 -0
- package/dist/tools/oauth-providers.js +21 -0
- package/dist/tools/playwright-explorer.d.ts +2 -1
- package/dist/tools/playwright-explorer.d.ts.map +1 -1
- package/dist/tools/playwright-explorer.js +21 -3
- package/dist/tools/public-surface.d.ts +5 -0
- package/dist/tools/public-surface.d.ts.map +1 -0
- package/dist/tools/public-surface.js +13 -0
- package/dist/tools/user-providers.d.ts +15 -0
- package/dist/tools/user-providers.d.ts.map +1 -0
- package/dist/tools/user-providers.js +62 -0
- package/package.json +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gCAAgC,EAChC,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,cAAc,EACd,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,KAAK,GACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,6BAA6B,EAC7B,KAAK,WAAW,EAChB,KAAK,GAAG,EACR,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,uBAAuB,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,mBAAmB,EACnB,4BAA4B,EAC5B,6BAA6B,EAC7B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,4BAA4B,CAAC"}
|
package/dist/schemas/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
export { HarnessConfigSchema, AuthConfigSchema, DetectedAuthSchema, } from './config.schema.js';
|
|
1
|
+
export { HarnessConfigSchema, resolveMaxOutputTokensPerLlmCall, AuthConfigSchema, DetectedAuthSchema, AuthPathRequirementsSchema, AuthPathSchema, AuthExplorationSchema, } from './config.schema.js';
|
|
2
2
|
export { DecisionLogEntrySchema, } from './decision-log.schema.js';
|
|
3
3
|
export { RouteInventorySchema, RouteSchema, A11yViolationSchema, BrokenLinkSchema, } from './route-inventory.schema.js';
|
|
4
4
|
export { GapAnalysisSchema, GapSchema, NeutralScenarioSchema, GeneratedTestSchema, TestStepSchema, FrameworkRecommendationSchema, } from './gap-analysis.schema.js';
|
|
5
|
+
export { CostIntelligenceSchema, LlmUsageRecordSchema, LlmDataQualitySchema, LlmOperationTypeSchema, RepeatedAiPatternSchema, DeterministicMaturitySchema, } from './cost-intelligence.schema.js';
|
|
5
6
|
export { RepoAnalysisSchema, } from './repo-analysis.schema.js';
|
|
7
|
+
export { PublicSurfaceSchema, PublicSurfaceViolationSchema, PublicSurfaceBrokenLinkSchema, } from './public-surface.schema.js';
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PublicSurfaceViolationSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
impact: z.ZodString;
|
|
5
|
+
helpUrl: z.ZodString;
|
|
6
|
+
nodeCount: z.ZodNumber;
|
|
7
|
+
} & {
|
|
8
|
+
path: z.ZodString;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
path: string;
|
|
11
|
+
id: string;
|
|
12
|
+
impact: string;
|
|
13
|
+
helpUrl: string;
|
|
14
|
+
nodeCount: number;
|
|
15
|
+
}, {
|
|
16
|
+
path: string;
|
|
17
|
+
id: string;
|
|
18
|
+
impact: string;
|
|
19
|
+
helpUrl: string;
|
|
20
|
+
nodeCount: number;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const PublicSurfaceBrokenLinkSchema: z.ZodObject<{
|
|
23
|
+
url: z.ZodString;
|
|
24
|
+
status: z.ZodNullable<z.ZodNumber>;
|
|
25
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
26
|
+
} & {
|
|
27
|
+
path: z.ZodString;
|
|
28
|
+
}, "strip", z.ZodTypeAny, {
|
|
29
|
+
status: number | null;
|
|
30
|
+
path: string;
|
|
31
|
+
url: string;
|
|
32
|
+
reason?: string | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
status: number | null;
|
|
35
|
+
path: string;
|
|
36
|
+
url: string;
|
|
37
|
+
reason?: string | undefined;
|
|
38
|
+
}>;
|
|
39
|
+
export declare const PublicSurfaceSchema: z.ZodObject<{
|
|
40
|
+
pages: z.ZodArray<z.ZodObject<{
|
|
41
|
+
path: z.ZodString;
|
|
42
|
+
pageTitle: z.ZodString;
|
|
43
|
+
links: z.ZodArray<z.ZodString, "many">;
|
|
44
|
+
formCount: z.ZodNumber;
|
|
45
|
+
buttonLabels: z.ZodArray<z.ZodString, "many">;
|
|
46
|
+
consoleErrors: z.ZodArray<z.ZodString, "many">;
|
|
47
|
+
brokenLinks: z.ZodArray<z.ZodObject<{
|
|
48
|
+
url: z.ZodString;
|
|
49
|
+
status: z.ZodNullable<z.ZodNumber>;
|
|
50
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, "strip", z.ZodTypeAny, {
|
|
52
|
+
status: number | null;
|
|
53
|
+
url: string;
|
|
54
|
+
reason?: string | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
status: number | null;
|
|
57
|
+
url: string;
|
|
58
|
+
reason?: string | undefined;
|
|
59
|
+
}>, "many">;
|
|
60
|
+
a11yViolations: z.ZodArray<z.ZodObject<{
|
|
61
|
+
id: z.ZodString;
|
|
62
|
+
impact: z.ZodString;
|
|
63
|
+
helpUrl: z.ZodString;
|
|
64
|
+
nodeCount: z.ZodNumber;
|
|
65
|
+
}, "strip", z.ZodTypeAny, {
|
|
66
|
+
id: string;
|
|
67
|
+
impact: string;
|
|
68
|
+
helpUrl: string;
|
|
69
|
+
nodeCount: number;
|
|
70
|
+
}, {
|
|
71
|
+
id: string;
|
|
72
|
+
impact: string;
|
|
73
|
+
helpUrl: string;
|
|
74
|
+
nodeCount: number;
|
|
75
|
+
}>, "many">;
|
|
76
|
+
statusCode: z.ZodOptional<z.ZodNumber>;
|
|
77
|
+
}, "strip", z.ZodTypeAny, {
|
|
78
|
+
path: string;
|
|
79
|
+
pageTitle: string;
|
|
80
|
+
links: string[];
|
|
81
|
+
formCount: number;
|
|
82
|
+
buttonLabels: string[];
|
|
83
|
+
consoleErrors: string[];
|
|
84
|
+
brokenLinks: {
|
|
85
|
+
status: number | null;
|
|
86
|
+
url: string;
|
|
87
|
+
reason?: string | undefined;
|
|
88
|
+
}[];
|
|
89
|
+
a11yViolations: {
|
|
90
|
+
id: string;
|
|
91
|
+
impact: string;
|
|
92
|
+
helpUrl: string;
|
|
93
|
+
nodeCount: number;
|
|
94
|
+
}[];
|
|
95
|
+
statusCode?: number | undefined;
|
|
96
|
+
}, {
|
|
97
|
+
path: string;
|
|
98
|
+
pageTitle: string;
|
|
99
|
+
links: string[];
|
|
100
|
+
formCount: number;
|
|
101
|
+
buttonLabels: string[];
|
|
102
|
+
consoleErrors: string[];
|
|
103
|
+
brokenLinks: {
|
|
104
|
+
status: number | null;
|
|
105
|
+
url: string;
|
|
106
|
+
reason?: string | undefined;
|
|
107
|
+
}[];
|
|
108
|
+
a11yViolations: {
|
|
109
|
+
id: string;
|
|
110
|
+
impact: string;
|
|
111
|
+
helpUrl: string;
|
|
112
|
+
nodeCount: number;
|
|
113
|
+
}[];
|
|
114
|
+
statusCode?: number | undefined;
|
|
115
|
+
}>, "many">;
|
|
116
|
+
gaps: z.ZodArray<z.ZodObject<{
|
|
117
|
+
id: z.ZodString;
|
|
118
|
+
path: z.ZodString;
|
|
119
|
+
severity: z.ZodEnum<["critical", "high", "medium", "low"]>;
|
|
120
|
+
reason: z.ZodString;
|
|
121
|
+
category: z.ZodEnum<["untested-route", "a11y", "console-error", "broken-link", "auth-surface", "coverage"]>;
|
|
122
|
+
description: z.ZodOptional<z.ZodString>;
|
|
123
|
+
recommendation: z.ZodOptional<z.ZodString>;
|
|
124
|
+
}, "strip", z.ZodTypeAny, {
|
|
125
|
+
path: string;
|
|
126
|
+
id: string;
|
|
127
|
+
severity: "high" | "medium" | "low" | "critical";
|
|
128
|
+
reason: string;
|
|
129
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
|
|
130
|
+
recommendation?: string | undefined;
|
|
131
|
+
description?: string | undefined;
|
|
132
|
+
}, {
|
|
133
|
+
path: string;
|
|
134
|
+
id: string;
|
|
135
|
+
severity: "high" | "medium" | "low" | "critical";
|
|
136
|
+
reason: string;
|
|
137
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
|
|
138
|
+
recommendation?: string | undefined;
|
|
139
|
+
description?: string | undefined;
|
|
140
|
+
}>, "many">;
|
|
141
|
+
accessibilityViolations: z.ZodArray<z.ZodObject<{
|
|
142
|
+
id: z.ZodString;
|
|
143
|
+
impact: z.ZodString;
|
|
144
|
+
helpUrl: z.ZodString;
|
|
145
|
+
nodeCount: z.ZodNumber;
|
|
146
|
+
} & {
|
|
147
|
+
path: z.ZodString;
|
|
148
|
+
}, "strip", z.ZodTypeAny, {
|
|
149
|
+
path: string;
|
|
150
|
+
id: string;
|
|
151
|
+
impact: string;
|
|
152
|
+
helpUrl: string;
|
|
153
|
+
nodeCount: number;
|
|
154
|
+
}, {
|
|
155
|
+
path: string;
|
|
156
|
+
id: string;
|
|
157
|
+
impact: string;
|
|
158
|
+
helpUrl: string;
|
|
159
|
+
nodeCount: number;
|
|
160
|
+
}>, "many">;
|
|
161
|
+
brokenLinks: z.ZodArray<z.ZodObject<{
|
|
162
|
+
url: z.ZodString;
|
|
163
|
+
status: z.ZodNullable<z.ZodNumber>;
|
|
164
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
165
|
+
} & {
|
|
166
|
+
path: z.ZodString;
|
|
167
|
+
}, "strip", z.ZodTypeAny, {
|
|
168
|
+
status: number | null;
|
|
169
|
+
path: string;
|
|
170
|
+
url: string;
|
|
171
|
+
reason?: string | undefined;
|
|
172
|
+
}, {
|
|
173
|
+
status: number | null;
|
|
174
|
+
path: string;
|
|
175
|
+
url: string;
|
|
176
|
+
reason?: string | undefined;
|
|
177
|
+
}>, "many">;
|
|
178
|
+
}, "strip", z.ZodTypeAny, {
|
|
179
|
+
gaps: {
|
|
180
|
+
path: string;
|
|
181
|
+
id: string;
|
|
182
|
+
severity: "high" | "medium" | "low" | "critical";
|
|
183
|
+
reason: string;
|
|
184
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
|
|
185
|
+
recommendation?: string | undefined;
|
|
186
|
+
description?: string | undefined;
|
|
187
|
+
}[];
|
|
188
|
+
brokenLinks: {
|
|
189
|
+
status: number | null;
|
|
190
|
+
path: string;
|
|
191
|
+
url: string;
|
|
192
|
+
reason?: string | undefined;
|
|
193
|
+
}[];
|
|
194
|
+
pages: {
|
|
195
|
+
path: string;
|
|
196
|
+
pageTitle: string;
|
|
197
|
+
links: string[];
|
|
198
|
+
formCount: number;
|
|
199
|
+
buttonLabels: string[];
|
|
200
|
+
consoleErrors: string[];
|
|
201
|
+
brokenLinks: {
|
|
202
|
+
status: number | null;
|
|
203
|
+
url: string;
|
|
204
|
+
reason?: string | undefined;
|
|
205
|
+
}[];
|
|
206
|
+
a11yViolations: {
|
|
207
|
+
id: string;
|
|
208
|
+
impact: string;
|
|
209
|
+
helpUrl: string;
|
|
210
|
+
nodeCount: number;
|
|
211
|
+
}[];
|
|
212
|
+
statusCode?: number | undefined;
|
|
213
|
+
}[];
|
|
214
|
+
accessibilityViolations: {
|
|
215
|
+
path: string;
|
|
216
|
+
id: string;
|
|
217
|
+
impact: string;
|
|
218
|
+
helpUrl: string;
|
|
219
|
+
nodeCount: number;
|
|
220
|
+
}[];
|
|
221
|
+
}, {
|
|
222
|
+
gaps: {
|
|
223
|
+
path: string;
|
|
224
|
+
id: string;
|
|
225
|
+
severity: "high" | "medium" | "low" | "critical";
|
|
226
|
+
reason: string;
|
|
227
|
+
category: "untested-route" | "a11y" | "console-error" | "broken-link" | "auth-surface" | "coverage";
|
|
228
|
+
recommendation?: string | undefined;
|
|
229
|
+
description?: string | undefined;
|
|
230
|
+
}[];
|
|
231
|
+
brokenLinks: {
|
|
232
|
+
status: number | null;
|
|
233
|
+
path: string;
|
|
234
|
+
url: string;
|
|
235
|
+
reason?: string | undefined;
|
|
236
|
+
}[];
|
|
237
|
+
pages: {
|
|
238
|
+
path: string;
|
|
239
|
+
pageTitle: string;
|
|
240
|
+
links: string[];
|
|
241
|
+
formCount: number;
|
|
242
|
+
buttonLabels: string[];
|
|
243
|
+
consoleErrors: string[];
|
|
244
|
+
brokenLinks: {
|
|
245
|
+
status: number | null;
|
|
246
|
+
url: string;
|
|
247
|
+
reason?: string | undefined;
|
|
248
|
+
}[];
|
|
249
|
+
a11yViolations: {
|
|
250
|
+
id: string;
|
|
251
|
+
impact: string;
|
|
252
|
+
helpUrl: string;
|
|
253
|
+
nodeCount: number;
|
|
254
|
+
}[];
|
|
255
|
+
statusCode?: number | undefined;
|
|
256
|
+
}[];
|
|
257
|
+
accessibilityViolations: {
|
|
258
|
+
path: string;
|
|
259
|
+
id: string;
|
|
260
|
+
impact: string;
|
|
261
|
+
helpUrl: string;
|
|
262
|
+
nodeCount: number;
|
|
263
|
+
}[];
|
|
264
|
+
}>;
|
|
265
|
+
export type PublicSurface = z.infer<typeof PublicSurfaceSchema>;
|
|
266
|
+
export type PublicSurfaceViolation = z.infer<typeof PublicSurfaceViolationSchema>;
|
|
267
|
+
export type PublicSurfaceBrokenLink = z.infer<typeof PublicSurfaceBrokenLinkSchema>;
|
|
268
|
+
//# sourceMappingURL=public-surface.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-surface.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/public-surface.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;EAEvC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;EAExC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAClF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { GapSchema } from './gap-analysis.schema.js';
|
|
3
|
+
import { A11yViolationSchema, BrokenLinkSchema, RouteSchema } from './route-inventory.schema.js';
|
|
4
|
+
export const PublicSurfaceViolationSchema = A11yViolationSchema.extend({
|
|
5
|
+
path: z.string(),
|
|
6
|
+
});
|
|
7
|
+
export const PublicSurfaceBrokenLinkSchema = BrokenLinkSchema.extend({
|
|
8
|
+
path: z.string(),
|
|
9
|
+
});
|
|
10
|
+
export const PublicSurfaceSchema = z.object({
|
|
11
|
+
pages: z.array(RouteSchema),
|
|
12
|
+
gaps: z.array(GapSchema),
|
|
13
|
+
accessibilityViolations: z.array(PublicSurfaceViolationSchema),
|
|
14
|
+
brokenLinks: z.array(PublicSurfaceBrokenLinkSchema),
|
|
15
|
+
});
|
|
@@ -5,12 +5,12 @@ export declare const RepoRouteSchema: z.ZodObject<{
|
|
|
5
5
|
method: z.ZodEnum<["GET", "POST", "PUT", "DELETE", "PATCH", "unknown"]>;
|
|
6
6
|
}, "strip", z.ZodTypeAny, {
|
|
7
7
|
path: string;
|
|
8
|
-
file: string;
|
|
9
8
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
9
|
+
file: string;
|
|
10
10
|
}, {
|
|
11
11
|
path: string;
|
|
12
|
-
file: string;
|
|
13
12
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
13
|
+
file: string;
|
|
14
14
|
}>;
|
|
15
15
|
export declare const TestFileSchema: z.ZodObject<{
|
|
16
16
|
file: z.ZodString;
|
|
@@ -62,12 +62,12 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
|
|
|
62
62
|
method: z.ZodEnum<["GET", "POST", "PUT", "DELETE", "PATCH", "unknown"]>;
|
|
63
63
|
}, "strip", z.ZodTypeAny, {
|
|
64
64
|
path: string;
|
|
65
|
-
file: string;
|
|
66
65
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
66
|
+
file: string;
|
|
67
67
|
}, {
|
|
68
68
|
path: string;
|
|
69
|
-
file: string;
|
|
70
69
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
70
|
+
file: string;
|
|
71
71
|
}>, "many">;
|
|
72
72
|
testFiles: z.ZodArray<z.ZodObject<{
|
|
73
73
|
file: z.ZodString;
|
|
@@ -115,8 +115,8 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
|
|
|
115
115
|
scannedAt: string;
|
|
116
116
|
routes: {
|
|
117
117
|
path: string;
|
|
118
|
-
file: string;
|
|
119
118
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
119
|
+
file: string;
|
|
120
120
|
}[];
|
|
121
121
|
repoPath: string;
|
|
122
122
|
testFiles: {
|
|
@@ -139,8 +139,8 @@ export declare const RepoAnalysisSchema: z.ZodObject<{
|
|
|
139
139
|
scannedAt: string;
|
|
140
140
|
routes: {
|
|
141
141
|
path: string;
|
|
142
|
-
file: string;
|
|
143
142
|
method: "unknown" | "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
143
|
+
file: string;
|
|
144
144
|
}[];
|
|
145
145
|
repoPath: string;
|
|
146
146
|
testFiles: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-block-gap.d.ts","sourceRoot":"","sources":["../../src/tools/auth-block-gap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mCAAmC,CAAC;AAE7D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAiBlD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function buildAuthBlockGap(url) {
|
|
2
|
+
const host = (() => {
|
|
3
|
+
try {
|
|
4
|
+
return new URL(url).hostname;
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return url;
|
|
8
|
+
}
|
|
9
|
+
})();
|
|
10
|
+
return {
|
|
11
|
+
id: 'auth-block',
|
|
12
|
+
path: '/',
|
|
13
|
+
severity: 'critical',
|
|
14
|
+
category: 'coverage',
|
|
15
|
+
reason: `Scan blocked by authentication. No authenticated pages were evaluated for ${host}.`,
|
|
16
|
+
description: 'Scan blocked by authentication. 0 authenticated pages were evaluated.',
|
|
17
|
+
recommendation: `Run \`qulib auth init --base-url ${url}\` to capture a storage state, then re-run with --auth storage-state.`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { DetectedAuth } from '../schemas/config.schema.js';
|
|
2
|
-
|
|
2
|
+
import type { AnalyzeProgressSink } from '../harness/progress-log.js';
|
|
3
|
+
export declare function detectAuth(url: string, timeoutMs?: number, progress?: AnalyzeProgressSink): Promise<DetectedAuth>;
|
|
3
4
|
//# sourceMappingURL=auth-detector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-detector.d.ts","sourceRoot":"","sources":["../../src/tools/auth-detector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-detector.d.ts","sourceRoot":"","sources":["../../src/tools/auth-detector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAgEtE,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,SAAQ,EACjB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAAC,YAAY,CAAC,CA8HvB"}
|
|
@@ -50,20 +50,31 @@ async function firstTextInputNameForLogin(page) {
|
|
|
50
50
|
}
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
|
-
|
|
53
|
+
function debugAuth() {
|
|
54
|
+
return process.env.QULIB_DEBUG === '1';
|
|
55
|
+
}
|
|
56
|
+
export async function detectAuth(url, timeoutMs = 15000, progress) {
|
|
54
57
|
const browser = await launchBrowser();
|
|
55
58
|
try {
|
|
56
59
|
const context = await browser.newContext();
|
|
57
60
|
const page = await context.newPage();
|
|
61
|
+
progress?.info(`detect_auth URL=${url}`);
|
|
58
62
|
await page.goto(url, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
|
|
59
63
|
await waitNetworkIdleBestEffort(page);
|
|
64
|
+
if (debugAuth()) {
|
|
65
|
+
const html = await page.content();
|
|
66
|
+
progress?.debug(`detect_auth HTML byteLength=${Buffer.byteLength(html, 'utf8')}`);
|
|
67
|
+
}
|
|
60
68
|
let loginUrl = url;
|
|
61
69
|
const looksLikeLoginPage = /login|sign[- ]?in|auth/i.test(page.url()) ||
|
|
62
70
|
(await page.locator('input[type="password"]').count()) > 0;
|
|
63
71
|
if (!looksLikeLoginPage) {
|
|
64
72
|
const loginLink = page.locator('a').filter({ hasText: /^(log ?in|sign ?in|sign in)$/i }).first();
|
|
65
|
-
|
|
73
|
+
const loginLinkCount = await loginLink.count();
|
|
74
|
+
progress?.debug(`detect_auth selector loginLink count=${loginLinkCount}`);
|
|
75
|
+
if (loginLinkCount > 0) {
|
|
66
76
|
const href = await loginLink.getAttribute('href');
|
|
77
|
+
progress?.debug(`detect_auth selector loginLink href matched=${Boolean(href)}`);
|
|
67
78
|
if (href) {
|
|
68
79
|
loginUrl = new URL(href, url).toString();
|
|
69
80
|
await page.goto(loginUrl, { timeout: timeoutMs, waitUntil: 'domcontentloaded' });
|
|
@@ -73,16 +84,24 @@ export async function detectAuth(url, timeoutMs = 15000) {
|
|
|
73
84
|
}
|
|
74
85
|
const passwordInputs = page.locator('input[type="password"]');
|
|
75
86
|
const passwordCount = await passwordInputs.count();
|
|
87
|
+
progress?.debug(`detect_auth selector input[type=password] count=${passwordCount}`);
|
|
76
88
|
const hasFormLogin = passwordCount > 0;
|
|
77
89
|
const oauthButtons = [];
|
|
78
90
|
const buttonTexts = await page.locator('button, a').allInnerTexts();
|
|
79
91
|
for (const text of buttonTexts) {
|
|
80
92
|
const trimmed = text.trim();
|
|
81
93
|
if (!textLooksLikeOAuthIdpButton(trimmed)) {
|
|
94
|
+
if (debugAuth() && trimmed.length > 0 && trimmed.length <= 120) {
|
|
95
|
+
progress?.debug(`detect_auth oauth text skipped (not Idp-shaped) sample="${trimmed.slice(0, 80)}"`);
|
|
96
|
+
}
|
|
82
97
|
continue;
|
|
83
98
|
}
|
|
84
99
|
for (const { provider, patterns } of OAUTH_PROVIDERS) {
|
|
85
|
-
|
|
100
|
+
const matched = patterns.some((p) => p.test(trimmed));
|
|
101
|
+
if (debugAuth()) {
|
|
102
|
+
progress?.debug(`detect_auth oauth pattern try provider=${provider} matched=${matched}`);
|
|
103
|
+
}
|
|
104
|
+
if (matched) {
|
|
86
105
|
if (!oauthButtons.find((b) => b.provider === provider)) {
|
|
87
106
|
oauthButtons.push({ provider, text: trimmed.slice(0, 100) });
|
|
88
107
|
}
|
|
@@ -114,6 +133,9 @@ export async function detectAuth(url, timeoutMs = 15000) {
|
|
|
114
133
|
passwordSelector: passwordName ? `input[name="${passwordName}"]` : null,
|
|
115
134
|
submitSelector: submitName ? `button[name="${submitName}"]` : 'button[type="submit"]',
|
|
116
135
|
};
|
|
136
|
+
if (debugAuth()) {
|
|
137
|
+
progress?.debug(`detect_auth resolved selectors username=${observedSelectors.usernameSelector ?? 'null'} password=${observedSelectors.passwordSelector ?? 'null'} submit=${observedSelectors.submitSelector}`);
|
|
138
|
+
}
|
|
117
139
|
recommendation = `Form login detected. Configure auth with type="form-login", credentials, and the selectors above. Test selectors in your browser dev tools to confirm.`;
|
|
118
140
|
}
|
|
119
141
|
else if (hasMagicLink) {
|
|
@@ -128,6 +150,9 @@ export async function detectAuth(url, timeoutMs = 15000) {
|
|
|
128
150
|
type = 'none';
|
|
129
151
|
recommendation = `No authentication required for the entry URL. Qulib can scan anonymously.`;
|
|
130
152
|
}
|
|
153
|
+
const providerList = oauthButtons.length > 0 ? oauthButtons.map((b) => b.provider).join(', ') : provider ?? 'none';
|
|
154
|
+
const automatable = type === 'form-login';
|
|
155
|
+
progress?.info(`Auth detected: ${type} (${providerList}) automatable=${automatable}`);
|
|
131
156
|
return {
|
|
132
157
|
hasAuth: type !== 'none',
|
|
133
158
|
type,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type AuthExploration } from '../schemas/config.schema.js';
|
|
2
|
+
import type { AnalyzeProgressSink } from '../harness/progress-log.js';
|
|
3
|
+
export declare function exploreAuth(url: string, timeoutMs?: number, progress?: AnalyzeProgressSink): Promise<AuthExploration>;
|
|
4
|
+
//# sourceMappingURL=auth-explorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-explorer.d.ts","sourceRoot":"","sources":["../../src/tools/auth-explorer.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAiNtE,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,SAAS,SAAQ,EACjB,QAAQ,CAAC,EAAE,mBAAmB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAgL1B"}
|