@panguard-ai/panguard-auth 0.1.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/auth.d.ts +32 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +68 -0
- package/dist/auth.js.map +1 -0
- package/dist/crypto.d.ts +21 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +60 -0
- package/dist/crypto.js.map +1 -0
- package/dist/database.d.ts +266 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +936 -0
- package/dist/database.js.map +1 -0
- package/dist/email-verify.d.ts +31 -0
- package/dist/email-verify.d.ts.map +1 -0
- package/dist/email-verify.js +506 -0
- package/dist/email-verify.js.map +1 -0
- package/dist/error-tracker.d.ts +24 -0
- package/dist/error-tracker.d.ts.map +1 -0
- package/dist/error-tracker.js +80 -0
- package/dist/error-tracker.js.map +1 -0
- package/dist/google-oauth.d.ts +40 -0
- package/dist/google-oauth.d.ts.map +1 -0
- package/dist/google-oauth.js +77 -0
- package/dist/google-oauth.js.map +1 -0
- package/dist/google-sheets.d.ts +35 -0
- package/dist/google-sheets.d.ts.map +1 -0
- package/dist/google-sheets.js +128 -0
- package/dist/google-sheets.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/lemonsqueezy.d.ts +61 -0
- package/dist/lemonsqueezy.d.ts.map +1 -0
- package/dist/lemonsqueezy.js +254 -0
- package/dist/lemonsqueezy.js.map +1 -0
- package/dist/middleware.d.ts +22 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +40 -0
- package/dist/middleware.js.map +1 -0
- package/dist/openapi.d.ts +17 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +683 -0
- package/dist/openapi.js.map +1 -0
- package/dist/rate-limiter.d.ts +46 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +64 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/routes/admin.d.ts +30 -0
- package/dist/routes/admin.d.ts.map +1 -0
- package/dist/routes/admin.js +490 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/auth.d.ts +18 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +426 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/billing.d.ts +14 -0
- package/dist/routes/billing.d.ts.map +1 -0
- package/dist/routes/billing.js +176 -0
- package/dist/routes/billing.js.map +1 -0
- package/dist/routes/index.d.ts +60 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +133 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/oauth.d.ts +15 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +215 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/shared.d.ts +71 -0
- package/dist/routes/shared.d.ts.map +1 -0
- package/dist/routes/shared.js +100 -0
- package/dist/routes/shared.js.map +1 -0
- package/dist/routes/totp.d.ts +14 -0
- package/dist/routes/totp.d.ts.map +1 -0
- package/dist/routes/totp.js +166 -0
- package/dist/routes/totp.js.map +1 -0
- package/dist/routes/usage.d.ts +14 -0
- package/dist/routes/usage.d.ts.map +1 -0
- package/dist/routes/usage.js +127 -0
- package/dist/routes/usage.js.map +1 -0
- package/dist/routes/waitlist.d.ts +16 -0
- package/dist/routes/waitlist.d.ts.map +1 -0
- package/dist/routes/waitlist.js +171 -0
- package/dist/routes/waitlist.js.map +1 -0
- package/dist/routes.d.ts +72 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +1806 -0
- package/dist/routes.js.map +1 -0
- package/dist/totp.d.ts +41 -0
- package/dist/totp.d.ts.map +1 -0
- package/dist/totp.js +129 -0
- package/dist/totp.js.map +1 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/usage-meter.d.ts +49 -0
- package/dist/usage-meter.d.ts.map +1 -0
- package/dist/usage-meter.js +123 -0
- package/dist/usage-meter.js.map +1 -0
- package/package.json +33 -0
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI 3.0 specification and Swagger UI HTML generator.
|
|
3
|
+
*
|
|
4
|
+
* Generates a complete API spec from route definitions and serves
|
|
5
|
+
* an embedded Swagger UI page via CDN.
|
|
6
|
+
*
|
|
7
|
+
* @module @panguard-ai/panguard-auth/openapi
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Generate the OpenAPI 3.0 specification as a JSON-serializable object.
|
|
11
|
+
*/
|
|
12
|
+
export function generateOpenApiSpec(baseUrl) {
|
|
13
|
+
return {
|
|
14
|
+
openapi: '3.0.3',
|
|
15
|
+
info: {
|
|
16
|
+
title: 'Panguard AI API',
|
|
17
|
+
version: '1.0.0',
|
|
18
|
+
description: 'REST API for Panguard AI — authentication, billing, usage metering, admin management, and threat intelligence.',
|
|
19
|
+
contact: { email: 'support@panguard.ai', url: 'https://panguard.ai' },
|
|
20
|
+
license: { name: 'BSL 1.1', url: 'https://panguard.ai/legal/terms' },
|
|
21
|
+
},
|
|
22
|
+
servers: [{ url: baseUrl, description: 'Panguard API Server' }],
|
|
23
|
+
tags: [
|
|
24
|
+
{ name: 'Auth', description: 'Authentication and session management' },
|
|
25
|
+
{ name: 'Account', description: 'Account management (GDPR, 2FA)' },
|
|
26
|
+
{ name: 'Billing', description: 'Subscription and payment (Lemon Squeezy)' },
|
|
27
|
+
{ name: 'Usage', description: 'Usage metering and quota' },
|
|
28
|
+
{ name: 'Waitlist', description: 'Waitlist management' },
|
|
29
|
+
{ name: 'Admin', description: 'Admin dashboard API' },
|
|
30
|
+
{ name: 'Threat Cloud', description: 'Threat intelligence API' },
|
|
31
|
+
],
|
|
32
|
+
components: {
|
|
33
|
+
securitySchemes: {
|
|
34
|
+
bearerAuth: {
|
|
35
|
+
type: 'http',
|
|
36
|
+
scheme: 'bearer',
|
|
37
|
+
bearerFormat: 'session-token',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
schemas: {
|
|
41
|
+
Error: {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
ok: { type: 'boolean', example: false },
|
|
45
|
+
error: { type: 'string' },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
User: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
id: { type: 'integer' },
|
|
52
|
+
email: { type: 'string', format: 'email' },
|
|
53
|
+
name: { type: 'string' },
|
|
54
|
+
role: { type: 'string', enum: ['user', 'admin'] },
|
|
55
|
+
tier: { type: 'string', enum: ['community', 'solo', 'pro', 'business', 'enterprise'] },
|
|
56
|
+
createdAt: { type: 'string', format: 'date-time' },
|
|
57
|
+
planExpiresAt: { type: 'string', format: 'date-time', nullable: true },
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
UsageSummary: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
resource: { type: 'string' },
|
|
64
|
+
current: { type: 'integer' },
|
|
65
|
+
limit: { type: 'integer', description: '-1 means unlimited' },
|
|
66
|
+
percentage: { type: 'integer', minimum: 0, maximum: 100 },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
QuotaCheck: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
allowed: { type: 'boolean' },
|
|
73
|
+
current: { type: 'integer' },
|
|
74
|
+
limit: { type: 'integer' },
|
|
75
|
+
remaining: { type: 'integer' },
|
|
76
|
+
resource: { type: 'string' },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
paths: {
|
|
82
|
+
'/health': {
|
|
83
|
+
get: {
|
|
84
|
+
tags: ['System'],
|
|
85
|
+
summary: 'Health check',
|
|
86
|
+
responses: {
|
|
87
|
+
200: {
|
|
88
|
+
description: 'Service is healthy',
|
|
89
|
+
content: {
|
|
90
|
+
'application/json': {
|
|
91
|
+
schema: {
|
|
92
|
+
type: 'object',
|
|
93
|
+
properties: {
|
|
94
|
+
ok: { type: 'boolean' },
|
|
95
|
+
data: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
properties: {
|
|
98
|
+
status: { type: 'string' },
|
|
99
|
+
uptime: { type: 'number' },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
// ── Auth ──
|
|
111
|
+
'/api/auth/register': {
|
|
112
|
+
post: {
|
|
113
|
+
tags: ['Auth'],
|
|
114
|
+
summary: 'Register a new account',
|
|
115
|
+
requestBody: {
|
|
116
|
+
required: true,
|
|
117
|
+
content: {
|
|
118
|
+
'application/json': {
|
|
119
|
+
schema: {
|
|
120
|
+
type: 'object',
|
|
121
|
+
required: ['email', 'password', 'name'],
|
|
122
|
+
properties: {
|
|
123
|
+
email: { type: 'string', format: 'email' },
|
|
124
|
+
password: { type: 'string', minLength: 8 },
|
|
125
|
+
name: { type: 'string' },
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
responses: {
|
|
132
|
+
201: { description: 'Account created' },
|
|
133
|
+
400: { description: 'Validation error' },
|
|
134
|
+
409: { description: 'Email already registered' },
|
|
135
|
+
429: { description: 'Rate limit exceeded' },
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
'/api/auth/login': {
|
|
140
|
+
post: {
|
|
141
|
+
tags: ['Auth'],
|
|
142
|
+
summary: 'Log in with email and password',
|
|
143
|
+
requestBody: {
|
|
144
|
+
required: true,
|
|
145
|
+
content: {
|
|
146
|
+
'application/json': {
|
|
147
|
+
schema: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
required: ['email', 'password'],
|
|
150
|
+
properties: {
|
|
151
|
+
email: { type: 'string', format: 'email' },
|
|
152
|
+
password: { type: 'string' },
|
|
153
|
+
totpCode: { type: 'string', description: '6-digit TOTP code (if 2FA enabled)' },
|
|
154
|
+
backupCode: { type: 'string', description: 'Backup code (if 2FA enabled)' },
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
responses: {
|
|
161
|
+
200: { description: 'Login successful (returns token)' },
|
|
162
|
+
202: { description: 'Requires 2FA (requiresTwoFactor: true)' },
|
|
163
|
+
401: { description: 'Invalid credentials' },
|
|
164
|
+
429: { description: 'Rate limit exceeded' },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
'/api/auth/logout': {
|
|
169
|
+
post: {
|
|
170
|
+
tags: ['Auth'],
|
|
171
|
+
summary: 'Invalidate current session',
|
|
172
|
+
security: [{ bearerAuth: [] }],
|
|
173
|
+
responses: { 200: { description: 'Session invalidated' } },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
'/api/auth/me': {
|
|
177
|
+
get: {
|
|
178
|
+
tags: ['Auth'],
|
|
179
|
+
summary: 'Get current user profile',
|
|
180
|
+
security: [{ bearerAuth: [] }],
|
|
181
|
+
responses: {
|
|
182
|
+
200: {
|
|
183
|
+
description: 'User profile',
|
|
184
|
+
content: {
|
|
185
|
+
'application/json': {
|
|
186
|
+
schema: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
properties: {
|
|
189
|
+
ok: { type: 'boolean' },
|
|
190
|
+
data: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: { user: { $ref: '#/components/schemas/User' } },
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
401: { description: 'Not authenticated' },
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
'/api/auth/forgot-password': {
|
|
204
|
+
post: {
|
|
205
|
+
tags: ['Auth'],
|
|
206
|
+
summary: 'Request password reset email',
|
|
207
|
+
requestBody: {
|
|
208
|
+
required: true,
|
|
209
|
+
content: {
|
|
210
|
+
'application/json': {
|
|
211
|
+
schema: {
|
|
212
|
+
type: 'object',
|
|
213
|
+
required: ['email'],
|
|
214
|
+
properties: { email: { type: 'string', format: 'email' } },
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
responses: {
|
|
220
|
+
200: { description: 'Reset email sent (always returns 200 for anti-enumeration)' },
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
'/api/auth/reset-password': {
|
|
225
|
+
post: {
|
|
226
|
+
tags: ['Auth'],
|
|
227
|
+
summary: 'Reset password with token',
|
|
228
|
+
requestBody: {
|
|
229
|
+
required: true,
|
|
230
|
+
content: {
|
|
231
|
+
'application/json': {
|
|
232
|
+
schema: {
|
|
233
|
+
type: 'object',
|
|
234
|
+
required: ['token', 'password'],
|
|
235
|
+
properties: {
|
|
236
|
+
token: { type: 'string' },
|
|
237
|
+
password: { type: 'string', minLength: 8 },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
responses: {
|
|
244
|
+
200: { description: 'Password reset successful' },
|
|
245
|
+
400: { description: 'Invalid or expired token' },
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
// ── Account (GDPR, 2FA) ──
|
|
250
|
+
'/api/auth/delete-account': {
|
|
251
|
+
delete: {
|
|
252
|
+
tags: ['Account'],
|
|
253
|
+
summary: 'Delete account and all data (GDPR)',
|
|
254
|
+
security: [{ bearerAuth: [] }],
|
|
255
|
+
requestBody: {
|
|
256
|
+
required: true,
|
|
257
|
+
content: {
|
|
258
|
+
'application/json': {
|
|
259
|
+
schema: {
|
|
260
|
+
type: 'object',
|
|
261
|
+
required: ['password'],
|
|
262
|
+
properties: { password: { type: 'string' } },
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
responses: {
|
|
268
|
+
200: { description: 'Account deleted' },
|
|
269
|
+
401: { description: 'Invalid password' },
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
'/api/auth/export-data': {
|
|
274
|
+
get: {
|
|
275
|
+
tags: ['Account'],
|
|
276
|
+
summary: 'Export all user data (GDPR)',
|
|
277
|
+
security: [{ bearerAuth: [] }],
|
|
278
|
+
responses: { 200: { description: 'JSON export of all user data' } },
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
'/api/auth/totp/setup': {
|
|
282
|
+
post: {
|
|
283
|
+
tags: ['Account'],
|
|
284
|
+
summary: 'Generate TOTP secret for 2FA setup',
|
|
285
|
+
security: [{ bearerAuth: [] }],
|
|
286
|
+
responses: { 200: { description: 'Returns secret, QR URI, and backup codes' } },
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
'/api/auth/totp/verify': {
|
|
290
|
+
post: {
|
|
291
|
+
tags: ['Account'],
|
|
292
|
+
summary: 'Verify TOTP code to enable 2FA',
|
|
293
|
+
security: [{ bearerAuth: [] }],
|
|
294
|
+
requestBody: {
|
|
295
|
+
required: true,
|
|
296
|
+
content: {
|
|
297
|
+
'application/json': {
|
|
298
|
+
schema: {
|
|
299
|
+
type: 'object',
|
|
300
|
+
required: ['code'],
|
|
301
|
+
properties: { code: { type: 'string', pattern: '^\\d{6}$' } },
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
responses: { 200: { description: '2FA enabled' }, 400: { description: 'Invalid code' } },
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
'/api/auth/totp/disable': {
|
|
310
|
+
post: {
|
|
311
|
+
tags: ['Account'],
|
|
312
|
+
summary: 'Disable 2FA',
|
|
313
|
+
security: [{ bearerAuth: [] }],
|
|
314
|
+
requestBody: {
|
|
315
|
+
required: true,
|
|
316
|
+
content: {
|
|
317
|
+
'application/json': {
|
|
318
|
+
schema: {
|
|
319
|
+
type: 'object',
|
|
320
|
+
required: ['password'],
|
|
321
|
+
properties: { password: { type: 'string' } },
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
responses: { 200: { description: '2FA disabled' } },
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
'/api/auth/totp/status': {
|
|
330
|
+
get: {
|
|
331
|
+
tags: ['Account'],
|
|
332
|
+
summary: 'Check 2FA status',
|
|
333
|
+
security: [{ bearerAuth: [] }],
|
|
334
|
+
responses: { 200: { description: 'Returns enabled status and backup codes remaining' } },
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
// ── Billing ──
|
|
338
|
+
'/api/billing/checkout': {
|
|
339
|
+
post: {
|
|
340
|
+
tags: ['Billing'],
|
|
341
|
+
summary: 'Create a Lemon Squeezy checkout session',
|
|
342
|
+
security: [{ bearerAuth: [] }],
|
|
343
|
+
requestBody: {
|
|
344
|
+
required: true,
|
|
345
|
+
content: {
|
|
346
|
+
'application/json': {
|
|
347
|
+
schema: {
|
|
348
|
+
type: 'object',
|
|
349
|
+
properties: {
|
|
350
|
+
tier: { type: 'string', enum: ['solo', 'pro', 'business'] },
|
|
351
|
+
variantId: {
|
|
352
|
+
type: 'string',
|
|
353
|
+
description: 'Lemon Squeezy variant ID (alternative to tier)',
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
responses: {
|
|
361
|
+
200: { description: 'Returns checkout URL' },
|
|
362
|
+
400: { description: 'Invalid tier or variant' },
|
|
363
|
+
501: { description: 'Billing not configured' },
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
'/api/billing/portal': {
|
|
368
|
+
get: {
|
|
369
|
+
tags: ['Billing'],
|
|
370
|
+
summary: 'Get subscription management portal URL',
|
|
371
|
+
security: [{ bearerAuth: [] }],
|
|
372
|
+
responses: {
|
|
373
|
+
200: { description: 'Returns portal URL' },
|
|
374
|
+
404: { description: 'No active subscription' },
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
'/api/billing/status': {
|
|
379
|
+
get: {
|
|
380
|
+
tags: ['Billing'],
|
|
381
|
+
summary: 'Get current billing status',
|
|
382
|
+
security: [{ bearerAuth: [] }],
|
|
383
|
+
responses: { 200: { description: 'Returns tier and subscription details' } },
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
'/api/billing/webhook': {
|
|
387
|
+
post: {
|
|
388
|
+
tags: ['Billing'],
|
|
389
|
+
summary: 'Lemon Squeezy webhook handler',
|
|
390
|
+
description: 'Receives subscription lifecycle events. Verified via HMAC SHA-256.',
|
|
391
|
+
responses: { 200: { description: 'Webhook processed' } },
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
// ── Usage ──
|
|
395
|
+
'/api/usage': {
|
|
396
|
+
get: {
|
|
397
|
+
tags: ['Usage'],
|
|
398
|
+
summary: 'Get usage summary for current user',
|
|
399
|
+
security: [{ bearerAuth: [] }],
|
|
400
|
+
responses: {
|
|
401
|
+
200: {
|
|
402
|
+
description: 'Usage summary',
|
|
403
|
+
content: {
|
|
404
|
+
'application/json': {
|
|
405
|
+
schema: {
|
|
406
|
+
type: 'object',
|
|
407
|
+
properties: {
|
|
408
|
+
ok: { type: 'boolean' },
|
|
409
|
+
data: {
|
|
410
|
+
type: 'object',
|
|
411
|
+
properties: {
|
|
412
|
+
usage: {
|
|
413
|
+
type: 'array',
|
|
414
|
+
items: { $ref: '#/components/schemas/UsageSummary' },
|
|
415
|
+
},
|
|
416
|
+
tier: { type: 'string' },
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
'/api/usage/limits': {
|
|
428
|
+
get: {
|
|
429
|
+
tags: ['Usage'],
|
|
430
|
+
summary: 'Get quota limits for current tier',
|
|
431
|
+
security: [{ bearerAuth: [] }],
|
|
432
|
+
responses: { 200: { description: 'Quota limits' } },
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
'/api/usage/check': {
|
|
436
|
+
post: {
|
|
437
|
+
tags: ['Usage'],
|
|
438
|
+
summary: 'Check if quota is available for a resource',
|
|
439
|
+
security: [{ bearerAuth: [] }],
|
|
440
|
+
requestBody: {
|
|
441
|
+
required: true,
|
|
442
|
+
content: {
|
|
443
|
+
'application/json': {
|
|
444
|
+
schema: {
|
|
445
|
+
type: 'object',
|
|
446
|
+
required: ['resource'],
|
|
447
|
+
properties: {
|
|
448
|
+
resource: {
|
|
449
|
+
type: 'string',
|
|
450
|
+
enum: [
|
|
451
|
+
'scan',
|
|
452
|
+
'guard_endpoints',
|
|
453
|
+
'reports',
|
|
454
|
+
'api_calls',
|
|
455
|
+
'notifications',
|
|
456
|
+
'trap_instances',
|
|
457
|
+
],
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
responses: {
|
|
465
|
+
200: {
|
|
466
|
+
description: 'Quota check result',
|
|
467
|
+
content: {
|
|
468
|
+
'application/json': {
|
|
469
|
+
schema: {
|
|
470
|
+
type: 'object',
|
|
471
|
+
properties: {
|
|
472
|
+
ok: { type: 'boolean' },
|
|
473
|
+
data: { $ref: '#/components/schemas/QuotaCheck' },
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
'/api/usage/record': {
|
|
483
|
+
post: {
|
|
484
|
+
tags: ['Usage'],
|
|
485
|
+
summary: 'Record usage for a resource',
|
|
486
|
+
security: [{ bearerAuth: [] }],
|
|
487
|
+
requestBody: {
|
|
488
|
+
required: true,
|
|
489
|
+
content: {
|
|
490
|
+
'application/json': {
|
|
491
|
+
schema: {
|
|
492
|
+
type: 'object',
|
|
493
|
+
required: ['resource'],
|
|
494
|
+
properties: {
|
|
495
|
+
resource: { type: 'string' },
|
|
496
|
+
count: { type: 'integer', default: 1 },
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
responses: {
|
|
503
|
+
200: { description: 'Usage recorded' },
|
|
504
|
+
429: { description: 'Quota exceeded' },
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
// ── Admin ──
|
|
509
|
+
'/api/admin/dashboard': {
|
|
510
|
+
get: {
|
|
511
|
+
tags: ['Admin'],
|
|
512
|
+
summary: 'Get dashboard statistics',
|
|
513
|
+
security: [{ bearerAuth: [] }],
|
|
514
|
+
responses: {
|
|
515
|
+
200: { description: 'Dashboard stats' },
|
|
516
|
+
403: { description: 'Admin required' },
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
'/api/admin/users': {
|
|
521
|
+
get: {
|
|
522
|
+
tags: ['Admin'],
|
|
523
|
+
summary: 'List all users',
|
|
524
|
+
security: [{ bearerAuth: [] }],
|
|
525
|
+
responses: { 200: { description: 'User list' }, 403: { description: 'Admin required' } },
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
'/api/admin/sessions': {
|
|
529
|
+
get: {
|
|
530
|
+
tags: ['Admin'],
|
|
531
|
+
summary: 'List active sessions',
|
|
532
|
+
security: [{ bearerAuth: [] }],
|
|
533
|
+
responses: {
|
|
534
|
+
200: { description: 'Session list' },
|
|
535
|
+
403: { description: 'Admin required' },
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
'/api/admin/activity': {
|
|
540
|
+
get: {
|
|
541
|
+
tags: ['Admin'],
|
|
542
|
+
summary: 'Get recent activity log',
|
|
543
|
+
security: [{ bearerAuth: [] }],
|
|
544
|
+
responses: {
|
|
545
|
+
200: { description: 'Activity items' },
|
|
546
|
+
403: { description: 'Admin required' },
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
// ── Threat Cloud ──
|
|
551
|
+
'/api/threats': {
|
|
552
|
+
post: {
|
|
553
|
+
tags: ['Threat Cloud'],
|
|
554
|
+
summary: 'Upload anonymized threat data',
|
|
555
|
+
description: 'Submit threat intelligence with auto-sighting. Max 1MB body.',
|
|
556
|
+
responses: {
|
|
557
|
+
200: { description: 'Threat recorded' },
|
|
558
|
+
429: { description: 'Rate limited' },
|
|
559
|
+
},
|
|
560
|
+
},
|
|
561
|
+
},
|
|
562
|
+
'/api/iocs': {
|
|
563
|
+
get: {
|
|
564
|
+
tags: ['Threat Cloud'],
|
|
565
|
+
summary: 'Search indicators of compromise',
|
|
566
|
+
parameters: [
|
|
567
|
+
{
|
|
568
|
+
name: 'type',
|
|
569
|
+
in: 'query',
|
|
570
|
+
schema: { type: 'string' },
|
|
571
|
+
description: 'IoC type filter',
|
|
572
|
+
},
|
|
573
|
+
{ name: 'limit', in: 'query', schema: { type: 'integer', default: 50 } },
|
|
574
|
+
{ name: 'offset', in: 'query', schema: { type: 'integer', default: 0 } },
|
|
575
|
+
],
|
|
576
|
+
responses: { 200: { description: 'IoC list with pagination' } },
|
|
577
|
+
},
|
|
578
|
+
},
|
|
579
|
+
'/api/stats': {
|
|
580
|
+
get: {
|
|
581
|
+
tags: ['Threat Cloud'],
|
|
582
|
+
summary: 'Get threat statistics',
|
|
583
|
+
responses: { 200: { description: 'Aggregated threat stats' } },
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
'/api/rules': {
|
|
587
|
+
get: {
|
|
588
|
+
tags: ['Threat Cloud'],
|
|
589
|
+
summary: 'Fetch community detection rules',
|
|
590
|
+
parameters: [
|
|
591
|
+
{ name: 'since', in: 'query', schema: { type: 'string', format: 'date-time' } },
|
|
592
|
+
],
|
|
593
|
+
responses: { 200: { description: 'Detection rules (Sigma YAML)' } },
|
|
594
|
+
},
|
|
595
|
+
post: {
|
|
596
|
+
tags: ['Threat Cloud'],
|
|
597
|
+
summary: 'Publish a detection rule',
|
|
598
|
+
responses: { 200: { description: 'Rule published' } },
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
'/api/feeds/ip-blocklist': {
|
|
602
|
+
get: {
|
|
603
|
+
tags: ['Threat Cloud'],
|
|
604
|
+
summary: 'IP blocklist feed',
|
|
605
|
+
description: 'Plaintext IP list for firewall integration.',
|
|
606
|
+
responses: { 200: { description: 'Newline-separated IP addresses' } },
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
'/api/feeds/domain-blocklist': {
|
|
610
|
+
get: {
|
|
611
|
+
tags: ['Threat Cloud'],
|
|
612
|
+
summary: 'Domain blocklist feed',
|
|
613
|
+
responses: { 200: { description: 'Newline-separated domains' } },
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Generate a self-contained Swagger UI HTML page that loads from CDN.
|
|
621
|
+
*/
|
|
622
|
+
export function generateSwaggerHtml(specUrl) {
|
|
623
|
+
return `<!DOCTYPE html>
|
|
624
|
+
<html lang="en">
|
|
625
|
+
<head>
|
|
626
|
+
<meta charset="UTF-8">
|
|
627
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
628
|
+
<title>Panguard AI - API Documentation</title>
|
|
629
|
+
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
|
|
630
|
+
<style>
|
|
631
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
632
|
+
body { background: #1A1614; }
|
|
633
|
+
.swagger-ui { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
634
|
+
.swagger-ui .topbar { display: none; }
|
|
635
|
+
.swagger-ui .info { margin: 24px 0; }
|
|
636
|
+
.swagger-ui .info .title { color: #F5F1E8; }
|
|
637
|
+
.swagger-ui .info .description p { color: #A09890; }
|
|
638
|
+
.swagger-ui .scheme-container { background: #1F1C19; border-bottom: 1px solid #2E2A27; }
|
|
639
|
+
.swagger-ui .opblock-tag { color: #F5F1E8; border-bottom: 1px solid #2E2A27; }
|
|
640
|
+
.swagger-ui .opblock { border-color: #2E2A27; background: #1F1C19; }
|
|
641
|
+
.swagger-ui .opblock .opblock-summary { border-color: #2E2A27; }
|
|
642
|
+
.swagger-ui .opblock-description-wrapper p { color: #A09890; }
|
|
643
|
+
.swagger-ui .btn { border-color: #8B9A8E; color: #8B9A8E; }
|
|
644
|
+
.swagger-ui .btn.authorize { background: #8B9A8E; color: #1A1614; }
|
|
645
|
+
.swagger-ui section.models { border: 1px solid #2E2A27; }
|
|
646
|
+
.swagger-ui .model-title { color: #F5F1E8; }
|
|
647
|
+
.pg-header {
|
|
648
|
+
background: #1F1C19;
|
|
649
|
+
border-bottom: 1px solid #2E2A27;
|
|
650
|
+
padding: 16px 24px;
|
|
651
|
+
display: flex;
|
|
652
|
+
align-items: center;
|
|
653
|
+
gap: 12px;
|
|
654
|
+
}
|
|
655
|
+
.pg-header svg { color: #8B9A8E; }
|
|
656
|
+
.pg-header span { font-weight: 700; color: #8B9A8E; letter-spacing: 0.05em; font-size: 14px; }
|
|
657
|
+
.pg-header .tag { font-size: 10px; color: #706860; text-transform: uppercase; letter-spacing: 0.1em; }
|
|
658
|
+
</style>
|
|
659
|
+
</head>
|
|
660
|
+
<body>
|
|
661
|
+
<div class="pg-header">
|
|
662
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
663
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
664
|
+
<path d="M9 12l2 2 4-4"/>
|
|
665
|
+
</svg>
|
|
666
|
+
<span>PANGUARD</span>
|
|
667
|
+
<span class="tag">API Documentation</span>
|
|
668
|
+
</div>
|
|
669
|
+
<div id="swagger-ui"></div>
|
|
670
|
+
<script src="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js"></script>
|
|
671
|
+
<script>
|
|
672
|
+
SwaggerUIBundle({
|
|
673
|
+
url: '${specUrl}',
|
|
674
|
+
dom_id: '#swagger-ui',
|
|
675
|
+
deepLinking: true,
|
|
676
|
+
presets: [SwaggerUIBundle.presets.apis, SwaggerUIBundle.SwaggerUIStandalonePreset],
|
|
677
|
+
layout: 'BaseLayout',
|
|
678
|
+
});
|
|
679
|
+
</script>
|
|
680
|
+
</body>
|
|
681
|
+
</html>`;
|
|
682
|
+
}
|
|
683
|
+
//# sourceMappingURL=openapi.js.map
|