@semilayer/core 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.
@@ -0,0 +1,1032 @@
1
+ declare const FACET_NAMES: readonly ["search", "similar"];
2
+ type FacetName = (typeof FACET_NAMES)[number];
3
+ /** Facets planned for future releases. Config types exist but no runtime support yet. */
4
+ declare const FUTURE_FACETS: readonly ["dedup", "classify"];
5
+ declare const FIELD_TYPES: readonly ["text", "number", "boolean", "date", "json", "enum", "relation"];
6
+ type FieldType = (typeof FIELD_TYPES)[number];
7
+ declare const INGEST_JOB_TYPES: readonly ["full", "incremental", "delete", "records"];
8
+ type IngestJobType = (typeof INGEST_JOB_TYPES)[number];
9
+ declare const LENS_STATUSES: readonly ["paused", "indexing", "ready", "error"];
10
+ type LensStatus = (typeof LENS_STATUSES)[number];
11
+ declare const INGEST_STATUSES: readonly ["queued", "running", "completed", "failed"];
12
+ type IngestStatus = (typeof INGEST_STATUSES)[number];
13
+ declare const KEY_PREFIXES: {
14
+ readonly serviceKey: "sk_";
15
+ readonly publishableKey: "pk_";
16
+ readonly ingestKey: "ik_";
17
+ };
18
+ declare const DEPLOYMENT_MODES: readonly ["saas", "enterprise"];
19
+ type DeploymentMode = (typeof DEPLOYMENT_MODES)[number];
20
+ declare const SOURCE_FEATURES: readonly ["incremental", "change-tracking", "streaming"];
21
+ type SourceFeature = (typeof SOURCE_FEATURES)[number];
22
+ declare const TRANSFORM_TYPES: readonly ["toString", "toNumber", "toBoolean", "toDate", "round", "trim", "lowercase", "uppercase", "default", "split", "join", "truncate", "replace", "custom"];
23
+ type TransformType = (typeof TRANSFORM_TYPES)[number];
24
+ declare const MERGE_STRATEGIES: readonly ["concat", "coalesce"];
25
+ type MergeStrategy = (typeof MERGE_STRATEGIES)[number];
26
+
27
+ interface FieldConfig {
28
+ type: FieldType;
29
+ primaryKey?: boolean;
30
+ /**
31
+ * Opt-in for embedding. Only fields with searchable are included in the embedding text.
32
+ * - `true` — include once (weight 1)
33
+ * - `{ weight: N }` — repeat N times in embedding text for stronger relevance
34
+ * - `false` / omitted — not embedded
35
+ */
36
+ searchable?: boolean | {
37
+ weight?: number;
38
+ };
39
+ /** Source column name(s). Omit for identity (source col = output field name). */
40
+ from?: string | string[];
41
+ /** Merge strategy when from is string[]. Required for multi-source. */
42
+ merge?: MergeStrategy;
43
+ /** Separator for merge: 'concat'. Required when merge is 'concat'. */
44
+ separator?: string;
45
+ /** Transform chain applied to the resolved value. */
46
+ transform?: TransformSpec;
47
+ /** Replace null values with this. 'omit' removes the key, 'undefined' sets undefined. */
48
+ nullAs?: unknown;
49
+ /** Replace undefined/missing values with this. */
50
+ undefinedAs?: unknown;
51
+ values?: string[];
52
+ to?: string;
53
+ }
54
+ interface SearchFacetConfig {
55
+ fields: string[];
56
+ mode?: 'semantic' | 'keyword' | 'hybrid';
57
+ weights?: Record<string, number>;
58
+ }
59
+ interface SimilarFacetConfig {
60
+ fields: string[];
61
+ limit?: number;
62
+ }
63
+ /** Future: duplicate detection based on embedding similarity threshold */
64
+ interface DedupFacetConfig {
65
+ fields: string[];
66
+ threshold?: number;
67
+ }
68
+ /** Future: zero-shot classification by embedding similarity to labels */
69
+ interface ClassifyFacetConfig {
70
+ labels: string[];
71
+ field?: string;
72
+ }
73
+ type FacetConfig = SearchFacetConfig | SimilarFacetConfig | DedupFacetConfig | ClassifyFacetConfig;
74
+ interface JwtClaims {
75
+ sub: string;
76
+ [key: string]: unknown;
77
+ }
78
+ interface AccessRuleResult {
79
+ filter?: Record<string, unknown>;
80
+ }
81
+ /** Serializable claim-based access rule (stored in DB jsonb) */
82
+ interface ClaimCheck {
83
+ authenticated: true;
84
+ claims: Record<string, string | string[]>;
85
+ }
86
+ type AccessRule = 'public' | 'authenticated' | ClaimCheck | ((claims: JwtClaims) => AccessRuleResult | boolean);
87
+ /** Per-environment auth provider config (JWKS) */
88
+ interface EnvironmentAuthConfig {
89
+ jwksUrl: string;
90
+ issuer: string;
91
+ audience?: string;
92
+ }
93
+ interface JwtConfig {
94
+ jwksUrl?: string;
95
+ issuer?: string;
96
+ audience?: string;
97
+ claims?: Record<string, string>;
98
+ }
99
+ interface AuthConfig {
100
+ server?: {
101
+ key?: string;
102
+ };
103
+ client?: {
104
+ jwt?: JwtConfig;
105
+ publishableKey?: string;
106
+ rules?: LensRules;
107
+ };
108
+ }
109
+ type LensRuleKey = FacetName | 'query';
110
+ type LensRules = Partial<Record<LensRuleKey, AccessRule>>;
111
+ interface EmbeddingConfig {
112
+ provider: string;
113
+ model: string;
114
+ apiKey?: string;
115
+ baseUrl?: string;
116
+ }
117
+ interface SourceConfig {
118
+ bridge: string;
119
+ features?: SourceFeature[];
120
+ /** Max query timeout in ms. Default: 30000. On timeout: returns error (504). */
121
+ timeout?: number;
122
+ [key: string]: unknown;
123
+ }
124
+ interface ToStringTransform {
125
+ type: 'toString';
126
+ }
127
+ interface ToNumberTransform {
128
+ type: 'toNumber';
129
+ }
130
+ interface ToBooleanTransform {
131
+ type: 'toBoolean';
132
+ }
133
+ interface ToDateTransform {
134
+ type: 'toDate';
135
+ format?: string;
136
+ }
137
+ interface RoundTransform {
138
+ type: 'round';
139
+ decimals?: number;
140
+ mode?: 'round' | 'ceil' | 'floor';
141
+ }
142
+ interface TrimTransform {
143
+ type: 'trim';
144
+ }
145
+ interface LowercaseTransform {
146
+ type: 'lowercase';
147
+ }
148
+ interface UppercaseTransform {
149
+ type: 'uppercase';
150
+ }
151
+ interface DefaultTransform {
152
+ type: 'default';
153
+ value: unknown;
154
+ }
155
+ interface SplitTransform {
156
+ type: 'split';
157
+ separator: string;
158
+ }
159
+ interface JoinTransform {
160
+ type: 'join';
161
+ separator: string;
162
+ }
163
+ interface TruncateTransform {
164
+ type: 'truncate';
165
+ length: number;
166
+ }
167
+ interface ReplaceTransform {
168
+ type: 'replace';
169
+ pattern: string;
170
+ replacement: string;
171
+ }
172
+ interface CustomTransform {
173
+ type: 'custom';
174
+ body: string;
175
+ }
176
+ type BuiltinTransform = ToStringTransform | ToNumberTransform | ToBooleanTransform | ToDateTransform | RoundTransform | TrimTransform | LowercaseTransform | UppercaseTransform | DefaultTransform | SplitTransform | JoinTransform | TruncateTransform | ReplaceTransform | CustomTransform;
177
+ type TransformSpec = BuiltinTransform | BuiltinTransform[];
178
+ type SyncInterval = '1m' | '5m' | '15m' | '30m' | '1h' | '6h' | '24h';
179
+ interface LensConfig {
180
+ source: string;
181
+ table: string;
182
+ primaryKey?: string;
183
+ fields: Record<string, FieldConfig>;
184
+ nullValues?: unknown[];
185
+ syncInterval?: SyncInterval;
186
+ changeTrackingColumn?: string;
187
+ facets: Record<string, FacetConfig>;
188
+ rules?: LensRules;
189
+ }
190
+ interface SemiLayerConfig {
191
+ stack: string;
192
+ sources: Record<string, SourceConfig>;
193
+ lenses: Record<string, LensConfig>;
194
+ auth?: AuthConfig;
195
+ embeddings?: EmbeddingConfig;
196
+ }
197
+
198
+ declare function validateConfig(config: SemiLayerConfig): void;
199
+
200
+ /**
201
+ * Returns the list of source column names that the bridge needs to read.
202
+ * Derives from `from` properties on fields, falling back to the output field name.
203
+ */
204
+ declare function resolveSourceColumns(fields: Record<string, FieldConfig>): string[];
205
+ interface EmbeddingField {
206
+ field: string;
207
+ weight: number;
208
+ }
209
+ /**
210
+ * Returns the output field names that are marked for embedding,
211
+ * with their weights. Weight controls how many times a field's text
212
+ * is repeated in the embedding input (higher = more relevance).
213
+ */
214
+ declare function resolveEmbeddingFields(fields: Record<string, FieldConfig>): EmbeddingField[];
215
+ /**
216
+ * Convenience: returns just the field names (for APIs that only need names).
217
+ */
218
+ declare function resolveEmbeddingFieldNames(fields: Record<string, FieldConfig>): string[];
219
+
220
+ /**
221
+ * Creates a deterministic SHA-256 hash of any JSON-serializable value.
222
+ * Object keys are sorted recursively to ensure determinism regardless of insertion order.
223
+ */
224
+ declare function canonicalHash(obj: unknown): string;
225
+
226
+ /**
227
+ * Maps a raw database column type to a SemiLayer FieldType.
228
+ * Falls back to 'text' for unknown types.
229
+ */
230
+ declare function mapDbTypeToFieldType(dbType: string): FieldType;
231
+
232
+ type TransportMode = 'http' | 'ws' | 'stream';
233
+ interface TransportOptions {
234
+ mode?: TransportMode;
235
+ timeout?: number;
236
+ }
237
+
238
+ type WhereClause = Record<string, unknown>;
239
+ interface OrderByClause {
240
+ field: string;
241
+ dir?: 'asc' | 'desc';
242
+ }
243
+ interface QueryOptions {
244
+ where?: WhereClause;
245
+ orderBy?: OrderByClause | OrderByClause[];
246
+ limit?: number;
247
+ offset?: number;
248
+ cursor?: string;
249
+ select?: string[];
250
+ transport?: TransportMode;
251
+ }
252
+ interface QueryResult<T> {
253
+ rows: T[];
254
+ total?: number;
255
+ nextCursor?: string;
256
+ }
257
+
258
+ type BridgeRow = Record<string, unknown>;
259
+ interface ReadOptions {
260
+ fields?: string[];
261
+ cursor?: string;
262
+ limit?: number;
263
+ changedSince?: Date;
264
+ changeTrackingColumn?: string;
265
+ }
266
+ interface ReadResult {
267
+ rows: BridgeRow[];
268
+ nextCursor?: string;
269
+ total?: number;
270
+ }
271
+ interface TargetColumnInfo {
272
+ name: string;
273
+ /** Raw database type (e.g., 'varchar', 'integer', 'jsonb') */
274
+ type: string;
275
+ nullable: boolean;
276
+ primaryKey: boolean;
277
+ }
278
+ interface TargetSchema {
279
+ name: string;
280
+ columns: TargetColumnInfo[];
281
+ rowCount?: number;
282
+ }
283
+ interface Bridge {
284
+ connect(): Promise<void>;
285
+ read(target: string, options?: ReadOptions): Promise<ReadResult>;
286
+ count(target: string): Promise<number>;
287
+ disconnect(): Promise<void>;
288
+ query?(target: string, options: QueryOptions): Promise<QueryResult<BridgeRow>>;
289
+ /** List available targets (tables, collections, etc.). Not all bridges support this. */
290
+ listTargets?(): Promise<string[]>;
291
+ /** Introspect a target's schema (columns, types, PKs). Not all bridges support this. */
292
+ introspectTarget?(target: string): Promise<TargetSchema>;
293
+ }
294
+ type BridgeConstructor = new (config: Record<string, unknown>) => Bridge;
295
+
296
+ /** Thin envelope — what the service enqueues */
297
+ interface IngestJobPayload {
298
+ environmentId: string;
299
+ lensName: string;
300
+ sourceName: string;
301
+ type: 'full' | 'incremental' | 'delete';
302
+ cursor?: string;
303
+ /** True when triggered by a platform admin (bypasses quotas) */
304
+ adminInvoked?: boolean;
305
+ /** OIDC sub of the user who triggered this job */
306
+ invokedBy?: string;
307
+ }
308
+ /**
309
+ * Full job data for v0.1 standalone/test mode.
310
+ * In production, the worker resolves configs from the platform DB
311
+ * using only the fields from IngestJobPayload.
312
+ */
313
+ interface IngestJobData extends IngestJobPayload {
314
+ bridgeName: string;
315
+ sourceConfig: Record<string, unknown>;
316
+ lensConfig: {
317
+ table: string;
318
+ primaryKey: string;
319
+ fields: string[];
320
+ embeddingFields: string[];
321
+ };
322
+ embeddingConfig: {
323
+ provider: string;
324
+ model: string;
325
+ dimensions: number;
326
+ apiKey?: string;
327
+ baseUrl?: string;
328
+ };
329
+ }
330
+ /** State-based ingest control (stored in status table / platform DB) */
331
+ interface IngestControl {
332
+ status: IngestStatus;
333
+ pausedAt?: Date;
334
+ lastFullIngestAt?: Date;
335
+ lastIncrementalAt?: Date;
336
+ }
337
+ /** Rate limit state — visible in status introspection */
338
+ interface RateLimitState {
339
+ limited: boolean;
340
+ retryAfter?: Date;
341
+ provider: string;
342
+ reason?: string;
343
+ lastError?: string;
344
+ }
345
+ /** Individual error entry in the ring buffer */
346
+ interface IngestErrorEntry {
347
+ timestamp: Date;
348
+ message: string;
349
+ type?: string;
350
+ }
351
+ /** Per-lens status — what `semilayer status` shows */
352
+ interface LensStatusInfo {
353
+ name: string;
354
+ status: LensStatus;
355
+ paused: boolean;
356
+ vectorCount: number;
357
+ totalRows?: number;
358
+ lastIngestAt?: Date;
359
+ lastIngestType?: 'full' | 'incremental';
360
+ cursor?: string;
361
+ error?: string;
362
+ rateLimit?: RateLimitState;
363
+ errorCount: number;
364
+ lastErrors: IngestErrorEntry[];
365
+ circuitBreakerUntil?: Date;
366
+ }
367
+ /** Queue health — what `semilayer status` shows */
368
+ interface QueueCounts {
369
+ active: number;
370
+ pending: number;
371
+ deferred: number;
372
+ failed: number;
373
+ completed24h: number;
374
+ }
375
+ /** Failed job info from dead letter queue */
376
+ interface FailedJobInfo {
377
+ id: string;
378
+ queue: string;
379
+ data: Record<string, unknown>;
380
+ error: string;
381
+ failedAt: Date;
382
+ retryCount: number;
383
+ }
384
+
385
+ /** ISO 8601 date string (e.g. "2026-04-06T12:00:00.000Z"). Dates serialize to strings over the wire. */
386
+ type ISODateString = string;
387
+ interface Org {
388
+ id: string;
389
+ name: string;
390
+ slug: string;
391
+ tierId: string | null;
392
+ createdAt: ISODateString;
393
+ }
394
+ interface Project {
395
+ id: string;
396
+ name: string;
397
+ slug: string;
398
+ createdAt: ISODateString;
399
+ }
400
+ interface Environment {
401
+ id: string;
402
+ name: string;
403
+ slug: string;
404
+ authConfig?: EnvironmentAuthConfig | null;
405
+ createdAt: ISODateString;
406
+ }
407
+ interface Source {
408
+ id: string;
409
+ name: string;
410
+ bridge: string;
411
+ createdAt: ISODateString;
412
+ }
413
+ interface Lens {
414
+ id: string;
415
+ name: string;
416
+ status: LensStatus;
417
+ createdAt: ISODateString;
418
+ updatedAt: ISODateString;
419
+ }
420
+ interface ApiKeyInfo {
421
+ id: string;
422
+ type: string;
423
+ key: string;
424
+ label: string | null;
425
+ createdAt: ISODateString;
426
+ }
427
+ interface Member {
428
+ id: string;
429
+ userId: string;
430
+ email: string;
431
+ role: string;
432
+ invitedBy: string | null;
433
+ createdAt: ISODateString;
434
+ }
435
+ interface IngestRun {
436
+ id: string;
437
+ status: IngestStatus;
438
+ recordsProcessed: number;
439
+ recordsFailed: number;
440
+ startedAt: ISODateString | null;
441
+ completedAt: ISODateString | null;
442
+ error: string | null;
443
+ adminInvoked: boolean;
444
+ invokedBy: string | null;
445
+ createdAt: ISODateString;
446
+ }
447
+ interface Tier {
448
+ id: string;
449
+ name: string;
450
+ slug: string;
451
+ stripePriceMonthly: string | null;
452
+ stripePriceYearly: string | null;
453
+ priceCentsMonthly: number | null;
454
+ priceCentsYearly: number | null;
455
+ embeddingTokensPerMonth: number | null;
456
+ vectorsStored: number | null;
457
+ ingestJobsPerDay: number | null;
458
+ apiRequestsPerMonth: number | null;
459
+ /** Step 12 — per-minute burst protection. */
460
+ apiRequestsPerMinute: number | null;
461
+ environmentsPerProject: number | null;
462
+ projectsPerOrg: number | null;
463
+ membersPerOrg: number | null;
464
+ /** Step 12 — per-user org creation cap. */
465
+ orgsPerUser: number | null;
466
+ /** Step 12 — per-minute ingest webhook rate limit. */
467
+ ingestWebhooksPerMinute: number | null;
468
+ features: Record<string, unknown>;
469
+ displayOrder: number;
470
+ isDefault: boolean;
471
+ visible: boolean;
472
+ createdAt: ISODateString;
473
+ updatedAt: ISODateString;
474
+ }
475
+ interface TierOverride {
476
+ id: string;
477
+ orgId: string;
478
+ embeddingTokensPerMonth: number | null;
479
+ vectorsStored: number | null;
480
+ ingestJobsPerDay: number | null;
481
+ apiRequestsPerMonth: number | null;
482
+ apiRequestsPerMinute: number | null;
483
+ environmentsPerProject: number | null;
484
+ projectsPerOrg: number | null;
485
+ membersPerOrg: number | null;
486
+ orgsPerUser: number | null;
487
+ ingestWebhooksPerMinute: number | null;
488
+ features: Record<string, unknown> | null;
489
+ note: string | null;
490
+ createdAt: ISODateString;
491
+ updatedAt: ISODateString;
492
+ }
493
+ interface AuthUser {
494
+ sub: string;
495
+ email: string;
496
+ name?: string;
497
+ }
498
+ interface AuthOrg {
499
+ id: string;
500
+ slug: string;
501
+ role: string;
502
+ }
503
+ interface MeResponse {
504
+ user: AuthUser;
505
+ orgs: AuthOrg[];
506
+ platformAdmin?: boolean;
507
+ /** Step 12 — exposes deployment mode so the Console can hide billing UI in enterprise mode without flashing it on mount. */
508
+ deploymentMode?: 'saas' | 'enterprise';
509
+ }
510
+ interface PlatformAdmin {
511
+ id: string;
512
+ userId: string | null;
513
+ email: string;
514
+ grantedBy: string | null;
515
+ createdAt: ISODateString;
516
+ }
517
+ interface AuditLogEntry {
518
+ id: string;
519
+ adminUserId: string;
520
+ adminEmail: string;
521
+ action: string;
522
+ resourceType: string | null;
523
+ resourceId: string | null;
524
+ orgSlug: string | null;
525
+ details: Record<string, unknown> | null;
526
+ ipAddress: string;
527
+ createdAt: ISODateString;
528
+ }
529
+ interface PlatformStats {
530
+ orgCount: number;
531
+ userCount: number;
532
+ projectCount: number;
533
+ environmentCount: number;
534
+ lensCount: number;
535
+ vectorCount: number;
536
+ activeIngestJobs: number;
537
+ }
538
+ interface SystemHealth {
539
+ database: {
540
+ connected: boolean;
541
+ poolSize: number;
542
+ idleCount: number;
543
+ waitingCount: number;
544
+ };
545
+ queue: {
546
+ activeJobs: number;
547
+ pendingJobs: number;
548
+ failedJobs24h: number;
549
+ };
550
+ vectorStore: {
551
+ totalVectors: number;
552
+ partitionCount: number;
553
+ };
554
+ }
555
+ interface InAppNotification {
556
+ id: string;
557
+ orgId: string;
558
+ userId: string;
559
+ type: string;
560
+ title: string;
561
+ body: string;
562
+ data: Record<string, unknown>;
563
+ actionUrl: string | null;
564
+ readAt: ISODateString | null;
565
+ createdAt: ISODateString;
566
+ }
567
+ interface NotificationPreferenceSummary {
568
+ type: string;
569
+ email: boolean;
570
+ inApp: boolean;
571
+ mandatory: boolean;
572
+ }
573
+ interface NewKeyPair {
574
+ key: string;
575
+ type: string;
576
+ }
577
+ interface CreateProjectResponse {
578
+ project: Project;
579
+ environment: Environment;
580
+ keys: NewKeyPair[];
581
+ }
582
+ interface CreateEnvResponse {
583
+ environment: Environment;
584
+ keys: NewKeyPair[];
585
+ }
586
+ interface PushLensSummary {
587
+ created: string[];
588
+ updated: string[];
589
+ unchanged: string[];
590
+ deleted: string[];
591
+ }
592
+ interface PushIngestJob {
593
+ lensName: string;
594
+ type: string;
595
+ jobId: string | null;
596
+ }
597
+ interface PushResponse {
598
+ lenses: PushLensSummary;
599
+ ingestJobs: PushIngestJob[];
600
+ }
601
+ interface StatusEnvironment {
602
+ id: string;
603
+ slug: string;
604
+ project: string;
605
+ org: string;
606
+ }
607
+ interface StatusResponse {
608
+ environment: StatusEnvironment;
609
+ lenses: LensStatusInfo[];
610
+ queue: QueueCounts;
611
+ }
612
+ /** Slim tier shape used inside `OrgDetailResponse` and similar nested contexts. */
613
+ interface TierSummary {
614
+ id: string;
615
+ name: string;
616
+ slug: string;
617
+ }
618
+ /** Row shape returned by `GET /admin/orgs` — enriched with tier name and counts. */
619
+ interface OrgListItem {
620
+ id: string;
621
+ name: string;
622
+ slug: string;
623
+ tierId: string | null;
624
+ tierName: string | null;
625
+ memberCount: number;
626
+ projectCount: number;
627
+ createdAt: ISODateString;
628
+ }
629
+ /** Composite returned by `GET /admin/orgs/:orgSlug` */
630
+ interface OrgDetailResponse {
631
+ org: Org;
632
+ tier: TierSummary | null;
633
+ override: TierOverride | null;
634
+ members: Member[];
635
+ projects: Project[];
636
+ }
637
+ /** Project enriched with its environments — used in admin project browser and similar UIs. */
638
+ interface ProjectWithEnvs extends Project {
639
+ environments: Environment[];
640
+ }
641
+ /** Returned by `GET /v1/invites/:token` — used by the invite acceptance page. */
642
+ interface InviteInfo {
643
+ orgName: string;
644
+ orgSlug: string;
645
+ role: string;
646
+ inviterEmail: string | null;
647
+ expired: boolean;
648
+ }
649
+ /** Per-lens drift summary — returned by `GET .../envs/:envSlug/drift`. */
650
+ interface DriftLensInfo {
651
+ name: string;
652
+ configHash: string | null;
653
+ lastModifiedBy: string | null;
654
+ updatedAt: ISODateString;
655
+ }
656
+ /** Wraps the drift list returned by `GET .../envs/:envSlug/drift`. */
657
+ interface DriftResponse {
658
+ lenses: DriftLensInfo[];
659
+ }
660
+ /** Wraps the env list returned by `GET /v1/orgs/:org/projects/:project/envs`. */
661
+ interface EnvsResponse {
662
+ environments: Environment[];
663
+ }
664
+ /** Wraps the config payload returned by `GET .../envs/:envSlug/config/export`. */
665
+ interface ConfigExportResponse {
666
+ config: SemiLayerConfig;
667
+ }
668
+ /** Per-lens diff entry built client-side from two env exports + drift summaries. */
669
+ interface LensComparison {
670
+ name: string;
671
+ leftConfig: LensConfig | null;
672
+ rightConfig: LensConfig | null;
673
+ leftDrift: DriftLensInfo | null;
674
+ rightDrift: DriftLensInfo | null;
675
+ status: 'identical' | 'modified' | 'only-left' | 'only-right';
676
+ }
677
+ /** Returned by `POST .../envs/:envSlug/lenses` — slim summary of the created/updated lens. */
678
+ interface LensCreateResponse {
679
+ id: string;
680
+ name: string;
681
+ status: string;
682
+ updated: boolean;
683
+ }
684
+ /** Today's live activity snapshot — `GET /admin/metrics/daily`. */
685
+ interface DailyMetrics {
686
+ date: string;
687
+ logins: number;
688
+ keyCreations: number;
689
+ apiRequests: number;
690
+ ingestJobs: number;
691
+ feedbackCount: number;
692
+ vectorsTotal: number;
693
+ }
694
+ /** Single point in a metric time series — `GET /admin/metrics?from=...`. */
695
+ interface MetricPoint {
696
+ date: string;
697
+ metric: string;
698
+ value: number;
699
+ }
700
+ /** Active platform-wide banner — controlled from the admin dashboard. */
701
+ interface BannerData {
702
+ id: string;
703
+ message: string;
704
+ variant: string;
705
+ dismissible: boolean;
706
+ }
707
+ /** Feedback list row — `GET /admin/feedback`. */
708
+ interface FeedbackItem {
709
+ id: string;
710
+ orgSlug: string;
711
+ email: string;
712
+ body: string;
713
+ hasScreenshot: boolean;
714
+ status: string;
715
+ adminNote: string | null;
716
+ readBy: string | null;
717
+ readAt: ISODateString | null;
718
+ createdAt: ISODateString;
719
+ }
720
+ /** Feedback detail view — `GET /admin/feedback/:id`. Includes screenshot data. */
721
+ interface FeedbackDetail extends FeedbackItem {
722
+ screenshotData: string | null;
723
+ screenshotMime: string | null;
724
+ userId: string;
725
+ }
726
+ /** Banned IP address — `GET /admin/bans` (ip tab). */
727
+ interface BannedIp {
728
+ id: string;
729
+ ipAddress: string;
730
+ reason: string | null;
731
+ bannedBy: string;
732
+ expiresAt: ISODateString | null;
733
+ active: boolean;
734
+ createdAt: ISODateString;
735
+ }
736
+ /** Banned user — `GET /admin/bans` (user tab). */
737
+ interface BannedUser {
738
+ id: string;
739
+ userId: string;
740
+ email: string;
741
+ reason: string | null;
742
+ bannedBy: string;
743
+ expiresAt: ISODateString | null;
744
+ active: boolean;
745
+ createdAt: ISODateString;
746
+ }
747
+ interface SearchParams {
748
+ query: string;
749
+ limit?: number;
750
+ minScore?: number;
751
+ /** Override search mode. Defaults to lens facet config, then 'semantic'. */
752
+ mode?: 'semantic' | 'keyword' | 'hybrid';
753
+ }
754
+ interface SearchResult<M = Record<string, unknown>> {
755
+ id: string;
756
+ sourceRowId: string;
757
+ content: string | null;
758
+ metadata: M;
759
+ score: number;
760
+ }
761
+ interface SearchResponse<M = Record<string, unknown>> {
762
+ results: SearchResult<M>[];
763
+ meta: {
764
+ lens: string;
765
+ query: string;
766
+ count: number;
767
+ durationMs: number;
768
+ };
769
+ }
770
+ interface SimilarParams {
771
+ id: string;
772
+ limit?: number;
773
+ minScore?: number;
774
+ }
775
+ interface SimilarResponse<M = Record<string, unknown>> {
776
+ results: SearchResult<M>[];
777
+ meta: {
778
+ lens: string;
779
+ sourceId: string;
780
+ count: number;
781
+ durationMs: number;
782
+ };
783
+ }
784
+ interface QueryParams {
785
+ where?: Record<string, unknown>;
786
+ orderBy?: {
787
+ field: string;
788
+ dir?: 'asc' | 'desc';
789
+ } | Array<{
790
+ field: string;
791
+ dir?: 'asc' | 'desc';
792
+ }>;
793
+ limit?: number;
794
+ offset?: number;
795
+ cursor?: string;
796
+ select?: string[];
797
+ }
798
+ interface QueryResponse<M = Record<string, unknown>> {
799
+ rows: M[];
800
+ meta: {
801
+ lens: string;
802
+ total?: number;
803
+ nextCursor?: string;
804
+ count: number;
805
+ durationMs: number;
806
+ };
807
+ }
808
+ /** One row in the admin users list — derived by aggregating members + sessions + bans. */
809
+ interface AdminUserListItem {
810
+ userId: string;
811
+ email: string;
812
+ orgCount: number;
813
+ banned: boolean;
814
+ banId: string | null;
815
+ lastSeenAt: ISODateString | null;
816
+ firstSeenAt: ISODateString;
817
+ }
818
+ /** Wraps the list returned by `GET /admin/users`. */
819
+ interface AdminUserListResponse {
820
+ users: AdminUserListItem[];
821
+ total: number;
822
+ }
823
+ /** Org membership view inside `AdminUserDetail`. */
824
+ interface AdminUserOrgMembership {
825
+ memberId: string;
826
+ orgId: string;
827
+ orgSlug: string;
828
+ orgName: string;
829
+ role: string;
830
+ joinedAt: ISODateString;
831
+ }
832
+ /** Detail view returned by `GET /admin/users/:userId`. */
833
+ interface AdminUserDetail {
834
+ userId: string;
835
+ email: string;
836
+ banned: boolean;
837
+ banId: string | null;
838
+ banReason: string | null;
839
+ bannedAt: ISODateString | null;
840
+ lastSeenAt: ISODateString | null;
841
+ firstSeenAt: ISODateString;
842
+ memberships: AdminUserOrgMembership[];
843
+ }
844
+ /** Body for `POST /admin/users/:userId/orgs` — assign user to an org. */
845
+ interface AdminAssignUserBody {
846
+ orgSlug: string;
847
+ role: string;
848
+ }
849
+ /** One pending invite row — derived from `members WHERE invite_token IS NOT NULL`. */
850
+ interface PendingInvite {
851
+ memberId: string;
852
+ email: string;
853
+ role: string;
854
+ orgId: string;
855
+ orgSlug: string;
856
+ orgName: string;
857
+ invitedByEmail: string | null;
858
+ expiresAt: ISODateString | null;
859
+ expired: boolean;
860
+ createdAt: ISODateString;
861
+ }
862
+ /** Wraps the list returned by `GET /admin/invites`. */
863
+ interface PendingInvitesResponse {
864
+ invites: PendingInvite[];
865
+ total: number;
866
+ }
867
+ /** Snapshot of an org's plan + usage + cycle. Returned by `GET /v1/orgs/:org/billing`. */
868
+ interface BillingSnapshot {
869
+ plan: BillingPlan | null;
870
+ usage: Record<string, UsageMetricSnapshot>;
871
+ cycle: BillingCycleInfo;
872
+ }
873
+ /** Pricing + identity for the org's current plan. Null on enterprise mode. */
874
+ interface BillingPlan {
875
+ tierId: string;
876
+ tierName: string;
877
+ tierSlug: string;
878
+ priceCents: number;
879
+ /** 'monthly' | 'yearly' — null when org has no Stripe subscription (Free tier). */
880
+ interval: 'monthly' | 'yearly' | null;
881
+ features: Record<string, unknown>;
882
+ }
883
+ /** Single usage dimension for the current cycle. Used by Console usage cards + sidebar indicator. */
884
+ interface UsageMetricSnapshot {
885
+ /** Internal name: 'embedding_tokens' | 'vectors_stored' | 'api_requests' | 'ingest_jobs' | etc. */
886
+ metric: string;
887
+ current: number;
888
+ /** null = unlimited (Scale tier or enterprise). */
889
+ limit: number | null;
890
+ /** 0..100, or null when limit is null (unlimited). */
891
+ percentage: number | null;
892
+ }
893
+ /** Active billing cycle. Drives the "X days remaining" + reset date display. */
894
+ interface BillingCycleInfo {
895
+ periodStart: ISODateString;
896
+ periodEnd: ISODateString;
897
+ status: 'active' | 'past_due' | 'canceled';
898
+ daysRemaining: number;
899
+ }
900
+ /** Stripe invoice projection — billing page invoices table + admin events. */
901
+ interface Invoice {
902
+ id: string;
903
+ amountCents: number;
904
+ currency: string;
905
+ status: string;
906
+ created: ISODateString;
907
+ pdfUrl: string | null;
908
+ hostedUrl: string | null;
909
+ }
910
+ /** Detailed tier shape used by the upgrade picker + admin tier editor. Includes all limit fields. */
911
+ interface TierFull {
912
+ id: string;
913
+ name: string;
914
+ slug: string;
915
+ stripePriceMonthly: string | null;
916
+ stripePriceYearly: string | null;
917
+ priceCentsMonthly: number | null;
918
+ priceCentsYearly: number | null;
919
+ embeddingTokensPerMonth: number | null;
920
+ vectorsStored: number | null;
921
+ ingestJobsPerDay: number | null;
922
+ apiRequestsPerMonth: number | null;
923
+ apiRequestsPerMinute: number | null;
924
+ environmentsPerProject: number | null;
925
+ projectsPerOrg: number | null;
926
+ membersPerOrg: number | null;
927
+ orgsPerUser: number | null;
928
+ ingestWebhooksPerMinute: number | null;
929
+ features: Record<string, unknown>;
930
+ displayOrder: number;
931
+ isDefault: boolean;
932
+ visible: boolean;
933
+ createdAt: ISODateString;
934
+ updatedAt: ISODateString;
935
+ }
936
+ /** Wraps `GET /v1/tiers` (public endpoint). */
937
+ interface TiersResponse {
938
+ tiers: TierFull[];
939
+ }
940
+ /** Body for `POST /v1/orgs/:org/billing/checkout`. */
941
+ interface CheckoutRequest {
942
+ tierSlug: string;
943
+ interval: 'monthly' | 'yearly';
944
+ }
945
+ /** Response from `POST .../billing/checkout` and `POST .../billing/portal` — Stripe-hosted URL. */
946
+ interface BillingRedirectResponse {
947
+ url: string;
948
+ }
949
+ /** Body for `POST /v1/orgs/:org/billing/cancel`. */
950
+ interface CancelSubscriptionRequest {
951
+ /** false = cancel at period end (default). true = cancel immediately. */
952
+ immediately?: boolean;
953
+ }
954
+ /** Admin: monthly recurring revenue snapshot. `GET /v1/admin/billing/mrr`. */
955
+ interface AdminMrrSnapshot {
956
+ mrrCents: number;
957
+ arrCents: number;
958
+ activeSubscriptions: Record<string, number>;
959
+ churnThisMonth: number;
960
+ failedPayments: number;
961
+ }
962
+ /** Admin: cash collected this month — separate from MRR (literal Stripe invoice sum). `GET /v1/admin/billing/cash`. */
963
+ interface AdminCashSnapshot {
964
+ totalCents: number;
965
+ currency: string;
966
+ invoiceCount: number;
967
+ /** ISO timestamp of when the snapshot was computed (for the 5min cache). */
968
+ computedAt: ISODateString;
969
+ }
970
+ /** Admin: one row from `processed_stripe_events` for the events table. */
971
+ interface AdminStripeEventRow {
972
+ id: string;
973
+ stripeEventId: string;
974
+ eventType: string;
975
+ status: 'pending' | 'succeeded' | 'failed';
976
+ error: string | null;
977
+ processedAt: ISODateString;
978
+ }
979
+ /** Admin: org usage detail for `GET /v1/admin/orgs/:id/usage`. */
980
+ interface AdminOrgUsage {
981
+ orgId: string;
982
+ cycle: BillingCycleInfo;
983
+ usage: Record<string, UsageMetricSnapshot>;
984
+ tierName: string | null;
985
+ hasOverride: boolean;
986
+ }
987
+ /** Admin: top consumers row for `GET /v1/admin/usage/top?metric=...`. */
988
+ interface AdminTopConsumerRow {
989
+ orgId: string;
990
+ orgSlug: string;
991
+ orgName: string;
992
+ tierName: string | null;
993
+ metric: string;
994
+ current: number;
995
+ limit: number | null;
996
+ percentage: number | null;
997
+ }
998
+ /** Wraps `GET /v1/admin/usage/top`. */
999
+ interface AdminTopConsumersResponse {
1000
+ metric: string;
1001
+ rows: AdminTopConsumerRow[];
1002
+ }
1003
+ /** Body for `PUT /v1/admin/orgs/:id/override`. All fields nullable — null = use tier value. */
1004
+ interface TierOverrideRequest {
1005
+ embeddingTokensPerMonth?: number | null;
1006
+ vectorsStored?: number | null;
1007
+ ingestJobsPerDay?: number | null;
1008
+ apiRequestsPerMonth?: number | null;
1009
+ apiRequestsPerMinute?: number | null;
1010
+ environmentsPerProject?: number | null;
1011
+ projectsPerOrg?: number | null;
1012
+ membersPerOrg?: number | null;
1013
+ orgsPerUser?: number | null;
1014
+ ingestWebhooksPerMinute?: number | null;
1015
+ features?: Record<string, unknown> | null;
1016
+ note?: string | null;
1017
+ }
1018
+ /** Response shape for structured 403 quota errors. Console renders these uniformly. */
1019
+ interface QuotaErrorResponse {
1020
+ error: string;
1021
+ message: string;
1022
+ limit: number;
1023
+ current: number;
1024
+ upgradeUrl: string;
1025
+ }
1026
+
1027
+ declare function getDeploymentMode(): DeploymentMode;
1028
+ declare function isSaasMode(): boolean;
1029
+
1030
+ declare function defineConfig(config: SemiLayerConfig): SemiLayerConfig;
1031
+
1032
+ export { type AccessRule, type AccessRuleResult, type AdminAssignUserBody, type AdminCashSnapshot, type AdminMrrSnapshot, type AdminOrgUsage, type AdminStripeEventRow, type AdminTopConsumerRow, type AdminTopConsumersResponse, type AdminUserDetail, type AdminUserListItem, type AdminUserListResponse, type AdminUserOrgMembership, type ApiKeyInfo, type AuditLogEntry, type AuthConfig, type AuthOrg, type AuthUser, type BannedIp, type BannedUser, type BannerData, type BillingCycleInfo, type BillingPlan, type BillingRedirectResponse, type BillingSnapshot, type Bridge, type BridgeConstructor, type BridgeRow, type BuiltinTransform, type CancelSubscriptionRequest, type CheckoutRequest, type ClaimCheck, type ClassifyFacetConfig, type ConfigExportResponse, type CreateEnvResponse, type CreateProjectResponse, DEPLOYMENT_MODES, type DailyMetrics, type DedupFacetConfig, type DeploymentMode, type DriftLensInfo, type DriftResponse, type EmbeddingConfig, type EmbeddingField, type Environment, type EnvironmentAuthConfig, type EnvsResponse, FACET_NAMES, FIELD_TYPES, FUTURE_FACETS, type FacetConfig, type FacetName, type FailedJobInfo, type FeedbackDetail, type FeedbackItem, type FieldConfig, type FieldType, INGEST_JOB_TYPES, INGEST_STATUSES, type ISODateString, type InAppNotification, type IngestControl, type IngestErrorEntry, type IngestJobData, type IngestJobPayload, type IngestJobType, type IngestRun, type IngestStatus, type InviteInfo, type Invoice, type JwtClaims, type JwtConfig, KEY_PREFIXES, LENS_STATUSES, type Lens, type LensComparison, type LensConfig, type LensCreateResponse, type LensRuleKey, type LensRules, type LensStatus, type LensStatusInfo, MERGE_STRATEGIES, type MeResponse, type Member, type MergeStrategy, type MetricPoint, type NewKeyPair, type NotificationPreferenceSummary, type OrderByClause, type Org, type OrgDetailResponse, type OrgListItem, type PendingInvite, type PendingInvitesResponse, type PlatformAdmin, type PlatformStats, type Project, type ProjectWithEnvs, type PushIngestJob, type PushLensSummary, type PushResponse, type QueryOptions, type QueryParams, type QueryResponse, type QueryResult, type QueueCounts, type QuotaErrorResponse, type RateLimitState, type ReadOptions, type ReadResult, SOURCE_FEATURES, type SearchFacetConfig, type SearchParams, type SearchResponse, type SearchResult, type SemiLayerConfig, type SimilarFacetConfig, type SimilarParams, type SimilarResponse, type Source, type SourceConfig, type SourceFeature, type StatusEnvironment, type StatusResponse, type SyncInterval, type SystemHealth, TRANSFORM_TYPES, type TargetColumnInfo, type TargetSchema, type Tier, type TierFull, type TierOverride, type TierOverrideRequest, type TierSummary, type TiersResponse, type TransformSpec, type TransformType, type TransportMode, type TransportOptions, type UsageMetricSnapshot, type WhereClause, canonicalHash, defineConfig, getDeploymentMode, isSaasMode, mapDbTypeToFieldType, resolveEmbeddingFieldNames, resolveEmbeddingFields, resolveSourceColumns, validateConfig };