@littlebearapps/platform-admin-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +112 -0
  2. package/dist/index.d.ts +16 -0
  3. package/dist/index.js +89 -0
  4. package/dist/prompts.d.ts +27 -0
  5. package/dist/prompts.js +80 -0
  6. package/dist/scaffold.d.ts +5 -0
  7. package/dist/scaffold.js +65 -0
  8. package/dist/templates.d.ts +16 -0
  9. package/dist/templates.js +131 -0
  10. package/package.json +46 -0
  11. package/templates/full/migrations/006_pattern_discovery.sql +199 -0
  12. package/templates/full/migrations/007_notifications_search.sql +127 -0
  13. package/templates/full/workers/lib/pattern-discovery/ai-prompt.ts +644 -0
  14. package/templates/full/workers/lib/pattern-discovery/clustering.ts +278 -0
  15. package/templates/full/workers/lib/pattern-discovery/shadow-evaluation.ts +603 -0
  16. package/templates/full/workers/lib/pattern-discovery/storage.ts +806 -0
  17. package/templates/full/workers/lib/pattern-discovery/types.ts +159 -0
  18. package/templates/full/workers/lib/pattern-discovery/validation.ts +278 -0
  19. package/templates/full/workers/pattern-discovery.ts +661 -0
  20. package/templates/full/workers/platform-alert-router.ts +1809 -0
  21. package/templates/full/workers/platform-notifications.ts +424 -0
  22. package/templates/full/workers/platform-search.ts +480 -0
  23. package/templates/full/workers/platform-settings.ts +436 -0
  24. package/templates/full/wrangler.alert-router.jsonc.hbs +34 -0
  25. package/templates/full/wrangler.notifications.jsonc.hbs +23 -0
  26. package/templates/full/wrangler.pattern-discovery.jsonc.hbs +33 -0
  27. package/templates/full/wrangler.search.jsonc.hbs +16 -0
  28. package/templates/full/wrangler.settings.jsonc.hbs +23 -0
  29. package/templates/shared/README.md.hbs +69 -0
  30. package/templates/shared/config/budgets.yaml.hbs +72 -0
  31. package/templates/shared/config/services.yaml.hbs +45 -0
  32. package/templates/shared/migrations/001_core_tables.sql +117 -0
  33. package/templates/shared/migrations/002_usage_warehouse.sql +830 -0
  34. package/templates/shared/migrations/003_feature_tracking.sql +250 -0
  35. package/templates/shared/migrations/004_settings_alerts.sql +452 -0
  36. package/templates/shared/migrations/seed.sql.hbs +4 -0
  37. package/templates/shared/package.json.hbs +21 -0
  38. package/templates/shared/scripts/sync-config.ts +242 -0
  39. package/templates/shared/tsconfig.json +12 -0
  40. package/templates/shared/workers/lib/analytics-engine.ts +357 -0
  41. package/templates/shared/workers/lib/billing.ts +293 -0
  42. package/templates/shared/workers/lib/circuit-breaker-middleware.ts +25 -0
  43. package/templates/shared/workers/lib/control.ts +292 -0
  44. package/templates/shared/workers/lib/economics.ts +368 -0
  45. package/templates/shared/workers/lib/metrics.ts +103 -0
  46. package/templates/shared/workers/lib/platform-settings.ts +407 -0
  47. package/templates/shared/workers/lib/shared/allowances.ts +333 -0
  48. package/templates/shared/workers/lib/shared/cloudflare.ts +1362 -0
  49. package/templates/shared/workers/lib/shared/types.ts +58 -0
  50. package/templates/shared/workers/lib/telemetry-sampling.ts +360 -0
  51. package/templates/shared/workers/lib/usage/collectors/example.ts +96 -0
  52. package/templates/shared/workers/lib/usage/collectors/index.ts +128 -0
  53. package/templates/shared/workers/lib/usage/handlers/audit.ts +306 -0
  54. package/templates/shared/workers/lib/usage/handlers/backfill.ts +845 -0
  55. package/templates/shared/workers/lib/usage/handlers/behavioral.ts +429 -0
  56. package/templates/shared/workers/lib/usage/handlers/data-queries.ts +507 -0
  57. package/templates/shared/workers/lib/usage/handlers/dlq-admin.ts +364 -0
  58. package/templates/shared/workers/lib/usage/handlers/health-trends.ts +222 -0
  59. package/templates/shared/workers/lib/usage/handlers/index.ts +35 -0
  60. package/templates/shared/workers/lib/usage/handlers/usage-admin.ts +421 -0
  61. package/templates/shared/workers/lib/usage/handlers/usage-features.ts +1262 -0
  62. package/templates/shared/workers/lib/usage/handlers/usage-metrics.ts +2420 -0
  63. package/templates/shared/workers/lib/usage/handlers/usage-settings.ts +610 -0
  64. package/templates/shared/workers/lib/usage/queue/budget-enforcement.ts +1032 -0
  65. package/templates/shared/workers/lib/usage/queue/cost-budget-enforcement.ts +128 -0
  66. package/templates/shared/workers/lib/usage/queue/cost-calculator.ts +77 -0
  67. package/templates/shared/workers/lib/usage/queue/dlq-handler.ts +161 -0
  68. package/templates/shared/workers/lib/usage/queue/index.ts +19 -0
  69. package/templates/shared/workers/lib/usage/queue/telemetry-processor.ts +790 -0
  70. package/templates/shared/workers/lib/usage/scheduled/anomaly-detection.ts +732 -0
  71. package/templates/shared/workers/lib/usage/scheduled/data-collection.ts +956 -0
  72. package/templates/shared/workers/lib/usage/scheduled/error-digest.ts +343 -0
  73. package/templates/shared/workers/lib/usage/scheduled/index.ts +18 -0
  74. package/templates/shared/workers/lib/usage/scheduled/rollups.ts +1561 -0
  75. package/templates/shared/workers/lib/usage/shared/constants.ts +362 -0
  76. package/templates/shared/workers/lib/usage/shared/index.ts +14 -0
  77. package/templates/shared/workers/lib/usage/shared/types.ts +1066 -0
  78. package/templates/shared/workers/lib/usage/shared/utils.ts +795 -0
  79. package/templates/shared/workers/platform-usage.ts +1915 -0
  80. package/templates/shared/wrangler.usage.jsonc.hbs +58 -0
  81. package/templates/standard/migrations/005_error_collection.sql +162 -0
  82. package/templates/standard/workers/error-collector.ts +2670 -0
  83. package/templates/standard/workers/lib/error-collector/capture.ts +213 -0
  84. package/templates/standard/workers/lib/error-collector/digest.ts +448 -0
  85. package/templates/standard/workers/lib/error-collector/email-health-alerts.ts +262 -0
  86. package/templates/standard/workers/lib/error-collector/fingerprint.ts +258 -0
  87. package/templates/standard/workers/lib/error-collector/gap-alerts.ts +293 -0
  88. package/templates/standard/workers/lib/error-collector/github.ts +329 -0
  89. package/templates/standard/workers/lib/error-collector/types.ts +262 -0
  90. package/templates/standard/workers/lib/sentinel/gap-detection.ts +734 -0
  91. package/templates/standard/workers/lib/shared/slack-alerts.ts +585 -0
  92. package/templates/standard/workers/platform-sentinel.ts +1744 -0
  93. package/templates/standard/wrangler.error-collector.jsonc.hbs +44 -0
  94. package/templates/standard/wrangler.sentinel.jsonc.hbs +45 -0
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Audit Handlers for platform-usage
3
+ *
4
+ * Provides API endpoints for accessing audit reports.
5
+ * Part of Phase 2 Usage Capture Audit.
6
+ *
7
+ * Endpoints:
8
+ * - GET /usage/audit - Latest comprehensive audit report
9
+ * - GET /usage/audit/history - Comprehensive audit history
10
+ * - GET /usage/audit/attribution - Latest attribution report
11
+ * - GET /usage/audit/features - Latest feature coverage report
12
+ *
13
+ * @module workers/lib/usage/handlers/audit
14
+ * @created 2026-01-29
15
+ */
16
+
17
+ import type { D1Database, KVNamespace } from '@cloudflare/workers-types';
18
+
19
+ /**
20
+ * Environment bindings for audit handlers
21
+ */
22
+ export interface AuditHandlerEnv {
23
+ PLATFORM_DB: D1Database;
24
+ PLATFORM_CACHE: KVNamespace;
25
+ }
26
+
27
+ /**
28
+ * Handle GET /usage/audit - Get latest comprehensive audit report
29
+ */
30
+ export async function handleGetAudit(env: AuditHandlerEnv): Promise<Response> {
31
+ try {
32
+ const result = await env.PLATFORM_DB.prepare(
33
+ `
34
+ SELECT report_json, generated_at
35
+ FROM comprehensive_audit_reports
36
+ ORDER BY generated_at DESC
37
+ LIMIT 1
38
+ `
39
+ ).first<{ report_json: string; generated_at: string }>();
40
+
41
+ if (!result) {
42
+ return Response.json(
43
+ {
44
+ success: false,
45
+ error: 'No comprehensive audit reports found',
46
+ message: 'Run platform-auditor to generate a report',
47
+ },
48
+ { status: 404 }
49
+ );
50
+ }
51
+
52
+ const report = JSON.parse(result.report_json);
53
+
54
+ return Response.json({
55
+ success: true,
56
+ data: report,
57
+ generatedAt: result.generated_at,
58
+ timestamp: new Date().toISOString(),
59
+ });
60
+ } catch (error) {
61
+ const message = error instanceof Error ? error.message : 'Unknown error';
62
+ return Response.json(
63
+ { success: false, error: 'Failed to get audit report', message },
64
+ { status: 500 }
65
+ );
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Handle GET /usage/audit/history - Get comprehensive audit history
71
+ */
72
+ export async function handleGetAuditHistory(
73
+ request: Request,
74
+ env: AuditHandlerEnv
75
+ ): Promise<Response> {
76
+ const url = new URL(request.url);
77
+ const limit = parseInt(url.searchParams.get('limit') || '10', 10);
78
+ const offset = parseInt(url.searchParams.get('offset') || '0', 10);
79
+
80
+ try {
81
+ const result = await env.PLATFORM_DB.prepare(
82
+ `
83
+ SELECT
84
+ id,
85
+ generated_at,
86
+ gap_events_count,
87
+ total_missing_hours,
88
+ average_gap_severity,
89
+ total_resources,
90
+ attributed_count,
91
+ unattributed_count,
92
+ defined_features_count,
93
+ active_features_count,
94
+ dormant_features_count,
95
+ undefined_features_count,
96
+ ai_judge_avg_score,
97
+ action_items_count,
98
+ critical_items_count
99
+ FROM comprehensive_audit_reports
100
+ ORDER BY generated_at DESC
101
+ LIMIT ? OFFSET ?
102
+ `
103
+ )
104
+ .bind(limit, offset)
105
+ .all<{
106
+ id: string;
107
+ generated_at: string;
108
+ gap_events_count: number;
109
+ total_missing_hours: number;
110
+ average_gap_severity: string;
111
+ total_resources: number;
112
+ attributed_count: number;
113
+ unattributed_count: number;
114
+ defined_features_count: number;
115
+ active_features_count: number;
116
+ dormant_features_count: number;
117
+ undefined_features_count: number;
118
+ ai_judge_avg_score: number | null;
119
+ action_items_count: number;
120
+ critical_items_count: number;
121
+ }>();
122
+
123
+ // Get total count
124
+ const countResult = await env.PLATFORM_DB.prepare(
125
+ `SELECT COUNT(*) as count FROM comprehensive_audit_reports`
126
+ ).first<{ count: number }>();
127
+
128
+ return Response.json({
129
+ success: true,
130
+ data: result.results ?? [],
131
+ pagination: {
132
+ limit,
133
+ offset,
134
+ total: countResult?.count ?? 0,
135
+ },
136
+ timestamp: new Date().toISOString(),
137
+ });
138
+ } catch (error) {
139
+ const message = error instanceof Error ? error.message : 'Unknown error';
140
+ return Response.json(
141
+ { success: false, error: 'Failed to get audit history', message },
142
+ { status: 500 }
143
+ );
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Handle GET /usage/audit/attribution - Get latest attribution report
149
+ */
150
+ export async function handleGetAttribution(env: AuditHandlerEnv): Promise<Response> {
151
+ try {
152
+ const result = await env.PLATFORM_DB.prepare(
153
+ `
154
+ SELECT
155
+ id,
156
+ discovery_time,
157
+ total_resources,
158
+ attributed_count,
159
+ unattributed_count,
160
+ report_json
161
+ FROM attribution_reports
162
+ ORDER BY discovery_time DESC
163
+ LIMIT 1
164
+ `
165
+ ).first<{
166
+ id: string;
167
+ discovery_time: string;
168
+ total_resources: number;
169
+ attributed_count: number;
170
+ unattributed_count: number;
171
+ report_json: string;
172
+ }>();
173
+
174
+ if (!result) {
175
+ return Response.json(
176
+ {
177
+ success: false,
178
+ error: 'No attribution reports found',
179
+ message: 'platform-mapper has not yet run or attribution checking is not enabled',
180
+ },
181
+ { status: 404 }
182
+ );
183
+ }
184
+
185
+ const report = JSON.parse(result.report_json);
186
+
187
+ return Response.json({
188
+ success: true,
189
+ data: {
190
+ id: result.id,
191
+ discoveryTime: result.discovery_time,
192
+ summary: {
193
+ totalResources: result.total_resources,
194
+ attributedCount: result.attributed_count,
195
+ unattributedCount: result.unattributed_count,
196
+ attributionRate:
197
+ result.total_resources > 0
198
+ ? Math.round((result.attributed_count / result.total_resources) * 100)
199
+ : 100,
200
+ },
201
+ unattributed: report.unattributed ?? [],
202
+ },
203
+ timestamp: new Date().toISOString(),
204
+ });
205
+ } catch (error) {
206
+ const message = error instanceof Error ? error.message : 'Unknown error';
207
+ return Response.json(
208
+ { success: false, error: 'Failed to get attribution report', message },
209
+ { status: 500 }
210
+ );
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Handle GET /usage/audit/features - Get latest feature coverage report
216
+ */
217
+ export async function handleGetFeatureCoverage(
218
+ request: Request,
219
+ env: AuditHandlerEnv
220
+ ): Promise<Response> {
221
+ const url = new URL(request.url);
222
+ const project = url.searchParams.get('project');
223
+ const status = url.searchParams.get('status');
224
+
225
+ try {
226
+ // Get latest audit time
227
+ const latestResult = await env.PLATFORM_DB.prepare(
228
+ `SELECT MAX(audit_time) as latest FROM feature_coverage_audit`
229
+ ).first<{ latest: string | null }>();
230
+
231
+ if (!latestResult?.latest) {
232
+ return Response.json(
233
+ {
234
+ success: false,
235
+ error: 'No feature coverage audits found',
236
+ message: 'platform-auditor has not yet run feature coverage audit',
237
+ },
238
+ { status: 404 }
239
+ );
240
+ }
241
+
242
+ // Build query with optional filters
243
+ let query = `
244
+ SELECT
245
+ project,
246
+ feature,
247
+ status,
248
+ last_heartbeat,
249
+ events_last_7d,
250
+ defined_budget,
251
+ budget_unit
252
+ FROM feature_coverage_audit
253
+ WHERE audit_time = ?
254
+ `;
255
+ const bindings: (string | number)[] = [latestResult.latest];
256
+
257
+ if (project) {
258
+ query += ' AND project = ?';
259
+ bindings.push(project);
260
+ }
261
+
262
+ if (status) {
263
+ query += ' AND status = ?';
264
+ bindings.push(status);
265
+ }
266
+
267
+ query += ' ORDER BY project, feature';
268
+
269
+ const result = await env.PLATFORM_DB.prepare(query)
270
+ .bind(...bindings)
271
+ .all<{
272
+ project: string;
273
+ feature: string;
274
+ status: string;
275
+ last_heartbeat: string | null;
276
+ events_last_7d: number;
277
+ defined_budget: number | null;
278
+ budget_unit: string | null;
279
+ }>();
280
+
281
+ // Build summary
282
+ const entries = result.results ?? [];
283
+ const summary = {
284
+ active: entries.filter((e) => e.status === 'active').length,
285
+ dormant: entries.filter((e) => e.status === 'dormant').length,
286
+ undefined: entries.filter((e) => e.status === 'undefined').length,
287
+ total: entries.length,
288
+ };
289
+
290
+ return Response.json({
291
+ success: true,
292
+ data: {
293
+ auditTime: latestResult.latest,
294
+ summary,
295
+ features: entries,
296
+ },
297
+ timestamp: new Date().toISOString(),
298
+ });
299
+ } catch (error) {
300
+ const message = error instanceof Error ? error.message : 'Unknown error';
301
+ return Response.json(
302
+ { success: false, error: 'Failed to get feature coverage', message },
303
+ { status: 500 }
304
+ );
305
+ }
306
+ }