@prave/shared 1.4.16 → 1.5.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/dist/schemas/hook.schema.d.ts +246 -0
- package/dist/schemas/hook.schema.d.ts.map +1 -0
- package/dist/schemas/hook.schema.js +129 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/install.schema.d.ts +1 -0
- package/dist/schemas/install.schema.d.ts.map +1 -1
- package/dist/schemas/search.schema.d.ts +3 -0
- package/dist/schemas/search.schema.d.ts.map +1 -1
- package/dist/schemas/security-audit.schema.d.ts +231 -0
- package/dist/schemas/security-audit.schema.d.ts.map +1 -0
- package/dist/schemas/security-audit.schema.js +76 -0
- package/dist/schemas/skill-dependency.schema.d.ts +1 -0
- package/dist/schemas/skill-dependency.schema.d.ts.map +1 -1
- package/dist/schemas/skill.schema.d.ts +10 -0
- package/dist/schemas/skill.schema.d.ts.map +1 -1
- package/dist/schemas/skill.schema.js +11 -0
- package/package.json +1 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Hook registry shape — the parallel-to-Skills primitive.
|
|
4
|
+
*
|
|
5
|
+
* V1 is **scraper-only**: rows arrive from the worker's
|
|
6
|
+
* scan-github-hook job. The web UI does not author hooks; the
|
|
7
|
+
* "Suggest a hook" modal calls `POST /api/v1/hooks/submit` with a
|
|
8
|
+
* GitHub URL, which enqueues a scan job. End-users never POST/PUT/
|
|
9
|
+
* DELETE the hook content itself.
|
|
10
|
+
*/
|
|
11
|
+
export declare const hookEventSchema: z.ZodEnum<["PreToolUse", "PostToolUse", "UserPromptSubmit", "Stop", "SubagentStop", "Notification", "PreCompact", "SessionStart"]>;
|
|
12
|
+
export type HookEvent = z.infer<typeof hookEventSchema>;
|
|
13
|
+
export declare const hookVisibilitySchema: z.ZodEnum<["public", "private"]>;
|
|
14
|
+
export type HookVisibility = z.infer<typeof hookVisibilitySchema>;
|
|
15
|
+
export declare const hookSchema: z.ZodObject<{
|
|
16
|
+
id: z.ZodString;
|
|
17
|
+
owner_id: z.ZodNullable<z.ZodString>;
|
|
18
|
+
name: z.ZodString;
|
|
19
|
+
slug: z.ZodString;
|
|
20
|
+
description: z.ZodNullable<z.ZodString>;
|
|
21
|
+
/** Claude Code lifecycle event the hook listens on. */
|
|
22
|
+
event: z.ZodEnum<["PreToolUse", "PostToolUse", "UserPromptSubmit", "Stop", "SubagentStop", "Notification", "PreCompact", "SessionStart"]>;
|
|
23
|
+
/**
|
|
24
|
+
* Tool-name glob — only relevant on the tool-events
|
|
25
|
+
* (`Pre/PostToolUse`). `null` means "any tool" and Claude Code
|
|
26
|
+
* treats it as the universal matcher.
|
|
27
|
+
*/
|
|
28
|
+
matcher: z.ZodNullable<z.ZodString>;
|
|
29
|
+
/** Shell command Claude Code spawns when the event fires. */
|
|
30
|
+
command: z.ZodString;
|
|
31
|
+
/** Optional per-hook timeout in seconds (1–600). */
|
|
32
|
+
timeout_seconds: z.ZodNullable<z.ZodNumber>;
|
|
33
|
+
visibility: z.ZodDefault<z.ZodEnum<["public", "private"]>>;
|
|
34
|
+
source_repo: z.ZodNullable<z.ZodString>;
|
|
35
|
+
license: z.ZodDefault<z.ZodString>;
|
|
36
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
37
|
+
install_count: z.ZodDefault<z.ZodNumber>;
|
|
38
|
+
is_verified: z.ZodDefault<z.ZodBoolean>;
|
|
39
|
+
version: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
/** Same enum as Feature 1's security_rating; opt-in for hooks. */
|
|
41
|
+
security_rating: z.ZodOptional<z.ZodNullable<z.ZodEnum<["trusted", "low_risk", "med_risk", "critical", "pending"]>>>;
|
|
42
|
+
/** Attached by the API on GET when authenticated. */
|
|
43
|
+
bookmarked: z.ZodOptional<z.ZodBoolean>;
|
|
44
|
+
/** Attached by the API on GET when authenticated. */
|
|
45
|
+
installed: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
/** Attached by the API: public slice of the owner profile. */
|
|
47
|
+
owner: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
48
|
+
id: z.ZodString;
|
|
49
|
+
username: z.ZodNullable<z.ZodString>;
|
|
50
|
+
display_name: z.ZodNullable<z.ZodString>;
|
|
51
|
+
avatar_url: z.ZodNullable<z.ZodString>;
|
|
52
|
+
is_creator: z.ZodBoolean;
|
|
53
|
+
is_partner: z.ZodBoolean;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
id: string;
|
|
56
|
+
username: string | null;
|
|
57
|
+
display_name: string | null;
|
|
58
|
+
avatar_url: string | null;
|
|
59
|
+
is_creator: boolean;
|
|
60
|
+
is_partner: boolean;
|
|
61
|
+
}, {
|
|
62
|
+
id: string;
|
|
63
|
+
username: string | null;
|
|
64
|
+
display_name: string | null;
|
|
65
|
+
avatar_url: string | null;
|
|
66
|
+
is_creator: boolean;
|
|
67
|
+
is_partner: boolean;
|
|
68
|
+
}>>>;
|
|
69
|
+
created_at: z.ZodString;
|
|
70
|
+
updated_at: z.ZodString;
|
|
71
|
+
}, "strip", z.ZodTypeAny, {
|
|
72
|
+
id: string;
|
|
73
|
+
created_at: string;
|
|
74
|
+
updated_at: string;
|
|
75
|
+
slug: string;
|
|
76
|
+
name: string;
|
|
77
|
+
description: string | null;
|
|
78
|
+
install_count: number;
|
|
79
|
+
owner_id: string | null;
|
|
80
|
+
visibility: "public" | "private";
|
|
81
|
+
source_repo: string | null;
|
|
82
|
+
license: string;
|
|
83
|
+
tags: string[];
|
|
84
|
+
is_verified: boolean;
|
|
85
|
+
version: number;
|
|
86
|
+
event: "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification" | "PreCompact" | "SessionStart";
|
|
87
|
+
matcher: string | null;
|
|
88
|
+
command: string;
|
|
89
|
+
timeout_seconds: number | null;
|
|
90
|
+
bookmarked?: boolean | undefined;
|
|
91
|
+
owner?: {
|
|
92
|
+
id: string;
|
|
93
|
+
username: string | null;
|
|
94
|
+
display_name: string | null;
|
|
95
|
+
avatar_url: string | null;
|
|
96
|
+
is_creator: boolean;
|
|
97
|
+
is_partner: boolean;
|
|
98
|
+
} | null | undefined;
|
|
99
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
100
|
+
installed?: boolean | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
id: string;
|
|
103
|
+
created_at: string;
|
|
104
|
+
updated_at: string;
|
|
105
|
+
slug: string;
|
|
106
|
+
name: string;
|
|
107
|
+
description: string | null;
|
|
108
|
+
owner_id: string | null;
|
|
109
|
+
source_repo: string | null;
|
|
110
|
+
event: "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification" | "PreCompact" | "SessionStart";
|
|
111
|
+
matcher: string | null;
|
|
112
|
+
command: string;
|
|
113
|
+
timeout_seconds: number | null;
|
|
114
|
+
install_count?: number | undefined;
|
|
115
|
+
visibility?: "public" | "private" | undefined;
|
|
116
|
+
license?: string | undefined;
|
|
117
|
+
tags?: string[] | undefined;
|
|
118
|
+
is_verified?: boolean | undefined;
|
|
119
|
+
bookmarked?: boolean | undefined;
|
|
120
|
+
owner?: {
|
|
121
|
+
id: string;
|
|
122
|
+
username: string | null;
|
|
123
|
+
display_name: string | null;
|
|
124
|
+
avatar_url: string | null;
|
|
125
|
+
is_creator: boolean;
|
|
126
|
+
is_partner: boolean;
|
|
127
|
+
} | null | undefined;
|
|
128
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
129
|
+
version?: number | undefined;
|
|
130
|
+
installed?: boolean | undefined;
|
|
131
|
+
}>;
|
|
132
|
+
export type Hook = z.infer<typeof hookSchema>;
|
|
133
|
+
export declare const hookSortSchema: z.ZodEnum<["trending", "popular", "newest", "relevance"]>;
|
|
134
|
+
export type HookSort = z.infer<typeof hookSortSchema>;
|
|
135
|
+
export declare const hookSearchQuerySchema: z.ZodObject<{
|
|
136
|
+
q: z.ZodOptional<z.ZodString>;
|
|
137
|
+
event: z.ZodOptional<z.ZodEnum<["PreToolUse", "PostToolUse", "UserPromptSubmit", "Stop", "SubagentStop", "Notification", "PreCompact", "SessionStart"]>>;
|
|
138
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
139
|
+
sort: z.ZodDefault<z.ZodEnum<["trending", "popular", "newest", "relevance"]>>;
|
|
140
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
141
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
142
|
+
}, "strip", z.ZodTypeAny, {
|
|
143
|
+
sort: "trending" | "popular" | "newest" | "relevance";
|
|
144
|
+
limit: number;
|
|
145
|
+
offset: number;
|
|
146
|
+
q?: string | undefined;
|
|
147
|
+
tag?: string | undefined;
|
|
148
|
+
event?: "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification" | "PreCompact" | "SessionStart" | undefined;
|
|
149
|
+
}, {
|
|
150
|
+
sort?: "trending" | "popular" | "newest" | "relevance" | undefined;
|
|
151
|
+
q?: string | undefined;
|
|
152
|
+
tag?: string | undefined;
|
|
153
|
+
limit?: number | undefined;
|
|
154
|
+
offset?: number | undefined;
|
|
155
|
+
event?: "PreToolUse" | "PostToolUse" | "UserPromptSubmit" | "Stop" | "SubagentStop" | "Notification" | "PreCompact" | "SessionStart" | undefined;
|
|
156
|
+
}>;
|
|
157
|
+
export type HookSearchQuery = z.infer<typeof hookSearchQuerySchema>;
|
|
158
|
+
/**
|
|
159
|
+
* `POST /api/v1/hooks/submit` body — a user proposes a GitHub URL,
|
|
160
|
+
* the worker scans it. The endpoint dedupes pending scans by repo URL
|
|
161
|
+
* so spamming the form is harmless.
|
|
162
|
+
*/
|
|
163
|
+
export declare const submitHookByUrlSchema: z.ZodObject<{
|
|
164
|
+
repo_url: z.ZodEffects<z.ZodString, string, string>;
|
|
165
|
+
}, "strip", z.ZodTypeAny, {
|
|
166
|
+
repo_url: string;
|
|
167
|
+
}, {
|
|
168
|
+
repo_url: string;
|
|
169
|
+
}>;
|
|
170
|
+
export type SubmitHookByUrlInput = z.infer<typeof submitHookByUrlSchema>;
|
|
171
|
+
/**
|
|
172
|
+
* `github-hook-scan` queue payload. Scans one GitHub repo for
|
|
173
|
+
* `hook.json` files + sibling `claude/hooks/*.json`, validates them
|
|
174
|
+
* against `hookSchema`, secret-scans the command, upserts.
|
|
175
|
+
*/
|
|
176
|
+
export declare const scanGithubHookJobSchema: z.ZodObject<{
|
|
177
|
+
repo_url: z.ZodString;
|
|
178
|
+
source: z.ZodEnum<["manual", "seed", "cron", "submit"]>;
|
|
179
|
+
submitted_by: z.ZodOptional<z.ZodString>;
|
|
180
|
+
}, "strip", z.ZodTypeAny, {
|
|
181
|
+
repo_url: string;
|
|
182
|
+
source: "seed" | "manual" | "cron" | "submit";
|
|
183
|
+
submitted_by?: string | undefined;
|
|
184
|
+
}, {
|
|
185
|
+
repo_url: string;
|
|
186
|
+
source: "seed" | "manual" | "cron" | "submit";
|
|
187
|
+
submitted_by?: string | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
export type ScanGithubHookJob = z.infer<typeof scanGithubHookJobSchema>;
|
|
190
|
+
/**
|
|
191
|
+
* `discover-github-hook` queue payload. Wide-scope GitHub code-search
|
|
192
|
+
* to find any public repo with a `hook.json` we don't already know.
|
|
193
|
+
*/
|
|
194
|
+
export declare const discoverGithubHookJobSchema: z.ZodObject<{
|
|
195
|
+
query: z.ZodString;
|
|
196
|
+
max_repos: z.ZodDefault<z.ZodNumber>;
|
|
197
|
+
}, "strip", z.ZodTypeAny, {
|
|
198
|
+
max_repos: number;
|
|
199
|
+
query: string;
|
|
200
|
+
}, {
|
|
201
|
+
query: string;
|
|
202
|
+
max_repos?: number | undefined;
|
|
203
|
+
}>;
|
|
204
|
+
export type DiscoverGithubHookJob = z.infer<typeof discoverGithubHookJobSchema>;
|
|
205
|
+
/** `index-hook` queue payload. */
|
|
206
|
+
export declare const indexHookJobSchema: z.ZodObject<{
|
|
207
|
+
hook_id: z.ZodString;
|
|
208
|
+
op: z.ZodEnum<["upsert", "delete"]>;
|
|
209
|
+
}, "strip", z.ZodTypeAny, {
|
|
210
|
+
op: "upsert" | "delete";
|
|
211
|
+
hook_id: string;
|
|
212
|
+
}, {
|
|
213
|
+
op: "upsert" | "delete";
|
|
214
|
+
hook_id: string;
|
|
215
|
+
}>;
|
|
216
|
+
export type IndexHookJob = z.infer<typeof indexHookJobSchema>;
|
|
217
|
+
/** `describe-hook` queue payload — Haiku-generated description. */
|
|
218
|
+
export declare const describeHookJobSchema: z.ZodObject<{
|
|
219
|
+
hook_id: z.ZodString;
|
|
220
|
+
force: z.ZodOptional<z.ZodBoolean>;
|
|
221
|
+
}, "strip", z.ZodTypeAny, {
|
|
222
|
+
hook_id: string;
|
|
223
|
+
force?: boolean | undefined;
|
|
224
|
+
}, {
|
|
225
|
+
hook_id: string;
|
|
226
|
+
force?: boolean | undefined;
|
|
227
|
+
}>;
|
|
228
|
+
export type DescribeHookJob = z.infer<typeof describeHookJobSchema>;
|
|
229
|
+
export declare const hookBulkSyncInputSchema: z.ZodObject<{
|
|
230
|
+
slugs: z.ZodArray<z.ZodString, "many">;
|
|
231
|
+
}, "strip", z.ZodTypeAny, {
|
|
232
|
+
slugs: string[];
|
|
233
|
+
}, {
|
|
234
|
+
slugs: string[];
|
|
235
|
+
}>;
|
|
236
|
+
export type HookBulkSyncInput = z.infer<typeof hookBulkSyncInputSchema>;
|
|
237
|
+
export interface HookBulkSyncItem {
|
|
238
|
+
slug: string;
|
|
239
|
+
hook: Hook | null;
|
|
240
|
+
error: string | null;
|
|
241
|
+
}
|
|
242
|
+
export interface HookBulkSyncResponse {
|
|
243
|
+
items: HookBulkSyncItem[];
|
|
244
|
+
missing: string[];
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=hook.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/hook.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;GAQG;AAEH,eAAO,MAAM,eAAe,oIAS1B,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEvD,eAAO,MAAM,oBAAoB,kCAAgC,CAAA;AACjE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE,eAAO,MAAM,UAAU;;;;;;IAWrB,uDAAuD;;IAEvD;;;;OAIG;;IAEH,6DAA6D;;IAE7D,oDAAoD;;;;;;;;;IAWpD,kEAAkE;;IAMlE,qDAAqD;;IAErD,qDAAqD;;IAErD,8DAA8D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAe9D,CAAA;AACF,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AAI7C,eAAO,MAAM,cAAc,2DAAyD,CAAA;AACpF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAErD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;EAOhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAInE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;EAQhC,CAAA;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAIxE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;EAIlC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAEvE;;;GAGG;AACH,eAAO,MAAM,2BAA2B;;;;;;;;;EAGtC,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAE/E,kCAAkC;AAClC,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,mEAAmE;AACnE,eAAO,MAAM,qBAAqB;;;;;;;;;EAGhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAInE,eAAO,MAAM,uBAAuB;;;;;;EAElC,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code Hook registry shape — the parallel-to-Skills primitive.
|
|
4
|
+
*
|
|
5
|
+
* V1 is **scraper-only**: rows arrive from the worker's
|
|
6
|
+
* scan-github-hook job. The web UI does not author hooks; the
|
|
7
|
+
* "Suggest a hook" modal calls `POST /api/v1/hooks/submit` with a
|
|
8
|
+
* GitHub URL, which enqueues a scan job. End-users never POST/PUT/
|
|
9
|
+
* DELETE the hook content itself.
|
|
10
|
+
*/
|
|
11
|
+
export const hookEventSchema = z.enum([
|
|
12
|
+
'PreToolUse',
|
|
13
|
+
'PostToolUse',
|
|
14
|
+
'UserPromptSubmit',
|
|
15
|
+
'Stop',
|
|
16
|
+
'SubagentStop',
|
|
17
|
+
'Notification',
|
|
18
|
+
'PreCompact',
|
|
19
|
+
'SessionStart',
|
|
20
|
+
]);
|
|
21
|
+
export const hookVisibilitySchema = z.enum(['public', 'private']);
|
|
22
|
+
export const hookSchema = z.object({
|
|
23
|
+
id: z.string().uuid(),
|
|
24
|
+
owner_id: z.string().uuid().nullable(),
|
|
25
|
+
name: z.string().min(1).max(120),
|
|
26
|
+
slug: z
|
|
27
|
+
.string()
|
|
28
|
+
.min(1)
|
|
29
|
+
.max(120)
|
|
30
|
+
.regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, 'slug must be kebab-case'),
|
|
31
|
+
description: z.string().max(500).nullable(),
|
|
32
|
+
/** Claude Code lifecycle event the hook listens on. */
|
|
33
|
+
event: hookEventSchema,
|
|
34
|
+
/**
|
|
35
|
+
* Tool-name glob — only relevant on the tool-events
|
|
36
|
+
* (`Pre/PostToolUse`). `null` means "any tool" and Claude Code
|
|
37
|
+
* treats it as the universal matcher.
|
|
38
|
+
*/
|
|
39
|
+
matcher: z.string().max(120).nullable(),
|
|
40
|
+
/** Shell command Claude Code spawns when the event fires. */
|
|
41
|
+
command: z.string().min(1).max(4000),
|
|
42
|
+
/** Optional per-hook timeout in seconds (1–600). */
|
|
43
|
+
timeout_seconds: z.number().int().min(1).max(600).nullable(),
|
|
44
|
+
visibility: hookVisibilitySchema.default('public'),
|
|
45
|
+
source_repo: z.string().url().nullable(),
|
|
46
|
+
license: z.string().default('MIT'),
|
|
47
|
+
tags: z.array(z.string()).default([]),
|
|
48
|
+
install_count: z.number().int().nonnegative().default(0),
|
|
49
|
+
is_verified: z.boolean().default(false),
|
|
50
|
+
version: z.number().int().positive().default(1),
|
|
51
|
+
/** Same enum as Feature 1's security_rating; opt-in for hooks. */
|
|
52
|
+
security_rating: z
|
|
53
|
+
.enum(['trusted', 'low_risk', 'med_risk', 'critical', 'pending'])
|
|
54
|
+
.nullable()
|
|
55
|
+
.optional(),
|
|
56
|
+
/** Attached by the API on GET when authenticated. */
|
|
57
|
+
bookmarked: z.boolean().optional(),
|
|
58
|
+
/** Attached by the API on GET when authenticated. */
|
|
59
|
+
installed: z.boolean().optional(),
|
|
60
|
+
/** Attached by the API: public slice of the owner profile. */
|
|
61
|
+
owner: z
|
|
62
|
+
.object({
|
|
63
|
+
id: z.string().uuid(),
|
|
64
|
+
username: z.string().nullable(),
|
|
65
|
+
display_name: z.string().nullable(),
|
|
66
|
+
avatar_url: z.string().nullable(),
|
|
67
|
+
is_creator: z.boolean(),
|
|
68
|
+
is_partner: z.boolean(),
|
|
69
|
+
})
|
|
70
|
+
.nullable()
|
|
71
|
+
.optional(),
|
|
72
|
+
created_at: z.string().datetime(),
|
|
73
|
+
updated_at: z.string().datetime(),
|
|
74
|
+
});
|
|
75
|
+
/* ─── Discovery query ──────────────────────────────────────────── */
|
|
76
|
+
export const hookSortSchema = z.enum(['trending', 'popular', 'newest', 'relevance']);
|
|
77
|
+
export const hookSearchQuerySchema = z.object({
|
|
78
|
+
q: z.string().trim().max(200).optional(),
|
|
79
|
+
event: hookEventSchema.optional(),
|
|
80
|
+
tag: z.string().optional(),
|
|
81
|
+
sort: hookSortSchema.default('trending'),
|
|
82
|
+
limit: z.coerce.number().int().min(1).max(100).default(24),
|
|
83
|
+
offset: z.coerce.number().int().nonnegative().default(0),
|
|
84
|
+
});
|
|
85
|
+
/* ─── Submit-by-URL ────────────────────────────────────────────── */
|
|
86
|
+
/**
|
|
87
|
+
* `POST /api/v1/hooks/submit` body — a user proposes a GitHub URL,
|
|
88
|
+
* the worker scans it. The endpoint dedupes pending scans by repo URL
|
|
89
|
+
* so spamming the form is harmless.
|
|
90
|
+
*/
|
|
91
|
+
export const submitHookByUrlSchema = z.object({
|
|
92
|
+
repo_url: z
|
|
93
|
+
.string()
|
|
94
|
+
.url()
|
|
95
|
+
.refine((s) => /^https?:\/\/(www\.)?github\.com\//i.test(s), 'Only GitHub repository URLs are supported'),
|
|
96
|
+
});
|
|
97
|
+
/* ─── Worker job payloads ──────────────────────────────────────── */
|
|
98
|
+
/**
|
|
99
|
+
* `github-hook-scan` queue payload. Scans one GitHub repo for
|
|
100
|
+
* `hook.json` files + sibling `claude/hooks/*.json`, validates them
|
|
101
|
+
* against `hookSchema`, secret-scans the command, upserts.
|
|
102
|
+
*/
|
|
103
|
+
export const scanGithubHookJobSchema = z.object({
|
|
104
|
+
repo_url: z.string().url(),
|
|
105
|
+
source: z.enum(['manual', 'seed', 'cron', 'submit']),
|
|
106
|
+
submitted_by: z.string().uuid().optional(),
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* `discover-github-hook` queue payload. Wide-scope GitHub code-search
|
|
110
|
+
* to find any public repo with a `hook.json` we don't already know.
|
|
111
|
+
*/
|
|
112
|
+
export const discoverGithubHookJobSchema = z.object({
|
|
113
|
+
query: z.string(),
|
|
114
|
+
max_repos: z.number().int().min(1).max(1000).default(300),
|
|
115
|
+
});
|
|
116
|
+
/** `index-hook` queue payload. */
|
|
117
|
+
export const indexHookJobSchema = z.object({
|
|
118
|
+
hook_id: z.string().uuid(),
|
|
119
|
+
op: z.enum(['upsert', 'delete']),
|
|
120
|
+
});
|
|
121
|
+
/** `describe-hook` queue payload — Haiku-generated description. */
|
|
122
|
+
export const describeHookJobSchema = z.object({
|
|
123
|
+
hook_id: z.string().uuid(),
|
|
124
|
+
force: z.boolean().optional(),
|
|
125
|
+
});
|
|
126
|
+
/* ─── Bulk sync (mirror of skills bulk sync) ───────────────────── */
|
|
127
|
+
export const hookBulkSyncInputSchema = z.object({
|
|
128
|
+
slugs: z.array(z.string().min(1).max(120)).min(1).max(250),
|
|
129
|
+
});
|
package/dist/schemas/index.d.ts
CHANGED
|
@@ -10,4 +10,6 @@ export * from './install.schema.js';
|
|
|
10
10
|
export * from './intelligence.schema.js';
|
|
11
11
|
export * from './api-keys.schema.js';
|
|
12
12
|
export * from './skill-report.schema.js';
|
|
13
|
+
export * from './security-audit.schema.js';
|
|
14
|
+
export * from './hook.schema.js';
|
|
13
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA"}
|
package/dist/schemas/index.js
CHANGED
|
@@ -124,6 +124,7 @@ export declare const installRowSchema: z.ZodObject<{
|
|
|
124
124
|
is_creator: boolean;
|
|
125
125
|
is_partner: boolean;
|
|
126
126
|
}>>>;
|
|
127
|
+
security_rating: z.ZodOptional<z.ZodNullable<z.ZodEnum<["trusted", "low_risk", "med_risk", "critical", "pending"]>>>;
|
|
127
128
|
created_at: z.ZodString;
|
|
128
129
|
updated_at: z.ZodString;
|
|
129
130
|
}, "id" | "updated_at" | "slug" | "name" | "description" | "visibility" | "license">, "strip", z.ZodTypeAny, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/install.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,4DAA4D;AAC5D,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;EAMxB,CAAA;AACF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAEnD,wDAAwD;AACxD,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"install.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/install.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,4DAA4D;AAC5D,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;EAMxB,CAAA;AACF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAEnD,wDAAwD;AACxD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAU3B,iEAAiE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEjE,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,eAAO,MAAM,wBAAwB;IACnC,0EAA0E;;;;;;EAE1E,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA"}
|
|
@@ -99,6 +99,7 @@ export declare const skillSearchHitSchema: z.ZodObject<{
|
|
|
99
99
|
is_creator: boolean;
|
|
100
100
|
is_partner: boolean;
|
|
101
101
|
}>>>;
|
|
102
|
+
security_rating: z.ZodOptional<z.ZodNullable<z.ZodEnum<["trusted", "low_risk", "med_risk", "critical", "pending"]>>>;
|
|
102
103
|
created_at: z.ZodString;
|
|
103
104
|
updated_at: z.ZodString;
|
|
104
105
|
} & {
|
|
@@ -156,6 +157,7 @@ export declare const skillSearchHitSchema: z.ZodObject<{
|
|
|
156
157
|
is_creator: boolean;
|
|
157
158
|
is_partner: boolean;
|
|
158
159
|
} | null | undefined;
|
|
160
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
159
161
|
score?: number | undefined;
|
|
160
162
|
highlight?: Record<string, string[]> | undefined;
|
|
161
163
|
}, {
|
|
@@ -210,6 +212,7 @@ export declare const skillSearchHitSchema: z.ZodObject<{
|
|
|
210
212
|
is_creator: boolean;
|
|
211
213
|
is_partner: boolean;
|
|
212
214
|
} | null | undefined;
|
|
215
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
213
216
|
score?: number | undefined;
|
|
214
217
|
highlight?: Record<string, string[]> | undefined;
|
|
215
218
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/search.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;GAGG;AACH,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"search.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/search.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAG/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE,gDAAgD;AAChD,eAAO,MAAM,mBAAmB;;;;;;;;;EAG9B,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAE/D,gDAAgD;AAChD,eAAO,MAAM,mBAAmB;;;;;;;;;EAG9B,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;IAEjC,iFAAiF;;;;;;;;EAEjF,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB;IAClC,kFAAkF;;IAElF,0EAA0E;;;;;;;;EAE1E,CAAA;AACF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Per-skill security audit shape returned by
|
|
4
|
+
* `GET /api/v1/skills/:slug/security`. Three independent sources
|
|
5
|
+
* (GEN · Socket · Snyk) are aggregated into a single overall_rating
|
|
6
|
+
* using a worst-source-wins rule (see worker `security-audit.job.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Missing API keys for Socket/Snyk surface as `unavailable` rather
|
|
9
|
+
* than crashing the audit — the UI renders them as a hairline-ringed
|
|
10
|
+
* pill labelled "Audit unavailable" without affecting the trusted/
|
|
11
|
+
* critical signal from the sources that did run.
|
|
12
|
+
*
|
|
13
|
+
* GEN always runs (no external dependency); a `trusted` overall_rating
|
|
14
|
+
* still requires gen_status = 'safe' even when both vendors are
|
|
15
|
+
* unavailable.
|
|
16
|
+
*/
|
|
17
|
+
export declare const securityFindingSeveritySchema: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
18
|
+
export type SecurityFindingSeverity = z.infer<typeof securityFindingSeveritySchema>;
|
|
19
|
+
export declare const genFindingSchema: z.ZodObject<{
|
|
20
|
+
pattern: z.ZodString;
|
|
21
|
+
severity: z.ZodEnum<["warning", "danger"]>;
|
|
22
|
+
file: z.ZodString;
|
|
23
|
+
line: z.ZodNumber;
|
|
24
|
+
snippet: z.ZodString;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
pattern: string;
|
|
27
|
+
severity: "warning" | "danger";
|
|
28
|
+
file: string;
|
|
29
|
+
line: number;
|
|
30
|
+
snippet: string;
|
|
31
|
+
}, {
|
|
32
|
+
pattern: string;
|
|
33
|
+
severity: "warning" | "danger";
|
|
34
|
+
file: string;
|
|
35
|
+
line: number;
|
|
36
|
+
snippet: string;
|
|
37
|
+
}>;
|
|
38
|
+
export type GenFinding = z.infer<typeof genFindingSchema>;
|
|
39
|
+
export declare const socketAlertSchema: z.ZodObject<{
|
|
40
|
+
package: z.ZodString;
|
|
41
|
+
version: z.ZodOptional<z.ZodString>;
|
|
42
|
+
type: z.ZodString;
|
|
43
|
+
severity: z.ZodOptional<z.ZodString>;
|
|
44
|
+
description: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
type: string;
|
|
47
|
+
package: string;
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
version?: string | undefined;
|
|
50
|
+
severity?: string | undefined;
|
|
51
|
+
}, {
|
|
52
|
+
type: string;
|
|
53
|
+
package: string;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
version?: string | undefined;
|
|
56
|
+
severity?: string | undefined;
|
|
57
|
+
}>;
|
|
58
|
+
export type SocketAlert = z.infer<typeof socketAlertSchema>;
|
|
59
|
+
export declare const snykVulnSchema: z.ZodObject<{
|
|
60
|
+
package: z.ZodString;
|
|
61
|
+
version: z.ZodOptional<z.ZodString>;
|
|
62
|
+
id: z.ZodString;
|
|
63
|
+
severity: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
64
|
+
title: z.ZodString;
|
|
65
|
+
url: z.ZodOptional<z.ZodString>;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
id: string;
|
|
68
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
69
|
+
package: string;
|
|
70
|
+
title: string;
|
|
71
|
+
url?: string | undefined;
|
|
72
|
+
version?: string | undefined;
|
|
73
|
+
}, {
|
|
74
|
+
id: string;
|
|
75
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
76
|
+
package: string;
|
|
77
|
+
title: string;
|
|
78
|
+
url?: string | undefined;
|
|
79
|
+
version?: string | undefined;
|
|
80
|
+
}>;
|
|
81
|
+
export type SnykVuln = z.infer<typeof snykVulnSchema>;
|
|
82
|
+
export declare const genStatusSchema: z.ZodEnum<["pending", "safe", "warning", "danger", "failed"]>;
|
|
83
|
+
export declare const socketStatusSchema: z.ZodEnum<["pending", "ok", "alerts", "unavailable", "failed"]>;
|
|
84
|
+
export declare const snykStatusSchema: z.ZodEnum<["pending", "ok", "low", "medium", "high", "critical", "unavailable", "failed"]>;
|
|
85
|
+
export declare const overallRatingSchema: z.ZodEnum<["pending", "trusted", "low_risk", "med_risk", "critical"]>;
|
|
86
|
+
export type GenStatus = z.infer<typeof genStatusSchema>;
|
|
87
|
+
export type SocketStatus = z.infer<typeof socketStatusSchema>;
|
|
88
|
+
export type SnykStatus = z.infer<typeof snykStatusSchema>;
|
|
89
|
+
export type OverallRating = z.infer<typeof overallRatingSchema>;
|
|
90
|
+
export declare const skillSecurityAuditSchema: z.ZodObject<{
|
|
91
|
+
skill_id: z.ZodString;
|
|
92
|
+
gen_status: z.ZodEnum<["pending", "safe", "warning", "danger", "failed"]>;
|
|
93
|
+
gen_findings: z.ZodArray<z.ZodObject<{
|
|
94
|
+
pattern: z.ZodString;
|
|
95
|
+
severity: z.ZodEnum<["warning", "danger"]>;
|
|
96
|
+
file: z.ZodString;
|
|
97
|
+
line: z.ZodNumber;
|
|
98
|
+
snippet: z.ZodString;
|
|
99
|
+
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
pattern: string;
|
|
101
|
+
severity: "warning" | "danger";
|
|
102
|
+
file: string;
|
|
103
|
+
line: number;
|
|
104
|
+
snippet: string;
|
|
105
|
+
}, {
|
|
106
|
+
pattern: string;
|
|
107
|
+
severity: "warning" | "danger";
|
|
108
|
+
file: string;
|
|
109
|
+
line: number;
|
|
110
|
+
snippet: string;
|
|
111
|
+
}>, "many">;
|
|
112
|
+
socket_status: z.ZodEnum<["pending", "ok", "alerts", "unavailable", "failed"]>;
|
|
113
|
+
socket_alerts: z.ZodArray<z.ZodObject<{
|
|
114
|
+
package: z.ZodString;
|
|
115
|
+
version: z.ZodOptional<z.ZodString>;
|
|
116
|
+
type: z.ZodString;
|
|
117
|
+
severity: z.ZodOptional<z.ZodString>;
|
|
118
|
+
description: z.ZodOptional<z.ZodString>;
|
|
119
|
+
}, "strip", z.ZodTypeAny, {
|
|
120
|
+
type: string;
|
|
121
|
+
package: string;
|
|
122
|
+
description?: string | undefined;
|
|
123
|
+
version?: string | undefined;
|
|
124
|
+
severity?: string | undefined;
|
|
125
|
+
}, {
|
|
126
|
+
type: string;
|
|
127
|
+
package: string;
|
|
128
|
+
description?: string | undefined;
|
|
129
|
+
version?: string | undefined;
|
|
130
|
+
severity?: string | undefined;
|
|
131
|
+
}>, "many">;
|
|
132
|
+
snyk_status: z.ZodEnum<["pending", "ok", "low", "medium", "high", "critical", "unavailable", "failed"]>;
|
|
133
|
+
snyk_vulns: z.ZodArray<z.ZodObject<{
|
|
134
|
+
package: z.ZodString;
|
|
135
|
+
version: z.ZodOptional<z.ZodString>;
|
|
136
|
+
id: z.ZodString;
|
|
137
|
+
severity: z.ZodEnum<["low", "medium", "high", "critical"]>;
|
|
138
|
+
title: z.ZodString;
|
|
139
|
+
url: z.ZodOptional<z.ZodString>;
|
|
140
|
+
}, "strip", z.ZodTypeAny, {
|
|
141
|
+
id: string;
|
|
142
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
143
|
+
package: string;
|
|
144
|
+
title: string;
|
|
145
|
+
url?: string | undefined;
|
|
146
|
+
version?: string | undefined;
|
|
147
|
+
}, {
|
|
148
|
+
id: string;
|
|
149
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
150
|
+
package: string;
|
|
151
|
+
title: string;
|
|
152
|
+
url?: string | undefined;
|
|
153
|
+
version?: string | undefined;
|
|
154
|
+
}>, "many">;
|
|
155
|
+
overall_rating: z.ZodEnum<["pending", "trusted", "low_risk", "med_risk", "critical"]>;
|
|
156
|
+
audited_at: z.ZodNullable<z.ZodString>;
|
|
157
|
+
updated_at: z.ZodString;
|
|
158
|
+
}, "strip", z.ZodTypeAny, {
|
|
159
|
+
skill_id: string;
|
|
160
|
+
updated_at: string;
|
|
161
|
+
gen_status: "pending" | "failed" | "warning" | "danger" | "safe";
|
|
162
|
+
gen_findings: {
|
|
163
|
+
pattern: string;
|
|
164
|
+
severity: "warning" | "danger";
|
|
165
|
+
file: string;
|
|
166
|
+
line: number;
|
|
167
|
+
snippet: string;
|
|
168
|
+
}[];
|
|
169
|
+
socket_status: "pending" | "failed" | "ok" | "alerts" | "unavailable";
|
|
170
|
+
socket_alerts: {
|
|
171
|
+
type: string;
|
|
172
|
+
package: string;
|
|
173
|
+
description?: string | undefined;
|
|
174
|
+
version?: string | undefined;
|
|
175
|
+
severity?: string | undefined;
|
|
176
|
+
}[];
|
|
177
|
+
snyk_status: "critical" | "pending" | "failed" | "medium" | "low" | "high" | "ok" | "unavailable";
|
|
178
|
+
snyk_vulns: {
|
|
179
|
+
id: string;
|
|
180
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
181
|
+
package: string;
|
|
182
|
+
title: string;
|
|
183
|
+
url?: string | undefined;
|
|
184
|
+
version?: string | undefined;
|
|
185
|
+
}[];
|
|
186
|
+
overall_rating: "trusted" | "low_risk" | "med_risk" | "critical" | "pending";
|
|
187
|
+
audited_at: string | null;
|
|
188
|
+
}, {
|
|
189
|
+
skill_id: string;
|
|
190
|
+
updated_at: string;
|
|
191
|
+
gen_status: "pending" | "failed" | "warning" | "danger" | "safe";
|
|
192
|
+
gen_findings: {
|
|
193
|
+
pattern: string;
|
|
194
|
+
severity: "warning" | "danger";
|
|
195
|
+
file: string;
|
|
196
|
+
line: number;
|
|
197
|
+
snippet: string;
|
|
198
|
+
}[];
|
|
199
|
+
socket_status: "pending" | "failed" | "ok" | "alerts" | "unavailable";
|
|
200
|
+
socket_alerts: {
|
|
201
|
+
type: string;
|
|
202
|
+
package: string;
|
|
203
|
+
description?: string | undefined;
|
|
204
|
+
version?: string | undefined;
|
|
205
|
+
severity?: string | undefined;
|
|
206
|
+
}[];
|
|
207
|
+
snyk_status: "critical" | "pending" | "failed" | "medium" | "low" | "high" | "ok" | "unavailable";
|
|
208
|
+
snyk_vulns: {
|
|
209
|
+
id: string;
|
|
210
|
+
severity: "critical" | "medium" | "low" | "high";
|
|
211
|
+
package: string;
|
|
212
|
+
title: string;
|
|
213
|
+
url?: string | undefined;
|
|
214
|
+
version?: string | undefined;
|
|
215
|
+
}[];
|
|
216
|
+
overall_rating: "trusted" | "low_risk" | "med_risk" | "critical" | "pending";
|
|
217
|
+
audited_at: string | null;
|
|
218
|
+
}>;
|
|
219
|
+
export type SkillSecurityAudit = z.infer<typeof skillSecurityAuditSchema>;
|
|
220
|
+
/**
|
|
221
|
+
* BullMQ job payload for the worker's `security-audit` queue.
|
|
222
|
+
* Enqueued from three places:
|
|
223
|
+
* • the Postgres trigger (via the outbox-style pending row)
|
|
224
|
+
* • scan-github-repo, immediately after a skill upsert
|
|
225
|
+
* • the API's manual `POST /skills/:slug/security/rescan`
|
|
226
|
+
*/
|
|
227
|
+
export interface SecurityAuditJob {
|
|
228
|
+
skill_id: string;
|
|
229
|
+
trigger?: 'scan' | 'trigger' | 'rescan' | 'backfill' | 'cron';
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=security-audit.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-audit.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/security-audit.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,6BAA6B,kDAAgD,CAAA;AAC1F,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAA;AAEnF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAM3B,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEzD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAM5B,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;EAOzB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAErD,eAAO,MAAM,eAAe,+DAA6D,CAAA;AACzF,eAAO,MAAM,kBAAkB,iEAM7B,CAAA;AACF,eAAO,MAAM,gBAAgB,4FAS3B,CAAA;AACF,eAAO,MAAM,mBAAmB,uEAM9B,CAAA;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AACvD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAC7D,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACzD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAE/D,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWnC,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAEzE;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAA;CAC9D"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Per-skill security audit shape returned by
|
|
4
|
+
* `GET /api/v1/skills/:slug/security`. Three independent sources
|
|
5
|
+
* (GEN · Socket · Snyk) are aggregated into a single overall_rating
|
|
6
|
+
* using a worst-source-wins rule (see worker `security-audit.job.ts`).
|
|
7
|
+
*
|
|
8
|
+
* Missing API keys for Socket/Snyk surface as `unavailable` rather
|
|
9
|
+
* than crashing the audit — the UI renders them as a hairline-ringed
|
|
10
|
+
* pill labelled "Audit unavailable" without affecting the trusted/
|
|
11
|
+
* critical signal from the sources that did run.
|
|
12
|
+
*
|
|
13
|
+
* GEN always runs (no external dependency); a `trusted` overall_rating
|
|
14
|
+
* still requires gen_status = 'safe' even when both vendors are
|
|
15
|
+
* unavailable.
|
|
16
|
+
*/
|
|
17
|
+
export const securityFindingSeveritySchema = z.enum(['low', 'medium', 'high', 'critical']);
|
|
18
|
+
export const genFindingSchema = z.object({
|
|
19
|
+
pattern: z.string(),
|
|
20
|
+
severity: z.enum(['warning', 'danger']),
|
|
21
|
+
file: z.string(),
|
|
22
|
+
line: z.number().int().nonnegative(),
|
|
23
|
+
snippet: z.string().max(240),
|
|
24
|
+
});
|
|
25
|
+
export const socketAlertSchema = z.object({
|
|
26
|
+
package: z.string(),
|
|
27
|
+
version: z.string().optional(),
|
|
28
|
+
type: z.string(),
|
|
29
|
+
severity: z.string().optional(),
|
|
30
|
+
description: z.string().optional(),
|
|
31
|
+
});
|
|
32
|
+
export const snykVulnSchema = z.object({
|
|
33
|
+
package: z.string(),
|
|
34
|
+
version: z.string().optional(),
|
|
35
|
+
id: z.string(),
|
|
36
|
+
severity: securityFindingSeveritySchema,
|
|
37
|
+
title: z.string(),
|
|
38
|
+
url: z.string().url().optional(),
|
|
39
|
+
});
|
|
40
|
+
export const genStatusSchema = z.enum(['pending', 'safe', 'warning', 'danger', 'failed']);
|
|
41
|
+
export const socketStatusSchema = z.enum([
|
|
42
|
+
'pending',
|
|
43
|
+
'ok',
|
|
44
|
+
'alerts',
|
|
45
|
+
'unavailable',
|
|
46
|
+
'failed',
|
|
47
|
+
]);
|
|
48
|
+
export const snykStatusSchema = z.enum([
|
|
49
|
+
'pending',
|
|
50
|
+
'ok',
|
|
51
|
+
'low',
|
|
52
|
+
'medium',
|
|
53
|
+
'high',
|
|
54
|
+
'critical',
|
|
55
|
+
'unavailable',
|
|
56
|
+
'failed',
|
|
57
|
+
]);
|
|
58
|
+
export const overallRatingSchema = z.enum([
|
|
59
|
+
'pending',
|
|
60
|
+
'trusted',
|
|
61
|
+
'low_risk',
|
|
62
|
+
'med_risk',
|
|
63
|
+
'critical',
|
|
64
|
+
]);
|
|
65
|
+
export const skillSecurityAuditSchema = z.object({
|
|
66
|
+
skill_id: z.string().uuid(),
|
|
67
|
+
gen_status: genStatusSchema,
|
|
68
|
+
gen_findings: z.array(genFindingSchema),
|
|
69
|
+
socket_status: socketStatusSchema,
|
|
70
|
+
socket_alerts: z.array(socketAlertSchema),
|
|
71
|
+
snyk_status: snykStatusSchema,
|
|
72
|
+
snyk_vulns: z.array(snykVulnSchema),
|
|
73
|
+
overall_rating: overallRatingSchema,
|
|
74
|
+
audited_at: z.string().datetime().nullable(),
|
|
75
|
+
updated_at: z.string().datetime(),
|
|
76
|
+
});
|
|
@@ -128,6 +128,7 @@ export declare const dependencyRowSchema: z.ZodObject<{
|
|
|
128
128
|
is_creator: boolean;
|
|
129
129
|
is_partner: boolean;
|
|
130
130
|
}>>>;
|
|
131
|
+
security_rating: z.ZodOptional<z.ZodNullable<z.ZodEnum<["trusted", "low_risk", "med_risk", "critical", "pending"]>>>;
|
|
131
132
|
created_at: z.ZodString;
|
|
132
133
|
updated_at: z.ZodString;
|
|
133
134
|
}, "id" | "slug" | "name" | "description" | "visibility">, "strip", z.ZodTypeAny, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-dependency.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/skill-dependency.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;EAMhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"skill-dependency.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/skill-dependency.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;EAMhC,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ9B,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAE/D,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,kBAAkB,EAAE,CAAA;IAC3B,SAAS,EAAE,kBAAkB,EAAE,CAAA;CAChC;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED,eAAO,MAAM,wBAAwB;;;;;;;;;;;;EAOnC,CAAA;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA"}
|
|
@@ -176,6 +176,14 @@ export declare const skillSchema: z.ZodObject<{
|
|
|
176
176
|
is_creator: boolean;
|
|
177
177
|
is_partner: boolean;
|
|
178
178
|
}>>>;
|
|
179
|
+
/**
|
|
180
|
+
* Attached by the API on list + detail GETs once the worker has
|
|
181
|
+
* audited this skill. `null` = audit row exists but is still
|
|
182
|
+
* pending; `undefined` = no audit row at all (pre-trigger backlog).
|
|
183
|
+
* Cards + the detail page render a `SecurityBadge` from this value
|
|
184
|
+
* so the user can see the rating before opening anything.
|
|
185
|
+
*/
|
|
186
|
+
security_rating: z.ZodOptional<z.ZodNullable<z.ZodEnum<["trusted", "low_risk", "med_risk", "critical", "pending"]>>>;
|
|
179
187
|
created_at: z.ZodString;
|
|
180
188
|
updated_at: z.ZodString;
|
|
181
189
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -230,6 +238,7 @@ export declare const skillSchema: z.ZodObject<{
|
|
|
230
238
|
is_creator: boolean;
|
|
231
239
|
is_partner: boolean;
|
|
232
240
|
} | null | undefined;
|
|
241
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
233
242
|
}, {
|
|
234
243
|
id: string;
|
|
235
244
|
content: string | null;
|
|
@@ -282,6 +291,7 @@ export declare const skillSchema: z.ZodObject<{
|
|
|
282
291
|
is_creator: boolean;
|
|
283
292
|
is_partner: boolean;
|
|
284
293
|
} | null | undefined;
|
|
294
|
+
security_rating?: "trusted" | "low_risk" | "med_risk" | "critical" | "pending" | null | undefined;
|
|
285
295
|
}>;
|
|
286
296
|
export type Skill = z.infer<typeof skillSchema>;
|
|
287
297
|
export declare const createSkillInputSchema: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/skill.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,qBAAqB,kCAAgC,CAAA;AAClE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS1B,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEvD,iFAAiF;AACjF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;EAO5B,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,eAAO,MAAM,WAAW;;;;;;;;;;;;IAgBtB;;;;;;;;;OASG;;;;;;;IAQH;;;;;OAKG;;;;IAIH,kEAAkE;;;;;;;;;;;;;;;;;;;;;;;IAElE,6DAA6D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE7D,6EAA6E;;IAE7E,mEAAmE;;IAEnE,+EAA+E;;IAE/E,gGAAgG
|
|
1
|
+
{"version":3,"file":"skill.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/skill.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -86,6 +86,17 @@ export const skillSchema = z.object({
|
|
|
86
86
|
})
|
|
87
87
|
.nullable()
|
|
88
88
|
.optional(),
|
|
89
|
+
/**
|
|
90
|
+
* Attached by the API on list + detail GETs once the worker has
|
|
91
|
+
* audited this skill. `null` = audit row exists but is still
|
|
92
|
+
* pending; `undefined` = no audit row at all (pre-trigger backlog).
|
|
93
|
+
* Cards + the detail page render a `SecurityBadge` from this value
|
|
94
|
+
* so the user can see the rating before opening anything.
|
|
95
|
+
*/
|
|
96
|
+
security_rating: z
|
|
97
|
+
.enum(['trusted', 'low_risk', 'med_risk', 'critical', 'pending'])
|
|
98
|
+
.nullable()
|
|
99
|
+
.optional(),
|
|
89
100
|
created_at: z.string().datetime(),
|
|
90
101
|
updated_at: z.string().datetime(),
|
|
91
102
|
});
|