@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.
Files changed (87) hide show
  1. package/README.md +45 -3
  2. package/dist/analyze.d.ts +16 -4
  3. package/dist/analyze.d.ts.map +1 -1
  4. package/dist/analyze.js +98 -38
  5. package/dist/cli/cost-doctor.d.ts +2 -0
  6. package/dist/cli/cost-doctor.d.ts.map +1 -0
  7. package/dist/cli/cost-doctor.js +72 -0
  8. package/dist/cli/index.js +61 -0
  9. package/dist/harness/progress-log.d.ts +7 -0
  10. package/dist/harness/progress-log.d.ts.map +1 -0
  11. package/dist/harness/progress-log.js +1 -0
  12. package/dist/harness/run-options.d.ts +2 -0
  13. package/dist/harness/run-options.d.ts.map +1 -1
  14. package/dist/index.d.ts +6 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -0
  17. package/dist/llm/content-hash.d.ts +2 -0
  18. package/dist/llm/content-hash.d.ts.map +1 -0
  19. package/dist/llm/content-hash.js +4 -0
  20. package/dist/llm/context-builder.js +1 -1
  21. package/dist/llm/cost-intelligence.d.ts +29 -0
  22. package/dist/llm/cost-intelligence.d.ts.map +1 -0
  23. package/dist/llm/cost-intelligence.js +153 -0
  24. package/dist/llm/provider.d.ts +11 -1
  25. package/dist/llm/provider.d.ts.map +1 -1
  26. package/dist/llm/provider.js +43 -4
  27. package/dist/phases/act.d.ts.map +1 -1
  28. package/dist/phases/act.js +4 -1
  29. package/dist/phases/observe.js +1 -1
  30. package/dist/phases/think-finalize.d.ts +6 -0
  31. package/dist/phases/think-finalize.d.ts.map +1 -0
  32. package/dist/phases/think-finalize.js +164 -0
  33. package/dist/phases/think.d.ts +2 -0
  34. package/dist/phases/think.d.ts.map +1 -1
  35. package/dist/phases/think.js +16 -65
  36. package/dist/reporters/markdown-reporter.d.ts.map +1 -1
  37. package/dist/reporters/markdown-reporter.js +23 -3
  38. package/dist/schemas/config.schema.d.ts +364 -0
  39. package/dist/schemas/config.schema.d.ts.map +1 -1
  40. package/dist/schemas/config.schema.js +55 -1
  41. package/dist/schemas/cost-intelligence.schema.d.ts +229 -0
  42. package/dist/schemas/cost-intelligence.schema.d.ts.map +1 -0
  43. package/dist/schemas/cost-intelligence.schema.js +41 -0
  44. package/dist/schemas/decision-log.schema.d.ts +2 -2
  45. package/dist/schemas/gap-analysis.schema.d.ts +288 -49
  46. package/dist/schemas/gap-analysis.schema.d.ts.map +1 -1
  47. package/dist/schemas/gap-analysis.schema.js +7 -3
  48. package/dist/schemas/index.d.ts +3 -1
  49. package/dist/schemas/index.d.ts.map +1 -1
  50. package/dist/schemas/index.js +3 -1
  51. package/dist/schemas/public-surface.schema.d.ts +268 -0
  52. package/dist/schemas/public-surface.schema.d.ts.map +1 -0
  53. package/dist/schemas/public-surface.schema.js +15 -0
  54. package/dist/schemas/repo-analysis.schema.d.ts +6 -6
  55. package/dist/tools/auth-block-gap.d.ts +3 -0
  56. package/dist/tools/auth-block-gap.d.ts.map +1 -0
  57. package/dist/tools/auth-block-gap.js +19 -0
  58. package/dist/tools/auth-detector.d.ts +2 -1
  59. package/dist/tools/auth-detector.d.ts.map +1 -1
  60. package/dist/tools/auth-detector.js +28 -3
  61. package/dist/tools/auth-explorer.d.ts +4 -0
  62. package/dist/tools/auth-explorer.d.ts.map +1 -0
  63. package/dist/tools/auth-explorer.js +346 -0
  64. package/dist/tools/auth-surface-analyzer.d.ts +4 -0
  65. package/dist/tools/auth-surface-analyzer.d.ts.map +1 -0
  66. package/dist/tools/auth-surface-analyzer.js +154 -0
  67. package/dist/tools/cypress-explorer.d.ts +2 -1
  68. package/dist/tools/cypress-explorer.d.ts.map +1 -1
  69. package/dist/tools/cypress-explorer.js +1 -1
  70. package/dist/tools/explorer.interface.d.ts +2 -1
  71. package/dist/tools/explorer.interface.d.ts.map +1 -1
  72. package/dist/tools/gap-engine.d.ts +3 -1
  73. package/dist/tools/gap-engine.d.ts.map +1 -1
  74. package/dist/tools/gap-engine.js +39 -12
  75. package/dist/tools/oauth-providers.d.ts +7 -0
  76. package/dist/tools/oauth-providers.d.ts.map +1 -0
  77. package/dist/tools/oauth-providers.js +21 -0
  78. package/dist/tools/playwright-explorer.d.ts +2 -1
  79. package/dist/tools/playwright-explorer.d.ts.map +1 -1
  80. package/dist/tools/playwright-explorer.js +21 -3
  81. package/dist/tools/public-surface.d.ts +5 -0
  82. package/dist/tools/public-surface.d.ts.map +1 -0
  83. package/dist/tools/public-surface.js +13 -0
  84. package/dist/tools/user-providers.d.ts +15 -0
  85. package/dist/tools/user-providers.d.ts.map +1 -0
  86. package/dist/tools/user-providers.js +62 -0
  87. 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,GAClB,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,kBAAkB,EAClB,KAAK,YAAY,GAClB,MAAM,2BAA2B,CAAC"}
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"}
@@ -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,3 @@
1
+ import type { Gap } from '../schemas/gap-analysis.schema.js';
2
+ export declare function buildAuthBlockGap(url: string): Gap;
3
+ //# sourceMappingURL=auth-block-gap.d.ts.map
@@ -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
- export declare function detectAuth(url: string, timeoutMs?: number): Promise<DetectedAuth>;
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;AA4DhE,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAkGtF"}
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
- export async function detectAuth(url, timeoutMs = 15000) {
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
- if ((await loginLink.count()) > 0) {
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
- if (patterns.some((p) => p.test(trimmed))) {
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"}